john@novavax.UUCP (John Paul O'Brien) (05/15/86)
#! /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: # README # makefile # termio.c # termio.h # wsstrip.c # wsstrip.l # xmodemio.c # xum.l # xumodem.c # This archive created: Thu May 15 14:38:15 1986 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'README' then echo shar: "will not over-write existing file 'README'" else cat << \SHAR_EOF > 'README' XUM is a xmodem protocol package for BSD 4.2 unix. I don't know if it will work with other flavors of unix but it likes BSD 4.2 just fine. The man page for xum makes a reference to a program called wsstrip so I have included that one also. It will take a wordstar format file and take out all the funny characters so that vi will not complain. XUM was written with the novice unix user in mind; there are no command line options (though I would like to put them in someday). Instead, it is menu driven so the novice users will not bang their heads against the wall try to figure out which options to select. In other words I tried to make it village-idiot proof. The thing that distinguishes xum from other xmodem packages is the way in which I wrote it. It is VERY modular. If you want to incorporate xmodem i/o in another package you are writing then just use the termio.c, termio.h, and xmodemio.c files; all that you need to pass to send or receive a file with xmodem i/o is your terminal fid and a file fid. Also, the termio package can be used by itself for setting modes on a terminal, allocating a terminal, and using termcap to perform simple screen i/o without having to go through the bother of using curses or writing your own code. Any comments or suggestions would be appreciated. Send them to me at: {allegra, ucf-cs, usfvax2}!novavax!john SHAR_EOF if test 1358 -ne "`wc -c < 'README'`" then echo shar: "error transmitting 'README'" '(should have been 1358 characters)' fi fi if test -f 'makefile' then echo shar: "will not over-write existing file 'makefile'" else cat << \SHAR_EOF > 'makefile' # Makefile 1.0 3/20/86 # # make file for Xmodem on Unix Protocol Package # # CFLAGS= -O -s OBJS= termio.o xmodemio.o SOURCES= termio.c xmodemio.c xumodem.c CXREF= /usr/ucb/ctags -xw xum: makefile ${OBJS} xumodem.o ${CC} ${CFLAGS} -o xum ${OBJS} xumodem.o -ltermlib test: ${OBJS} test.o ${CC} ${CFLAGS} -o txum ${OBJS} test.o termio.o: termio.c ${CC} ${CFLAGS} -c termio.c xmodemio.o: xmodemio.c ${CC} ${CFLAGS} -c xmodemio.c ${OBJS}: termio.h test.o: test.c ${CC} ${CFLAGS} -c test.c clean: rm -f xum txum *.o print: @pr makefile @pr termio.h ${SOURCES} @${CXREF} termio.h ${SOURCES} | pr -h XREF lint: -lint -hbacvx ${SOURCES} SHAR_EOF if test 649 -ne "`wc -c < 'makefile'`" then echo shar: "error transmitting 'makefile'" '(should have been 649 characters)' fi fi if test -f 'termio.c' then echo shar: "will not over-write existing file 'termio.c'" else cat << \SHAR_EOF > 'termio.c' #include "termio.h" char *getenv(), /* These are here so we can use termlib */ *tgetstr(), PC; /* global used for padding character */ #undef putchar /* need to undefine it so we can redefine it */ int putchar(); short ospeed; /* global used by tputs */ char *term_name, str_buf[60], *ptr2ptr, *cl_str, *cm_str, *ce_str, terminfo_buff[1024]; int timer(); /* pre-declare for signal setup in unblocked_io */ jmp_buf env; /* environment storage for setjmp/longjmp */ struct sgttyb org_stty, /* Global so that we can restore Exact state */ cur_stty; /* Assign_tty: Attempts to open a tty device by pathname (ie. /dev/ttyi2). If successful, then return file descriptor, else return -1. Will also set terminal for exclusive use mode if open was successful. On Entry: string pointer to tty pathname On Exit: file descriptor or -1 for failure */ assign_tty(path) char *path; { int tty_fd; if ( (tty_fd = open(path, O_RDWR)) >= 0 ) { if ( ioctl(tty_fd, TIOCEXCL) == -1 ) { tty_fd = -1; } } return((tty_fd < 0) ? -1 : tty_fd); } /* Deassign_tty: Attempts to close a tty device by file descriptor. First, will reset tty to non-exclusive use mode. On Entry: int file descriptor On Exit: 0 for success or -1 for failure */ deassign_tty(tty_fd) int tty_fd; { ioctl(tty_fd, TIOCNXCL); return(close(tty_fd)); } /* Get_tty: Will return the current sgttyb structure information for a previously assigned tty. On Entry: tty file descriptor, and a pointer to a structure to store the information in. On Exit: return -1 if error else tty info in structure if all ok */ get_tty(tty_fd, tty_struct) int tty_fd; struct sgttyb *tty_struct; { return(ioctl(tty_fd, TIOCGETP, tty_struct)); } /* Set_tty: Will set a previously assigned tty to the parameters passed in the sgttyb structure. On Entry: tty file descriptor, and a pointer to a structure to read the information from. On Exit: return -1 if error. */ set_tty(tty_fd, tty_struct) int tty_fd; struct sgttyb *tty_struct; { return(ioctl(tty_fd, TIOCSETP, tty_struct)); } /* Raw_tty: Attempts to open a tty device by pathname (ie. /dev/ttyi2), and then will set terminal up for raw i/o mode. On Entry: string pointer to tty pathname On Exit: file descriptor or -1 for failure */ raw_tty(terminal) char *terminal; { int tty_fd; if ( -1 == (tty_fd = assign_tty(terminal)) ) { return(-1); /* return with error code */ } if ( -1 == get_tty(tty_fd, &org_stty) ) { deassign_tty(tty_fd); return(-1); /* return with error code */ } cur_stty = org_stty; /* copy information */ cur_stty.sg_flags |= RAW; /* raw mode (all 8 bits pass) */ cur_stty.sg_flags &= ~(TANDEM|ECHO|CRMOD); /* remove all char processing */ if ( -1 == set_tty(tty_fd, &cur_stty) ) { deassign_tty(tty_fd); return(-1); /* return with error code */ } return(tty_fd); /* all went well, return tty file desc */ } /* cook_tty: Will set a terminal back to its original state by file descriptor and will leave that descriptor open. On Entry: tty file descriptor On Exit: returns 0 on success or -1 on failure */ cook_tty(tty_fd) int tty_fd; { if ( -1 == set_tty(tty_fd, &org_stty) ) { return(-1); /* return with error code */ } return(0); /* return with no errors */ } /* uncook_tty: Will set a terminal back to its raw state by file descriptor and will leave that descriptor open. On Entry: tty file descriptor On Exit: returns 0 on success or -1 on failure */ uncook_tty(tty_fd) int tty_fd; { if ( -1 == set_tty(tty_fd, &cur_stty) ) { return(-1); /* return with error code */ } return(0); /* return with no errors */ } /* reset_tty: Attempts to set a terminal back to its original state by file descriptor and then will close tty file descriptor. On Entry: tty file descriptor On Exit: returns 0 on success or -1 on failure */ reset_tty(tty_fd) int tty_fd; { if ( -1 == set_tty(tty_fd, &org_stty) ) { deassign_tty(tty_fd); return(-1); /* return with error code */ } deassign_tty(tty_fd); return(0); /* return with no errors */ } /* blocked_io: Attempts to set a terminal to blocked i/o mode by file descriptor. On Entry: tty file descriptor On Exit: returns fcntl value on success or -1 on failure */ blocked_io(tty_fd) int tty_fd; { int f_flags; f_flags = fcntl(tty_fd, F_GETFL, 0); /* get current file flags */ if (f_flags == -1) { return(-1); } f_flags += FNDELAY; /* no delay on read/write (no blocking i/o) */ return(fcntl(tty_fd, F_SETFL, f_flags)); } /* unblocked_io: Attempts to set a terminal to unblocked i/o mode by file descriptor. On Entry: tty file descriptor On Exit: returns fcntl value on success or -1 on failure */ unblocked_io(tty_fd) int tty_fd; { int f_flags; f_flags = fcntl(tty_fd, F_GETFL, 0); /* get current file flags */ if (f_flags == -1) { return(-1); } f_flags -= FNDELAY; /* delay on read/write (blocking i/o) */ return(fcntl(tty_fd, F_SETFL, f_flags)); } /* timer: Is an interrupt routine that will perform a longjmp */ /* when it is called by the alarm interrupt. */ timer(signal) int signal; /* variable to catch signal sent to routine. */ /* we will just ignore it. */ { longjmp(env, 1); } /* timed_read: Will attempt to read from the terminal specified */ /* by the tty file descriptor for a set period of time.*/ /* */ /* On Entry: tty file descriptor to read from, pointer to a byte */ /* to return received char in number of bytes to read */ /* and time in seconds. */ /* On Exit: 0 for ok read or -1 for no char received. */ /* */ timed_read(tty_fd, ch, count, seconds) int tty_fd, count; byte *ch; unsigned seconds; { int ret_code, tim_code; signal(SIGALRM, timer); alarm(seconds); ret_code = -1; /* assume bad read */ tim_code = setjmp(env); while ( (tim_code == 0) && (ret_code != 1) ) { ret_code = read(tty_fd, ch, count); } alarm(0); /* turn alarms off */ signal(SIGALRM, SIG_DFL); return( ((ret_code != -1) && (ret_code == count)) ? 0 : -1 ); } /* stimed_read: Will attempt to read from the terminal specified */ /* by the tty file descriptor for a set period of time.*/ /* */ /* On Entry: tty file descriptor to read from, pointer to a byte */ /* to return received char in. */ /* and time in seconds. */ /* On Exit: 0 for ok read or -1 for no char received. */ /* */ stimed_read(tty_fd, ch, seconds) int tty_fd; byte *ch; unsigned seconds; { int ret_code, tim_code; signal(SIGALRM, timer); alarm(seconds); ret_code = -1; /* assume bad read */ tim_code = setjmp(env); while ( (tim_code == 0) && (ret_code != 1) ) { ret_code = read(tty_fd, ch, 1); } alarm(0); /* turn alarms off */ signal(SIGALRM, SIG_DFL); return( (ret_code != -1) ? 0 : ret_code ); } term_setup() { term_name = getenv("TERM"); /* get terminal type name */ if (term_name == (char *) 0) /* see if TERM is defined */ { return(-1); /* no, so return error */ } if (tgetent(terminfo_buff, term_name) != 1) /* read termcap info */ { return(-1); /* if not in termcap then return error */ } gtty(1, &org_stty); /* get stdout info */ ospeed = org_stty.sg_ospeed; /* set global for tputs to use */ ptr2ptr = str_buf; /* setup pointer to a pointer */ cm_str = tgetstr("pc", &ptr2ptr); /* get pad character */ if (cm_str) /* if any pad character */ { PC = *cm_str; /* set global to it */ } else { PC = 0; /* else say no padding needed */ } cl_str = tgetstr("cl", &ptr2ptr); /* get clear screen string */ cm_str = tgetstr("cm", &ptr2ptr); /* get cursor motion string */ ce_str = tgetstr("ce", &ptr2ptr); /* get clear to end of line */ return(0); /* return all ok */ } cls() { tputs(cl_str, tgetnum("li"), putchar); } clr_eol() { tputs(ce_str, tgetnum("li"), putchar); } mov_cur(col, line) int col, line; { col--; /* termlib starts screens at 0,0 so we */ line--; /* need to normalize OUR coordinates */ tputs(tgoto(cm_str, col, line), 1, putchar); } tolower(ch) char ch; { return( ( (ch >= 'A') && (ch <= 'Z') ) ? ch + ' ' : ch ); } SHAR_EOF if test 8135 -ne "`wc -c < 'termio.c'`" then echo shar: "error transmitting 'termio.c'" '(should have been 8135 characters)' fi fi if test -f 'termio.h' then echo shar: "will not over-write existing file 'termio.h'" else cat << \SHAR_EOF > 'termio.h' #include <stdio.h> #include <sgtty.h> #include <signal.h> #include <setjmp.h> #include <sys/file.h> #include <sys/errno.h> typedef unsigned char byte; typedef unsigned short word; int errno; /* define this globally so that Unix can set it */ SHAR_EOF if test 245 -ne "`wc -c < 'termio.h'`" then echo shar: "error transmitting 'termio.h'" '(should have been 245 characters)' fi fi if test -f 'wsstrip.c' then echo shar: "will not over-write existing file 'wsstrip.c'" else cat << \SHAR_EOF > 'wsstrip.c' /* wsstrip.c */ /* Program to strip out funny characters from a wordstar */ /* document file kermited over in binary format. */ /* */ /* Written March 19, 1985 by John Paul O'Brien */ /* for Nova University Computer Center */ /* */ #include <stdio.h> main() { char ch; while ( (ch = getchar()) != EOF ) /* get all chars from stdin */ { ch &= 0x7f; /* strip off all high bits */ if ( (ch != '\r') && /* see if not cr or ^Z */ (ch != 0x1a) ) /* If not, then candidate */ /* for output. */ { if ( (ch < ' ') && /* see if is a control char */ (ch != '\n') && /* excluding lf, */ (ch != '\t') && /* excluding tab, */ (ch != 0x07) ) /* and bell */ { /* if control character but */ /* not one of the exclusions */ /* then don't output it */ } else { putchar(ch); /* if ok then put to stdout */ } } } } SHAR_EOF if test 939 -ne "`wc -c < 'wsstrip.c'`" then echo shar: "error transmitting 'wsstrip.c'" '(should have been 939 characters)' fi fi if test -f 'wsstrip.l' then echo shar: "will not over-write existing file 'wsstrip.l'" else cat << \SHAR_EOF > 'wsstrip.l' .tr ~ \ .TH WSSTRIP l local .SH NAME wsstrip \- text file stripper to remove "bad" control characters .SH SYNOPSIS .BR "wsstrip <infile >outfile .PP .SH DESCRIPTION .I Wsstrip strips out unwanted control characters from text files usually created by uploading a \fIWordStar\fR document file via kermit binary transfer. The control characters stripped out are: .PP any byte with the 7th bit turned on (larger than 0x80) has that bit stripped off to normalize the character .br any control character that is not \\n, \\t, bell .br .pp .SH EXAMPLE For this example we will assume the file to be processed is text.bad. We will generate the file text.good. .PP .sp 1 We type: wsstrip <text.bad >text.good .sp 1 .pp .SH AUTHORS WSSTRIP was written by: John Paul O'Brien, Coordinator of Technical Support Nova University Computer Center 3301 College Ave. Ft. Lauderdale, Fl. 33314 (305) 475-7633 {allegra, ucf-cs, usfvax2}!novavax!john .PP .SH BUGS AND CAVEATS Receive mode is too slow. Needs to be fixed. Should also include a command line mode to bypass menu constraint (ie. xum -st file). .PP .SH BUGS AND CAVEATS Options should be installed for different flavors of stripping. Should also not use redirection (looks messy). SHAR_EOF if test 1231 -ne "`wc -c < 'wsstrip.l'`" then echo shar: "error transmitting 'wsstrip.l'" '(should have been 1231 characters)' fi fi if test -f 'xmodemio.c' then echo shar: "will not over-write existing file 'xmodemio.c'" else cat << \SHAR_EOF > 'xmodemio.c' #include <stdio.h> unsigned char mk_chksum(); #define NUL 0x00 #define SOH 0x01 #define EOT 0x04 #define ACK 0x06 #define NAK 0x15 #define CAN 0x18 #define RETRY_MAX 10 #define BUFF_SIZE 128 /* Send_file() */ /* Routine to send a file from Unix to another computer via */ /* /dev/tty using the xmodem protocol in checksum mode. */ /* */ /* On Entry: terminal file id, and file to send file id /* On Exit: returns 0 for success or -1 for failure */ send_file(tty_fid, file_id) int tty_fid, file_id; { int ret_code, read_status, tty_status, ack_status, retry_counter; unsigned char checksum, sector_num, temp_byte, start_bad; char cpm_buff[BUFF_SIZE]; /* CP/M disk buffers are ALWAYS 128 bytes */ ret_code = 0; /* assume no errors */ cls(); mov_cur(12, 10); printf("You have 1 minute to start receiving (control X to quit)....\n"); uncook_tty(tty_fid); retry_counter = 0; /* reset counter */ do /* wait for NAK from receiver so we can get in sync */ { tty_status = timed_read(tty_fid, &temp_byte, 1, 6); if ( (tty_status == 0) && ((temp_byte == NAK) || (temp_byte == CAN)) ) { if (temp_byte == NAK) { start_bad = 0; break; } else { start_bad = 1; break; } } else { start_bad = 1; retry_counter++; } } while (retry_counter < RETRY_MAX); if (start_bad) { ret_code = -1; /* say error */ /* We timed out or we got too much noise */ } else { sector_num = 0; do { read_status = read(file_id, cpm_buff, BUFF_SIZE); sector_num++; if (read_status > 0) { for(; read_status < BUFF_SIZE; read_status++) { cpm_buff[read_status] = 0x1a; /* CP/M eof */ } retry_counter = 0; /* reset to send actual packet */ do { temp_byte = SOH; write(tty_fid, &temp_byte, 1); /* send SOH */ temp_byte = ~sector_num; /* get ones complement of sector number */ write(tty_fid, §or_num, 1); /* sector count */ write(tty_fid, &temp_byte, 1); /* and its complement */ checksum = mk_chksum(cpm_buff, BUFF_SIZE); write(tty_fid, cpm_buff, BUFF_SIZE); write(tty_fid, &checksum, 1); /* send checksum */ if ((ack_status = getack(tty_fid)) == -1) { retry_counter++; } } while ( (ack_status == -1) && (retry_counter < RETRY_MAX) ); } } while ( (read_status > 0) && (retry_counter < RETRY_MAX) ); retry_counter = 0; do { temp_byte = EOT; write(tty_fid, &temp_byte, 1); /* send EOT */ } while ( (getack(tty_fid) != 0) && (retry_counter++ < RETRY_MAX) ); } if (retry_counter >= RETRY_MAX) { ret_code = -1; } close(file_id); return(ret_code); } /* Recv_file() */ /* Routine to receive a file to Unix from another computer via */ /* /dev/tty using the xmodem protocol in checksum mode. */ /* */ /* On Entry: terminal file id, file to recv file id /* On Exit: returns 0 for success or -1 for failure */ recv_file(tty_fid, file_id) int tty_fid; { int ret_code, read_status, tty_status, ack_status, retry_counter; unsigned char checksum, sector_num, temp_byte, dummys[5], start_bad; char cpm_buff[BUFF_SIZE]; /* CP/M disk buffers are ALWAYS 128 bytes */ ret_code = 0; /* assume no errors */ cls(); mov_cur(12, 10); printf("You have 1 minute to start sending (control X to quit)....\n"); retry_counter = 0; /* reset counter */ do /* send a NAK to sender so we can get in sync */ { temp_byte = NAK; write(tty_fid, &temp_byte, 1); tty_status = timed_read(tty_fid, &temp_byte, 1, 6); if ( (tty_status == 0) && ((temp_byte == SOH) || (temp_byte == CAN)) ) { if (temp_byte == SOH) { start_bad = 0; break; } else { start_bad = 1; break; } } else { start_bad = 1; retry_counter++; } } while (retry_counter < RETRY_MAX); if (start_bad) { ret_code = -1; /* say error */ /* We timed out or we got too much noise */ } else { retry_counter = 0; sector_num = 1; /* to compare with sent sector number */ /* First SOH was caught in NAK, CAN, code above. */ while ( (temp_byte == SOH) && (retry_counter < RETRY_MAX) ) { tty_status = stimed_read(tty_fid, &dummys[0], 2); tty_status += stimed_read(tty_fid, &dummys[1], 2); for (ack_status = 0; ack_status < BUFF_SIZE; ack_status++) { tty_status += stimed_read(tty_fid, &cpm_buff[ack_status], 2); } tty_status += stimed_read(tty_fid, &dummys[2], 2); checksum = mk_chksum(cpm_buff, BUFF_SIZE); if ( (tty_status == 0) && (sector_num == dummys[0]) && ((~sector_num & 0xff) == dummys[1]) && (checksum == dummys[2]) ) { ack_status == write(file_id, cpm_buff, BUFF_SIZE); if (ack_status == BUFF_SIZE) { temp_byte = ACK; write(tty_fid, &temp_byte, 1); retry_counter = 0; ret_code = 0; sector_num++; } else { temp_byte = NAK; write(tty_fid, &temp_byte, 1); retry_counter++; ret_code = -1; } } else { temp_byte = NAK; write(tty_fid, &temp_byte, 1); retry_counter++; ret_code = -1; } tty_status = stimed_read(tty_fid, &temp_byte, 2); while ( (temp_byte != SOH) && (temp_byte != EOT) && (retry_counter < RETRY_MAX) ) { retry_counter++; tty_status = stimed_read(tty_fid, &temp_byte, 2); } if (retry_counter >= RETRY_MAX) { ret_code = -1; break; } retry_counter = 0; if (temp_byte == EOT) { temp_byte = ACK; write(tty_fid, &temp_byte, 1); break; } } } close(file_id); return(ret_code); } /* getack: Will do a timed read on a pre-selected tty and will return the status. On Entry: is passed the file id of the tty to use On Exit: returns 0 if got an ACK else returns -1 */ getack(tty_fid) int tty_fid; { char temp_byte; if ( (timed_read(tty_fid, &temp_byte, 1, 5) == 0) && (temp_byte == ACK) ) { return(0); /* got ACK ok */ } else { return(-1); /* timed out or wrong character */ } } /* mk_chksum: Will generate a checksum on array of specified size and return that checksum. On Entry: is passed the array and size to use On Exit: returns checksum */ unsigned char mk_chksum(array, size) char *array; int size; { int counter; unsigned char checksum; checksum = 0; for (counter = 0; counter < size; counter++) { checksum += array[counter]; /* build up checksum */ } return(checksum); } SHAR_EOF if test 6442 -ne "`wc -c < 'xmodemio.c'`" then echo shar: "error transmitting 'xmodemio.c'" '(should have been 6442 characters)' fi fi if test -f 'xum.l' then echo shar: "will not over-write existing file 'xum.l'" else cat << \SHAR_EOF > 'xum.l' .tr ~ \ .TH XUM l local .SH NAME xum \- Xmodem file transfer for BSD 4.x Unix Systems (pronounced Zoom!) .SH SYNOPSIS .BR "xum .PP .SH DESCRIPTION .I Xum will transfer a text or binary file using the xmodem (a.k.a. modem7) protocol. All commands to \fIXum\fR are entered into a menu which offers these choices: Selection of \fIbinary\fR or \fItext\fR file transfer. Selection of \fIsend\fR or \fIreceive\fR from/to the host system. \fIQuit\fI \fIXum\fR and return to \fIUnix\fR. .SH NOTES \fIXUM\fR needs to have a valid TERM entry in your environment to display the menu. \fIBinary\fR mode will transfer a file completely intact with no characters added or deleted. \fIBinary\fR mode should be used for uploading \fIWordstar\fR files. Then these files should be "cleaned up" for use with \fIUnix\fR (see man entry for \fIwsstrip\fR). \fIText\fR mode will, on upload, strip out all occurances of the carrage return and control Z characters. On download, \fItext\fR mode will add a carrage return before every linefeed (newline) character. .pp .SH AUTHOR XUM was written by: John Paul O'Brien, Coordinator of Technical Support Nova University Computer Center 3301 College Ave. Ft. Lauderdale, Fl. 33314 (305) 475-7633 {allegra, ucf-cs, usfvax2}!novavax!john .PP .SH BUGS AND CAVEATS Receive mode is too slow. Needs to be fixed. Should also include a command line mode to bypass menu constraint (ie. xum -st file). SHAR_EOF if test 1422 -ne "`wc -c < 'xum.l'`" then echo shar: "error transmitting 'xum.l'" '(should have been 1422 characters)' fi fi if test -f 'xumodem.c' then echo shar: "will not over-write existing file 'xumodem.c'" else cat << \SHAR_EOF > 'xumodem.c' #include <stdio.h> #include <sys/file.h> #define BUFF_SIZE 128 main() { int tty_fid, file_fid, cnt0, cnt1, t_tmp; char ch_reply, tmp_filename[24], file_name[50], /* arbitrary size */ f_buff[BUFF_SIZE], file_type; FILE *f_tmp; if (term_setup() != 0) { printf("Warning: This program needs to have the\n"); printf("TERM environment variable setup before\n"); printf("being run. Make sure this is done before\n"); printf("executing xumodem again (set yourself up like\n"); printf("you were going to use vi).\n"); exit(1); } tty_fid = raw_tty("/dev/tty"); if (tty_fid == -1) { printf("Error opening terminal for raw i/o\n"); exit(1); } ch_reply = 0; file_type = 0; cls(); mov_cur(22, 1); printf("XUMODEM - Xmodem for Unix Systems"); mov_cur(9, 3); printf("NOTICE: This version of XUMODEM supports checksum transfers only."); mov_cur(7,10); printf("Send a file, Receive a file, set Text file xfer, set Binary file xfer,"); mov_cur(25, 12); printf("or Quit (s, r, t, b, q): "); clr_eol(); mov_cur(24, 7); printf("File transfer mode = "); while (ch_reply != 'q') { mov_cur(45, 7); if (file_type == 0) { printf("text files"); } else { printf("binary files"); } clr_eol(); mov_cur(50, 12); ch_reply = tolower(0x7f & getchar()); switch(ch_reply) { case 's' : file_fid = get_fileid(tty_fid, file_name, ch_reply); if (file_fid >= 0) { if (file_type == 0) { sprintf(tmp_filename, "/tmp/xum%d", getpid()); f_tmp = fopen(tmp_filename, "w+"); while( (cnt0 = read(file_fid, f_buff, BUFF_SIZE)) > 0 ) { for (cnt1 = 0; cnt1 < cnt0; cnt1++) { if (f_buff[cnt1] == '\n') { fputc('\r', f_tmp); } fputc(f_buff[cnt1], f_tmp); } } fclose(f_tmp); close(file_fid); file_fid = open(tmp_filename, O_RDONLY); } send_file(tty_fid, file_fid); if (file_type == 0) { unlink(tmp_filename); } } ch_reply = 'q'; break; case 'r' : file_fid = get_fileid(tty_fid, file_name, ch_reply); if (file_fid >= 0) { cnt0 = recv_file(tty_fid, file_fid); if ( (file_type == 0) && (cnt0 == 0) ) { sprintf(tmp_filename, "/tmp/xum%d", getpid()); f_tmp = fopen(tmp_filename, "w+"); file_fid = open(file_name, O_RDONLY); while( (cnt0 = read(file_fid, f_buff, BUFF_SIZE)) > 0 ) { for (cnt1 = 0; cnt1 < cnt0; cnt1++) { if ( (f_buff[cnt1] != '\r') && (f_buff[cnt1] != 0x1a) ) { fputc(f_buff[cnt1], f_tmp); } } } close(file_fid); fclose(f_tmp); t_tmp = open(tmp_filename, O_RDONLY); file_fid = open(file_name, O_CREAT | O_TRUNC | O_WRONLY, 0600); while( (cnt0 = read(t_tmp, f_buff, BUFF_SIZE)) > 0 ) { write(file_fid, f_buff, cnt0); } close(file_fid); close(t_tmp); unlink(tmp_filename); } } ch_reply = 'q'; break; case 't' : file_type = 0; break; case 'b' : file_type = 1; break; default : break; } } mov_cur(50, 12); clr_eol(); printf("Quit"); reset_tty(tty_fid); mov_cur(1, 24); } /* Get_fileid() */ /* Routine to ask for a filename and do processing based on send */ /* or receive mode. */ /* */ /* On Entry: terminal file id, array for file name, and */ /* type of file function (send, recv). */ /* On Exit: returns opened or created file id or -1 for failure */ /* and file_name is the file name used. */ get_fileid(tty_fid, file_name, file_func) int tty_fid; char *file_name, file_func; { int file_id; char temp_byte; if (file_func == 'r') { printf("receive a file"); mov_cur(1, 14); clr_eol(); mov_cur(10, 14); printf("Input filename to receive: "); clr_eol(); cook_tty(tty_fid); scanf("%s", file_name); uncook_tty(tty_fid); file_id = open(file_name, O_CREAT | O_TRUNC | O_EXCL | O_WRONLY, 0600); if (-1 == file_id) { printf("\nError creating %s. File may exist. Overwrite (y, n) ? ", file_name); temp_byte = tolower(0x7f & getchar()); while ( (temp_byte != 'y') && (temp_byte != 'n') ) { temp_byte = tolower(0x7f & getchar()); } if (temp_byte == 'y') { file_id = open(file_name, O_CREAT | O_TRUNC | O_WRONLY, 0600); } } if (file_id < 0) { printf("\r\nError opening file; can not create %s\r\n", file_name); } } else { printf("send a file"); mov_cur(10, 14); printf("Input filename to send: "); clr_eol(); cook_tty(tty_fid); scanf("%s", file_name); uncook_tty(tty_fid); if (-1 == (file_id = open(file_name, O_RDONLY))) { printf("Error opening %s; file does not exist\n", file_name); } } return(file_id); } SHAR_EOF if test 4841 -ne "`wc -c < 'xumodem.c'`" then echo shar: "error transmitting 'xumodem.c'" '(should have been 4841 characters)' fi fi exit 0 # End of shell archive