/* * astutl.c Packet handling and misc. routines for ATARI ST kermit */ #include #include #include "astinc.h" #include "astobj.h" extern *msg_string(); /* * KERMIT utilities. */ /* * s p a c k * * Send a Packet */ spack(type,num,len,data) char type, *data; int num, len; { int i; /* Character loop counter */ char chksum, buffer[100]; /* Checksum, packet buffer */ register char *bufp; /* Buffer pointer */ if (ibmmode) wait_handshake(); /* if ibm mode wait for handshake */ if(type != 'Y' && type != 'N') flushinput(); /* dump any leftovers */ len=len & 0x7f; /* Make sure len is not > 127 */ if (len > MAXPACKSIZ ) /* Make sure not larger than buffer */ len = MAXPACKSIZ-4; /* IF so limit it */ msgdeb(MSGTLNPS,type,len,num); /* Display outgoing packet */ if (data != NIL) data[len] = '\0'; /* Null-terminate data to print it */ if (data != NIL) msgdeb(MSGDATPS,data); bufp = buffer; /* Set up buffer pointer */ if (padding) /* Do padding */ for (i=1; i<=spad; i++) Cauxout(spadc); if (debug && (debug > 1)) msgdeb(MSGCHPAD,spad,spadc); *bufp++ = spcks; /* Packet marker, usally SOH */ *bufp++ = tochar(len+3); /* Send the character count */ chksum = tochar(len+3); /* Initialize the checksum */ *bufp++ = tochar(num); /* Packet number */ chksum += tochar(num); /* Update checksum */ *bufp++ = type; /* Packet type */ chksum += type; /* Update checksum */ for (i=0; i> 6)+chksum)&077; /* Compute final checksum */ *bufp++ = tochar(chksum); /* Put it in the packet */ *bufp++ = seol; /* Extra-packet line terminator */ *bufp = '\0'; auxsend(buffer); /* Send the packet */ return(TRUE); } /* * r p a c k * * Read a Packet */ char rpack(len,num,data) int *len, *num; /* Packet length, number */ char *data; /* Packet data */ { int i,j, eolwc, done; /* Data character number, loop exit */ int read_abort; /* 0 = timeout, 'A' = abort requested */ int abort; /* restart current packet */ char t, /* Current input character */ type, /* Packet type */ cchksum, /* Our (computed) checksum */ rchksum; /* Checksum received from other host */ start_timer(&startpckt); if (testat(&read_abort)) return(read_abort); do { if (readtimed(&t,&read_abort)) return(read_abort); } while ((t&127) != rpcks); /* Wait for packet header */ done = FALSE; /* Got SOH, init loop */ while (!done) /* Loop to get a packet */ { if(readtimed(&t,&read_abort)) return(read_abort); /* read character, or timeout */ /* if (!image) I guess, that's nonsense! */ t &= 0177; /* Handle parity */ if (t == rpcks) continue; /* Resynchronize if SOH */ cchksum = t; /* Start the checksum */ *len = unchar(t)-3; /* Character count */ if(readtimed(&t, &read_abort)) return(read_abort); /* read character, or timeout */ /* if (!image) nonsense ? */ t &= 0177; /* Handle parity */ if (t == rpcks) continue; /* Resynchronize if SOH */ cchksum = cchksum + t; /* Update checksum */ *num = unchar(t); /* Packet number */ if(readtimed(&t, &read_abort)) return(read_abort); /* read character, or timeout */ /* if (!image) nonsense ? */ t &= 0177; /* Handle parity */ if (t == rpcks) continue; /* Resynchronize if SOH */ cchksum = cchksum + t; /* Update checksum */ type = t; /* Packet type */ abort=FALSE; for (i=0; i<*len; i++) /* The data itself, if any */ { /* Loop for character count */ if(readtimed(&t, &read_abort)) return(read_abort); /* read character, or timeout */ if (!image || ebq) t &= 0177; /* Handle parity */ if (t == rpcks) { /* Resynch if SOH */ abort=TRUE; break; } cchksum = cchksum + t; /* Update checksum */ data[i] = t; /* Put it in the data buffer */ } if(abort)continue; data[*len] = 0; /* Mark the end of the data */ if(readtimed(&t, &read_abort)) return(read_abort); /* read character, or timeout */ t &= 0177; /* do not use parity bit of checksum */ rchksum = unchar(t); /* Convert to numeric */ if (t == rpcks) continue; /* Resynchronize if SOH */ done = TRUE; /* Got checksum, done */ } if (data != NIL) data[*len] = '\0'; /* Null-terminate data to print it */ msgdeb(MSGTLNPR,type,*len,*num); if (data != NIL) msgdeb(MSGDATPR,data); /* Fold in bits 7,8 to compute */ cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* final checksum */ if (cchksum != rchksum) { msgdeb(MSGCHKERR,rchksum,cchksum); return(FALSE); } /* wait for eol to avoid lost packages */ for (eolwc=0; eolwc<100; eolwc++) if (Cauxis()) break; else evnt_timer(1,0); return(type); /* All OK, return packet type */ } /* * compute 'universal time' */ long univ_time(t) int t; { long int res; res = 60 * ((t >> 11) & 0x1FL); res = 60 * (res + ((t >> 5) & 0x3FL)); res = res + ((t & 0x1FL) << 1); return (res); } /* * start timer */ start_timer(t0) long int *t0; {*t0 = univ_time(Tgettime()); } /* * compute difference to start time */ int timer(t0) long int t0; {long int t1; t1 = univ_time(Tgettime()); if (t1 < t0) return ((int) (t1+(24*60*69)-t0)); else return ((int) max((t1 - t0),1)); } /* readtimed: read a character or timeout * timeout is relative to start of waiting for packet */ readtimed(c,flag) char *c; /* character received */ int *flag; /* flag showing reason for abort: 0=timeout,'A'=user aborted */ { while(!Cauxis()) { *flag = sleepwait(50); if (*flag == 'A') /* abort requested */ { msgdeb(MSGUSRABO); return(TRUE); }; if (state == 'W') start_timer(&startpckt); /* no timeout in server wait */ if ((*flag == 'T') || (stimint && dotimout && (timer(startpckt) >= stimint))) { msgdeb(MSGTIMOUT); timcnt += 1; *flag = 0; return(TRUE); }; }; *c = Cauxin(); if (debug && (deblevel > 1)) msgdeb(MSGCHRD,timer(startpckt),*c,(*c & 0x7F)); return(FALSE); } /* * test for abort or timeout request */ int testat(flag) int *flag; { *flag = sleepwait(0); if (*flag == 'A') /* abort requested */ { msgdeb(MSGUSRABO); return(TRUE); }; if (*flag == 'T') { msgdeb(MSGTIMOUT); timcnt += 1; *flag = FALSE; return(TRUE); }; return(FALSE); } /* * b u f i l l * * Get a bufferful of data from the file that's being sent. * Only control-quoting is done; 8-bit & repeat count prefixes are * not handled. The last sentence is obsolete! */ bufill(buffer) char buffer[]; /* Buffer */ { int i, /* Loop index */ t; /* Char read from file */ char t7; /* 7-bit version of above */ char t9; /* dup of data char t */ char b8; /* 8th bit */ i = 0; /* Init data buffer pointer */ while(TRUE) { t = getc(fp); /* Get the next character */ bytecnt++; if (feof(fp)) break; t9=t; /* Keep original pattern */ t7 = t & 0177; /* Get low order 7 bits */ b8 = t & 0200; /* Get MSB */ if (ebq && b8 && image) buffer[i++] = ebq; if ((t7 < SP) || (t7==DEL) || (t7==squote) || ((t7 == ebq) && ebq)) /* Does this char require */ { /* special handling? */ if (t=='\n' && !image) { /* Do LF->CRLF mapping if !image */ buffer[i++] = squote; buffer[i++] = ctl('\r'); } buffer[i++] = squote; /* Quote the character */ if ((t7 != squote) && ((t7 != ebq) || !ebq)) { t = ctl(t); /* and uncontrolify */ t7 = ctl(t7); }; }; if (image && !ebq) buffer[i++] = t; /* Deposit the character itself */ else buffer[i++] = t7; if (i >= spsiz-8) return(i); /* Check length */ } if (i==0) return(EOF); /* Wind up here only on EOF */ return(i); /* Handle partial buffer */ } /* * b u f e m p * * Put data from an incoming packet into a file. */ bufemp(buffer,len) char buffer[]; /* Buffer */ int len; /* Length */ { int i; /* Counter */ char t; /* Character holder */ int b8; /* 8th bit flag */ for (i=0; i 1)) msgdeb(MSGCHFLU,c,(c & 0x7F)); }; } /* * send one string to the aux port */ auxsend(str) char *str; { while (*str != '\0') {if (debug && (deblevel > 1)) msgdeb(MSGCHSND,*str,(*str & 0x7F)); Cauxout(*str++); }; } /* * wait for handshake character */ wait_handshake() /* * wait for turnchar * if received wait another 100 msecs and if no char received return. * if no char received within 1000 msecs assume we missed turnchar * otherwise return after a maximum of 4 secs */ { int waitc; /* wait counter */ char c; /* last char read */ int nochrec; /* no char received */ long int starthw; /* start time for wait */ waitc = 0; start_timer(&starthw); while (TRUE) {if (timer(starthw) >= 4) break; if ((waitc >= 10) && !Cauxis()) break; if (Cauxis()) {waitc = 0; while (Cauxis()) {c = Cauxin() & 0x7F; if (debug && (deblevel > 1)) msgdeb(MSGCHWHC,c,c); }; }; evnt_timer(100,0); if ((c == rturnchar) && !Cauxis()) {msgdeb(MSGHNDOK); return(FALSE); }; waitc++; }; msgdeb(MEGHNDFA); return(FALSE); } /* * Kermit printing routines: * */ /* * Print message on DEBUG file * First arg is object index of the KRMESSS object */ msgdeb(fmtix, a1, a2, a3, a4, a5) int fmtix; long a1,a2,a3,a4,a5; { if (debug) { fprintf(deb,msg_string(fmtix),a1,a2,a3,a4,a5); putc('\n',deb); }; } /* * Print message on LOG file * if first arg >= 0 then display an alert box too */ msglog(alertix,fmtix,a1,a2,a3,a4,a5) int fmtix, alertix; long a1, a2, a3, a4, a5; { if (translog) { fprintf(log,msg_string(fmtix),a1,a2,a3,a4,a5); putc('\n',log); }; if (alertix >= 0) displ_alert(1,alertix); } /* * Print message on DEBUG and LOG file * and perhaps display an alert box */ msgall(alertix,fmtix,a1,a2,a3,a4,a5) int fmtix, alertix; { msgdeb(fmtix,a1,a2,a3,a4,a5); msglog(alertix,fmtix,a1,a2,a3,a4,a5); } /* * p r e r r p k t * * Print contents of error packet received from remote host. */ prerrpkt(msg) char *msg; { msgall(-1,MSGERRPK,msg); displ_pckerr(msg); }