#include "ufk.h" #include #include #include #include #include /* * split command line into seperate strings */ split(cmd_str) char *cmd_str; { char *malloc(); char pass, *p, *q, result[128]; numprm = 0; /* no parameters yet */ for (pass = 0; pass < 2; pass++) /* find # of params in pass 1 */ { /* alloc pointer array and store */ if (pass > 0) /* pointers in pass 2 */ { if ((params = malloc(numprm * sizeof(char *))) == NULL) { /* allocate space for pointer array to parameters */ prterr(ER_NOMEM); kerm_exit(); } numprm = 0; /* restart scan */ } p = cmd_str; /* setup pointer to input string */ while (*p && (*p != COMMENT)) /* do till end of string */ { while (isspace(*p)) /* strip leading white space */ p++; if (pass > 0) { sscanf(p, "%s", result); /* get part of input string */ if ((q = malloc(strlen(result) + 1)) == NULL) /* get str space */ { prterr(ER_NOMEM); kerm_exit(); } strcpy(q, result); /* copy part to allocated memory */ params[numprm] = q; /* save pointer to string */ } numprm++; /* one more */ while ((!isspace(*p)) && *p) /* skip to end of this string */ p++; } } return (TRUE); } /* * parse command components */ parse(command_string, table) char *command_string; TABLE table[]; { char i = 0, j; int mstat, cmd_num = 0, tv = 0, unique = FALSE; make_lower(command_string); /* convert to lower case */ while (*table[i].string) /* do until end of command table */ { mstat = match(table[i].string, command_string); /* do compare */ if (mstat == -1) return (table[i].funcadr); /* exact match found */ if (mstat != 0) /* some characters did match */ { if (mstat > tv) /* longer than so far ? */ { tv = mstat; /* save longest length */ cmd_num = i; /* remember which command */ unique = TRUE; /* it's unique so far */ } j = i; while (*table[++j].string) /* start new search from next entry */ { mstat = match(table[j].string, command_string); /* other match ? */ if (mstat == -1) return (table[j].funcadr); /* exact match */ if (mstat != 0) /* some characters did match */ { if (mstat > tv) /* longer than so far ? */ { tv = mstat; /* save greatest length */ cmd_num = i; /* remember which command */ unique = TRUE; /* it's unique so far */ } if (mstat == tv) /* another one of the same length ? */ unique = FALSE; /* yes, it's not unique anymore */ } } if (!unique) /* if it was'nt unique it's ambiguous */ return (NULL); else return (table[cmd_num].funcadr); /* else it's a valid command */ } i++; /* try next entry */ } if (cmd_num == 0) return (ERROR); /* no such command */ else return (table[cmd_num].funcadr); /* return command number */ } match(s, t) char *s, *t; { int len = 0, inputlen; inputlen = strlen(t); /* length of input command */ while (*s) /* do until end of string */ { if (*s++ != *t++) /* if no match */ { if (inputlen == 0) /* total command checked */ return (len); /* return matched length */ else return (0); /* no match for this command */ } len++; /* one more character done */ --inputlen; /* count down input string length */ } return (-1); /* full match found */ } /* * m a k e _ u p p e r * * Convert string to upper case */ make_upper(p) char *p; { while (*p) { if (islower(*p)) *p = toupper(*p); p++; } } /* * m a k e _ l o w e r * * Convert string to lower case */ make_lower(p) char *p; { while (*p) { if (isupper(*p)) *p = tolower(*p); p++; } } /* * p r e r r p k t * * Print contents of error packet received from remote host. */ prerrpkt(msg) char *msg; { if (!nooutput) { disp(0,19,"Kermit aborting with following error from remote host:"); foreground(); disp(0,20,msg); background(); beep(); } } /* * send ASCII file to remote without protocol. * handshake is used. */ jmp_buf trn_env; trnsmit() { FILE *xmitfp; char c1; int c, trnsm_int(); struct sgttyb mode; if (numprm <= 1) /* check for parameters */ prterr(ER_FSPCREQ); else { if ((xmitfp = fopen(params[1], "r")) == NULL) prterr(ER_OPENERR); else { if (!open_port(FALSE,FALSE)) prterr(ER_POPNERR); else { signal(SIGINT,trnsm_int); if (!setjmp(trn_env)) while ((c = getc(xmitfp)) != EOF) /* get character from file */ { if (debug) putc(c, stdout); /* send to console as well */ gtty(ttyfd,&mode); if (mode.sg_speed & INCHR) { read(ttyfd,&c1,1); /* Check received character */ if ((c1 & 0177) == dstop && dstop != 0)/* Stop chr ? */ do /* Yes */ read(ttyfd,&c1,1); /* Wait for next character */ while ((c1 & 0177) != dstart);/* Wait for start chr */ } c1 = c; /* Only high byte of int would be send (=0) */ write(ttyfd,&c1,1); /* Send to output port */ } else if (debug) fputs("\n",stdout); fclose(xmitfp); kdelay(1); /* Give the port time to finish */ close_port(FALSE,FALSE); } } } } trnsm_int() { longjmp(trn_env,TRUE); /* Transmit interrupted... */ } /* * Read KERMIT commands from file */ take(fspec,echo) char *fspec, echo; { FILE *tfp; char data[133], /* Command input */ fname[80]; if (fspec == NULL) { if (numprm > 1) strcpy(fname, params[1]); else return(prterr(ER_FSPCREQ)); } else strcpy(fname,fspec); if ((tfp = fopen(fname,"r")) != NULL) /* Look for command file */ { /* Found file, read commands */ while (fgets(data,132,tfp)) { if (echo) { fputs(prompt,stdout); /* Echo prompt */ fputs(data,stdout); /* Echo command */ } data[strlen(data) - 1] = '\0'; /* Zap newline */ if (data[0] && data[0] != COMMENT) /* Not a blank line */ kerm_command(data); /* Do command */ } fclose(tfp); } else { if (fspec == NULL) return(prterr(ER_OPENERR)); else return(ER_OPENERR); } return(NULL); } /* * call UniFLEX to perform external command */ do_uniflex() { static char *shell = { "/bin/shell" }; static char *opt = { "+xc" }; char *prm[4], *p, cmdline[256]; int i, kerm_exit(); prm[0] = &shell[5]; /* setup program name */ prm[1] = prm[3] = 0; /* end of parameters pointer */ if (numprm > 1) { prm[1] = opt; /* one shot option */ prm[2] = p = cmdline; /* pointers to start of commandline */ for (i = 1; i < numprm; i++) { strcpy(p,params[i]); /* copy params into one line */ p += strlen(p); /* point after command */ *p++ = ' '; /* separator */ } *p = '\0'; /* end of string */ } if (!fork()) /* duplicate myself */ { execvp(shell,prm); /* execute command in child */ prterr(ER_SPAWN); /* should not come here */ } else { signal(SIGTERM,SIG_IGN); /* Ignore this signals */ signal(SIGHUP,SIG_IGN); signal(SIGQUIT,SIG_IGN); signal(SIGINT,SIG_IGN); wait(0); /* wait for child to die */ signal(SIGTERM,kerm_exit); /* Set signals again */ signal(SIGHUP,kerm_exit); signal(SIGQUIT,SIG_DFL); /* Make these default */ signal(SIGINT,SIG_DFL); } } disk_free() { char dev[30]; long size; if (numprm <= 1) strcpy(dev,"."); /* use current place if not specified */ else strcpy(dev,params[1]); /* use specified place */ if ((size = get_free(dev)) != -1l)/* if no error... */ printf("Number of free blocks: %ld (%ld bytes)\n",size, size * 512); } chd() { struct passwd *p; if (numprm <= 1) { if ((p = getpwuid(getuid())) == NULL) prterr(ER_GETPWDID); chdir(p->pw_dir); set_dir(p->pw_dir); } else { if (chdir(params[1]) == ERROR) prterr(ER_INVDIR); else set_dir(params[1]); } } /* * show statistics about connection */ statistics() { static char s1[] = "Characters sent:\t\t%ld\n"; static char s2[] = "Data characters sent:\t\t%ld\n"; static char s3[] = "NAK's sent:\t\t\t%d\n"; static char s4[] = "Packets sent:\t\t\t%d\n"; static char s5[] = "Characters received:\t\t%ld\n"; static char s6[] = "Data characters received:\t%ld\n"; static char s7[] = "NAK's received:\t\t\t%d\n"; static char s8[] = "Packets received:\t\t%d\n"; printf("Totals for the last transfer:\n\n"); printf(s1, chr_sent); printf(s2, dchr_sent); printf(s3, nak_sent); printf(s4, pack_sent); printf(s5, chr_rec); printf(s6, dchr_rec); printf(s7, nak_rec); printf(s8, pack_rec); printf("Effective data rate:\t\t%d baud\n", data_rate); printf("\nTotals since KERMIT was started:\n\n"); printf(s1, t_chr_sent); printf(s2, t_dchr_sent); printf(s3, t_nak_sent); printf(s4, t_pack_sent); printf(s5, t_chr_rec); printf(s6, t_dchr_rec); printf(s7, t_nak_rec); printf(s8, t_pack_rec); printf("Mean effective data rate:\t%d baud\n", t_data_rate); } #define POLYIT 0x8408 /* Polynomial for CRC-CCITT */ #define POLY16 0xa001 /* Polynomial for CRC-16 (not used here) */ unsigned int crc_value, crc[256]; /* Global accessible variables */ init_crc_table() { int count, nr; unsigned int accum, crcch; for (count = 0; count < 256; count++) /* Build CRC lookup table */ { accum = 0; crcch = count; for (nr = 0; nr < 8; nr++) { if (((accum & 0xff) ^ crcch) & 1) accum = (accum / 2) ^ POLYIT; else accum = (accum / 2); crcch = (crcch / 2); } crc[count] = accum; /* Save calculated value in table */ } } zero_crc() { crc_value = 0; /* Initial value is zero */ } unsigned int calc_crc(value) unsigned char value; { crc_value = crc[value ^ (crc_value & 0xff)] ^ ((crc_value >> 8) & 0xff); return crc_value; /* Return accumulated value so far */ } beep() { if (!remote && !nooutput) putc(BELL,stdout); } disp(x,y,string) int x,y; char *string; { if (!remote) { posit(x,y); fputs(string,stdout); if (!screen && !nooutput) fputs("\n",stdout); } } set_frame() { if (screen && !remote && !nooutput) { clear_screen(); posit(28,0); foreground(); fprintf(stdout," KERMIT version %s ",VERSION); background(); if (sflg || rflg) { disp(0,4,"Transferred:"); disp(27,4,"Percentage:"); } disp(0,6,"Packet received:"); disp(0,7,"Packet transmitted:"); if (debug >= 1) { disp(0,9,"Data received:"); disp(0,11,"Data transmitted:"); disp(0,13,"Receive state:"); disp(36,13,"Send state:"); disp(27,6,"Type:"); disp(27,7,"Type:"); disp(37,6,"Length:"); disp(37,7,"Length:"); disp(50,6,"Checksum:"); disp(50,7,"Checksum:"); } curs_off(); /* Turn off cursor */ } } disp_state(x,y,state) int x,y; char state; { static char sa[] = "Attribute "; static char sb[] = "Break "; static char sc[] = "Complete "; static char sd[] = "Data "; static char sf[] = "Filename "; static char sq[] = "Abort "; static char sr[] = "Receive init"; static char ss[] = "Send init "; static char st[] = "Timeout "; static char sz[] = "End of file "; static char un[] = "Unknown "; char dsc[5]; if (debug == 2) strcpy(dsc,"%s\r"); else strcpy(dsc,"%s\r\l"); posit(x,y); switch(state) { case 'A': prtdbg(dsc,sa); break; case 'B': prtdbg(dsc,sb); break; case 'C': prtdbg(dsc,sc); break; case 'D': prtdbg(dsc,sd); break; case 'F': prtdbg(dsc,sf); break; case 'Q': prtdbg(dsc,sq); break; case 'R': prtdbg(dsc,sr); break; case 'S': prtdbg(dsc,ss); break; case 'T': prtdbg(dsc,st); break; case 'Z': prtdbg(dsc,sz); break; default: prtdbg(dsc,un); } } prtdbg(fmt, a1, a2, a3, a4, a5, a6) char *fmt; { if ((debug >= 1) && !remote) fprintf(stdout,fmt,a1,a2,a3,a4,a5,a6); if (debug == 2) fprintf(dbgfil,fmt,a1,a2,a3,a4,a5,a6); } prtdbgf(fmt, a1, a2, a3, a4, a5, a6) char *fmt; { if (debug == 2) fprintf(dbgfil,fmt,a1,a2,a3,a4,a5,a6); } map_case(name,mode) char *name; int mode; { if (mapping) { if (mode == IN) make_lower(name); else if (mode == OUT) make_upper(name); } } new_name(s) char *s; { struct stat buf; int num; char new_str[15], num_str[5]; num = 0; do /* Construct new filename */ { /* until new name not found */ if (num++ > 4095) /* Bump counter */ { error(PER_CREATE,"%s",new_str);/* FATAL error */ kerm_exit(); /* More than 4096 files ??? */ } strncpy(new_str,s,10); /* Copy 10 characters at most */ new_str[10] = '\0'; /* Truncate at position 10 */ sprintf(num_str,".%03x",num); /* Format new filename */ strcat(new_str,num_str); } while (!stat(new_str,&buf)); /* If it exists, try again */ strcpy(s,new_str); /* Save new filename */ } synerr(threshold) int threshold; { if ((threshold != 0) && (numprm >= threshold)) return FALSE; prterr(ER_SYNERR); return TRUE; } check_bg() { int oldsig; oldsig = signal(SIGINT,SIG_IGN); /* Get old KBD signal */ signal(SIGINT,oldsig); /* Restore */ return oldsig; /* TRUE if we're in the background */ }