<<< flbuff.c >>> #include "FLK.H" /* * b u f i l l * * Get a bufferful of data from the file that's being sent. * Control-quoting, 8-bit & repeat count prefixes are handled. */ char *bptr; /* Buffer pointer */ bufill(buffer,first_time) char buffer[]; /* Buffer */ char first_time; /* Called for the first time */ { int new_char, /* Char read from file */ rpt_count, max_data_size, bufsize; static int old_char; /* Previous character */ static char *savptr, /* Must be saved between calls */ *savbptr, savbuf[6]; bptr = buffer; /* Init data buffer pointer */ max_data_size = spsiz - 3 - (block_check_type - 1); if (first_time) { old_char = getc(fp); /* Pre-read character first time */ savbptr = savbuf; } if (savbptr != savbuf) /* Data left from previous call */ for (savptr = savbuf; savptr != savbptr;) *bptr++ = *savptr++; /* Copy old data to buffer */ savbptr = savbuf; /* No more data in save buffer */ while (old_char != EOF) /* Do until no more data */ { rpt_count = 1; while(((new_char = getc(fp)) != EOF) && (rpt_count < 94) && (repeat_quote != 0) && (new_char == old_char) && ((new_char != '\n') || image)) /* No repeat for newline */ rpt_count++; /* Count consecutive match */ if (rpt_count > 1) /* We've had more of these */ if (rpt_count == 2) insbuf(old_char); /* Insert twice if only 2 char's */ else { *bptr++ = repeat_quote; /* Setup repeat quote character */ *bptr++ = tochar(rpt_count); /* Send count */ } transmit_chr_count += rpt_count; /* Counter for total data */ insbuf(old_char); old_char = new_char; /* Copy next character */ bufsize = bptr - buffer; /* Current number of characters */ if (bufsize > max_data_size) /* Check length */ { while (savptr != bptr) *savbptr++ = *savptr++; /* Copy excess data */ return (bufsize - (savbptr - savbuf)); } else if (bufsize == max_data_size) /* Exact fit */ return (bufsize); savptr = bptr; } if (bptr == buffer) /* Wind up here only on EOF */ return(EOF); return(bptr - buffer); /* Handle partial buffer */ } insbuf(o_char) int o_char; { char chr7; chr7 = o_char & 0177; /* Get low order 7 bits */ if ((o_char > 127) && (eight_quote != 0)) *bptr++ = eight_quote; /* Eight_bit quoting done */ if (chr7 < SP || chr7 == DEL || chr7 == quote || chr7 == repeat_quote || chr7 == eight_quote) { /* Special handling required ? */ if (o_char == '\n' && !image) { /* Do LF->CRLF mapping if !image */ *bptr++ = quote; *bptr++ = ctl('\r'); } *bptr++ = quote; /* Quote the character */ if ((chr7 == 0) || ((chr7 != quote) && (chr7 != repeat_quote) && (chr7 != eight_quote))) { o_char = ctl(o_char); /* Uncontrolify it */ chr7 = ctl(chr7); } } if (image && (eight_quote == 0)) *bptr++ = o_char; /* Deposit the character itself */ else *bptr++ = chr7; /* Only send the low bits */ } /* * b u f e m p * * Put data from an incoming packet into a file. * Control-quoting, 8-bit & repeat count prefixes are handled. */ bufemp(buffer,len) char buffer[]; /* Buffer */ int len; /* Length */ { int i, j, /* Counters */ rpt_count; /* Repeat counter */ char t, t7, /* Character holder */ set_bit_eight; /* flag to set bit eight */ for (i = 0; i < len; i++) /* Loop thru the data field */ { t = buffer[i]; /* Get character */ if (t == repeat_quote) /* Repeat quoting ? */ { rpt_count = unchar(buffer[i+1]); /* Get repeat count */ i++; /* Increment here because of compiler bug */ t = buffer[++i]; /* Get next character */ } else rpt_count = 1; /* No repeat quoting, count = 1 */ if (t == eight_quote) /* Eight-bit quoting ? */ { set_bit_eight = TRUE; /* Set bit eight */ t = buffer[++i]; /* Get next character */ } else set_bit_eight = FALSE; /* Don't set bit eight */ if (t == quote) /* Control quote? */ { /* Yes */ t = buffer[++i]; /* Get the quoted character */ t7 = t & 0177; /* Character without parity bit */ if ((t7 >= ctl(DEL)) && (t7 <= ctl(DEL) + 32)) t = ctl(t); /* Undo what others did to it */ } if (set_bit_eight) t |= 0x80; /* Set bit eight on request */ transmit_chr_count += rpt_count; /* Counter for total data */ for (j = 0; j < rpt_count; j++) if (image) { if (putc(t,fp) == ERROR) /* send to file if image mode */ return(ERROR); } else { if (t == LF) /* strip LF in non-image mode */ break; if (t == TAB) /* expand tabs to spaces */ { while (--tabsleft >= 0) if (putc(' ',fp) == ERROR) return(ERROR); tabsleft = TABSIZE; /* reset tabcounter */ } else /* pass character */ { if (putc(t,fp) == ERROR) return(ERROR); if ((--tabsleft <= 0) || (t == CR)) tabsleft = TABSIZE; /* take care of tabcount */ } } } return(NULL); } <<< flconn.c >>> #include "FLK.H" /* * c o n n e c t * * Establish a virtual terminal connection with the remote host * */ char stop_send; connect() { int save_port; /* Temp port address */ char c, got_escape; stop_send = FALSE; /* No stop character send yet */ save_port = ttyfd; /* Save old port address */ if (numprm > 1) { sscanf(params[1],"%x",&ttyfd); /* Get hex address */ if (initport(ttyfd,0) == FALSE) /* Try to init the port */ { prterr("No such line available"); if ((ttyfd = save_port) != REMOTE) /* Restore port if not remote */ initport(ttyfd,0); return; /* Error in port setting */ } else remote = FALSE; } if (remote) prterr("No line to connect to\7"); /* We're remote.... */ else { start_remote(); /* Enable interrupt if any */ puts("Connected...\n"); cflg = TRUE; /* Put us in "connect mode" */ purgeline(ttyfd); /* eat pending input */ if (logfileopen) logging = TRUE; /* if file available, turn log on */ plog = &logbuf[0]; /* set pointer to log data area */ got_escape = FALSE; /* no escape char received yet */ while (cflg) /* do as long as we're connected */ { if (instat(consfd)) /* got something from the console */ { c = inchar(consfd) & 0177; /* get character */ if ((c == escchr) || (got_escape)) /* check for escape character */ { if (!(got_escape = ~got_escape)) { if (c == escchr) /* maybe another one */ { outchar(c,ttyfd); /* yes, echo it */ if (!fulldup) { outchar(c,consfd); /* echo if half duplex */ write_log(c,FALSE); /* send to log file as well */ } } else switch (tolower(c&0177)) /* special character */ { case '0': outchar(NULL,ttyfd); /* send NULL */ break; case 'b': send_break(ttyfd); /* send BREAK */ break; case 'c': cflg = FALSE; /* disconnect */ write (consfd,"\r\n",0); break; case 'h': write(consfd,"\r\nYes, I'm still here...\r\n",0); break; /* tell him i'm still available */ case 'q': if (logfileopen) { logging = FALSE; /* suspend logging */ write(consfd,"\r\nLogging suspended\r\n",0); } else write(consfd,"\r\nLog file is not open\r\n",0); break; case 'r': if (logfileopen) { logging = TRUE; /* resume logging */ write(consfd,"\r\nLogging resumed\r\n",0); } else write(consfd,"\r\nLog file is not open\r\n",0); break; case 's': write(consfd,"\r\nLog file status: ",0); if (logfileopen) write(consfd,"open\r\n",0); else write(consfd,"closed\r\n",0); write(consfd,"Logging status: ",0); if (logging) write(consfd,"on\r\n",0); else write(consfd,"off\r\n",0); break; case '?': /* display commands */ write(consfd,"\r\nArguments available:\r\n\n",0); write(consfd,"? - Show this help message\r\n",0); write(consfd,"0 - Transmit NULL\r\n",0); write(consfd,"B - Transmit 'BREAK'\r\n",0); write(consfd,"C - Close connection\r\n",0); write(consfd,"H - Report availability\r\n",0); write(consfd,"Q - Quit logging (if started)\r\n",0); write(consfd,"R - Resume logging\r\n",0); write(consfd,"S - Show status of connection\r\n",0); break; default: beep(); /* unknown, ring the bell */ break; } } } else { outchar(c,ttyfd); /* write it out */ if (!fulldup) { outchar(c,consfd); /* to console if half duplex */ write_log(c,FALSE); /* send to logfile */ } } } else if(instat(ttyfd)) /* see remote keyboard */ { c = inchar(ttyfd); /* get character */ outchar(c,consfd); /* send to local screen */ write_log(c,FALSE); /* and to logfile */ wtcnt = WAITVAL; /* reset wait counter */ } else if (stop_send) /* stop sent to remote */ if (!(--wtcnt)) /* did remote stop sending? */ flushlog(); /* yes, write buffer to disk */ } write_log(c,TRUE); /* write buffer to disk */ puts("Disconnected.\n"); finish_remote(); /* Disable interrupts if any */ if ((ttyfd = save_port) == REMOTE) /* Restore port */ remote = TRUE; else initport(ttyfd,0); } } /* * Write data to log buffer */ write_log(chr,flush) char chr; int flush; { if (flush) /* flush buffer ? */ flushlog(); else if (logging && logfileopen && chr != CR) { if (chr == LF) /* convert LF to CR */ chr = CR; if ((chr == BS) || (chr == DEL)) /* backspace or rubout */ { if (plog > &logbuf) /* check range of pointer */ --plog; } else *plog++ = chr; /* store char in buffer */ if (plog == &logbuf[LOGBUFSIZE-132]) /* time for diskwrite ? */ { outchar(dstop, ttyfd); /* stop remote */ stop_send = TRUE; /* stop signal send to remote */ wtcnt = WAITVAL; /* set counter */ } else if (plog == &logbuf[LOGBUFSIZE]) --plog; /* in case remote won't stop */ } } /* * Write buffer to disk */ flushlog() { char *savep = &logbuf[0]; /* initial pointer */ if (logfileopen) /* only if logfile open */ { while (savep != plog) /* if not at end of buffer */ if (putc(*savep++, lfp) == ERROR) /* write to file */ { prterr("Error writing log file -- logging stopped"); fclose(lfp); logging = logfileopen = FALSE; /* no more logging */ logfile[0] = '\0'; /* Zap filename */ break; } plog = &logbuf[0]; /* reset pointer */ if (stop_send == TRUE) { stop_send = FALSE; outchar(dstart, ttyfd); /* restart remote */ } } } <<< flcutl.c >>> #include "FLK.H" /* * s p a r * * Fill the data array with my send-init parameters * */ spar(data,len) char data[], *len; { data[0] = tochar(maxpacksiz); /* Biggest packet I can receive */ data[1] = tochar(mytime); /* When I want to be timed out */ data[2] = tochar(mypad); /* How much padding I need */ data[3] = ctl(mypchar); /* Padding character I want */ data[4] = tochar(myeol); /* End-Of-Line character I want */ data[5] = myquote; /* Control-Quote character I send */ if ((data[6] = eight_quote) == 0) data[6] = 'N'; /* No eight bit quoting */ else if (config > 3) /* 8 bits link */ data[6] = 'Y'; /* 8th bit quoting on request */ data[7] = block_check_type + '0'; /* Type of block check */ if ((data[8] = repeat_quote) == 0) /* Repeat count quote character */ data[8] = ' '; /* No repeat quoting done */ *len = 9; } /* r p a r * * Get the other host's send-init parameters * */ rpar(data,len) char data[], len; { char c; if (len > 0) spsiz = unchar(data[0]); /* Maximum send packet size */ else spsiz = I_MYPACKSIZE; /* Use default */ if (len > 1) timint = unchar(data[1]); /* When I should time out */ else timint = I_MYTIME; timecount = timint * DELAYVALUE; /* Setup new timeout counter */ if (len > 2) pad = unchar(data[2]); /* Number of pads to send */ else pad = I_MYPAD; if (len > 3) padchar = ctl(data[3]); /* Padding character to send */ else padchar = I_MYPCHAR; if (len > 4) eol = unchar(data[4]); /* EOL character I must send */ else eol = I_MYEOL; if (len > 5) quote = data[5]; /* Incoming data quote character */ else quote = I_MYQUOTE; if (len > 6) { if ((c = data[6]) == 'N') eight_quote = 0; /* Don't use eight_bit quoting */ else if (c == 'Y') { if (config <= 3) /* 7 bits link */ eight_quote = myeightquote; /* Use default */ else eight_quote = 0; /* Don't use it */ } else eight_quote = c; /* Use this char for eight bit quoting */ } else eight_quote = 0; /* Don't use it */ if ((len > 7) && ((c = data[7] - '0') == myblock_check_type)) block_check_type = c; /* Setup block check type */ else block_check_type = I_BLOCKCHECKTYPE;/* Set initial value */ if ((len > 8) && ((c = data[8]) == myrptquote) && (c != ' ')) repeat_quote = c; /* Setup repeat quote character */ else repeat_quote = 0; /* Don't use repeat quoting */ } set_default_comm() { eol = myeol; /* EOL for outgoing packets */ quote = myquote; /* Standard control-quote char "#" */ pad = mypad; /* No padding */ padchar = mypchar; /* Use null if any padding wanted */ timint = mytime; /* Timeout value */ eight_quote = myeightquote; /* Set eight_bit quote character */ repeat_quote = myrptquote; /* Set repeat quote character */ block_check_type = myblock_check_type; /* Set initial value */ } disp_size_transferred() { #ifdef SCREEN float xmitted, percentage; if (!remote && (transmit_chr_count != 0)) { xmitted = transmit_chr_count / 1024.; /* Size transferred so far in K */ posit(18,4); printf("%6.2f K", xmitted); if (image && sflg) { percentage = 100. * (transmit_chr_count / (file_size * 252.)); /* a FLEX data sector contains 252 bytes of data */ posit(39,4); printf("%3.0f %%", percentage); } } #endif } init_xfer() { chr_sent = datachr_sent = chr_rec = datachr_rec = 0; /* zero counters */ nak_sent = nak_rec = pack_sent = pack_rec = 0; data_rate = 0; #ifdef CLOCK start_time = read_clock(); #endif } fin_xfer() { int numbits; t_chr_sent += chr_sent; /* adjust performance counters */ t_datachr_sent += datachr_sent; t_nak_sent += nak_sent; t_pack_sent += pack_sent; t_chr_rec += chr_rec; t_datachr_rec += datachr_rec; t_nak_rec += nak_rec; t_pack_rec += pack_rec; #ifdef CLOCK end_time = read_clock(); /* Get current time */ /* calculate number of bits in transmission */ numbits = (config == 2 || config == 3 || config == 5) ? 10 : 11; if (end_time < start_time) end_time += 86400; /* correct for day overflow, */ /* add number of seconds for one day */ if (rflg) /* received data */ data_rate = (chr_rec / (end_time - start_time)) * (100 / numbits); else if (sflg) /* transmitted data */ data_rate = (chr_sent / (end_time - start_time)) * (100 / numbits); t_data_rate = (((t_data_rate == 0) ? data_rate : t_data_rate) + data_rate) / 2; #endif } #ifdef CLOCK long int read_clock() { char *clock, c_sec, c_min, c_hour, dummy; char bcdbin(); clock = RTCADR; /* point to register 0 */ clock[15] = 0xaa; /* test pattern */ dummy = 0; /* else clock won't be read again */ if ((clock[13] & 0x80) && (clock[15] == 0xaa)) { /* clock valid and set */ while (clock[10] & 0x80); /* check for update in progress */ c_sec = clock[0]; /* copy data */ c_min = clock[2]; c_hour = clock[4]; if (!(clock[11] & 0x02)) /* 12 hour format */ if (c_hour &= 0x80) c_hour += 12; if (!(clock[11] & 0x04)) { /* BCD data format */ c_sec = bcdbin(c_sec); /* convert BCD to BIN */ c_min = bcdbin(c_min); c_hour = bcdbin(c_hour); } return (long)c_hour * 3600 + (int)c_min * 60 + c_sec; } else return (NULL); /* invalid clock setting */ } /* * convert BCD number to binary */ char bcdbin(value) char value; { return ((value & 0x0f) + (10 * ((value & 0xf0) >> 4))); } #endif <<< fldir.c >>> #include "FLK.H" #include "flex.h" typedef struct fcbc FCB; /* * Get next file in a file group */ get_file_spec(firsttime) char firsttime; { char *wild_file_spec(), *status; static char my_firsttime; if (firsttime) { filenum = 1; /* First time initial values */ filecount = numprm - 1; my_firsttime = TRUE; } do { if (rflg != 2) { status = wild_file_spec(params[filenum], my_firsttime); my_firsttime = FALSE; } else { status = params[filenum++]; /* Don't parse for 'GET' */ if (filecount-- == 0) break; } if (status == ERROR) { prterr("Error opening directory"); break; } else if (status) /* Got valid spec */ { filnam = status; /* Setup pointer to spec */ if (rflg != 2) /* Don't convert for 'GET' */ cvt_case(filnam); /* Convert filename case */ return TRUE; } filenum++; /* Next parameter */ my_firsttime = TRUE; /* Start new directory search */ } while (--filecount); /* More to do */ return FALSE; /* done */ } char *wild_file_spec(mask,first) char mask[50], first; { static FCB *ptr; FCB *diropen(); static char filename[50]; if (first) if ((ptr = diropen(mask)) == ERROR) return (ERROR); /* Failed to open directory */ while (dirread(ptr,filename) != ERROR) if (mskcmp(filename,mask)) /* Check match */ return(filename); free(ptr); /* Release allocated memory */ return (FALSE); /* No more files */ } /* *** Compare against a mask * * This function compares a given string against a mask and returns * a 1 for 'compares' or a 0 for 'does not compare'. * * A mask is a concatenation of the following elements: * * c literal character * ? any character match except endstring null * [..] character class (all of these characters) * [^..] negated character class (all but these characters) * ^c negated character (all but this character) * * zone (match zero or more occurences) * * A character class consists of zero or more of the following * surrounded by [ and ]: * * c1-c2 range of ascii characters * c1-c2..c1-c3 multiple ranges * */ mskcmp(string,m) char *string,*m; { int k; char *sp,*sav,string2[128]; char *n,msk[128]; strcpy(sp = string2,string); cvt_case(sp); strcpy(n = msk,m); cvt_case(n); while (*n) { if (*n == '*') { sav = sp; if (!*++n) return (1); while (*sp && !mskcmp(sp,n)) ++sp; if (*sp) continue; sp = sav; } else if (!(k = onecmp(*sp,n))) return (0); else n += k; if (*sp) ++sp; } return (!*sp); } /* *** Compare only one character (for mskcmp) */ onecmp(s,m) char s,*m; { char c,setfind,setflag; char *mp; if ((c = *(mp = m)) == '?' && s); /* Okay as it is */ else if (c == '[') { setfind = setflag = 0; if (*++mp == '^') { setflag = 1; ++mp; } for (;(c = *mp) && c != ']'; ++mp) if (*mp == '-' && s >= *(mp - 1) && s <= *(mp + 1) && *(mp - 1) <= *(mp + 1)) { /* skip to trailing ']' */ while ((c = *(mp + 1)) && c != ']') ++mp; setfind = 1; } if (setfind == setflag) return (0); else return (mp - m + 1); } else if (c == '^' && *(mp + 1) != s) return (2); else if (c != s) return (0); return (1); } /* *** Open disk directory */ int drive; FCB *diropen(name) char *name; { FCB *ptr; int len; char *malloc(); drive = FLEX_DATA.work_drive; /* Assume work drive */ len = strlen(name); if (( len == 1) && isdigit(name[0])) drive = name[0] - '0'; /* Setup single drive number */ else { if ((isdigit(*name)) && (name[1] == '.')) { /* Leading drive number */ drive = name[0] - '0'; strcpy(name,name + 2); /* Strip number */ } else if ((isdigit(name[len - 1])) && (name[len - 2] == '.')) { /* Trailing drive number */ drive = name[len - 1] - '0'; /* Setup drive number */ name[len - 2] = '\0'; /* Strip number */ } } if ((ptr = (FCB *) malloc(sizeof(FCB))) == NULL) /* Allocate space */ return (ERROR); ptr->f.drive = drive; /* Insert drive number in FCB */ ptr->f.function = DR_OPEN; /* Open directory for read */ if (_fms(ptr,0) == ERROR) /* Open directory */ { free(ptr); /* Error, return memory */ return (ERROR); } else return (ptr); } dirread(ptr,filename) FCB *ptr; char *filename; { int i,j; ptr->f.function = GET_INF; /* Get info record function code */ while(_fms(ptr,0) != ERROR) { for (i = 0;i < 8;++i) filename[i] = ptr->f.filename[i]; filename[8] = '\0'; if (!*filename) return (ERROR); /* end of directory */ if (*filename != 0xff) /* not a deleted file */ { strcat(filename,"."); j = strlen(filename); for (i = 0;i < 3;++i) filename[j + i] = ptr->f.extension[i]; filename[j + 3] = '\0'; file_size = ptr->f.size; /* fill in file size */ transmit_chr_count = 0; /* start new sequence */ return (TRUE); } } return (ERROR); } <<< flhelp.c >>> #include "FLK.H" /* * Help processing */ help() { FILE *hlpfp; /* Pointer to help file */ char str[129], /* Temporary string holder */ tmpdrv, /* Save drive number */ found, /* Found correct record flag */ match, /* One record matched flag */ quit; /* Quit if no match flag */ int i, /* Counter */ level, /* Help level */ len1, /* String length counters */ len2, cmplen; /* Length to compare */ tmpdrv = workdrive; workdrive = load_drive; /* Look for file on drive KERMIT came from */ if ((hlpfp = fopen(HELPFILE,"r")) == ERROR) prterr("No help available."); /* Can't open help file */ else { if (numprm == 1) /* No parameters given */ { while ((get_rec(hlpfp,str)) && (str[0] != '0'));/* Find main record */ disp_rec(hlpfp,str); /* Show it */ } else { found = match = quit = FALSE; while (!quit && !found && get_rec(hlpfp,str)) /* until found or EOF */ for (i = 1; i < numprm; i++) /* Check each parameter */ { make_upper(params[i]); /* Force equal case */ make_upper(str); len1 = strlen(str) - 2; /* Correct for number and space */ len2 = strlen(params[i]); cmplen = len2 < len1 ? len2 : len1; /* Find length to match */ level = atoi(str); /* Get current level */ if (match && (level < i)) { quit = TRUE; /* New level, quit */ break; } if ((i == level) && (strncmp(&str[1],params[i],cmplen) == 0)) { /* This one is ok */ match = TRUE; if (i == numprm - 1) /* At the end ? */ found = TRUE; /* Done */ break; } if (!match) /* Stop if first string does'nt match */ break; } if (found) disp_rec(hlpfp,str); /* Show record */ else prterr("No such topic"); /* No match */ } fclose(hlpfp); workdrive = tmpdrv; /* Restore work drive */ } } get_rec(fp,str) FILE *fp; char str[]; { while (fgets(str,128,fp) != NULL) /* Until EOF */ if (isdigit(str[0])) /* Or no more digits */ return (TRUE); return (FALSE); /* End of file */ } disp_rec(fp,topic) FILE *fp; char *topic; { char string[129]; printf("\n%s\n",&topic[1]); /* Print current topic */ while ((fgets(string,128,fp) != NULL) && (!isdigit(string[0]))) puts(string); /* Print it as long as no digit */ puts("\n"); } <<< flio.c >>> #include "FLK.H" #ifdef VIDIS int v_speed_6850[] = /* valid speed settings for VIDIS 6850 */ { 75, 0, 300, 1, 600, 2, 1200, 3, 2400, 4, #ifdef INTERRUPT 4800, 5, 9600, 6, 19200, 7, #endif 0, 0 }; int v_speed_6551[] = /* valid speed settings for 6551 acia */ { 50, 1, 75, 2, 110, 3, 135, 4, 150, 5, 300, 6, 600, 7, 1200, 8, 1800, 9, 2400, 10, #ifdef INTERRUPT 3600, 11, 4800, 12, 7200, 13, 9600, 14, 19200, 15, #endif 0, 0 }; #else int v_speed_6850[] = /* valid speed settings for normal 6850 acia */ { 300, 2, 1200, 1, 0, 0 }; #endif char port_err, /* Flag to indicate error in port initialize */ *old_port, lastchar, irq_on = FALSE; /* * Initialize an acia type port */ initport(port,first_time) char port[]; char first_time; { int *p; if (!first_time) cleanup(); /* Reset old port */ #ifdef INTERRUPT save_vector = -1; /* Dummy vector */ #endif old_port = port; if (!get_acia_type(port)) return (FALSE); /* no such port available */ #ifdef INTERRUPT save_nmi = *dmem(NMIVEC); /* Save old NMI vector */ *dmem(NMIVEC) = &nmihdr; /* Setup NMI handler address */ inptr = outptr = &input_buffer[0]; /* Setup buffer pointers */ setirq_on(); /* Enable interrupts */ #endif #ifdef VIDIS if (use_6850) { port[0] = RESET_6850; /* reset the acia */ #ifdef INTERRUPT if (irq_on) { save_vector = *dmem(IRQVEC_6850); *dmem(IRQVEC_6850) = &irqprp; /* Setup interrupt vector */ port[0] = (config << 2) | 0x81; /* clock / 16, irq enable */ } else port[0] = (config << 2) | 0x01; /* clock / 16 */ #else port[0] = (config << 2) | 0x01; /* clock / 16 */ #endif p = v_speed_6850; /* point to speed table */ while (*p++ != speed) /* get valid speed */ p++; port[2] = *p; /* set hardware */ } else /* use 6551 */ { port[1] = RESET_6551; #ifdef INTERRUPT if (irq_on) { save_vector = *dmem(IRQVEC_6551); *dmem(IRQVEC_6551) = &irqprp; /* Setup interrupt vector */ port[2] = INITCMND_6551 & 0xfd; /* Enable interrupt */ } else port[2] = INITCMND_6551; #else port[2] = INITCMND_6551; #endif port[3] = INITCTRL_6551; switch(config) /* set configuration */ { case 0: port[2] |= 0x60; port[3] |= 0xa0; break; case 1: port[2] |= 0x20; port[3] |= 0xa0; break; case 2: port[2] |= 0x60; port[3] |= 0x20; break; case 3: port[2] |= 0x20; port[3] |= 0x20; break; case 4: port[3] |= 0x80; break; case 5: break; case 6: port[2] |= 0x60; break; case 7: port[2] |= 0x20; break; } p = v_speed_6551; /* point to valid speed table */ while (*p++ != speed) /* get valid speed */ p++; port[3] |= *p; /* set hardware */ } #else port[0] = RESET_6850; /* reset the acia */ p = v_speed_6850; /* point to valid speed table */ while (*p++ != speed) /* get valid speed */ p++; #ifdef INTERRUPT if (irq_on) { save_vector = *dmem(IRQVEC_6850); *dmem(IRQVEC_6850) = &irqprp; /* Setup interrupt vector */ port[0] = (config << 2) | *p | 0x80;/* set hardware, enable interrupt */ } else port[0] = (config << 2) | *p; /* set hardware */ #else port[0] = (config << 2) | *p; /* set hardware */ #endif #endif purgeline(port); /* eat old input */ return (TRUE); /* valid port found */ } /* * get acia type * return TRUE if port found, use_6850 = true if 6850, else 6551 */ get_acia_type(port) char port[]; { int dummy; char savep1, savep2, savep3; savep1 = port[0]; /* Save memory in case of failure */ savep2 = port[1]; savep3 = port[3]; port_err = FALSE; port[3] = 0; /* set initial value */ dummy = 0; /* else acia won't be read again */ if (port[3] != 0) /* still zero ? */ { port[0] = RESET_6850; /* no, reset special acia */ dummy = 0; /* else acia won't be read again */ if ((port[0] & 0xf3) == 0) /* check if 6850 available */ { use_6850 = TRUE; /* it's there */ return (TRUE); } } #ifdef VIDIS port[1] = RESET_6551; port[3] = 0; dummy = 0; /* else acia won't be read again */ if ((port[3] == 0) && (port[1] & 0x10))/* check if 6551 available */ { use_6850 = FALSE; /* 6551 found */ return (TRUE); } #endif port[0] = savep1; /* Restore memory in case of failure */ port[1] = savep2; port[3] = savep3; port_err = TRUE; /* Flag port error for cleanup */ return (FALSE); /* No such port there */ } /* * Setup line for remote connection */ start_remote() { if (remote) ttyfd = consfd; /* Must use this port */ irq_on = TRUE; initport(ttyfd,0); aborted = FALSE; } /* * Finish line for remote connection */ finish_remote() { if (remote) ttyfd = REMOTE; /* Restore setting */ irq_on = FALSE; initport(ttyfd,0); /* Re-init old port */ if (aborted) puts("\n"); } /* * read data from port */ read(dev,data,count) int dev,count; char *data; { int i; long int time; for (i = 0; i < count; i++) /* do it for the requested count */ { time = timecount; /* get timeout value */ while (!instat(dev)) /* no response yet */ if (--time == 0) { check_abort(); /* check for user abort after timeout */ return TIMEOUT; } lastchar = data[i] = inchar(dev); /* get character */ } if (rflg || sflg) chr_rec += count; /* count chars if sending or receiving */ return NULL; /* normal termination */ } /* * write characters to port */ write(dev,data,count) int dev,count; char *data; { int i; if (count == 0) /* determine count if not given */ count = strlen(data); for (i = 0; i < count; i++) outchar(data[i],dev); /* send to output port */ if (rflg || sflg) chr_sent += count; /* count chars if sending or receiving */ } /* * check for user abort */ check_abort() { char c; if (!cflg && !stopped) /* only when connect is inactive */ { /* and no stop character is sent */ if (instat(consfd)) /* if character available */ c = inchar(consfd); else { if (remote) c = lastchar; /* Only check typed character */ else /* if remote */ c = 0; } c &= 0177; /* strip parity */ lastchar = 0; if ((c == ABORTX) || (c == ABORTZ)) { /* and if it's the abort char */ aborted = c; /* flag abort */ return c; } else if (c == TOGDBG) /* Toggle debug ? */ { if (debug) { debug = FALSE; /* Switch off debug */ if (dbgfil != ERROR) { fclose(dbgfil); /* Close debug output file if open */ dbgfil = ERROR; } } else debug = TRUE; /* Switch on debug */ set_frame(); /* Make new display frame */ } else if (c == dstop) /* Wait.... */ while ((c = inchar(ttyfd) & 0177) != dstart); /* Wait for start */ } return NULL; /* no abort */ } /* * test for input character */ instat(port) char port[]; { #ifdef VIDIS if (port_err || ((port == consfd) && !remote)) return constat(); /* buffer status */ #ifdef INTERRUPT if (irq_on) return (inptr != outptr); #endif else if (use_6850) return(port[0] & 0x01); /* rcv ready bit 6850 */ else return(port[1] & 0x08); /* rcv ready bit 6551 */ #else #ifdef INTERRUPT if (irq_on) return (inptr != outptr); #endif return(port[0] & 0x01); /* rcv ready bit 6850 */ #endif } /* * get an input character */ inchar(port) char port[]; { char get_in_buf(); while (!instat(port)); /* wait for input */ #ifdef VIDIS if (port_err || ((port == consfd) && !remote)) return inchne(); /* use FLEX "input no echo" */ #ifdef INTERRUPT if (irq_on) return (get_in_buf()); #endif else if (use_6850) return port[1]; /* get data from 6850 */ else return port[0]; /* get data from 6551 */ #else #ifdef INTERRUPT if (irq_on) return (get_in_buf()); #endif return port[1]; /* get data from 6850 */ #endif } /* * test for output ready */ outstat(port) char port[]; { check_abort(); /* maybe he's aborting this */ #ifdef VIDIS if (port_err || ((port == consfd) && !remote)) return TRUE; /* console always ready in VIDIS */ else if (use_6850) return(port[0] & 0x02); /* xmit ready bit 6850 */ else return(port[1] & 0x10); /* xmit ready bit 6551 */ #else return (port[0] & 0x02); /* xmit ready bit 6850 */ #endif } /* * send a character */ outchar(c,port) char c,port[]; { long int time; time = timecount; while(!outstat(port)) /* wait for ready */ if ((--time == 0) && aborted) /* Acia not ready ? */ return; /* return in case of abort */ #ifdef VIDIS if (port == consfd) _putchr(c); /* use FLEX */ else if (use_6850) port[1] = c; /* send to 6850 */ else port[0] = c; /* send to 6551 */ #else port[1] = c; /* send to 6850 */ #endif } /* * purge a line of input data */ purgeline(port) char port[]; { while(instat(port)) /* eat characters */ inchar(port); } /* * send a break */ send_break(port) char port[]; { #ifdef VIDIS if (use_6850) { port[0] = 0x60; /* set line */ wait(300); /* delay 300 Ms */ initport(port,0); /* re-initialize */ } else { port[2] |= 0x0c; /* set line */ wait(300); /* delay 300 Ms */ initport(port,0); /* re-initialize */ } #else port[0] = 0x60; /* set line */ wait(300); /* delay 300 Ms */ initport(port,0); /* re-initialize */ #endif } /* * delay 'n' Ms */ wait(delay) int delay; { long int del_count; if (delay != 0) /* Only if we have to */ { del_count = (delay / 1000.) * DELAYVALUE * 3; /* Calculate value */ while (--del_count); /* Ordinary wait loop */ } } #ifdef INTERRUPT /* * Interrupt handler */ irqhdr() { char status; char *port; port = ttyfd; if (use_6850) { status = port[0]; if (status & 0x80) /* This port issued interrupt */ if (status & 0x01) /* Data available */ put_in_buf(port[1]); else if (status & 0x04) /* DCD lost interrupt */ status = port[1]; /* Dummy read */ } #ifdef VIDIS else /* 6551 */ { status = port[1]; if (status & 0x80) /* This port issued interrupt */ if (status & 0x08) /* Data available */ put_in_buf(port[0]); else if (status & 0x20) /* DCD lost interrupt */ status = port[0]; /* Dummy read */ } #endif } /* * Stuff character in data buffer * Use handshake if buffer becomes full */ put_in_buf(ch) char ch; { int numchar; *inptr++ = ch; /* Insert character */ if (inptr >= &input_buffer[INBUFSIZE]) /* Adjust pointer */ inptr = &input_buffer; numchar = calc_bsize(inptr,outptr); /* Calculate number of characters */ if (!stopped && (numchar > FULL_LIMIT)) /* Take care of pending overflow */ { stopped = TRUE; /* Flag stop character sent */ outchar(dstop,ttyfd); /* Stop remote */ } } /* * Get character from data buffer * Take care of handshake */ char get_in_buf() { int numchar; char ch; ch = *outptr++; /* Get character from buffer */ if (outptr >= &input_buffer[INBUFSIZE]) /* Adjust buffer pointer */ outptr = &input_buffer; numchar = calc_bsize(inptr,outptr); /* Calculate number of characters */ if (stopped && (numchar < EMPTY_LIMIT)) /* Take care of underflow */ { outchar(dstart,ttyfd); /* Re-start remote */ stopped = FALSE; /* Flag stop character sent */ } return ch; } /* * Calculate number of characters in buffer */ calc_bsize(i,o) char *i,*o; { if (i < o) return ((i + INBUFSIZE) - o); else return (i - o); } #endif /* * Cleanup interrupt vectors */ cleanup() { #ifdef INTERRUPT char *port; int *p; port = old_port; if (!port_err) /* Only restore if no error */ { if (use_6850) { port[0] = RESET_6850; /* reset the acia */ #ifdef VIDIS port[0] = (config << 2) | 0x01; #else p = v_speed_6850; /* point to valid speed table */ while (*p++ != speed) /* get valid speed */ p++; port[0] = (config << 2) | *p; /* set hardware */ #endif if (save_vector != -1) *dmem(IRQVEC_6850) = save_vector; } #ifdef VIDIS else { port[2] |= 0x02; /* Turn off interrupt enable */ if (save_vector != -1) *dmem(IRQVEC_6551) = save_vector; } #endif *dmem(NMIVEC) = save_nmi; } #endif } <<< flkerm.c >>> /* * K e r m i t File Transfer Utility * * FLEX Kermit... Adapted from UNIX version by * * Jur van der Burg * Nettelhorst 56 * 2402 LS Alphen aan den Rijn * The Netherlands * * Telephone: (0)1720 - 34057 * * Last update: 12 September 1986 * * This program runs under almost any FLEX-09 version. * Hardware dependent things are in the files FLK.H and FLIO.C * * Compiled with INTROL C (c) V 1.5 * */ #include "FLK.H" /* * Main command table */ TABLE command_table[] = { "send", 1, "receive", 2, "connect", 3, "get", 4, "set", 5, "show", 6, "server", 7, "help", 8, "exit", 9, "quit", 10, "bye", 11, "finish", 12, "transmit", 13, "flex", 14, "statistics", 15, "take", 16, "", 0 }; /* * Start of main program */ main(argc,argv) int argc; char **argv; { char input[257], /* Command input */ *s, /* Options pointer */ do_startup, /* Start file flag */ echo; /* Echo startup file */ do_startup = TRUE; /* Use startup command file */ echo = FALSE; /* Don't echo startup file */ while (--argc > 0 && (*++argv)[0] == '-') for (s = argv[0] + 1; *s != '\0'; s++) switch(tolower(*s)) { case 'n': do_startup = FALSE; /* Don't get commands from file */ break; case 'e': echo = TRUE; /* Echo startup file */ break; default: usage(); } init_par(do_startup,echo); /* Init all parameters */ for (;;) /* Do this forever */ { do { puts(prompt); /* Prompt user */ if (gets(input,256) == NULL) /* Get response */ kerm_exit(); /* E O F */ } while (!input[0]); /* Blank command line */ kerm_command(input); /* Process command */ } } init_par(autostart,echo) char autostart, echo; { char data[257]; /* Command input */ FILE *inifp; /* Initialize these values and hope the first packet will get across OK */ mypackstart = I_MYPACKSTART; /* Start of packet character */ maxpacksiz = I_MAXPACKSIZ; /* Maximum packet size */ maxtry = I_MAXTRY; /* Times to retry a packet */ myquote = I_MYQUOTE; /* Quote character I will use */ mypad = I_MYPAD; /* Number of padding chars I need */ mypchar = I_MYPCHAR; /* Padding character I need (NULL) */ myeol = I_MYEOL; /* End-Of-Line character I need */ mytime = I_MYTIME; /* My timeout in seconds */ myblock_check_type = I_BLOCKCHECKTYPE; /* Block check type */ myrptquote = I_MYRPTQUOTE; /* Repeat count quote character */ myeightquote = I_MYEIGHTQUOTE; /* Eight bit quote character */ send_delay = I_SEND_DELAY; /* Delay before sending */ load_drive = system_fcb_drive; /* Save drive KERMIT came from */ strcpy(prompt,DEFPROMPT); /* Setup prompt */ logfile[0] = '\0'; /* No log filename yet */ logfileopen = FALSE; /* No logging done yet */ speed = 1200; /* Default line speed */ config = 5; /* 8 bits, 1 stop, no parity */ image = FALSE; /* Translation */ save_file = FALSE; /* Don't save file on abort */ escchr = ESCCHR; /* Default escape character */ fulldup = TRUE; /* Default is full duplex */ warning = TRUE; /* File conflict warning */ t_chr_sent = t_datachr_sent = t_nak_sent = 0; /* reset counters */ t_chr_rec = t_datachr_rec = t_nak_rec = 0; dstop = XOFF; /* Init handshake characters */ dstart = XON; dbgfil = ERROR; /* No debug file */ remote = FALSE; /* No remote line */ stopped = FALSE; /* Not stopped with handshake */ init_crc_table(); /* Setup table for CRC calculation */ consfd = CONSOLE; /* Setup console port address */ #ifdef VIDIS ttyfd = ADDRESS_6850; if (initport(ttyfd,1) == FALSE) /* Look for a 6850 acia */ { ttyfd = ADDRESS_6551; /* No 6850 present */ initport(ttyfd,0); /* Use default 6551 acia */ } #else ttyfd = TTYPORT; /* tty is the communications line */ initport(ttyfd,1); /* Initialize 6850 acia */ #endif puts(IDENT); /* Tell him we're on the air! */ puts(VERSION); /* With this version */ puts("\n\n"); if (autostart) /* Startup with command file */ take(TRUE,echo); } /* * Process kermit command */ kerm_command(instrng) char *instrng; { int funcpoint; char *free(); if (split(instrng, params)) /* Split command line */ { /* into seperate strings */ cflg = sflg = rflg = 0; /* Turn off all flags */ tabsleft = TABSIZE; /* Default tab setting */ aborted = FALSE; /* Not yet aborted */ timint = I_MYTIME; /* Setup timeout value */ timecount = mytime * DELAYVALUE; /* Setup timeout counter */ funcpoint = parse(params[0], command_table);/* Find routine address */ if (funcpoint == NULL) /* Ambiguous */ prterr("Ambiguous command"); else if (funcpoint == ERROR) /* Unknown */ prterr("Unknown command"); else switch(funcpoint) /* Process command */ { case 1: sendfile(); break; case 2: recfile(); break; case 3: connect(); break; case 4: getfile(); break; case 5: set(); break; case 6: show(); break; case 7: server(); break; case 8: help(); break; case 9: case 10: kerm_exit(); break; case 11: bye(); break; case 12: finish(); break; case 13: transmit(); break; case 14: do_flex(); break; case 15: statistics(); break; case 16: take(FALSE,TRUE); break; } fclose(fp); /* Close file if we're aborted */ fp = ERROR; /* Indicate no file open yet */ } while (numprm) free(params[--numprm]); /* Free command string memory */ } usage() { puts("Usage: KERMIT -n Disable startup command file\n"); puts(" -e Echo startup command file\n"); exit(); } kerm_exit() { cleanup(); /* Restore interrupt vectors if any */ exit(); } <<< flpack.c >>> #include "FLK.H" /* * s p a c k * * Send a Packet */ spack(type,num,len,data,check) char type, *data, len, num, check; { int i; /* Character loop counter */ char buffer[100]; /* Packet buffer */ int crc, chksum, ck1, ck2, ck3; /* CRC value and checksum */ register char *bufp; /* Buffer pointer */ prtdbgf("Packet transmitted: %d, Type: %c, Length: %d\n",num,type,len); if (!remote) { #ifdef SCREEN posit(20,7); printf("%d ",num); #else printf("Packet transmitted: %d\n",num); #endif } if (debug) /* Display outgoing packet */ { #ifdef SCREEN disp(0,12,CLREOL); disp(20,11,CLREOL); #endif if ((debug >= 1) && !remote) { #ifdef SCREEN posit(33,7); printf("%c",type); posit(45,7); printf("%d ",len); #else printf("Type: %c Length: %d\n",type,len); #endif } if (len != 0) { data[len] = '\0'; /* Null terminate data to print it */ if ((debug >= 1) && !remote) { #ifdef SCREEN posit(20,11); putchar('"'); puts(data); putchar('"'); #else printf("Data transmitted: \"%s\"\n",data); #endif } prtdbgf("Data transmitted: \"%s\"\n",data); } } pack_sent++; /* Count packet */ bufp = buffer; /* Set up buffer pointer */ write(ttyfd,&padchar,pad); /* Issue any padding */ init_crc(); /* Initialize CRC calculation */ *bufp++ = mypackstart; /* Packet marker */ *bufp++ = tochar(len + check + 2); /* Send the character count */ chksum = tochar(len + check + 2); /* Initialize the checksum */ calc_crc(tochar(len + check + 2)); /* Calculate CRC */ *bufp++ = tochar(num); /* Packet number */ chksum += tochar(num); /* Update checksum */ calc_crc(tochar(num)); /* Calculate CRC */ *bufp++ = type; /* Packet type */ chksum += type; /* Update checksum */ crc = calc_crc(type); /* Calculate CRC */ if (type == 'N') nak_sent++; /* Count nak */ for (i=0; i> 6) + chksum) & 077; *bufp++ = (ck1 = tochar(chksum)); /* Put it in the packet */ } else if (check == 2) /* Two character checksum */ { *bufp++ = (ck1 = tochar((chksum >> 6) & 077)); *bufp++ = (ck2 = tochar(chksum & 077)); } else if (check == 3) /* Three character CRC */ { *bufp++ = (ck1 = tochar((crc >> 12) & 017)); *bufp++ = (ck2 = tochar((crc >> 6) & 077)); *bufp++ = (ck3 = tochar(crc & 077)); } if (debug) { if (debug >= 1) #ifdef SCREEN posit(59,7); #else puts("Checksum: "); #endif prtdbgf("Checksum: "); switch(check) { case 1: prtdbg("%02x\n",unchar(ck1)); break; case 2: prtdbg("%02x%02x\n",unchar(ck1),unchar(ck2)); break; case 3: prtdbg("%02x%02x%02x\n",unchar(ck1),unchar(ck2),unchar(ck3)); } } *bufp++ = eol; /* Extra-packet line terminator */ datachr_sent += len; /* Adjust character counters */ write(ttyfd, buffer,bufp-buffer); /* Send the packet */ if (sflg) disp_size_transferred(); /* Show how far we've got */ } /* * r p a c k * * Read a Packet */ rpack(len,num,data,check) char *num, check, /* length, number, checksum type */ *len, *data; /* Packet data */ { int i, done, /* Data char number, loop exit */ numtry, /* retry counter */ cchksum, /* Our (computed) checksum */ ck1, ck2, ck3, /* Temporary save */ rchksum, /* Checksum received from host */ crc; /* CRC value */ char t, /* Current input character */ type; /* Packet type */ do /* Wait for packet header */ { if (read(ttyfd,&t,1) == TIMEOUT) return ('T'); /* Return timeout */ t &= 0177; /* Handle parity */ } while (t != mypackstart); done = FALSE; /* Got packet start, init loop */ while (!done) /* Loop to get a packet */ { init_crc(); /* Start new CRC calculation */ if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */ return ('T'); t &= 0177; /* Handle parity */ if (t == mypackstart) /* Resynch if start of packet */ continue; cchksum = t; /* Start the checksum */ calc_crc(t); /* Calculate CRC */ *len = unchar(t)-check-2; /* Character count */ if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */ return ('T'); t &= 0177; /* Handle parity */ if (t == mypackstart) /* Resynch if start of packet */ continue; cchksum += t; /* Update checksum */ calc_crc(t); /* Calculate CRC */ *num = unchar(t); /* Packet number */ if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */ return ('T'); t &= 0177; /* Handle parity */ if (t == mypackstart) /* Resynch if start of packet */ continue; cchksum += t; /* Update checksum */ crc = calc_crc(t); /* Calculate CRC */ type = t; /* Packet type */ if (type == 'N') nak_rec++; /* Count received nak */ for (i = 0; i < (*len); i++) /* The data itself, if any */ { /* Loop for character count */ if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */ return ('T'); if (!image) /* Handle parity */ t &= 0177; if (t == mypackstart) /* Resynch if start of packet */ continue; cchksum += t; /* Update checksum */ crc = calc_crc(t); /* Calculate CRC */ data[i] = t; /* Put it in the data buffer */ } data[*len] = '\0'; /* Mark the end of the data */ if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */ return ('T'); if (check == 1) rchksum = (ck1 = unchar(t)); /* Convert to numeric */ else if (check == 2) { rchksum = (ck1 = unchar(t)) << 6; if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */ return ('T'); rchksum += (ck2 = unchar(t)); } else if (check == 3) { rchksum = (ck1 = unchar(t)) << 12; if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */ return ('T'); rchksum += (ck2 = unchar(t)) << 6; if (read(ttyfd,&t,1) == TIMEOUT) /* Get character */ return ('T'); rchksum += (ck3 = unchar(t)); } if (read(ttyfd,&t,1) == TIMEOUT) /* get EOL character and toss it */ return ('T'); t &= 0177; /* Handle parity */ if (t == mypackstart) /* Resynch if start of packet */ continue; done = TRUE; /* Got checksum, done */ } datachr_rec += *len; /* Count received data characters */ pack_rec++; /* Count packet */ if (check == 3) cchksum = crc; /* Set calculated value */ else if (check == 2) cchksum &= 07777; /* Strip result to 12 bits */ if (check == 1) cchksum = (((cchksum & 0300) >> 6) + cchksum) & 077; /* Final checksum */ prtdbgf("Packet received: %d, Type: %c, Length: %d\n",*num,type,*len); if (!remote) { #ifdef SCREEN posit(20,6); printf("%d ",*num); #else printf("Packet received: %d\n",*num); #endif } if (debug) /* Display incoming packet */ { if ((debug >= 1) && !remote) { #ifdef SCREEN posit(33,6); printf("%c",type); posit(45,6); printf("%d ",*len); posit(59,6); #else printf("Type: %c Length: %d\n",type,*len); #endif } prtdbgf("Checksum: "); #ifndef SCREEN puts("Checksum: "); #endif switch(check) { case 1: prtdbg("%02x\n",ck1); break; case 2: prtdbg("%02x%02x\n",ck1,ck2); break; case 3: prtdbg("%02x%02x%02x\n",ck1,ck2,ck3); } #ifdef SCREEN disp(20,9,CLREOL); disp(0,10,CLREOL); #endif if (*len != 0) { data[*len] = '\0'; /* Null terminate data to print it */ if ((debug >= 1) && !remote) { #ifdef SCREEN posit(20,9); putchar('"'); puts(data); putchar('"'); #else printf("Data received: \"%s\"\n",data); #endif } prtdbgf("Data received: \"%s\"\n",data); } } if (rflg) disp_size_transferred(); /* Show how far we've got */ if (cchksum != rchksum) return(FALSE); /* Checksum error */ else return(type); /* All OK, return packet type */ } <<< flrecs.c >>> #include "FLK.H" char rec_filnam[50], stopflag; recfile() { if (numprm > 2) prterr("Only one filename allowed"); else { if (numprm == 2) strcpy(rec_filnam,params[1]); /* Get filename to use */ else rec_filnam[0] = '\0'; /* Use default name */ rflg++; /* Receive command */ n = 0; /* Init packet number */ set_frame(); start_remote(); /* Setup port if remote */ purgeline(ttyfd); /* Eat old input */ if (!recsw('R')) /* Receive the file(s) */ disp(0,16,"Receive failed."); disp(0,20,CURSON); beep(); finish_remote(); } } getfile() { char status, i; if (numprm <= 1) /* check for parameter */ prterr("Filespec(s) required"); else { rec_filnam[0] = '\0'; /* Use default name */ rflg = 2; /* 'GET' command */ n = 0; /* Init packet number */ set_frame(); start_remote(); /* Setup port if remote */ i = TRUE; while (get_file_spec(i)) /* Get filespec */ { i = FALSE; if (!(status = get())) /* Get the file */ break; } if (!status) disp(0,16,"Get failed."); /* Report failure */ disp(0,20,CURSON); beep(); finish_remote(); } } /* * get file from remote server */ get() { char len, num; n = 0; numtry = 0; set_default_comm(); /* Set default communication */ aborted = FALSE; while(TRUE) { len = strlen(filnam); strcpy(packet,filnam); /* Setup filename */ if (debug) { prtdbgf("Receive state: "); #ifndef SCREEN puts("Receice state: "); #endif disp_state(20,13,'R'); } purgeline(ttyfd); /* Eat old input */ spack('R',n,len,packet,1); /* Receiver init */ switch(rpack(&len,&num,recpkt,1)) { case 'S': rpar(recpkt,len); /* Get the other side's init data */ spar(packet,&len); /* Fill up packet with my init info */ spack('Y',n,len,packet,1); /* ACK with my parameters */ oldtry = numtry; /* Save old try count */ numtry = 0; /* Start a new counter */ n = (n + 1) % 64; /* Bump packet number, mod 64 */ return(recsw('F')); /* Enter File-Receive state */ case 'E': prerrpkt(recpkt); /* error return */ return(FALSE); case 'T': if (aborted) /* user abort */ return(FALSE); default: if (numtry++ >= maxtry) return (FALSE); /* max try's exceeded */ } } } /* * r e c s w * * This is the state table switcher for receiving files. */ recsw(istate) char istate; { char rinit(), rfile(), rdata(); /* Use these procedures */ init_xfer(); /* reset character counters */ if (istate != 'F') /* if not already done */ set_default_comm(); /* Set default communication */ state = istate; /* set start state 'R' or 'F' */ numtry = 0; /* Say no tries yet */ stopflag = FALSE; /* Not stopped yet */ aborted = FALSE; /* Not aborted yet */ while(TRUE) { if (debug) { prtdbgf("Receive state: "); #ifndef SCREEN puts("Receive state: "); #endif disp_state(20,13,state); } switch(state) /* Do until done */ { case 'R': /* Receive-Init */ state = rinit(); break; case 'F': /* Receive-File */ state = rfile(); break; case 'D': /* Receive-Data */ state = rdata(); break; case 'C': /* Complete state */ fin_xfer(); return(TRUE); default: /* Unknown or abort */ fin_xfer(); return(FALSE); } } } /* * r i n i t * * Receive Initialization */ char rinit() { char len, num; /* Packet length, number */ if (numtry++ >= maxtry) /* If too many tries, "abort" */ return('A'); switch(rpack(&len,&num,packet,1)) /* Get a packet */ { case 'S': /* Send-Init */ rpar(packet,len); /* Get the other side's init data */ spar(packet,&len); /* Fill packet with my init info */ spack('Y',n,len,packet,1); /* ACK with my parameters */ oldtry = numtry; /* Save old try count */ numtry = 0; /* Start a new counter */ n = (n + 1) % 64; /* Bump packet number, mod 64 */ return('F'); /* Enter File-Receive state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case 'T': /* Timeout */ if (aborted) return('A'); /* aborted by user */ case FALSE: /* Didn't get packet */ spack('N',n,0,0,1); /* Return a NAK */ return(state); /* Keep trying */ default: /* Some other packet type, "abort" */ return('A'); } } /* * r f i l e * * Receive File Header */ char rfile() { char num, len, /* Packet number, length */ *w; if (numtry++ >= maxtry) /* "abort" if too many tries */ return('A'); switch(rpack(&len,&num,packet,block_check_type)) /* Get a packet */ { case 'S': /* Send-Init, maybe our ACK lost */ if (oldtry++ >= maxtry) /* If too many tries "abort" */ return('A'); if (num == ((n == 0) ? 63 : n-1)) /* Previous packet, mod 64? */ { /* Yes, ACK it again with */ spar(packet,&len); /* our Send-Init parameters */ spack('Y',num,len,packet,1); numtry = 0; /* Reset try counter */ return(state); /* Stay in this state */ } else /* Not previous packet, "abort" */ return('A'); case 'Z': /* End-Of-File */ if (oldtry++ >= maxtry) return('A'); if (num == ((n==0) ? 63 : n-1)) /* Previous packet, mod 64? */ { /* Yes, ACK it again. */ spack('Y',num,0,0,block_check_type); numtry = 0; return(state); /* Stay in this state */ } else /* Not previous packet, "abort" */ return('A'); case 'F': /* File Header (just what we want) */ if (num != n) /* The packet number must be right */ return('A'); if (!rec_filnam[0]) /* Copy filename if not given */ strcpy(rec_filnam, packet); cvt_case(rec_filnam); /* Convert case */ transmit_chr_count = 0; /* Counter for total data size */ if(image) w = "bw"; /* open binary file */ else w = "w"; /* open text file */ while ((fp = fopen(rec_filnam,"r")) != ERROR) { /* File already there */ fclose(fp); if (warning) /* File warning on ? */ { if (!remote) { posit(0,18); printf("%sWarning: File %s already exists, creating new name", CLREOL,rec_filnam); beep(); #ifndef SCREEN puts("\n"); #endif } new_name(rec_filnam); /* Create new filename */ } else break; /* Leave it as it is */ } if ((fp = fopen(rec_filnam,w)) == ERROR)/* Try to open new file */ { error(4,"%s",rec_filnam); /* Give up if error */ return('A'); } else /* OK, give message */ { disp(0,2,"Receiving: "); disp(20,2,rec_filnam); puts(CLREOL); prtdbgf("New file name: %s\n",rec_filnam); } purgeline(ttyfd); /* Eat old input */ spack('Y',n,0,0,block_check_type); /* Acknowledge file header */ oldtry = numtry; /* Reset try counters */ numtry = 0; /* ... */ stopflag = FALSE; /* In case we're aborted */ aborted = FALSE; n = (n + 1) % 64; /* Bump packet number, mod 64 */ return('D'); /* Switch to Data state */ case 'B': /* Break transmission (EOT) */ if (num != n) /* Need right packet number here */ return ('A'); spack('Y',n,0,0,block_check_type); /* Say OK */ return('C'); /* Go to complete state */ case 'E': /* Error packet received */ prerrpkt(packet); /* Print it out and */ return('A'); /* abort */ case 'T': /* Timeout */ if (aborted) { error(0); /* send error packet */ return('A'); /* aborted by user */ } case FALSE: /* Didn't get packet */ spack('N',n,0,0,block_check_type); /* Return a NAK */ return(state); /* Keep trying */ default: /* Some other packet, "abort" */ return ('A'); } } /* * r d a t a * * Receive Data */ char rdata() { char num, len, tlen; /* Packet number, length */ if (numtry++ >= maxtry) /* "abort" if too many tries */ return('A'); switch(rpack(&len,&num,packet,block_check_type)) /* Get packet */ { case 'D': /* Got Data packet */ if (num != n) /* Right packet? */ { /* No */ if (oldtry++ >= maxtry) return('A'); /* If too many tries, abort */ if (num == ((n==0) ? 63 : n-1)) /* Else check packet number */ { /* Previous packet again? */ spack('Y',num,0,0,block_check_type); /* Yes, re-ACK it */ numtry = 0; /* Reset try counter */ return(state); /* Don't write out data! */ } else /* sorry, wrong number */ return('A'); } if (stopflag) /* Other side still sending ? */ { error(0); /* Transfer aborted */ return('A'); } /* Got data with right packet number */ if (bufemp(packet,len) == ERROR) /* Write the data to the file */ { error(3,"%d",errno); /* FLEX error */ return('A'); /* enter abort state */ } tlen = 1; /* Assume aborted */ stopflag = TRUE; if (aborted == ABORTX) /* Abort current file ? */ packet[0] = 'X'; else if (aborted == ABORTZ) /* Abort whole batch ? */ { packet[0] = 'Z'; filecount = 0; /* No more files for 'GET' */ } else { tlen = 0; /* Nothing to abort, length = 0 */ stopflag = FALSE; } spack('Y',n,tlen,packet,block_check_type); /* Acknowledge packet */ oldtry = numtry; /* Reset the try counters */ numtry = 0; /* ... */ n = (n + 1) % 64; /* Bump packet number, mod 64 */ return('D'); /* Remain in data state */ case 'F': /* Got a File Header */ case 'X': if (oldtry++ >= maxtry) return('A'); /* If too many tries, "abort" */ if (num == ((n==0) ? 63 : n-1)) /* Else check packet number */ { /* It was the previous one */ spack('Y',num,0,0,block_check_type); /* ACK it again */ numtry = 0; /* Reset try counter */ return(state); /* Stay in Data state */ } else /* Not previous packet, "abort" */ return('A'); case 'Z': /* End-Of-File */ if (num != n) /* Must have right packet number */ return('A'); spack('Y',n,0,0,block_check_type); /* OK, ACK it. */ fclose(fp); /* Close the file */ if (len == 1) /* Interrupt */ { #ifdef SCREEN disp(0,18,CLREOL); disp(0,18,"Transfer aborted."); #else puts("Transfer aborted.\n"); #endif beep(); if ((packet[0] == 'D') && !save_file) unlink(rec_filnam); /* Discard input file */ } rec_filnam[0] = '\0'; /* Use default for next transfer */ n = (n + 1) % 64; /* Bump packet number */ return('F'); /* Go back to Receive File state */ case 'E': /* Error packet received */ prerrpkt(packet); /* Print it out and */ return('A'); /* abort */ case 'T': /* Timeout */ if (aborted) { error(0); /* send error packet */ return('A'); /* aborted by user */ } case FALSE: /* Didn't get packet */ spack('N',n,0,0,block_check_type); /* Return a NAK */ return(state); /* Keep trying */ default: /* Some other packet, "abort" */ return('A'); } } <<< flsend.c >>> #include "FLK.H" sendfile() { if (numprm <= 1) /* check parameter */ prterr("Filespec(s) required"); else if (!get_file_spec(TRUE)) /* Get filespec for send */ prterr("No files selected"); else { sflg++; set_frame(); start_remote(); /* Setup port if remote */ if (!sendsw()) /* Send the file(s) */ disp(0,16,"Send failed."); /* Report failure */ disp(0,20,CURSON); beep(); finish_remote(); } } /* * s e n d s w * * Sendsw is the state table switcher for sending files. It loops until * either it finishes, or an error is encountered. The routines called * by sendsw are responsible for changing the state. * */ sendsw() { char sinit(), sfile(), sdata(), seof(), sbreak(); init_xfer(); /* Reset counters */ set_default_comm(); /* Set communication parameters */ state = 'S'; /* Send initiate is start state */ n = 0; /* Initialize message number */ numtry = 0; /* Say no tries yet */ if (remote) wait(send_delay * 1000); /* Wait before sending if remote */ purgeline(ttyfd); /* Eat old input */ while(TRUE) /* Do this as long as necessary */ { if (debug) { prtdbgf("Send state: "); #ifndef SCREEN puts("Send state: "); #endif disp_state(20,14,state); } switch(state) { case 'S': /* Send-init */ state = sinit(); break; case 'F': /* Send-file */ state = sfile(); break; case 'D': /* Send-data */ state = sdata(); break; case 'Z': /* Send-End-of-File */ state = seof(); break; case 'B': /* Send-Break */ state = sbreak(); break; case 'C': /* Complete */ fin_xfer(); return (TRUE); default: /* Unknown or abort, fail */ fin_xfer(); return (FALSE); } } } /* * s i n i t * * Send Initiate: send this host's parameters and get other side's back. */ char sinit() { char num, len; /* Packet number, length */ if (numtry++ >= maxtry) /* If too many tries, give up */ return('A'); spar(packet,&len); /* Fill up init info packet */ spack('S',n,len,packet,1); /* Send an S packet */ switch(rpack(&len,&num,recpkt,1)) /* What was the reply? */ { case 'N': /* NAK, try it again */ return(state); case 'Y': /* ACK */ if (n != num) /* If wrong ACK, stay in S state */ return(state); /* and try again */ rpar(recpkt,len); /* Get other side's init info */ numtry = 0; /* Reset try counter */ n = ( n + 1) % 64; /* Bump packet count */ return('F'); /* OK, switch state to F */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* Abort */ case 'T': /* Timeout */ if (aborted) return('A'); /* aborted by user */ case FALSE: /* Receive failure, try again */ return(state); default: /* Anything else, just "abort" */ return('A'); } } /* * s f i l e * * Send File Header. */ char sfile() { char num, len, /* Packet number, length */ fnm[50]; extern int drive; if (numtry++ >= maxtry) /* If too many tries, give up */ return('A'); aborted = FALSE; if (fp == ERROR) /* If not already open, */ { fnm[0] = drive + '0'; /* Insert drive in spec */ fnm[1] = '.'; strcpy(&fnm[2],filnam); if (image) fp = fopen(fnm,"br"); /* open the file to be sent */ else fp = fopen(fnm,"r"); /* open the file to be sent */ if (fp == ERROR) /* If bad file pointer, give up */ { error(5,"%s",fnm); /* Can't open file */ if (!get_file_spec(FALSE)) return('C'); /* No more files to do */ else return('S'); /* Try next file */ } } disp(0,2,"Sending: "); disp(20,2,fnm); puts(CLREOL); len = strlen(filnam); spack('F',n,len,filnam,block_check_type); /* Send an F packet */ switch(rpack(&len,&num,recpkt,block_check_type)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */ if (n != num) /* which is just like an ACK for */ return(state); /* this packet so fall thru to... */ case 'Y': /* ACK */ if (n != num) /* If wrong ACK, stay in F state */ return(state); numtry = 0; /* Reset try counter */ n = (n + 1) % 64; /* Bump packet count */ size = bufill(packet,TRUE); /* Get first data from file */ return('D'); /* Switch state to D */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case 'T': /* Timeout */ if (aborted) { error(0); /* send error packet */ return('A'); /* aborted by user */ } case FALSE: /* Receive failure, stay in F */ return(state); default: /* Something else, just "abort" */ return('A'); } } /* * s d a t a * * Send File Data */ char sdata() { char num, len, /* Packet number, length */ tmpc; if (numtry++ >= maxtry) /* If too many tries, give up */ return('A'); spack('D',n,(char)size,packet,block_check_type); /* Send a D packet */ switch(rpack(&len,&num,recpkt,block_check_type)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */ if (n != num) /* which is just like an ACK for */ return(state); /* this packet so fall thru to... */ case 'Y': /* ACK */ if (n != num) /* If wrong ACK, fail */ return(state); numtry = 0; /* Reset try counter */ n = (n + 1) % 64; /* Bump packet count */ if ((size = bufill(packet,FALSE)) == EOF) /* Get data from file */ return('Z'); /* If EOF set state to that */ tmpc = recpkt[0]; if (len == 1) /* Data on ack */ { if (tmpc == 'Z') /* Stop entire batch */ filecount = 0; /* No more files to send */ if ((tmpc == 'X') || (tmpc == 'Z')) aborted = tmpc - 64; /* Make binary */ } if ((aborted == ABORTX) || (aborted == ABORTZ)) { #ifdef SCREEN disp(0,18,"Transfer interrupted."); #else puts("Transfer interrupted.\n"); #endif beep(); return('Z'); /* Send abort */ } return('D'); /* Got data, stay in state D */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case 'T': /* Timeout */ if (aborted) { error(0); /* send error packet */ return('A'); /* aborted by user */ } case FALSE: /* Receive failure, stay in D */ return(state); default: /* Anything else, "abort" */ return('A'); } } /* * s e o f * * Send End-Of-File. */ char seof() { char num, len, tlen; /* Packet number, length */ if (numtry++ >= maxtry) /* If too many tries, "abort" */ return('A'); tlen = 0; /* Assume no abort */ if ((aborted == ABORTX) || (aborted == ABORTZ)) { packet[0] = 'D'; /* Discard file on abort */ tlen = 1; } spack('Z',n,tlen,packet,block_check_type); /* Send a 'Z' packet */ switch(rpack(&len,&num,recpkt,block_check_type)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */ if (n != num) /* which is just like an ACK for */ return(state); /* this packet so fall thru to... */ case 'Y': /* ACK */ if (n != num) /* If wrong ACK, hold out */ return(state); numtry = 0; /* Reset try counter */ n = (n + 1) % 64; /* and bump packet count */ fclose(fp); /* Close the input file */ fp = ERROR; /* flag no file open */ if (!get_file_spec(FALSE)) return ('B'); /* Stop if no more files */ if (aborted == ABORTZ) /* Abort the rest ? */ { while (get_file_spec(FALSE)); /* FLush directory buffer */ return ('B'); } return('F'); /* More files, switch state to F */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case 'T': /* Timeout */ if (aborted) { error(0); /* send error packet */ return('A'); /* aborted by user */ } case FALSE: /* Receive failure, stay in Z */ return(state); default: /* Something else, "abort" */ return('A'); } } /* * s b r e a k * * Send Break (EOT) */ char sbreak() { char num, len; /* Packet number, length */ if (numtry++ >= maxtry) /* If too many tries "abort" */ return('A'); spack('B',n,0,packet,block_check_type);/* Send a B packet */ switch (rpack(&len,&num,recpkt,block_check_type)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num < 0 ? 63 : num); /* unless NAK for previous packet, */ if (n != num) /* which is just like an ACK for */ return(state); /* this packet so fall thru to... */ case 'Y': /* ACK */ if (n != num) /* If wrong ACK, fail */ return(state); numtry = 0; /* Reset try counter */ n = (n + 1) % 64; /* and bump packet count */ return('C'); /* Switch state to Complete */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('A'); /* abort */ case 'T': /* Timeout */ if (aborted) { error(0); /* send error packet */ return('A'); /* aborted by user */ } case FALSE: /* Receive failure, stay in B */ return(state); default: /* Other, "abort" */ return ('A'); } } <<< flserv.c >>> #include "FLK.H" /* * s e r v e r */ server() { char num, len, i; extern char rec_filnam[]; char filename[50]; n = 0; /* initialize message number */ numtry = 0; /* say no tries yet */ set_frame(); posit(0,20); puts("Server running... Type your kermit 'BYE' or 'FINISH'\n"); puts("commands, or ctrl-X to quit the server.\n"); set_default_comm(); /* Set default communication */ start_remote(); /* Setup port if remote */ while(TRUE) { switch(rpack(&len,&num,packet,1))/* do this for as long as necessary */ { case 'S': set_frame(); n = num; rpar(packet,len); /* setup receive parameters */ spar(packet,&len); /* setup transmit parameters */ spack('Y',n,len,packet,1); oldtry = numtry; numtry = 0; rec_filnam[0] = '\0'; /* Use default name */ n = (n + 1) % 64; rflg++; /* Flag receive file */ recsw('F'); /* switch to 'F' state */ break; case 'I': set_frame(); n = num; rpar(packet,len); /* setup receive parameters */ spar(packet,&len); /* setup transmit parameters */ spack('Y',n,len,packet,1); break; case 'R': i = 0; do filename[i] = packet[i]; /* copy filename */ while((packet[i++] != '\0') && (i < len)); filename[i] = '\0'; /* Mark end of string */ numprm = 2; params[1] = &filename; /* Setup pointer to filename */ get_file_spec(TRUE); /* Parse filespec */ sflg++; /* Flag end file */ sendsw(); /* Send file */ n = 0; break; case 'G': /* 'general' command */ set_frame(); switch(packet[0]) { case 'L': /* logout */ spack('Y',num,0,0,1); /* acknowledge */ disp(0,23,CURSON); finish_remote(); kerm_exit(); case 'F': /* finish */ spack('Y',num,0,0,1); /* acknowledge */ disp(0,23,CURSON); finish_remote(); return; default: error(1); /* Not implemented */ } break; case 'T': /* timeout */ if (aborted) { disp(0,23,CURSON); finish_remote(); return; /* aborted by user */ } spack('N',n,0,0,1); /* send NAK */ break; case 'N': case 'E': break; /* Eat NAK and error packet */ case FALSE: error(2); /* Packet error */ break; default: if (aborted) { disp(0,23,CURSON); finish_remote(); return; } error(1); /* Not implemented */ } rflg = sflg = 0; set_default_comm(); /* Set default communication */ } } /* * stop remote server */ finish() { if (remote) prterr("Not allowed if REMOTE"); else { if (!do_generic('F')) { disp(0,16,"Finish failed\n"); beep(); } disp(0,23,CURSON); finish_remote(); } } /* * log out remote server and local kermit */ bye() { if (remote) prterr("Not allowed if REMOTE"); else { if (!do_generic('L')) { disp(0,16,"Bye failed\n"); disp(0,23,CURSON); beep(); } else { disp(0,23,CURSON); kerm_exit(); /* stop program if successful */ } finish_remote(); } } /* * send server function */ do_generic(function) char function; { char len, num, status; n = 0; /* initialize message number */ numtry = 0; /* say no tries yet */ set_frame(); set_default_comm(); /* setup default communication */ start_remote(); /* Setup port if remote */ packet[0] = function; /* insert GENERIC command */ while(TRUE) { num = 0; spack('G',num,1,packet,1); /* send GENERIC packet */ switch(rpack(&len,&num,recpkt,1)) { case 'Y': return(TRUE); /* valid response */ case 'E': prerrpkt(recpkt); return(FALSE); /* received an error */ case 'T': if (aborted) return(FALSE); /* aborted by user */ default: if (numtry++ > maxtry) return(FALSE); /* too many errors */ } } } <<< flset.c >>> #include "FLK.H" TABLE set_table[] = { "debug", 1, "escape", 2, "line", 3, "baud", 4, "configuration", 5, "timeout", 6, "prompt", 7, "filetype", 8, "log", 9, "duplex", 10, "handshake", 11, "block_check_type", 12, "repeat_quote", 13, "retry", 14, "packet_length", 15, "padding", 16, "padchar", 17, "start_of_packet", 18, "end_of_line", 19, "quote", 20, "eight_bit_quote", 21, "incomplete", 22, "delay", 23, "warning", 24, "", 0 }; set() { int fpoint; fpoint = parse(params[1], set_table); /* Parse 'set' command */ if (fpoint == NULL) /* Ambiguous */ prterr("Ambiguous 'set' command"); else if (fpoint == ERROR) /* Unknown */ prterr("Unknown 'set' command"); else if (!synerr(3)) /* Dispatch to command if no error */ switch(fpoint) { case 1: set_debug(); break; case 2: set_escape(); break; case 3: set_line(); break; case 4: set_baud(); break; case 5: set_config(); break; case 6: set_timeout(); break; case 7: set_prompt(); break; case 8: set_filetype(); break; case 9: set_log(); break; case 10: set_dup(); break; case 11: set_hsh(); break; case 12: set_block_check_type(); break; case 13: set_repeat_quote(); break; case 14: set_retry(); break; case 15: set_packet_length(); break; case 16: set_padding(); break; case 17: set_padchar(); break; case 18: set_start_of_packet(); break; case 19: set_end_of_line(); break; case 20: set_quote(); break; case 21: set_eight_bit_quote(); break; case 22: set_incomplete(); break; case 23: set_delay(); break; case 24: set_warning(); } } set_debug() { int temp; if ((temp = set_onoff(2)) != ERROR) { debug = temp; if (dbgfil != ERROR) /* Close file */ fclose(dbgfil); dbgfil = ERROR; } else if (tolower(*params[2]) == 'l') /* Open debug log file */ { if (numprm < 4) prterr("Filespec required"); else if (dbgfil != ERROR) prterr("Debug log file already open"); else { strcpy(dbgfname,params[3]); cvt_case(params[3]); if ((dbgfil = fopen(params[3],"w")) == ERROR) prterr("Error opening debug log file %s, error number is %d", params[3], errno); else debug = 2; } } else synerr(0); } set_escape() { escchr = *params[2]; /* Get escape character */ } set_line() { if (tolower(*params[2]) == 'r') { cleanup(); /* Reset port */ ttyfd = REMOTE; /* Remote connection */ remote = TRUE; } else { sscanf(params[2],"%x",&ttyfd); /* Get hex address */ if (initport(ttyfd,0) == FALSE) /* Try to init the port */ prterr("No such line available"); else remote = FALSE; } } set_baud() { int temp, speed_value, found, *p; extern int v_speed_6850[]; #ifdef VIDIS extern int v_speed_6551[]; #endif #ifdef VIDIS if (use_6850) p = v_speed_6850; else p = v_speed_6551; #else p = v_speed_6850; #endif temp = atoi(params[2]); /* Get speed value */ found = FALSE; while (*p) /* Do until end of table */ { if (temp == *p++) { /* Match! */ speed_value = *p; found = TRUE; break; } p++; /* Skip speed value */ } if (found) { speed = temp; /* Set new speed value */ initport(ttyfd,0); /* Init the port */ } else prterr("Invalid speed"); } set_config() { int temp; temp = atoi(params[2]); /* Get configuration */ if ((temp < 0) || (temp > 7)) /* Check range */ prterr("Improper value"); else { config = temp; /* Set new value */ initport(ttyfd,0); /* Init the port */ } } set_timeout() { int temp; temp = atoi(params[2]); /* Get timeout value */ if ((temp <= 0) || (temp > 100)) /* Check range */ prterr("Improper value"); else mytime = temp; /* Set new value */ } set_prompt() { if (strlen(params[2]) > 20) params[2][20] = '\0'; /* Truncate string */ strcpy(prompt, params[2]); /* Setup new prompt */ } set_filetype() { char temp; temp = tolower(*params[2]); if (temp == 'a') /* ASCII */ image = FALSE; else if (temp == 'b') /* BINARY */ image = TRUE; else synerr(0); } set_log() { if ((params[2][0] == '-') && logfileopen) { /* Close file */ if (fclose(lfp) == ERROR) prterr("Error closing log file %s", logfile); logfile[0] = '\0'; /* Zap filename */ logfileopen = logging = FALSE; } else { if (logfileopen) prterr("Log file already open"); else { if (strlen(params[2]) > 20) params[2][20] = '\0'; /* Truncate string */ strcpy(logfile,params[2]); cvt_case(logfile); /* Take care of case mapping */ if ((lfp = fopen(logfile, "w")) == ERROR) { prterr("Error opening log file %s", logfile); logfile[0] = '\0'; /* Zap filename */ logfileopen = logging = FALSE; } else logfileopen = TRUE; } } } set_dup() { char ch; ch = tolower(*params[2]); if (ch == 'f') fulldup = TRUE; else if (ch == 'h') fulldup = FALSE; else synerr(0); } set_hsh() { char start_tmp, stop_tmp; if (!synerr(4)) /* Be sure there are enough parameters */ { start_tmp = atoi(params[2]); /* Set data start character */ stop_tmp = atoi(params[3]); /* Set data stop character */ if ((start_tmp < 0) || (start_tmp > 127) || (stop_tmp < 0) || (stop_tmp > 127)) prterr("Illegal value"); else dstart = start_tmp; dstop = stop_tmp; } } set_quote() { char c; if (check_quote(c = *params[2])) { if ((c != myeightquote) && (c != myrptquote)) myquote = c; else prterr("Character already in use"); } } set_eight_bit_quote() { char c; if (toupper(c = *params[2]) == 'N') myeightquote = 0; /* No eight bit quoting done */ else if (check_quote(c)) { if ((c != myquote) && (c != myrptquote)) myeightquote = c; else prterr("Character already in use"); } } set_repeat_quote() { char c; if (toupper(c = *params[2]) == 'N') myrptquote = 0; /* No repeat quoting done */ else if (check_quote(c)) { if ((c != myquote) && (c != myeightquote)) myrptquote = c; else prterr("Character already in use"); } } set_packet_length() { char size; size = atoi(params[2]); if ((size < 10) || (size > 94)) prterr("Invalid length"); else maxpacksiz = size; } set_padding() { int ptmp; ptmp = atoi(params[2]); if (ptmp > 94) prterr("Value out of range"); else mypad = ptmp; } set_padchar() { int ptmp; sscanf(params[2], "%x", &ptmp); mypchar = ptmp; } set_retry() { maxtry = atoi(params[2]); } set_end_of_line() { int etmp; sscanf(params[2], "%x", &etmp); if (etmp == mypackstart) prterr("End of line must be different of start of packet"); else myeol = etmp; } set_start_of_packet() { int ptmp; sscanf(params[2], "%x", &ptmp); if (ptmp == myeol) prterr("Start of packet must be different of end of line"); else mypackstart = ptmp; } set_block_check_type() { char c; c = atoi(params[2]); if ((c >= 1) && (c <= 3)) myblock_check_type = c; else prterr("Invalid check type"); } set_incomplete() { char c; c = toupper(*params[2]); if (c == 'K') save_file = TRUE; /* Keep file */ else if (c == 'D') save_file = FALSE; /* Discard file */ else synerr(0); } set_delay() { send_delay = atoi(params[2]); } set_warning() { int temp; temp = set_onoff(2); if (temp != ERROR) warning = temp; else synerr(0); } check_quote(qchar) char qchar; { if (((qchar >= '!') && (qchar <= '>')) || ((qchar >= '{') && (qchar <= '~')) || (qchar == '`')) return (TRUE); /* Valid character */ else { prterr("Invalid character"); return (FALSE); /* Invalid character */ } } set_onoff(i) int i; { make_lower(params[i]); if (strcmp(params[i], "on") == 0) return TRUE; else if ((strcmp(params[i], "of") == 0) || (strcmp(params[i], "off") == 0)) return FALSE; else return ERROR; } <<< flshow.c >>> #include "FLK.H" TABLE show_table[] = { "all", 1, "debug", 2, "escape", 3, "line", 4, "baud", 5, "configuration", 6, "timeout", 7, "filetype", 8, "log", 9, "duplex", 10, "handshake", 11, "block_check_type", 12, "repeat_quote", 13, "retry", 14, "packet_length", 15, "padding", 16, "padchar", 17, "start_of_packet", 18, "end_of_line", 19, "quote", 20, "eight_bit_quote", 21, "incomplete", 22, "delay", 23, "warning", 24, "", 0 }; show() { int fpoint; fpoint = parse(params[1], show_table); /* Parse 'show' command */ if (fpoint == NULL) /* Ambiguous */ prterr("Ambiguous 'show' command"); else if (fpoint == ERROR) /* Unknown */ prterr("Unknown 'show' command"); else /* Dispatch to command if no error */ switch(fpoint) { case 1: show_all(); break; case 2: show_debug(); break; case 3: show_escape(); break; case 4: show_line(); break; case 5: show_baud(); break; case 6: show_config(); break; case 7: show_timeout(); break; case 8: show_filetype(); break; case 9: show_log(); break; case 10: show_dup(); break; case 11: show_hsh(); break; case 12: show_block_check_type(); break; case 13: show_repeat_quote(); break; case 14: show_retry(); break; case 15: show_packet_length(); break; case 16: show_padding(); break; case 17: show_padchar(); break; case 18: show_start_of_packet(); break; case 19: show_end_of_line(); break; case 20: show_quote(); break; case 21: show_eight_bit_quote(); break; case 22: show_incomplete(); break; case 23: show_delay(); break; case 24: show_warning(); } } /* * Show various parameters */ show_all() { show_line(); show_baud(); show_config(); show_escape(); show_filetype(); show_warning(); show_log(); show_dup(); show_debug(); show_incomplete(); show_hsh(); show_retry(); show_timeout(); show_delay(); show_start_of_packet(); show_end_of_line(); show_quote(); show_eight_bit_quote(); show_repeat_quote(); show_packet_length(); show_padding(); show_padchar(); show_block_check_type(); } show_debug() { puts("Debug:\t\t\t\t"); if (debug != 2) show_onoff(debug); else printf("File: %s\n",dbgfname); } show_dup() { puts("Duplex:\t\t\t\t"); if (fulldup) puts("Full\n"); else puts("Half\n"); } show_escape() { printf("Escape character:\t\t%c\n", escchr); } show_line() { puts("Line:\t\t\t\t"); if (remote) puts("Remote\n"); else printf("%x\n", ttyfd); } show_baud() { printf("Baudrate:\t\t\t%d baud\n", speed); } show_config() { static int *conftab[] = { "7 bits, even parity, 2 stop bits", "7 bits, odd parity, 2 stop bits", "7 bits, even parity, 1 stop bit", "7 bits, odd parity, 1 stop bit", "8 bits, no parity, 2 stop bits", "8 bits, no parity, 1 stop bit", "8 bits, even parity, 1 stop bit", "8 bits, odd parity, 1 stop bit" }; printf("Configuration:\t\t\t%s\n", conftab[config]); } show_timeout() { printf("Timeout:\t\t\t%d seconds\n", mytime); } show_filetype() { puts("Filetype:\t\t\t", image); if (image) puts("Binary\n"); else puts("Ascii\n"); } show_log() { puts("Log file:\t\t\t"); if (logfile[0]) printf("%s\n", logfile); else puts("None\n"); } show_hsh() { printf("Handshake start:\t\t%d (dec)\n", dstart); printf("Handshake stop: \t\t%d (dec)\n", dstop); } show_quote() { printf("Quote character:\t\t%c\n", myquote); } show_repeat_quote() { puts("Repeat quote character:\t\t"); if (myrptquote == 0) puts("None\n"); else printf("%c\n",myrptquote); } show_eight_bit_quote() { puts("Eight-bit quote character:\t"); if (myeightquote == 0) puts("None\n"); else printf("%c\n",myeightquote); } show_start_of_packet() { printf("Start of packet:\t\t%02.2x (hex)\n", mypackstart); } show_retry() { printf("Maximum retry's:\t\t%d (dec)\n", maxtry); } show_packet_length() { printf("Packet length:\t\t\t%d (dec)\n", maxpacksiz); } show_end_of_line() { printf("End of line character:\t\t%02.2x (hex)\n", myeol); } show_padding() { printf("Padding count:\t\t\t%d (dec)\n", mypad); } show_padchar() { printf("Padding character:\t\t%02.2x (hex)\n", mypchar); } show_block_check_type() { puts("Blockcheck type:\t\t"); switch (myblock_check_type) { case 1: puts("One character checksum\n"); break; case 2: puts("Two character checksum\n"); break; case 3: puts("Three character CRC-CCITT\n"); break; } } show_incomplete() { puts("Incomplete file disposition:\t"); if (save_file) puts("Keep\n"); else puts("Discard\n"); } show_delay() { printf("Delay before sending:\t\t%d seconds\n",send_delay); } show_warning() { puts("File conflict warning:\t\t"); show_onoff(warning); } show_onoff(flag) int flag; { if (flag) puts("On\n"); else puts("Off\n"); } <<< flutil.c >>> #include "FLK.H" /* * split command line into seperate strings */ split(cmd_str, cmds) char *cmd_str[], *cmds[]; { char *malloc(); char *p, *q, result[128]; numprm = 0; /* no parameters yet */ p = cmd_str; /* setup pointer to input string */ while (*p) /* do till end of string */ { if (numprm == MAXPRM) /* no more space */ { prterr("Too many command parameters"); return(FALSE); } while (isspace(*p)) /* strip leading white space */ p++; sscanf(p, "%s", result); /* get part of input string */ if ((q = malloc(strlen(result) + 1)) == NULL) /* allocate string space */ { prterr("Fatal error allocating memory"); kerm_exit(); } strcpy(q, result); /* copy part to allocated memory */ cmds[numprm++] = q; /* save pointer to string */ 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) *p++ = toupper(*p); } /* * m a k e _ l o w e r * * Convert string to lower case */ make_lower(p) char *p; { while (*p) *p++ = tolower(*p); } prterr(fmt, a1, a2, a3, a4, a5) char *fmt; { printf(fmt,a1,a2,a3,a4,a5); printf("\n"); beep(); } /* * e r r o r * * Print error message. * * send an error packet with the message. */ error(number,fmt, a1, a2, a3, a4, a5) int number; char *fmt; { char msg1[80], msg2[80]; char len; static char *errmsg[] = { "Aborted by user", "Unimplemented server command", "Packet error", "FLEX error writing data, error number is ", "Cannot create file ", "Cannot open file " }; strcpy(msg1,prompt); /* Start with prompt */ strcat(msg1,": "); strcat(msg1,errmsg[number]); /* Append error string */ if (number > 2) { sprintf(msg2,fmt,a1,a2,a3,a4,a5); /* Make it a string */ strcat(msg1,msg2); /* Form one string */ } len = strlen(msg1); spack('E',n,len,msg1,block_check_type); /* Send the error packet */ #ifdef SCREEN disp(0,18,CLREOL); disp(0,18,"Error:"); disp(20,18,msg1); #else printf("Error: %s\n",msg1); #endif beep(); } /* * p r e r r p k t * * Print contents of error packet received from remote host. */ prerrpkt(msg) char *msg; { disp(0,18,"Kermit aborting with following error from remote host:"); disp(0,19,msg); beep(); } /* * send ASCII file to remote without protocol. * handshake is used. */ transmit() { FILE *xmitfp; char xmitfilename[20]; int c; if (numprm <= 1) /* check for parameters */ prterr("Filespec required"); else { strcpy(xmitfilename, params[1]); cvt_case(xmitfilename); /* take care of filename mapping */ if ((xmitfp = fopen(xmitfilename, "r")) == ERROR) prterr("Error opening %s", xmitfilename); else { while ((c = getc(xmitfp)) != EOF)/* get character from file */ { if (debug) { outchar(c, consfd); /* send to console as well */ if (c == LF) outchar(CR, consfd); } if (instat(ttyfd)) /* Check if character received */ if (inchar(ttyfd) == dstop) /* Stop character ? */ do /* Yes */ while (!instat(ttyfd)) /* Wait for next character */ if (aborted) /* Check user abort */ { puts("\n"); return; /* User abort */ } while (inchar(ttyfd) != dstart); /* Wait for start char */ if (aborted) /* Check user abort */ { puts("\n"); return; /* User abort */ } if (c == LF) /* Convert LF to CR */ c = CR; outchar(c, ttyfd); /* Send to output port */ } fclose(xmitfp); } } } /* * Read KERMIT commands from file */ take(startup,echo) char startup, echo; { FILE *tfp; char data[257], /* Command input */ fname[50]; if (startup) strcpy(fname, INITFILE); /* Use default name at startup */ else { if (numprm <= 1) /* Filename must be given */ { prterr("Filespec required"); return; } else strcpy(fname, params[1]); } cvt_case(fname); /* Take care of filename mapping */ if ((tfp = fopen(fname,"r")) != ERROR) /* Look for command file */ { /* Found file, read commands */ while (fgets(data,256,tfp)) { if (echo) { puts(prompt); /* Echo prompt */ puts(data); /* Echo command */ } if (data[0] != '\n') /* Not a blank line */ kerm_command(data); /* Do command */ } fclose(tfp); } else if (!startup) prterr("Error opening %s as input",fname); } /* * call FLEX to perform external command */ do_flex() { char *cp1, *cp2; int i; if (numprm <= 1) /* no command given */ { printf("Enter FLEX command: "); call(inbuff); /* use FLEX */ } else { cp1 = *flinepointer = flinebuffer; for(i = 1; i < numprm; i++) { /* copy command parameters to FLEX command buffer */ cp2 = params[i]; while (*cp2) /* copy string */ *cp1++ = *cp2++; *cp1++ = ' '; /* parameter seperator */ } *--cp1 = '\r'; /* required by flex */ } call(docmd); /* call FLEX */ puts("\n"); } /* * 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, datachr_sent); printf(s3, nak_sent); printf(s4, pack_sent); printf(s5, chr_rec); printf(s6, datachr_rec); printf(s7, nak_rec); printf(s8, pack_rec); #ifdef CLOCK printf("Effective data rate:\t\t%d baud\n", data_rate); #endif printf("\nTotals since KERMIT was started:\n\n"); printf(s1, t_chr_sent); printf(s2, t_datachr_sent); printf(s3, t_nak_sent); printf(s4, t_pack_sent); printf(s5, t_chr_rec); printf(s6, t_datachr_rec); printf(s7, t_nak_rec); printf(s8, t_pack_rec); #ifdef CLOCK printf("Mean effective data rate:\t%d baud\n", t_data_rate); #endif } #define POLYIT 0x8408 /* Polynomial for CRC-CCITT */ #define POLY16 0xa001 /* Polynomial for CRC-16 (not used here) */ 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 */ } } init_crc() { crc_value = 0; /* Initial value is zero */ } calc_crc(value) char value; { crc_value = crc[value ^ (crc_value & 0xff)] ^ ((crc_value >> 8) & 0xff); return crc_value; /* Return accumulated value so far */ } /* * Convert string case if mapping is off */ cvt_case(p) char *p; { if (mapup == 0x60) /* refer to flag in FLEX memory */ make_upper(p); } beep() { if (!remote) _putchr(BELL); } disp(x,y,string) int x,y; char *string; { if (!remote) { posit(x,y); #ifndef SCREEN puts("\n"); #endif puts(string); } } posit(x,y) int x,y; { #ifdef SCREEN if (!remote) { _putchr(ESC); _putchr(POSCUR); _putchr(y + CHROFS); _putchr(x + CHROFS); } #endif } set_frame() { #ifdef SCREEN if (!remote) { puts(CLRSCR); /* Clear screen */ puts(CURSOFF); /* Disable cursor */ puts(INVBEG); /* Start inverse screen */ puts(" KERMIT version "); puts(VERSION); puts(" "); puts(INVEND); /* End inverse screen */ if (sflg || rflg) { disp(0,4,"Transferred:"); if (image && sflg) 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(0,14,"Send state:"); disp(27,6,"Type:"); disp(27,7,"Type:"); disp(37,6,"Length:"); disp(37,7,"Length:"); disp(49,6,"Checksum:"); disp(49,7,"Checksum:"); } } #endif } disp_state(x,y,state) int x,y; char state; { static char sa[] = "Abort "; static char sb[] = "Break "; static char sc[] = "Complete "; static char sd[] = "Data "; static char sf[] = "Filename "; static char sr[] = "Receive init"; static char ss[] = "Send init "; static char st[] = "Timeout "; static char sz[] = "End of file "; static char un[] = "Unknown "; static char dsc[] = "%s\n"; 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 '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) printf(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); } new_name(s) char *s; { s += strlen(s) - 1; /* Point to last character */ if (isdigit(*s)) { /* Already a digit */ if (*s == '9') /* Test for wrap */ *s = '0'; else (*s)++; /* Form new number */ } else /* It was no digit, make one */ if (*--s == '.') /* Only one char in extension */ { s++; *++s = '0'; /* Append zero */ *++s = '\0'; /* Mark end of string */ } else *++s = '0'; /* More than one chr in extension */ } synerr(threshold) int threshold; { if ((threshold != 0) && (numprm >= threshold)) return FALSE; prterr("Syntax error"); return TRUE; } <<>> /* * KERMIT09 - flex version header file */ #include "stdio.h" #define VERSION "V 3.1" #define IDENT "KERMIT FLEX 6809 version " #define DEFPROMPT "Kermit-09>" #define INITFILE "KERMIT.INI" #define HELPFILE "KERMIT.HLP" /* * The VIDIS system normally only has a 6551 type acia available, * and optionally an 6850 acia. * At startup the program looks for an 6850 at address ADDRESS_6850. * If it's there, that one will be used initially. If not, * the 6551 acia at address ADDRESS_6551 will be used. * When issueing an SET LINE command, the program automatically * determines the acia type (6850 or 6551). * The speed setting depends on the acia. In case of a 6551, all * the values of the 6551 can be used. In case of a 6850, 1200 baud * will be selected by a clock divider of 16, and 300 baud by * a divider of 64. */ #ifdef VIDIS #define CLOCK /* Real time clock available (MC 146818) */ #endif /* * The clock will be used for determination of the effective data rate */ #ifdef VIDIS #define CLOCKSPEED 1.33333333 /* Clock speed in MHz */ #else #define CLOCKSPEED 1 /* Clock speed in MHz */ #endif #define DELAYVALUE (4300 * CLOCKSPEED) /* Count for 1 second delay */ /* Symbol Definitions */ #define SOH 1 /* Start of header */ #define BELL 7 /* ASCII Bell */ #define BS 8 /* ASCII Backspace */ #define TAB 9 /* ASCII Tab */ #define LF 10 /* ASCII Linefeed */ #define CR 13 /* ASCII Carriage Return */ #define ESC 27 /* ASCII Escape */ #define SP 32 /* ASCII space */ #define DEL 127 /* Delete (rubout) */ #define XON 17 /* Start output */ #define XOFF 19 /* Stop output */ #define ESCCHR '^' /* Default escape char for CONNECT */ #define TOGDBG 'D' - 64 /* Toggle debug on/off */ #define ABORTX 'X' - 64 /* Ctrl-X to abort transfer */ #define ABORTZ 'Z' - 64 /* Ctrl-Z to abort transfer */ #define TABSIZE 8 /* Tabstop every eight places */ #define I_MYPACKSTART SOH /* Start of packet character */ #define I_MAXPACKSIZ 94 /* Maximum packet size */ #define I_MYPACKSIZE 80 /* Default value if no 'S' packet */ #define I_MAXTRY 10 /* Times to retry a packet */ #define I_MYQUOTE '#' /* Quote character I will use */ #define I_MYPAD 0 /* Number of padding char's I need */ #define I_MYPCHAR 0 /* Padding character I need (NULL) */ #define I_MYEOL '\r' /* End-Of-Line character I need */ #define I_MYTIME 5 /* My timeout in seconds */ #define I_MYRPTQUOTE '~' /* Repeat quote character */ #define I_MYEIGHTQUOTE '&' /* Eight_bit quote character */ #define I_BLOCKCHECKTYPE 1 /* Initial checksum type */ #define I_SEND_DELAY 5 /* Delay time before sending */ #define MAXPRM 20 /* Max. number of command line parameters */ #define LOGBUFSIZE 5000 /* Size of log buffer */ #define WAITVAL 800 * CLOCKSPEED /* Wait counter in connect */ #define TIMEOUT 1 /* Internal codes */ #define REMOTE -1 #ifdef VIDIS #define CONSOLE 0 /* Dummy for console */ #define ADDRESS_6850 0xec24 /* Default modem acia address */ #define ADDRESS_6551 0xec00 /* VIDIS modem acia address */ #define INIT_6850 0x15 /* Port init 8 bits 1 stop clk/16 */ #define RESET_6850 0x03 #define RESET_6551 0x00 #define INITCMND_6551 0x0b /* Init for command register of 6551 acia */ #define INITCTRL_6551 0x10 /* Init for control register */ #define IRQVEC_6850 0xe810 #define IRQVEC_6551 0xe816 #define NMIVEC 0xe80c #else #define CONSOLE 0xe004 /* Console acia address */ #define TTYPORT 0xe000 /* Modem acia address */ #define INIT_6850 0x15 /* Port init 8 bits 1 stop clk/16 */ #define RESET_6850 0x03 #define IRQVEC_6850 0xdfc8 #define NMIVEC 0xdfca #endif #ifdef SCREEN #define POSCUR 'A' /* Cursor positioning character */ #define CHROFS 1 /* Character offset */ #define CLRSCR "\033D\f" /* Clear screen string */ #define INVBEG "\033U\033K" /* Start underline */ #define INVEND "\033U\033K" /* End underline */ #define CLREOL "\025" /* Clear till end of line */ #define CURSOFF "\033B" /* Cursor off */ #define CURSON "\033C" /* Cursor on */ #else #define CURSON "" /* Dummy's if no screen */ #define CURSOFF "" #define CLREOL "" #endif /* Macro Definitions */ /* * tochar: converts a control character to a printable one by adding a space. * * unchar: undoes tochar. * * ctl: converts between control characters and printable characters by * toggling the control bit (ie. ^A becomes A and A becomes ^A). */ #define tochar(ch) ((ch) + ' ') #define unchar(ch) ((ch) - ' ') #define ctl(ch) ((ch) ^ 64 ) #define callind(p1) (*(char (*)())*((int *)(&p1)))() #define call(p1) (*(char (*)())p1)() #define dmem(adr) ((int *)(adr)) #define mem(adr) ((char *)(adr)) /* * FLEX constants */ #define mapup (*mem(0xcc49)) /* place to find filename mapping flag */ #define inchne(p1) ((*(int (*)())*((int *)(0xd3e5)))(p1) >> 8) /* input char without echo */ #define workdrive (*mem(0xcc0c)) /* Work drive number */ #define system_fcb_drive (*mem(0xc843)) /* Drive KERMIT came from */ #define flinebuffer ((char *)0xc080) /* Line input buffer */ #define flinepointer ((unsigned *)0xcc14) /* Line buffer pointer */ #define inbuff 0xcd1b /* Get input buffer routine */ #define docmd 0xcd4b /* Call flex routine */ /* Global Variables */ /* Structure used by command parser */ typedef struct table_point { char *string; /* Command name */ int funcadr; /* Function address */ } TABLE; #ifdef CLOCK #define RTCADR 0xee20 /* Address of MC 146818 */ long int read_clock(), start_time, end_time; #endif int send_delay, /* Start sending delay time */ ttyfd, /* I/O port address */ consfd, /* Console port address */ wtcnt, /* stop time counter */ speed, /* line speed */ tabsleft, /* Tab counter */ file_size, /* Size of current file in blocks */ size, /* Size of present data */ nak_sent, /* nak's sent */ pack_sent, /* packets sent */ nak_rec, /* nak's received */ pack_rec, /* packets received */ data_rate, /* effective data rate */ t_nak_sent, /* total naks sent */ t_pack_sent, /* total packets sent */ t_nak_rec, /* total nak's received */ t_pack_rec, /* total packets received */ t_data_rate; /* total effective data rate */ long int chr_sent, /* characters sent */ datachr_sent, /* data characters sent */ chr_rec, /* characters received */ datachr_rec, /* data characters received */ t_chr_sent, /* total characters sent */ t_datachr_sent, /* total data characters sent */ t_chr_rec, /* total characters received */ t_datachr_rec, /* total data characters received */ timecount, /* Timeout counter */ transmit_chr_count; /* Character count for data size calculation */ char state, /* Present state of the automaton */ padchar, /* Padding character to send */ eol, /* End-Of-Line character to send */ escchr, /* Connect command escape character */ quote, /* Quote character in incoming data */ block_check_type, /* Checksum type */ eight_quote, /* eight_bit quote character */ repeat_quote, /* repeat quote character */ timint, /* Timeout for foreign host on sends */ spsiz, /* Maximum send packet size */ pad, /* How much padding to send */ n, /* Packet number */ numtry, /* Times this packet retried */ oldtry, /* Times previous packet retried */ image, /* TRUE means 8-bit mode */ warning, /* File conflict warning flag */ debug, /* indicates debugging output done (0=none) */ fulldup, /* TRUE means full duples in connect */ logfileopen, /* TRUE means log file open */ logging, /* TRUE means loggin active */ dstop, /* stop character for remote */ dstart, /* start character for remote */ stopped, /* TRUE if dstop sent */ filecount, /* Number of files left to send */ filenum, /* current filenumber */ config, /* initialize value */ numprm, /* number of command parameters */ aborted, /* TRUE means we're aborted */ save_file, /* keep/discard file on abort */ sflg, /* send active flag */ rflg, /* receive active flag */ cflg, /* connect active flag */ *filnam, /* Current file name */ use_6850, /* 6850 acia in use */ remote, /* Remote line in use */ *params[MAXPRM], /* parameter list */ prompt[21], /* prompt string */ logfile[21], /* filename for logfile */ recpkt[I_MAXPACKSIZ+5], /* Receive packet buffer */ packet[I_MAXPACKSIZ+5], /* Packet buffer */ logbuf[LOGBUFSIZE], /* buffer for log */ *plog, /* pointer for logbuffer */ dbgfname[50], /* Filename for debug file */ load_drive, /* Drive KERMIT came from */ mypackstart, /* Start of packet character */ maxpacksiz, /* Maximum packet size */ maxtry, /* Times to retry a packet */ myquote, /* Quote character I will use */ mypad, /* Number of padding characters I will need */ mypchar, /* Padding character I need (NULL) */ myeol, /* End-Of-Line character I need */ mytime, /* Seconds after which I should be timed out */ myrptquote, /* Repeat quote character */ myeightquote, /* Eight_bit quote character */ myblock_check_type; /* My checksum type */ FILE *fp, /* File pointer for current disk file */ *lfp, /* File pointer for log file */ *dbgfil; /* File pointer for debug file output */ #ifdef INTERRUPT #define INBUFSIZE 500 #define FULL_LIMIT (INBUFSIZE - 250) #define EMPTY_LIMIT 10 int irqhdr(), irqprp(), nmihdr(), save_vector, save_nmi; char input_buffer[INBUFSIZE], *inptr, *outptr; #endif