Path: seismo!harvard!husc6!panda!sources-request From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: 4.2BSD XMODEM programs Message-ID: <1857@panda.UUCP> Date: 13 May 86 03:28:53 GMT Sender: jpn@panda.UUCP Lines: 1953 Approved: jpn@panda.UUCP Mod.sources: Volume 4, Issue 118 Submitted by: seismo!uwvax!nicmad!brown (Mr. Video) #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # README # xmodrec.1 # xmodtran.1 # Makefile # add.c # addcr.c # addlf.c # copy.c # cr.c # cr2lf.c # del.c # delcr.c # lf.c # lf2cr.c # receive.c # to_pc.c # to_vax.c # transmit.c # This archive created: Mon May 12 23:22:53 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'README'" '(684 characters)' if test -f 'README' then echo shar: will not over-write existing file "'README'" else cat << \SHAR_EOF > 'README' To create the two xmodem programs, run: make all To (compile and) install run: make install There are two manual files: xmodtran.1 and xmodrec.1 The two compiled programs, xmodrec and xmodtran, will be moved to the /usr/local directory. If this is not where you want them, change the Makefile $PATH variable to what you want for your system. The programs are being used on a VAX 750 with BSD 4.2. They are used to transfer data between PCs and the VAX. If you have any questions or comments, send UUCP mail to: ihnp4------\ harvard-\ \ seismo!uwvax!nicmad!brown topaz-/ / decvax------/ Mike Brown SHAR_EOF if test 684 -ne "`wc -c < 'README'`" then echo shar: error transmitting "'README'" '(should have been 684 characters)' fi fi echo shar: extracting "'xmodrec.1'" '(579 characters)' if test -f 'xmodrec.1' then echo shar: will not over-write existing file "'xmodrec.1'" else cat << \SHAR_EOF > 'xmodrec.1' .TH XMODREC 1 .SH NAME xmodrec \- receive file using XMODEM protocol .SH SYNOPSIS .B xmodrec [ .B \-t ] filename .SH DESCRIPTION .I Xmodrec is used to receive a file from another computer, ie, IBM PC or look-alike. The computer from which the file is to be received must also have the XMODEM protocol. .PP This version of XMODEM uses the checksum method of error detection. .PP Options: .TP 6 .B \-t Remove the carriage returns from the incoming data. Also removes the ^Z end-of-file marker and any data after it. .SH AUTHOR Jim Hein {ihnp4,seismo}!uwvax!astroatc!nicmad!jhein SHAR_EOF if test 579 -ne "`wc -c < 'xmodrec.1'`" then echo shar: error transmitting "'xmodrec.1'" '(should have been 579 characters)' fi fi echo shar: extracting "'xmodtran.1'" '(614 characters)' if test -f 'xmodtran.1' then echo shar: will not over-write existing file "'xmodtran.1'" else cat << \SHAR_EOF > 'xmodtran.1' .TH XMODTRAN 1 .SH NAME xmodtran \- transmit a file using XMODEM protocol .SH SYNOPSIS .B xmodtran [ .B \-t ] filename .SH DESCRIPTION .I Xmodtran is used to transmit a file to another computer, ie, IBM PC or look-alike. The computer to which the file is to be transmitted must also have the XMODEM protocol. .PP This version of XMODEM uses the checksum method of error detection. .PP Options: .TP 6 .B \-t Adds carriage returns to each line of data being transmitted. Some computers require that the text file have a CR/LF at the end of each line. .SH AUTHOR Jim Hein {ihnp4,seismo}!uwvax!astroatc!nicmad!jhein SHAR_EOF if test 614 -ne "`wc -c < 'xmodtran.1'`" then echo shar: error transmitting "'xmodtran.1'" '(should have been 614 characters)' fi fi echo shar: extracting "'Makefile'" '(1340 characters)' if test -f 'Makefile' then echo shar: will not over-write existing file "'Makefile'" else cat << \SHAR_EOF > 'Makefile' FILES = receive.c transmit.c addcr.c delcr.c add.c del.c\ lf2cr.c cr.c lf.c cr2lf.c OBJS = receive.o transmit.o addcr.o delcr.o add.o del.o\ lf2cr.o cr.o lf.o cr2lf.o LIBS = -lcurses -ltermlib FLAGS = -O -c -I/sys/h PATH = /usr/local all: receive transmit clean: rm -f $(OBJS) receive transmit pr: lpr -Plp $(FILES) install: receive transmit strip receive cp receive $(PATH)/xmodrec strip transmit cp transmit $(PATH)/xmodtran receive.o: receive.c cc $(FLAGS) receive.c receive: receive.o del.o lf.o cc -O -o receive del.o lf.o receive.o $(LIBS) transmit.o: transmit.c cc $(FLAGS) transmit.c transmit: transmit.o add.o cr.o cc -O -o transmit add.o cr.o transmit.o $(LIBS) addcr.o: addcr.c cc $(FLAGS) addcr.c addcr: addcr.o add.o cc -O -o addcr add.o addcr.o strip addcr cp addcr $(PATH) delcr.o: delcr.c cc $(FLAGS) delcr.c delcr: delcr.o del.o cc -O -o delcr del.o delcr.o strip delcr cp delcr $(PATH) add.o: add.c cc $(FLAGS) add.c del.o: del.c cc $(FLAGS) del.c cr.o: cr.c cc $(FLAGS) cr.c lf2cr.o: lf2cr.c cc $(FLAGS) lf2cr.c lf2cr: lf2cr.o cr.o cc -O -o lf2cr lf2cr.o cr.o strip lf2cr cp lf2cr $(PATH) lf.o: lf.c cc $(FLAGS) lf.c cr2lf.o: cr2lf.c cc $(FLAGS) cr2lf.c cr2lf: cr2lf.o lf.o cc -O -o cr2lf cr2lf.o lf.o strip cr2lf cp cr2lf $(PATH) SHAR_EOF if test 1340 -ne "`wc -c < 'Makefile'`" then echo shar: error transmitting "'Makefile'" '(should have been 1340 characters)' fi fi echo shar: extracting "'add.c'" '(881 characters)' if test -f 'add.c' then echo shar: will not over-write existing file "'add.c'" else cat << \SHAR_EOF > 'add.c' # # include # define CR 13 # define NL 10 # define CTRL_Z 26 char * ADDCR(file) char *file; { int id, oid; char buf[512], *index(); static char temp[11]; char *end = "\r\n"; int ln, cnt; register char *ptr = buf, *od; register i, count; strcpy(temp,"tempXXXXXX"); mktemp(temp); if ((oid = open(temp,O_CREAT | O_WRONLY,0644)) < 0) { perror(temp); unlink(temp); exit(-1); } if ((id = open(file,O_RDONLY,0644)) < 0) { perror(file); unlink(temp); exit(-1); } while (ln = read(id,ptr,512)) { count = 0; while ( od = index(ptr,NL) ) { if (od > &buf[ln]) break; *od = '\0'; cnt = strlen(ptr); count += cnt; write(oid, ptr, cnt); write(oid, end, 2); ptr = ++od; count++; } if (count = ln - count) write(oid,ptr,count); ptr = buf; } *ptr = CTRL_Z; write(oid,ptr,1); close(oid); close(id); return(temp); } SHAR_EOF if test 881 -ne "`wc -c < 'add.c'`" then echo shar: error transmitting "'add.c'" '(should have been 881 characters)' fi fi echo shar: extracting "'addcr.c'" '(219 characters)' if test -f 'addcr.c' then echo shar: will not over-write existing file "'addcr.c'" else cat << \SHAR_EOF > 'addcr.c' main(argc,argv) int argc; char *argv[]; { char buf[512]; register int i; for (i = 1; i < argc; i++) { strcpy(buf,"mv "); strcat(buf,ADDCR(argv[i])); strcat(buf," "); strcat(buf,argv[i]); system(buf); } } SHAR_EOF if test 219 -ne "`wc -c < 'addcr.c'`" then echo shar: error transmitting "'addcr.c'" '(should have been 219 characters)' fi fi echo shar: extracting "'addlf.c'" '(935 characters)' if test -f 'addlf.c' then echo shar: will not over-write existing file "'addlf.c'" else cat << \SHAR_EOF > 'addlf.c' # # define CR 13 # define NL 10 main(argc,argv) int argc; char *argv[]; { int id, oid; char buf[512]; char *temp, *index(); char *end = "\r\n"; int ln, cnt; register char *ptr, *od; register i, count; for (i = 1; i < argc; i++) { if ((id = open(argv[i],0)) < 0) { printf("CAN NOT OPEN FILE `%s'. . . . .\n",argv[i]); break; } else { temp = "tempXXXXXX"; mktemp(temp); oid = creat(temp,0644); ptr = buf; while (ln = read(id,ptr,512)) { count = 0; while ( od = index(ptr,CR) ) { if (od > &buf[ln]) break; *od = '\0'; cnt = strlen(ptr); count += cnt; write(oid, ptr, cnt); write(oid, end, 2); ptr = ++od; count++; } if (count = ln - count) write(oid,ptr,count); ptr = buf; } close(oid); close(id); strcpy(buf,"mv "); strcat(buf,temp); strcat(buf," "); strcat(buf,argv[i]); system(buf); unlink(temp); } } } SHAR_EOF if test 935 -ne "`wc -c < 'addlf.c'`" then echo shar: error transmitting "'addlf.c'" '(should have been 935 characters)' fi fi echo shar: extracting "'copy.c'" '(6082 characters)' if test -f 'copy.c' then echo shar: will not over-write existing file "'copy.c'" else cat << \SHAR_EOF > 'copy.c' # #include #include #include #include #include #include #include /* ** copy - copy a subtree to a new directory ** preserving ownership and dates (access and modification only) ** ** Keith Thompson - Feb 7, 1981 ** revised - May 1, 1981 (added options) ** ** Options: (can only be used by superuser) ** ** -o login_name make all files owned by 'login_name' ** -u login_name make all user ownership 'login_name' ** -g group_name make all group ownership 'group_name' */ #define BSIZE 4096 #define DEST (argc-1) #define SRC (argc-2) #define EXISTS 0 #define READABLE 4 #define WRITEABLE 2 #define EXECUTABLE 1 #define MODE 0666 #define READ 0 #define strncat strcatn extern char *strcat(); extern char *strcpy(); int superuser; int user; int group; main(argc,argv) int argc; char **argv; { register i,j,badarg; register struct passwd *pw; extern struct passwd *getpwnam(); signal(SIGINT,SIG_IGN); signal(SIGHUP,SIG_IGN); signal(SIGQUIT,SIG_IGN); signal(SIGTERM,SIG_IGN); signal(SIGPIPE,SIG_IGN); user = getuid(); superuser = user == 0; group = superuser ? 0 : getgid(); badarg = 0; if(argc < 3) { fprintf(stderr,"usage: %s [ options ] src_dir dst_dir\n", argv[0]); exit(2); } if(superuser) for(i=1 ; i= SRC) { fprintf(stderr,"Invalid argument: %s\n",argv[i]); badarg++; break; } if(*ptr++ != '-') { fprintf(stderr,"Invalid argument: %s\n",argv[i]); badarg++; continue; } pw = getpwnam(argv[j]); j++; switch(*ptr) { case 'o': user = pw->pw_uid; group = pw->pw_gid; break; case 'u': user = pw->pw_uid; break; case 'g': group = pw->pw_gid; break; default: fprintf(stderr,"Bad option: %c\n",*(ptr-1)); badarg++; } } if(badarg) exit(4); if(!access(argv[DEST],EXISTS)) { fprintf(stderr,"%s already exists\n",argv[DEST]); exit(2); } if(access(argv[SRC],READABLE)) { fprintf(stderr,"%s not readable\n",argv[SRC]); exit(2); } copy(argv[SRC],argv[DEST]); } copy(src,dst) char *src,*dst; { struct direct dirbuf; union { char *c; struct direct *d; } u_dir; struct stat statbuf; struct stat srcstat; char src_file[256],dst_file[256]; int src_fd; u_dir.d = &dirbuf; if(stat(src,&srcstat)) { perror(src); exit(4); } if((srcstat.st_mode&S_IFMT) != S_IFDIR) { fprintf(stderr,"copy: %s is not a directory\n",src); exit(4); } /* ** src exists and is readable ** now make the target directory */ if(mkdir(dst)) { exit(4); } change(dst, &srcstat); if((src_fd = open(src,0)) < 0) { perror(src); exit(4); } while(read(src_fd,u_dir.c,sizeof(dirbuf)) == sizeof(dirbuf)) { /* ** test to see if the directory slot is in use */ if(!dirbuf.d_ino) { continue; } /* ** skip "." & "..", mkdir takes care of them */ if(!strcmp(".",dirbuf.d_name) || !strcmp("..",dirbuf.d_name)) { continue; } /* ** we have a file or directory to copy now */ mkname(src_file,src,dirbuf.d_name); mkname(dst_file,dst,dirbuf.d_name); if(stat(src_file,&statbuf)) { perror(src_file); exit(4); } if(!superuser && access(src_file,READABLE)) { fprintf(stdout,"copy: no access %s\n",src_file); continue; } /* ** do the copy depending on the file type ** ** directory: recursively copy the subtree ** regular: copy the file ** special: make a new node (super user only) */ switch((statbuf.st_mode)&S_IFMT) { case S_IFDIR: copy(src_file,dst_file); break; case S_IFCHR: case S_IFBLK: if(!superuser) break; fprintf(stdout,"making special file %s\n",dst_file); if(mknod(dst_file,(int) statbuf.st_mode, statbuf.st_rdev)) { } change(dst_file, &statbuf); utime(dst_file,&(statbuf.st_atime)); if(chmod(dst_file,(int) statbuf.st_mode)) { perror(dst_file); exit(4); } break; case S_IFREG: filecopy(src_file,dst_file); change(dst_file, &statbuf); utime(dst_file,&(statbuf.st_atime)); if(chmod(dst_file,(int) statbuf.st_mode)) { perror(dst_file); exit(4); } break; default: fprintf(stderr,"bad file type: %s\n",src_file); } } utime(dst,&(srcstat.st_atime)); if(chmod(dst,(int) srcstat.st_mode)) { perror(dst_file); exit(4); } close(src_fd); } mkname(dst,str1,str2) char *dst,*str1,*str2; { dst[0] = '\0'; strcat(dst,str1); strcat(dst,"/"); strncat(dst,str2,14); } filecopy(src,dst) char *src,*dst; { register int src_fd,dst_fd; char block[BSIZE]; register int size; if((src_fd = open(src,READ)) < 0) { perror(src); exit(4); } if((dst_fd = creat(dst,MODE)) < 0) { perror(dst); exit(4); } while((size = read(src_fd,block,BSIZE)) > 0) { if(write(dst_fd,block,size) != size) { perror(dst); exit(4); } } if(size < 0) { perror(src); exit(4); } if(close(src_fd)) { perror(src); exit(4); } if(close(dst_fd)) { perror(src); exit(4); } } change(file,status) char *file; struct stat *status; { int u,g; u = user; g = group; if(superuser) { if(!user) { u = status->st_uid; } if(!group) { g = status->st_gid; } } if(chown(file, u, g)) { perror(file); exit(4); } } mkdir(d) register char *d; { char pname[128], dname[128]; register i, slash = 0; pname[0] = '\0'; for(i = 0; d[i]; ++i) if(d[i] == '/') slash = i + 1; if(slash) strncpy(pname, d, slash); strcpy(pname+slash, "."); if (access(pname, WRITEABLE)) { fprintf(stderr,"mkdir: cannot access %s\n", pname); return(-1); } if ((mknod(d, 040777, 0)) < 0) { fprintf(stderr,"mkdir: cannot make directory %s\n", d); return(-1); } strcpy(dname, d); strcat(dname, "/."); if((link(d, dname)) < 0) { fprintf(stderr, "mkdir: cannot link %s\n", dname); unlink(d); return(-1); } strcat(dname, "."); if((link(pname, dname)) < 0) { fprintf(stderr, "mkdir: cannot link %s\n",dname); dname[strlen(dname)] = '\0'; unlink(dname); unlink(d); return(-1); } return(0); } SHAR_EOF if test 6082 -ne "`wc -c < 'copy.c'`" then echo shar: error transmitting "'copy.c'" '(should have been 6082 characters)' fi fi echo shar: extracting "'cr.c'" '(778 characters)' if test -f 'cr.c' then echo shar: will not over-write existing file "'cr.c'" else cat << \SHAR_EOF > 'cr.c' # #include #define CR 13 #define NL 10 char * LF2CR(file) char *file; { int id, oid; char buf[512], *index(); static char temp[11]; register char *ptr = buf; register ln, count; strcpy(temp,"tempXXXXXX"); mktemp(temp); if ((oid = open(temp,O_CREAT | O_WRONLY,0644)) < 0) { perror(temp); unlink(temp); exit(-1); } if ((id = open(file,O_RDONLY,0644)) < 0) { perror(file); unlink(temp); exit(-1); } count = 0; while (ln = read(id,ptr,512)) { while ( ptr = index(ptr,NL) ) { if (ptr > &buf[ln]) break; *ptr = CR; } write(oid,ptr = buf,ln); count += ln; } if (ln = count % 128) { count = 128 - ln; for (ln = 0, ptr = buf; ln < count ; ln++, *ptr++ = ' '); write(oid,buf,ln); } close(oid); close(id); return(temp); } SHAR_EOF if test 778 -ne "`wc -c < 'cr.c'`" then echo shar: error transmitting "'cr.c'" '(should have been 778 characters)' fi fi echo shar: extracting "'cr2lf.c'" '(129 characters)' if test -f 'cr2lf.c' then echo shar: will not over-write existing file "'cr2lf.c'" else cat << \SHAR_EOF > 'cr2lf.c' main(argc,argv) int argc; char *argv[]; { char buf[512]; register int i; for (i = 1; i < argc; i++) { CR2LF(argv[i]); } } SHAR_EOF if test 129 -ne "`wc -c < 'cr2lf.c'`" then echo shar: error transmitting "'cr2lf.c'" '(should have been 129 characters)' fi fi echo shar: extracting "'del.c'" '(1030 characters)' if test -f 'del.c' then echo shar: will not over-write existing file "'del.c'" else cat << \SHAR_EOF > 'del.c' # # include # define CR 13 # define NL 10 # define CTRL_Z 26 # define BLOCK 512 DELCR(file) char *file; { int id, oid; char buf[BLOCK+10], *index(); static char temp[11]; register char *ptr = buf, *od, *cz; register int len; strcpy(temp,"tempXXXXXX"); mktemp(temp); if ((oid = open(temp,O_CREAT | O_WRONLY,0644)) < 0) { perror(temp); unlink(temp); exit(-1); } if ((id = open(file,O_RDONLY,0644)) < 0) { perror(file); unlink(temp); exit(-1); } while ((len = read(id,ptr,BLOCK)) > 0) { *(ptr + len) = 0; while ( od = index(ptr,CR) ) { *od = '\0'; if (cz = index(ptr,CTRL_Z)) { *cz = '\0'; write(oid, ptr, strlen(ptr)); goto OUT; } write(oid, ptr, strlen(ptr)); ptr = ++od; } if (cz = index(ptr,CTRL_Z)) { *cz = '\0'; write(oid, ptr, strlen(ptr)); goto OUT; } if (len = strlen(ptr)) write(oid, ptr, len); ptr = buf; } OUT: close(oid); close(id); strcpy(buf,"mv "); strcat(buf,temp); strcat(buf," "); strcat(buf,file); system(buf); } SHAR_EOF if test 1030 -ne "`wc -c < 'del.c'`" then echo shar: error transmitting "'del.c'" '(should have been 1030 characters)' fi fi echo shar: extracting "'delcr.c'" '(129 characters)' if test -f 'delcr.c' then echo shar: will not over-write existing file "'delcr.c'" else cat << \SHAR_EOF > 'delcr.c' main(argc,argv) int argc; char *argv[]; { char buf[512]; register int i; for (i = 1; i < argc; i++) { DELCR(argv[i]); } } SHAR_EOF if test 129 -ne "`wc -c < 'delcr.c'`" then echo shar: error transmitting "'delcr.c'" '(should have been 129 characters)' fi fi echo shar: extracting "'lf.c'" '(1252 characters)' if test -f 'lf.c' then echo shar: will not over-write existing file "'lf.c'" else cat << \SHAR_EOF > 'lf.c' # #include #define CR 13 #define NL 10 #define BLOCK 512 #define STOP 0xff CR2LF(file) char *file; { int id, oid; char buf[BLOCK+1], *index(); char temp[11], temp1[11]; register char *ptr = buf; register int len; strcpy(temp,"tempXXXXXX"); mktemp(temp); if ((oid = open(temp,O_CREAT | O_RDWR,0644)) < 0) { perror(temp); unlink(temp); exit(-1); } if ((id = open(file,O_RDONLY,0644)) < 0) { perror(file); unlink(temp); exit(-1); } buf[BLOCK] = 0; while ((len = read(id,ptr,BLOCK)) > 0) { while ( ptr = index(ptr,CR) ) { *ptr = NL; } write(oid, ptr = buf, len); } close(id); lseek(oid,1,L_XTND); do { lseek(oid,-2,L_INCR); read(oid,ptr,1); } while ( *ptr != NL ); *ptr = STOP; write(oid,ptr,1); lseek(oid,0,L_SET); strcpy(temp1,"tempXXXXXX"); mktemp(temp1); if ((id = open(temp1,O_CREAT | O_WRONLY,0644)) < 0) { perror(temp1); unlink(temp1); unlink(temp); exit(-1); } ptr = buf; while ((len = read(oid,ptr,BLOCK)) > 0) { if (ptr = index(ptr,STOP)) { *ptr = 0; write(id, buf, strlen(buf)); break; } write(id, ptr = buf, len); } close(oid); close(id); strcpy(buf,"mv "); strcat(buf,temp1); strcat(buf," "); strcat(buf,file); system(buf); unlink(temp); } SHAR_EOF if test 1252 -ne "`wc -c < 'lf.c'`" then echo shar: error transmitting "'lf.c'" '(should have been 1252 characters)' fi fi echo shar: extracting "'lf2cr.c'" '(219 characters)' if test -f 'lf2cr.c' then echo shar: will not over-write existing file "'lf2cr.c'" else cat << \SHAR_EOF > 'lf2cr.c' main(argc,argv) int argc; char *argv[]; { char buf[512]; register int i; for (i = 1; i < argc; i++) { strcpy(buf,"mv "); strcat(buf,LF2CR(argv[i])); strcat(buf," "); strcat(buf,argv[i]); system(buf); } } SHAR_EOF if test 219 -ne "`wc -c < 'lf2cr.c'`" then echo shar: error transmitting "'lf2cr.c'" '(should have been 219 characters)' fi fi echo shar: extracting "'receive.c'" '(4527 characters)' if test -f 'receive.c' then echo shar: will not over-write existing file "'receive.c'" else cat << \SHAR_EOF > 'receive.c' /* ** receive filename */ # # include # include # include # include # include # define SOH 0x1 # define NAK 0x15 # define ACK 0x6 # define EOT 0x4 # define CANCEL 0x18 char filename[64]; int retries; /* retries counter */ int seq_num; /* sequence number */ int caught(); /* interrupt routine, called if haven't received a block in 1 second */ struct sigvec vec; jmp_buf env; main(argc,argv) int argc; char *argv[]; { int fd; char c; register int i; if (!((argc == 2) || (argc == 3))) { printf("ILLEGAL NUMBER OF ARGUMENTS.\n"); printf("SYNOPSIS: to_vax_x [-t] [-m] filename\n"); exit(-1); } if (argc == 3) { if (strcmp(argv[1],"-t") && strcmp(argv[1],"-m")) { printf("bad argument `%s'\n",argv[1]); printf("SYNOPSIS: to_vax_x [-t] [-m] filename\n"); exit(-1); } } strcpy(filename,argv[argc-1]); if ((fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0) { perror(filename); exit(-1); } initscr(); raw(); /* set terminal to 8-bit I/O */ noecho(); /* ** Ignore interrupts from the user. ** If the user could delete this program the terminal ** would be left in a undiserable state of mind. */ vec.sv_handler = caught; vec.sv_mask = vec.sv_onstack = 0; sigvec(SIGALRM,&vec,(struct sigvec *)0); sigsetmask(-1 ^ (1 << (SIGALRM-1))); /* enable alarm signal */ c = NAK; retries = 0; if (setjmp(env)) { write(1,&c,1); if (retries++ > 10) { reset(1); /* restore terminal to normal state */ printf("Can not get reply from transmitter\n"); exit(0); } } SET_TIMER(10); read(0,&c,1); DISABLE_TIMER(); seq_num = 1; retries = 0; for(;;) { if (retries == 10) { c = CANCEL; write(1,&c,1); reset(1); printf("Terminated after 10 retries\r\n"); exit(-1); } switch( c & 0x7f ) { case SOH: BLOCK(fd); break; case CANCEL: printf("Received CANCEL signal\r\n"); reset(1); exit(-1); case EOT: c = ACK; write(1,&c,1); reset(0); goto END; default: sleep(2); /* wait for a bit */ noraw(); /* flush input buffer */ raw(); c = NAK; write(1,&c,1); retries++; break; } c = NAK; if (setjmp(env)) { write(1,&c,1); if (retries++ > 10) { reset(1); /* restore terminal to normal state */ printf("Can not get reply from transmitter\n"); exit(0); } } SET_TIMER(10); read(0,&c,1); DISABLE_TIMER(); } END: close(fd); if (argc == 3) { switch( argv[1][1] ) { case 't': printf("Deleting carriage returns\n"); DELCR(filename); break; case 'm': printf("Changing cr's to lf's\n"); CR2LF(filename); } } } BLOCK(fd) int fd; { register i; register char *p; char block[131]; char c; int xsum; retries = 0; /* start fresh */ /* used to be 1 */ SET_TIMER(10); if (setjmp(env)) { noraw(); raw(); c = NAK; write(1,&c,1); retries++; return; } else { i = read(0,block,131); while( i < 131 ) { i += read(0,&block[i],131-i); /* data block */ } DISABLE_TIMER(); } if ( (block[0] & 0xff) != seq_num ) { i = (seq_num ? seq_num - 1 : 255); if ((block[0] & 0xff) != i ) { if ( (block[1] & 0xff) != (255 - seq_num) ) { i = 255 - i; if ((block[1] & 0xff) == i ) { c = NAK; write(1,&c,1); retries++; return; } c = CANCEL; /* loss of synchronization */ write(1,&c,1); reset(1); exit(-1); } } retries++; goto leave; } if ( (block[1] & 0xff) != (255 - seq_num) ) { c = NAK; write(1,&c,1); retries++; return; } xsum = 0; for (i = 0, p = &block[2]; i < 128; i++) xsum += (*p++ & 0xff); xsum &= 0xff; if ( (block[130] & 0xff) != xsum ) { c = NAK; write(1,&c,1); retries++; return; } write(fd,&block[2],128); retries = 0; seq_num = ++seq_num % 256; leave: c = ACK; write(1,&c,1); } reset(remove) int remove; { DISABLE_TIMER(); sigsetmask(0); vec.sv_handler = SIG_DFL; vec.sv_mask = vec.sv_onstack = 0; sigvec(SIGALRM,&vec,(struct sigvec *)0); noraw(); echo(); endwin(); if (remove) unlink(filename); } caught() { longjmp(env,1); } SET_TIMER(secs) int secs; { struct itimerval val; val.it_value.tv_sec = secs; val.it_value.tv_usec = secs * 1000; timerclear(&val.it_interval); setitimer(ITIMER_REAL,&val,(struct itimerval *)0); } DISABLE_TIMER() { struct itimerval val; timerclear(&val.it_value); setitimer(ITIMER_REAL,&val,(struct itimerval *)0); } SHAR_EOF if test 4527 -ne "`wc -c < 'receive.c'`" then echo shar: error transmitting "'receive.c'" '(should have been 4527 characters)' fi fi echo shar: extracting "'to_pc.c'" '(5027 characters)' if test -f 'to_pc.c' then echo shar: will not over-write existing file "'to_pc.c'" else cat << \SHAR_EOF > 'to_pc.c' # # include # include # include # define ST_BLK 33 /* ! */ # define READY 34 /* " */ # define OKAY 35 /* # */ # define NOT_OK 36 /* $ */ # define CANCEL 37 /* % */ # define CR 13 /* \r */ # define pad " " int seq_num, old, flags; char buf[95], seq[4], filename[64]; main(argc,argv) int argc; char *argv[]; { int fd; register i; register char *ptr; char *ADDCR(); char c, chunck[45]; char *MK_SEQ(), *MK_START(), *itos(); int lim, pid; int first = 1; flags = argc; if (!((argc == 2) || (argc == 3))) { printf("ILLEGAL NUMBER OF ARGUMENTS.\n"); printf("SYNOPSIS: to_pc [-t] filename\n"); exit(-1); } if (argc == 2) strcpy(filename,argv[1]); /* don't put in CR's */ else { if (strcmp(argv[1],"-t")) { printf("bad argument `%s'\n",argv[1]); printf("SYNOPSIS: to_pc [-t] filename\n"); exit(-1); } printf("Adding carriage returns, wait .......\n"); strcpy(filename,ADDCR(argv[2])); } if ((fd = open(filename,O_RDONLY,0644)) < 0) { perror(filename); exit(-1); } printf("\nPress Alt-F6 to transmit file to PC.\n"); initscr(); crmode(); /* set terminal to unbuffered I/O */ /* ** Ignore interrupts from the user. ** If the user could delete this program the terminal ** would be left in a undiserable state of mind. */ sigsetmask( -1 ); /* ignore all signals */ if ((pid = fork()) == 0) { /* child sends ready prompt */ sleep(8); i = 0; strcpy(buf,"\"\r"); while (1) { write(1, buf, 2); sleep(2); if ( i++ == 30 ) break; /* not receiving ready character */ } RESET(); /* restore terminal to normal state */ kill(0,SIGKILL); /* kill all processes */ } for(;;) { /* wait for ready character */ READ(buf); /* if not received in 68 sec's, program terminates */ if (buf[0] == OKAY) break; } kill(pid,SIGKILL); /* received ok response, so kill child */ wait(0); seq_num = 0; strcpy(chunck,argv[argc-1]); lim = strlen(chunck); do { /* make 90 character block */ ptr = MK_START(); /* make start of block */ if (first) { /* header record */ strcpy(ptr,"HH"); strcat(ptr,chunck); ptr = lim + &buf[6]; first = 0; } else { if (lim < 5) strcat(ptr,"0"); strcat(ptr,itos( 2 * lim )); ptr = &buf[6]; for (i = 0; i < lim; i++) { c = (chunck[i] & 0xf0) / 16 + '0'; *ptr++ = c > '9' ? c + 7 : c; c = (chunck[i] & 0xf) + '0'; *ptr++ = c > '9' ? c + 7 : c; } } strcat(ptr,MK_SEQ(MK_XSUM(ptr))); WRITE(); WAIT(chunck); ERR_CHECK(chunck); } while ( (lim = read(fd,chunck,40)) > 0 ); ptr = MK_START(); strcat(ptr,"EE"); ptr = &buf[6]; strcat(ptr,MK_SEQ(MK_XSUM(ptr))); WRITE(); READ(chunck); ERR_CHECK(chunck); RESET(); close(fd); } WAIT(s) char *s; { int pid; register i; if ((pid = fork()) == 0) { i = 1; while (i++ < 10) { WRITE(); } sleep(10); LEAVE(); kill(0,SIGKILL); /* kill all processes */ } READ(s); kill(pid,SIGKILL); /* received response, kill child */ wait(0); } MK_XSUM(s) char *s; { register xsum; register char *ptr; ptr = s; while ( ptr < &buf[86] ) *ptr++ = ' '; /* pad buffer with blanks */ xsum = 0; *ptr = '\0'; ptr = buf; while ( *ptr ) /* compute check sum */ xsum = (xsum ^ *ptr++) & 0177; return(xsum); } char *MK_START() { register char *ptr; ptr = buf; *ptr = ST_BLK; *(ptr + 1) = '\0'; seq_num = ++seq_num % 1000; strcpy(seq,MK_SEQ(seq_num)); strcat(ptr,seq); return( &buf[4] ); /* return address to record type */ } ERR_CHECK(resp) char *resp; { char ok[6]; int count = 1; while (*resp == NOT_OK) { if (count++ > 10) { /* tried 10 times so exit */ LEAVE(); exit(0); } WRITE(); WAIT(resp); } strcpy(ok,"#"); strcat(ok,seq); strcat(ok,"#"); count = 1; while (strncmp(ok,resp,5)) { /* used to be a literal control X */ if (*resp == '\030') { /* user terminated transfer Alt-F6 */ RESET(); exit(0); } if (*resp == CANCEL) { /* programs not in synch */ RESET(); exit(0); } if (count++ > 10) { /* gave up, tried ten times */ LEAVE(); exit(0); } WRITE(); WAIT(resp); } } LEAVE() { register char *ptr; ptr = MK_START(); strcat(ptr,"XX"); ptr = &buf[6]; strcat(ptr,MK_SEQ(MK_XSUM(ptr))); WRITE(); RESET(); } char *MK_SEQ(i) int i; { char *itos(); static char s[3]; if ( i < 100 ) strcpy(s,"0"); else s[0] = '\0'; if ( i < 10 ) strcat(s,"0"); strcat(s,itos(i)); return( s ); } READ(s) register char *s; { char c; while (read( 0, s++, 1) > 0) { /* read characters until a CR is read */ c = *(s-1); if ((c == '\n') || (c == CR)) break; } *s = '\0'; } WRITE() { buf[89] = CR; buf[90] = '\0'; write( 1, buf, 90); } RESET() { if (flags == 3) unlink(filename); endwin(); } char *itos(i1) int i1; { register char *a; register int i; static char buf[10]; i = i1; if (i < 0) i = -i; a = &buf[sizeof buf - 1]; *a-- = '\0'; do { *a-- = i % 10 + '0'; i /= 10; } while (i); if (i1 < 0) *a-- = '-'; a++; return (a); } SHAR_EOF if test 5027 -ne "`wc -c < 'to_pc.c'`" then echo shar: error transmitting "'to_pc.c'" '(should have been 5027 characters)' fi fi echo shar: extracting "'to_vax.c'" '(3655 characters)' if test -f 'to_vax.c' then echo shar: will not over-write existing file "'to_vax.c'" else cat << \SHAR_EOF > 'to_vax.c' # # include # include # include # define ST_BLK 33 # define READY 34 # define OKAY 35 # define NOT_OK 36 # define CANCEL 37 # define CR 13 # define ctoi(c) (c - '0' > 9 ? c - '0' - 7 : c - '0') char filename[64]; int old; main(argc,argv) int argc; char *argv[]; { int fd; register i; register char *ptr, *op; char buf[512], seq[4]; char *index(); int xsum, lim, old_seq, pid; if (!((argc == 2) || (argc == 3))) { printf("ILLEGAL NUMBER OF ARGUMENTS.\n"); printf("SYNOPSIS: to_vax [-t] filename\n"); exit(-1); } if (argc == 3) { if (strcmp(argv[1],"-t")) { printf("bad argument `%s'\n",argv[1]); printf("SYNOPSIS: to_vax [-t] filename\n"); exit(-1); } } strcpy(filename,argv[argc-1]); if ((fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0) { perror(filename); exit(-1); } initscr(); crmode(); /* set terminal to unbuffered I/O */ printf("\nPress Alt-F7 to transmit file to VAX.\n"); /* ** Ignore interrupts from the user. ** If the user could delete this program the terminal ** would be left in a undiserable state of mind. */ sigsetmask( -1 ); /* ignore all signals */ if ((pid = fork()) == 0) { sleep(100); RESET(fd); kill(0, SIGKILL); /* Can't wait forever for a READY reply */ } ptr = buf; while (1) { /* wait for ready character */ read(0,ptr,1); if (*ptr == READY) break; } kill(pid, SIGKILL); wait(0); read(0,ptr,1); /* get the CR from the READY */ WCHAR(OKAY); WCHAR(CR); for(;;) { input: if ((pid = fork()) == 0) { i = 0; while ( i++ < 10 ) { sleep(10); WCHAR(NOT_OK); WCHAR(CR); } sleep(10); RESET(fd); kill(0, SIGKILL); /* kill all processes */ } READ(buf); /* read data block */ kill( pid, SIGKILL ); /* kill child */ wait(0); /* check for 90 character block */ ptr = index(buf,ST_BLK); if (strlen(ptr) != 90) { WCHAR(NOT_OK); WCHAR(CR); goto input; } xsum = 0; while ( ptr < &buf[86] ) /* compute check sum */ xsum = (xsum ^ *ptr++) & 0177; if ( xsum != atoi(ptr) ) { /* check sum not ok */ WCHAR(NOT_OK); WCHAR(CR); goto input; } ptr = index(buf,ST_BLK) + 1; strncpy(seq,ptr,3); switch( (lim = atoi(seq)) - old_seq ) { case 0: /* reply garbled, resend reply */ WCHAR(OKAY); WSTR(seq); WCHAR(OKAY); WCHAR(CR); goto input; case 1: case -999: /* sequence number ok */ old_seq = lim; break; default: /* fatal loss of synchronization */ WCHAR(CANCEL); WCHAR(CANCEL); WCHAR(CANCEL); WCHAR(CR); RESET(fd); exit(-1); } ptr += 3; if (!(strncmp(ptr,"XX",2) && strncmp(ptr,"EE",2))) break; if (strncmp(ptr,"HH",2)) { /* decode data block */ lim = ctoi(*ptr) * 10 + ctoi(*(ptr+1)); op = buf; for ( i = 2; i < lim + 2; i += 2 ) *op++ = ctoi( *(ptr+i) ) * 16 + ctoi( *(ptr+i+1) ); write(fd, buf, lim/2); /* write data block to file */ } WCHAR(OKAY); WSTR(seq); WCHAR(OKAY); WCHAR(CR); } /* end while */ WCHAR(OKAY); WSTR(seq); WCHAR(OKAY); WCHAR(CR); nocrmode(); endwin(); close(fd); if (argc == 3) { printf("Deleting carriage returns\n"); DELCR(filename); } } /* end main */ WCHAR(c) char c; { /* write a character to standard output */ write(1, &c, 1); } WSTR(s) char *s; { /* write a string to standard output */ write(1, s, strlen(s)); } READ(s) char *s; { register char *ptr; ptr = s; while ( read(0, ptr, 1) > 0 ) { /* read characters until CR */ if (*ptr++ == CR) break; } *ptr = '\0'; } RESET(fd) int fd; { /* put terminal back into start up state */ nocrmode(); endwin(); close(fd); unlink(filename); } SHAR_EOF if test 3655 -ne "`wc -c < 'to_vax.c'`" then echo shar: error transmitting "'to_vax.c'" '(should have been 3655 characters)' fi fi echo shar: extracting "'transmit.c'" '(2908 characters)' if test -f 'transmit.c' then echo shar: will not over-write existing file "'transmit.c'" else cat << \SHAR_EOF > 'transmit.c' /* ** transmit filename */ # include # include # include # include # define SOH 0x1 # define NAK 0x15 # define ACK 0x6 # define EOT 0x4 # define CANCEL 0x18 int flags; char filename[64]; main(argc,argv) int argc; char *argv[]; { int fd; register i; register char *p; char block[132]; char c; int length, pid; int seq_num, xsum; int retries; struct sigvec vec; int caught(); flags = argc; if (!((argc == 2) || (argc == 3))) { printf("ILLEGAL NUMBER OF ARGUMENTS.\n"); printf("SYNOPSIS: to_pc_x [-t] [-m] filename\n"); exit(-1); } if (argc == 2) strcpy(filename,argv[1]); /* don't put in CR's */ else { switch (argv[1][1]) { case 't': printf("Adding carriage returns, wait .......\n"); strcpy(filename,ADDCR(argv[2])); printf("DONE\n"); break; case 'm': printf("Changing lf's to cr's, wait .......\n"); strcpy(filename,LF2CR(argv[2])); printf("DONE\n"); break; default: printf("bad argument `%s'\n",argv[1]); printf("SYNOPSIS: to_pc_x [-t] [-m] filename\n"); exit(-1); } } if ((fd = open(filename,O_RDONLY,0644)) < 0) { perror(filename); exit(-1); } initscr(); raw(); /* set terminal to 8-bit I/O */ noecho(); /* ** Ignore interrupts from the user. ** If the user could delete this program the terminal ** would be left in a undiserable state of mind. */ vec.sv_handler = caught; vec.sv_mask = vec.sv_onstack = 0; sigvec(SIGALRM,&vec,(struct sigvec *)0); sigsetmask(-1 ^ (1 << (SIGALRM-1))); SET_TIMER(); for(;;) { /* wait for NAK */ read(0,&c,1); /* if not received in 60 sec's, program terminates */ if ((c&0x7f) == NAK) break; } DISABLE_TIMER(); seq_num = 1; p = &block[3]; while ( (length = read(fd,p,128)) > 0 ) { p = block; *p++ = SOH; *p++ = seq_num; *p++ = 255 - seq_num; p += length; for( i = length; i < 128; i++) *p++ = 0; xsum = 0; for (i = 3; i < 131; i++) xsum += block[i]; *p = xsum & 0xff; retries = 0; do { if (retries) sleep(10); write(1,block,132); SET_TIMER(); read(0,&c,1); DISABLE_TIMER(); if ( (c&0x7f) == CANCEL ) {RESET(); exit(-1);} if (retries++ > 10 ) { c = CANCEL; write(1,&c,1); RESET(); exit(-1); } } while ( (c&0x7f) != ACK ); seq_num = ++seq_num % 256; p = &block[3]; } SET_TIMER(); do { c = EOT; write(1,&c,1); read(0,&c,1); } while ( (c&0x7f) != ACK ); DISABLE_TIMER(); RESET(); } RESET() { noraw(); echo(); endwin(); if (flags == 3) unlink(filename); } /* END */ caught() { RESET(); kill(0,SIGKILL); } SET_TIMER() { struct itimerval val; val.it_value.tv_sec = 60; val.it_value.tv_usec = 60 * 1000; timerclear(&val.it_interval); setitimer(ITIMER_REAL,&val,(struct itimerval *)0); } DISABLE_TIMER() { struct itimerval val; timerclear(&val.it_value); setitimer(ITIMER_REAL,&val,(struct itimerval *)0); } SHAR_EOF if test 2908 -ne "`wc -c < 'transmit.c'`" then echo shar: error transmitting "'transmit.c'" '(should have been 2908 characters)' fi fi exit 0 # End of shell archive