home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 019.lha / Aterm / Kermit.c < prev    next >
C/C++ Source or Header  |  1986-11-10  |  39KB  |  1,499 lines

  1. /*  K E R M I T  --  Main driver program for linking to user program */
  2.  
  3. /*
  4.  Maintenance Notes:
  5.  ..Aug86 - Module created by Jeff Lydiatt to interface Kermit to Aterm.
  6.  28Dec86 - For Receive: allow for * or directory name as file name.
  7.        If so, the host file name is used as the file name. For directory,
  8.        the the host file name will be dumped to the requested directory.
  9. */
  10. /*
  11.  Authors: Frank da Cruz, Bill Catchings, Jeff Damens;
  12.  Columbia University Center for Computing Activities, 1984-85.
  13.  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
  14.  Permission is granted to any individual or institution to use, copy, or
  15.  redistribute this software so long as it is not sold for profit, provided this
  16.  copyright notice is retained.
  17. */
  18. /*
  19.  The Kermit file transfer protocol was developed at Columbia University.
  20.  It is named after Kermit the Frog, star of the television series THE
  21.  MUPPET SHOW; the name is used by permission of Henson Associates, Inc.
  22.  "Kermit" is also Celtic for "free".
  23. */
  24. /*
  25.  Thanks to Herm Fischer of Encino, CA, for extensive contributions to
  26.  version 4, and to the following people for their contributions over the years:
  27.  
  28.    Larry Afrin, Clemson U
  29.    Charles Brooks, EDN
  30.    Bob Cattani & Chris Maio, Columbia CS Dept
  31.    Alan Crosswell, CUCCA
  32.    Carl Fongheiser, CWRU
  33.    Yekta Gursel, MIT
  34.    Jim Guyton, Rand Corp
  35.    Stan Hanks, Rice U.
  36.    Ken Harrenstein, SRI
  37.    Steve Hemminger, Tektronix
  38.    Randy Huntziger, NLM
  39.    Martin Minow, DEC
  40.    Tony Movshon, NYU
  41.    Ken Poulton, HP Labs
  42.    Frank Prindle, NADC
  43.    Stew Rubenstein, Harvard
  44.    Dan Schullman, DEC
  45.    Bradley Smith, UCLA
  46.    Dave Tweten, AMES-NAS
  47.    Walter Underwood, Ford Aerospace
  48.    Pieter Van Der Linden, Centre Mondial (Paris)
  49.    Mark Vasoll & Gregg Wonderly, Oklahoma State University
  50.    Lauren Weinstein, Vortex
  51.  
  52.  and many others.
  53. */
  54.  
  55. /* Includes */
  56.  
  57. #include <stdio.h>
  58. #include <fcntl.h>
  59. #include <ctype.h>
  60. #include <exec/types.h>
  61. #include <libraries/dos.h>
  62. #include <exec/memory.h>
  63. #include <functions.h>
  64. #include <setjmp.h>
  65. #include "lckdeb.h"
  66. #include "lckerm.h"
  67. #include "SerialIO.h"
  68. #include "ConsoleIO.h"
  69.  
  70. #define toupper(ch) _toupper(ch)    /* Use Aztec's macro          */
  71. #define tolower(ch) _tolower(ch)    /* Use Aztec's macro          */
  72. #define MAXWLD 500            /* Maximum wildcard filenames */
  73. #define ESC    27            /* Escape Character          */
  74.  
  75. /* Declarations for Send-Init Parameters */
  76.  
  77. int spsiz,                /* Biggest packet size we can send */
  78.     rpsiz,                /* Biggest we want to receive */
  79.     timint,                /* Timeout interval I use */
  80.     rtimo,                /* Timeout I want you to use */
  81.     timef,                /* Flag to override what you ask */
  82.     npad,                /* How much padding to send */
  83.     mypadn,                /* How much padding to ask for */
  84.     chklen,                 /* Length of block check */
  85.     bctr,                /* Block check type requested */
  86.     bctu,                /* Block check type used */
  87.     ebq,                /* 8th bit prefix */
  88.     ebqflg,                 /* 8th-bit quoting flag */
  89.     rpt,                /* Repeat count */
  90.     rptq,                /* Repeat prefix */
  91.     rptflg,                 /* Repeat processing flag */
  92.     capas;                /* Capabilities */
  93.  
  94. CHAR padch,                /* Padding character to send */
  95.     mypadc,                /* Padding character to ask for */
  96.     seol,                /* End-Of-Line character to send */
  97.     eol,                /* End-Of-Line character to look for */
  98.     ctlq,                /* Control prefix in incoming data */
  99.     myctlq;                /* Outbound control character prefix */
  100.  
  101. int wndmax,                /* Maximum window size for table */
  102.     wndsiz;                /* Window size I want */
  103.  
  104. /* Packet-related variables */
  105.  
  106. int pktnum = 0,             /* Current packet number */
  107.     prvpkt = -1,            /* Previous packet number */
  108.     sndtyp,                /* Type of packet just sent */
  109.     size,                /* Current size of output pkt data */
  110.     osize,                /* Previous output packet data size */
  111.     maxsize,                /* Max size for building data field */
  112.     spktl;                /* Length packet being sent */
  113.  
  114. CHAR sndpkt[MAXPACK*2],         /* Entire packet being sent */
  115.     recpkt[RBUFL+2],            /* Packet most recently received */
  116.     data[MAXPACK+4],            /* Packet data buffer */
  117.     srvcmd[MAXPACK*2],            /* Where to decode server command */
  118.     *srvptr,                /* Pointer to above */
  119.     mystch = SOH,            /* Outbound packet-start character */
  120.     stchr = SOH;            /* Incoming packet-start character */
  121.  
  122. /* File-related variables */
  123.  
  124. CHAR filnam[50];            /* Name of current file. */
  125. CHAR fildat[20];            /* File creation date */
  126.  
  127. int nfils;                /* Number of files in file group */
  128. long fsize;                /* Size of current file */
  129.  
  130. /* Communication line variables */
  131.  
  132. CHAR ttname[50];            /* Name of communication line. */
  133.  
  134. int parity,                /* Parity specified, 0,'e','o',etc */
  135.     flow = 0,                /* Flow control, 1 = xon/xoff */
  136.     speed = 300,            /* Line speed */
  137.     turn = 0,                /* Line turnaround handshake flag */
  138.     turnch = XON,            /* Line turnaround character */
  139.     duplex = 0,             /* Duplex, full by default */
  140.     escape = 034,            /* Escape character for connect */
  141.     delay = DDELAY,            /* Initial delay before sending */
  142.     cdetect = FALSE,            /* Carrier detect not required */
  143.     mdmtyp = 0;             /* Modem type (initially none)    */
  144.  
  145.  
  146. /* Statistics variables */
  147.  
  148. long filcnt,            /* Number of files in transaction */
  149.     flci,            /* Characters from line, current file */
  150.     flco,            /* Chars to line, current file    */
  151.     tlci,            /* Chars from line in transaction */
  152.     tlco,            /* Chars to line in transaction */
  153.     ffc,            /* Chars to/from current file */
  154.     tfc;            /* Chars to/from files in transaction */
  155.  
  156. /* Flags */
  157.  
  158. int deblog,                 /* Flag for debug logging */
  159.     pktlog,                 /* Flag for packet logging */
  160.     seslog,                /* Session logging */
  161.     tralog,                 /* Transaction logging */
  162.     displa,                 /* File transfer display on/off */
  163.     stdouf,                 /* Flag for output to stdout */
  164.     xflg,                 /* Flag for X instead of F packet */
  165.     hcflg,                 /* Doing Host command */
  166.     fncnv,                 /* Flag for file name conversion */
  167.     binary,                 /* Flag for binary file */
  168.     warn,                 /* Flag for file warning */
  169.     quiet,                 /* Be quiet during file transfer */
  170.     local,                 /* Flag for external tty vs stdout */
  171.     server,                 /* Flag for being a server */
  172.     cnflg,                 /* Connect after transaction */
  173.     cxseen,                 /* Flag for cancelling a file */
  174.     czseen,                 /* Flag for cancelling file group */
  175.     filatr,                 /* Flag for sending file attributes */
  176.  
  177.     nxtcas,                 /* Flag for sending next attribute */
  178.     capflg,                 /* Which capas are supported */
  179.     sldwnd,                 /* Flag for sliding window support */
  180.     window;                 /* Flag for windowing state */
  181.  
  182. /* Variables passed from command parser to protocol module */
  183.  
  184. CHAR sstate  = 0;            /* Starting state for automaton */
  185. CHAR *cmarg  = (CHAR *)"";         /* Pointer to command data */
  186. CHAR *cmarg2 = (CHAR *)"";               /* Pointer to 2nd command data */
  187. CHAR **cmlist= 0;
  188.  
  189. /* Variables and symbols local to this module */
  190.  
  191. static CHAR debfil[50];            /* Debugging log file name */
  192. static CHAR pktfil[50];            /* Packet log file name */
  193. static CHAR sesfil[50];            /* Session log file name */
  194. static CHAR trafil[50];            /* Transaction log file name */
  195. static CHAR dirname[50];        /* Dump file to "dirname" */
  196.  
  197. CHAR *strcpy(), *stpchr();
  198.  
  199. static int n,                /* General purpose int */
  200.     cflg,                /* Command-line connect cmd given */
  201.     action,                /* Action selected on command line*/
  202.     repars,                /* Reparse needed */
  203.     tlevel,
  204.     debugp = 0,             /* Debug print */
  205. /* Take command level */
  206.     cwdf = 0;                /* CWD has been done */
  207.  
  208.  
  209. /* AtermKermit Module Static Variables */
  210.  
  211. static long waitMask;
  212. static jmp_buf AbortEnv;
  213.  
  214. /*----------------------------------------------------------------------*/
  215. /*    SetWaitMask: Allow Waits for Timer, Console, or Serial Port.    */
  216. /*----------------------------------------------------------------------*/
  217.  
  218. static void SetWaitMask()
  219. {
  220.    waitMask = ( 1L << GetConsoleSigBit() )
  221.             | ( 1L << GetSerialSigBit()  )
  222.         | ( 1L << GetTimerSigBit()   );
  223. }
  224.  
  225. /* K I N I T  -- routine to initialize variable if kermit is linked to other
  226.          programs, returns action to take */
  227.  
  228. void kinit() {
  229.  
  230.     void ScreenInit();
  231.  
  232. /* Declarations for Send-Init Parameters */
  233.  
  234.     spsiz = DSPSIZ;            /* Biggest packet size we can send */
  235.     rpsiz = DRPSIZ;            /* Biggest we want to receive */
  236.     timint = DMYTIM;            /* Timeout interval I use */
  237.     rtimo = URTIME;            /* Timeout I want you to use */
  238.     timef = 0;                /* Flag to override what you ask */
  239.     npad = MYPADN;            /* How much padding to send */
  240.     mypadn = MYPADN;            /* How much padding to ask for */
  241.     chklen = 1;             /* Length of block check */
  242.     bctr = 3;                /* Block check type requested */
  243.     bctu = 1;                /* Block check type used */
  244.     ebq =  MYEBQ;            /* 8th bit prefix */
  245.     ebqflg = 0;             /* 8th-bit quoting flag */
  246.     rpt = 0;                /* Repeat count */
  247.     rptq = MYRPTQ;            /* Repeat prefix */
  248.     rptflg = 0;             /* Repeat processing flag */
  249.     capas = MYCAPA;            /* Capabilities */
  250.  
  251.     padch = MYPADC;            /* Padding character to send */
  252.     mypadc = MYPADC;            /* Padding character to ask for */
  253.     seol = MYEOL;            /* End-Of-Line character to send */
  254.     eol = MYEOL;            /* End-Of-Line character to look for */
  255.     ctlq = CTLQ;            /* Control prefix in incoming data */
  256.     myctlq = CTLQ;            /* Outbound control character prefix */
  257.     wndmax = 31;            /* Maximum window size for table */
  258.     wndsiz = 31;            /* Window size I want */
  259.  
  260. /* Flags */
  261.  
  262.     deblog = 0;             /* Flag for debug logging */
  263.     pktlog = 0;             /* Flag for packet logging */
  264.     seslog = 0;             /* Session logging */
  265.     tralog = 0;             /* Transaction logging */
  266.     displa = 1;             /* File transfer display on/off */
  267.     stdouf = 0;             /* Flag for output to stdout */
  268.     xflg   = 0;             /* Flag for X instead of F packet */
  269.     hcflg  = 0;             /* Doing Host command */
  270.     fncnv  = 1;             /* Flag for file name conversion */
  271.     binary = 1;             /* Flag for binary file */
  272.     warn   = 0;             /* Flag for file warning */
  273.     quiet  = 0;             /* Be quiet during file transfer */
  274.     local  = 1;             /* Flag for external tty vs stdout */
  275.     server = 0;             /* Flag for being a server */
  276.     cnflg  = 0;             /* Connect after transaction */
  277.     cxseen = 0;             /* Flag for cancelling a file */
  278.     czseen = 0;             /* Flag for cancelling file group */
  279.     filatr = 0;             /* Flag for sending file attributes */
  280.     nxtcas = 1;             /* Flag for sending next attribute */
  281.     capflg = 0;             /* Which capas are supported */
  282.     sldwnd = 0;             /* Flag for sliding window support */
  283.     window = 0;             /* Flag for windowing state */
  284.  
  285.     cmarg = (CHAR *)"";                         /* Initialize. */
  286.     cmarg2 = (CHAR *)"";
  287.     cmlist= 0;
  288.     action = cflg = 0;
  289.  
  290.     speed = 300;                /* set baud rate */
  291.     duplex = 1;
  292.     delay = DDELAY,               /* Initial delay before sending */
  293.     parity = '\0';               /* set parity e, m, n, s, or o */
  294.     ffc = 0;            /* screen() checks this for 1st time through */ 
  295.     fsize = 0;
  296.     *fildat = '\0';
  297.     *dirname= '\0';
  298.  
  299. #ifdef DEBUG
  300.     if ( !GetLine( "\nDebug Log? ", debfil) )
  301.        deblog = 0;
  302.     else
  303.       {
  304.     deblog = 1;
  305.     if (strcmp( debfil, "con" ) == 0)
  306.        debopn("CON:0/0/640/100/Kermit Debug Log");
  307.     else
  308.        debopn( debfil );
  309.       }
  310.     PutChar( '\n' );
  311. #endif
  312. #ifdef TLOG
  313.     if ( !GetLine( "\nLog File Name? ", trafil) )
  314.        tralog = 0;
  315.     else if ( !(tralog = zopeno( ZTFILE, trafil ) ) )
  316.        format( PutChar, "Can't Open Log File as: %s\xFF", &trafil );
  317.     PutChar( '\n' );
  318. #endif
  319.     SetWaitMask();
  320.     ScreenInit();
  321.  
  322. }
  323.  
  324. /*  D O E X I T  --  Exit from the program.  */
  325.  
  326. static void cleanup() 
  327. {
  328.     CursorXY( 1 , 18 ); /* Next Message starts Line 18 */
  329.  
  330.     if (deblog) 
  331.       {            /* Close any open logs. */
  332.     debug(F100,"Debug Log Closed","",0);
  333.     *debfil = '\0';
  334.     deblog = 0;
  335.     zclose(ZDFILE);
  336.       }
  337.     if (tralog) 
  338.       {
  339.     tlog(F100,"Transaction Log Closed","",0L);
  340.     *trafil = '\0';
  341.     tralog = 0;
  342.     zclose(ZTFILE);
  343.       }
  344. }
  345.  
  346. /*----------------------------------------------------------------------*/
  347. /*    KermitGet: external entry for Kermit Protocol get a file.    */
  348. /*----------------------------------------------------------------------*/
  349.  
  350. BOOL KermitGet( fileName )
  351. CHAR *fileName;
  352. {
  353.    BOOL status;
  354.    int len;
  355.    void kinit();
  356.    long zchki();
  357.    kinit();
  358.  
  359.    /* Set up Cmarg2: Handle a '*' or directory name in fileName */
  360.  
  361.    cmarg2 = '\0';
  362.    if ( zchki(fileName) == -2 /*Directory or volume*/)
  363.      {
  364.     strcpy(dirname, fileName);
  365.     len = strlen( dirname) -1;
  366.     if ( dirname[len] != ':' && dirname[len] != '/' )
  367.        strcat( dirname, "/" );
  368.      }
  369.    else if ( strcmp( fileName, "*" ) != 0 )
  370.      cmarg2 = fileName;
  371.    sstate = 'v';
  372.    if ( setjmp( AbortEnv) )
  373.       status = FALSE;
  374.    else
  375.      {
  376.     status = TRUE;
  377.         wart();
  378.      }
  379.    cleanup();
  380.    return status;
  381. }
  382.  
  383. /*----------------------------------------------------------------------*/
  384. /*    KermitPut: external entry for Kermit Protocol send a file.    */
  385. /*----------------------------------------------------------------------*/
  386.  
  387. BOOL KermitPut( fileName )
  388. CHAR *fileName;
  389. {
  390.    BOOL status;
  391.    void kinit();
  392.  
  393.    kinit();
  394.    sstate = 's';
  395.    nfils = 1;
  396.    cmlist = &fileName;
  397.    if ( setjmp( AbortEnv) )
  398.       status = FALSE;
  399.    else
  400.      {
  401.     status = TRUE;
  402.         wart();
  403.      }
  404.    cleanup();
  405.    return status;
  406. }
  407.  
  408.  
  409. /*  C K U U S R --  "User Interface" for PC-DOS Kermit  */
  410.  
  411. /* F. da Cruz, Columbia University Center for Computing Activities */
  412. /* Modified for use with PC-DOS by: Jan A. van der Eijk, NUS Corp., July 1985 */
  413. /*
  414.  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
  415.  Permission is granted to any individual or institution to use, copy, or
  416.  redistribute this software so long as it is not sold for profit, provided this
  417.  copyright notice is retained.
  418. */
  419.  
  420. /*  D E B O P N  --  Open a debugging file  */
  421.  
  422. debopn(s) 
  423. CHAR *s; 
  424. {
  425. #ifdef DEBUG
  426.     CHAR *tp;
  427.     zclose(ZDFILE);
  428.     deblog = zopeno(ZDFILE,s);
  429.     if (deblog > 0) 
  430.       {
  431.     strcpy(debfil,s);
  432.     ztime(&tp);
  433.     debug(F100,tp,"",0);
  434.       } 
  435.     else 
  436.     *debfil = '\0';
  437.     return(deblog);
  438. #else
  439.     return(0);
  440. #endif
  441. }
  442.  
  443. /*  I N T M S G  --  Issue message about terminal interrupts  */
  444.  
  445. intmsg(n) 
  446. long n; 
  447. {
  448.     extern CHAR *chstr();
  449.     CHAR buf[80];
  450.  
  451.     if ((!displa) || (quiet)) return;
  452.     if (n == 1) {
  453.  screen(SCR_TN,0,0L,"CTRL-F to cancel File,  CTRL-R to Resend current packet");
  454.  screen(SCR_TN,0,0L,"CTRL-B to cancel Batch, CTRL-K to abort Kermit and exit");
  455.  screen(SCR_TN,0,0L,"CTRL-A for status report: ");
  456.     }
  457.     else screen(SCR_TU,0,0L," ");
  458. }
  459.  
  460.  
  461. /*  C H K I N T  --  Check for console interrupts  */
  462.  
  463. chkint() 
  464. {
  465.     int ch, cn;
  466.  
  467.     if ((!local) || (quiet)) return(0); /* Only do this if local & not quiet */
  468.     if ( (ch = CheckKey()) == 0)
  469.        return 0;
  470.     switch (ch & 0177) 
  471.       {
  472.     case 0001:            /* CTRL-A */
  473.       break;
  474.  
  475.     case 0002:            /* CTRL-B */
  476.       screen(SCR_TN,0,0L,"^B - Cancelling Batch ");
  477.       czseen = 1;
  478.       break;
  479.  
  480.     case 0013:            /* CTRL-K */
  481.     case ESC:            /* ESC    */
  482.       screen(SCR_TN,0,0L,"^K - Aborting Kermit ");
  483.       errpkt("Tranfer aborted by otherside.");
  484.       czseen = 1; cxseen = 1;
  485.       clsif();clsof();
  486.       longjmp(AbortEnv, BAD_EXIT);
  487.       break;
  488.  
  489.     case 0006:            /* CTRL-F */
  490.       screen(SCR_TN,0,0L,"^F - Cancelling File ");
  491.       cxseen = 1;
  492.       break;
  493.  
  494.     case 0022:            /* CTRL-R */
  495.       screen(SCR_TN,0,0L,"^R - Resending ");
  496.       resend();
  497.       return(1);
  498.  
  499.     default:            /* Anything else, just ignore */
  500.       break;
  501.       }
  502.     return(1);
  503. }
  504.  
  505.  
  506. /*  D E B U G  --  Enter a record in the debugging log    */
  507.  
  508. /*
  509.  Call with a format, two strings, and a number:
  510.    f  - Format, a bit string in range 0-7.
  511.     If bit x is on, then argument number x is printed.
  512.    s1 - String, argument number 1.  If selected, printed as is.
  513.    s2 - String, argument number 2.  If selected, printed in brackets.
  514.    n  - Int, argument 3.  If selected, printed preceded by equals sign.
  515.  
  516.    f=0 is special: print s1,s2, and interpret n as a char.
  517. */
  518. #ifdef DEBUG
  519. debug(f,s1,s2,n) 
  520. int f, n; 
  521. CHAR *s1, *s2; 
  522. {
  523.     static CHAR s[200];
  524.     CHAR *sp = s;
  525.  
  526.     if (!deblog) return;        /* If no debug log, don't */
  527.     switch (f) {
  528.  
  529.     case F000:            /* 0, print both strings, */
  530.         sprintf(sp,"%s%s%c\n",s1,s2,n); /*  and interpret n as a char */
  531.         zsout(ZDFILE,s);
  532.         break;
  533.  
  534.     case F001:            /* 1, "=n" */
  535.         sprintf(sp,"=%d\n",n);
  536.         zsout(ZDFILE,s);
  537.         break;
  538.  
  539.     case F010:            /* 2, "[s2]" */
  540.         sprintf(sp,"[%s]\n",s2);
  541.         zsout(ZDFILE,"");
  542.         break;
  543.  
  544.     case F011:            /* 3, "[s2]=n" */
  545.         sprintf(sp,"[%s]=%d\n",s2,n);
  546.         zsout(ZDFILE,s);
  547.         break;
  548.  
  549.     case F100:            /* 4, "s1" */
  550.         zsoutl(ZDFILE,s1);
  551.         break;
  552.  
  553.     case F101:            /* 5, "s1=n" */
  554.         sprintf(sp,"%s=%d\n",s1,n);
  555.         zsout(ZDFILE,s);
  556.         break;
  557.  
  558.     case F110:            /* 6, "s1[s2]" */
  559.         sprintf(sp,"%s[%s]\n",s1,s2);
  560.         zsout(ZDFILE,s);
  561.         break;
  562.  
  563.     case F111:            /* 7, "s1[s2]=n" */
  564.         sprintf(sp,"%s[%s]=%d\n",s1,s2,n);
  565.         zsout(ZDFILE,s);
  566.         break;
  567.  
  568.     default:
  569.         sprintf(sp,"\n?Invalid format for debug() - %d\n",n);
  570.         zsout(ZDFILE,s);
  571.     }
  572. }
  573. #endif
  574.  
  575.  
  576. #ifdef TLOG
  577. /*  T L O G  --  Log a record in the transaction file  */
  578. /*
  579.  Call with a format and 3 arguments: two strings and a number:
  580.    f  - Format, a bit string in range 0-7, bit x is on, arg #x is printed.
  581.    s1,s2 - String arguments 1 and 2.
  582.    n  - Int, argument 3.
  583. */
  584. tlog(f,s1,s2,n) 
  585. int f; 
  586. long n; 
  587. CHAR *s1, *s2; 
  588. {
  589.     static CHAR s[200];
  590.     CHAR *sp = s; int x;
  591.  
  592.     if (!tralog) return;        /* If no transaction log, don't */
  593.     switch (f) {
  594.  
  595.     case F000:            /* 0 (special) "s1 n s2"  */
  596.         sprintf(sp,"%s %ld %s\n",s1,n,s2);
  597.         zsout(ZTFILE,s);
  598.         break;
  599.  
  600.     case F001:            /* 1, " n" */
  601.         sprintf(sp," %ld\n",n);
  602.         zsout(ZTFILE,s);
  603.         break;
  604.  
  605.     case F010:            /* 2, "[s2]" */
  606.         x = strlen(s2);
  607.         if (s2[x] == '\n') s2[x] = '\0';
  608.         sprintf(sp,"[%s]\n",s2);
  609.         zsout(ZTFILE,"");
  610.         break;
  611.  
  612.     case F011:            /* 3, "[s2] n" */
  613.         x = strlen(s2);
  614.         if (s2[x] == '\n') s2[x] = '\0';
  615.         sprintf(sp,"[%s] %ld\n",s2,n);
  616.         zsout(ZTFILE,s);
  617.         break;
  618.  
  619.     case F100:            /* 4, "s1" */
  620.         zsoutl(ZTFILE,s1);
  621.         break;
  622.  
  623.     case F101:            /* 5, "s1: n" */
  624.         sprintf(sp,"%s: %ld\n",s1,n);
  625.         zsout(ZTFILE,s);
  626.         break;
  627.  
  628.     case F110:            /* 6, "s1 s2" */
  629.         x = strlen(s2);
  630.         if (s2[x] == '\n') s2[x] = '\0';
  631.         sprintf(sp,"%s %s\n",s1,s2);
  632.         zsout(ZTFILE,s);
  633.         break;
  634.  
  635.     case F111:            /* 7, "s1 s2: n" */
  636.         x = strlen(s2);
  637.         if (s2[x] == '\n') s2[x] = '\0';
  638.         sprintf(sp,"%s %s: %ld\n",s1,s2,n);
  639.         zsout(ZTFILE,s);
  640.         break;
  641.  
  642.     default:
  643.         sprintf(sp,"\n?Invalid format for tlog() - %ld\n",n);
  644.         zsout(ZTFILE,s);
  645.     }
  646. }
  647. #endif
  648.  
  649. ermsg(msg) 
  650. CHAR *msg; 
  651. {         /* Print error message */
  652.     if (!quiet)
  653.       format( PutFormat, "\nHost: %s\n\xFF", &msg);
  654.     tlog(F110,"Error -",msg,0L);
  655. }
  656.  
  657.  
  658. /*--------ScreenInit: Format the screen for Super Kermit Window*/
  659. static void ScreenInit()
  660. {
  661.      format( PutFormat,
  662.      "\x0C          S U P E R   K E R M I T   S T A T U S\n\xFF");
  663.      
  664. }
  665.  
  666. /*--------errmsg: print an error message to screen--------------*/
  667.  
  668. static void errmsg( msg )
  669. char *msg;
  670. {
  671.    CursorXY(1, 17);
  672.    format( PutFormat, "\x9BK%s\xFF", &msg );
  673. }
  674. /*-----perror: print system error message---------*/
  675.  
  676. perror(s) 
  677. CHAR *s; 
  678. {
  679.      extern int errno;
  680.      struct p1
  681.        {
  682.      int errno;
  683.      CHAR *s;
  684.        } parm1;
  685.  
  686.      parm1.errno = errno;
  687.      parm1.s     = s;
  688.      CursorXY(1, 17);
  689.      errmsg( parm1 );
  690. }
  691.  
  692. /*  S C R E E N  --  Screen display function  */
  693.  
  694. /*  screen(f,c,n,s)
  695.       f - argument descriptor
  696.       c - a character or small integer
  697.       n - a long integer
  698.       s - a string.
  699.  Fill in this routine with the appropriate display update for the system.
  700.  This version is for full screen mode.
  701. */
  702. screen(f,c,n,s) 
  703. int f; 
  704. long n; 
  705. CHAR c; 
  706. CHAR *s; 
  707. {
  708.     static int filelen;            /* length of filename */    
  709.     static int badpkts;            /* number of bad packets */
  710.     static char msg[81];
  711.     char *msgPtr = msg;
  712.     struct table            /* x,y offsets for display */
  713.       {
  714.     int row;
  715.     int col;
  716.       };
  717.  
  718.     struct table *tablePtr;
  719.     int len;                /* Length of string */
  720.     static struct table location[] =
  721.       { { 3, 1    /* Filename    */},
  722.     { 3, 1    /* as-name    */},
  723.     { 6, 1    /* file-size    */},
  724.     {17, 1    /* x-packet data*/},
  725.     {12, 1    /* File status  */},
  726.     {17, 1    /* packet number*/},
  727.     {14, 1    /* packet type    */},
  728.     {17, 1    /* transaction complete */},
  729.     {17, 1    /* error message */},
  730.     {17, 1    /* warning message */},
  731.     {17, 1    /* arbitrary undelimited text */},
  732.     {17, 1    /* arbitrary new text, delimited at beginning */},
  733.     {17, 1    /* arbitrary text, delimited at end */},
  734.     { 6, 1    /* quantity equals (eg. "foo: 7") */},
  735.     { 4, 1    /* Print the date */},
  736.       };
  737.     struct parm
  738.       {
  739.     CHAR *s;
  740.     long  n;
  741.       } parm1;
  742.  
  743.     static char *transMode[] = { "Binary", "Ascii"};    
  744.     static char *checkMode[]=
  745.     { "8 Bit Checksum", "16 Bit Checksum", "16 Bit CRC", "Unknown" }; 
  746.     static char *onOFF[]= { "ON", "OFF" };
  747.     char *strPtr;
  748.  
  749.     if (!displa || quiet) return;    /* No update if display flag off */
  750.     len = strlen(s);            /* Length of string */
  751.  
  752.     /* Position the Cursor */
  753.     if ( (1 <= f) && (f <= SCR_DT))
  754.     tablePtr = &location[f-1];
  755.     else
  756.     tablePtr = &location[5];
  757.     CursorXY( tablePtr->col, tablePtr->row );
  758.  
  759.     switch (f) 
  760.       {
  761.  
  762.     case SCR_FN:            /* filename */
  763.        format( PutFormat, "Transferring %s \xFF", &s );
  764.        filelen = len+13;
  765.        badpkts = 0;
  766.  
  767.        /* Transfer Mode */
  768.        strPtr = transMode[ binary ? 0 : 1 ];
  769.         format( PutFormat, "\n\nTransfer Mode is... %s", &strPtr );
  770.  
  771.        /* Window Size */
  772.        format( PutFormat, "\n\n\nWindow Size ....... %d ", &wndsiz );
  773.  
  774.        /* Block Check Mode */
  775.        if ( (1 <= bctu) && (bctu <= 3) )
  776.           strPtr = checkMode[ bctu - 1 ];
  777.        else
  778.           strPtr = checkMode[ 3 ];
  779.        format( PutFormat, "\nBlock Check Mode... %s", &strPtr );
  780.  
  781.        /* Compression Mode */
  782.        strPtr = onOFF[ rptflg ? 0 : 1 ];
  783.        format( PutFormat, "\nCompression........ %s", &strPtr );
  784.  
  785.        /* 8 Bit Prefixing */
  786.        strPtr = onOFF[ ebqflg ? 0 : 1 ];
  787.        format( PutFormat, "\n8th Bit Prefixing.. %s", &strPtr ); 
  788.  
  789.        /* File Status */
  790.        format( PutFormat, "\nFile Status........ " );
  791.        format( PutFormat, "\n\x9BJ\xFF" ); /* Erase rest of Display */
  792.        return;
  793.  
  794.     case SCR_AN:            /* as-name */
  795.        CursorXY( tablePtr->col+filelen+1, tablePtr->row );
  796.        format( PutFormat, "as %s\xFF", &s );
  797.        return;
  798.  
  799.     case SCR_FS:            /* file-size */
  800.        format( PutFormat, "File Size.......... %ld\xFF", &n );
  801.        return;
  802.  
  803.     case SCR_DT:
  804.        sprintf( msg, "%2.2s/%2.2s/%2.2s -%s", &s[2], &s[4], &s[6], &s[8] ); 
  805.        format( PutFormat, "File Creation Date. %s\xFF", &msgPtr);
  806.        return;
  807.  
  808.     case SCR_XD:            /* x-packet data */
  809.        errmsg( s );
  810.        return;
  811.  
  812.     case SCR_ST:            /* File status */
  813.            switch (c)
  814.           {
  815.         case ST_OK:        /*  Transferred OK */
  816.            PutString( "\x9B20CFile Transferred OK" );
  817.            return;
  818.  
  819.         case ST_DISC:        /*  Discarded */
  820.                PutString( "\x9B20CFile was discarded" );
  821.            return;
  822.  
  823.         case ST_INT:        /*  Interrupted */
  824.            PutString( "\x9B20CTransfer is interrupted");
  825.            return;
  826.  
  827.         case ST_SKIP:        /*  Skipped */
  828.            format( PutFormat, "\x9B20CSkipping %s\xFF", &s );
  829.            return;
  830.  
  831.         default:
  832.                errmsg( "*** screen() called with bad status ***" );
  833.            return;
  834.              }
  835.  
  836.     case SCR_PN:            /* Packet number */
  837.        return;
  838.  
  839.     case SCR_PT:            /* Packet type or pseudotype */
  840.        switch ( c )
  841.          {
  842.         case 'D':
  843.            format( PutFormat, "Packet #%3d,", &pktnum );
  844.            format( PutFormat, "%7ld Bytes\xFF", &ffc  );
  845.            return;
  846.  
  847.         case 'E':
  848.            sprintf( msg, "Error: %s", s);
  849.            errmsg( msg );
  850.            return;
  851.  
  852.         case 'N':
  853.         case 'Q':
  854.            if ( ffc > 0 )
  855.              {
  856.             ++badpkts;
  857.             format( PutFormat, "\x9B25C, %3d Bad Packets\xFF",
  858.                 &badpkts );
  859.              }
  860.            else
  861.               format( PutFormat, "Negotiating for Parameters ...");             
  862.            return;
  863.  
  864.         case 'T':
  865.            errmsg( "Timeout" );
  866.            return;
  867.         
  868.         case 'Z':
  869.            /* Force File Size Update */ 
  870.                    screen( SCR_PT, 'D', 0L, "" );
  871.            return;
  872.  
  873.         default :
  874.            return;
  875.           }
  876.     case SCR_TC:            /* transaction complete */
  877.        PutChar(BEL);
  878.        return;
  879.  
  880.     case SCR_EM:            /* Error message */
  881.        sprintf( msg, "Error: %s", s);
  882.        errmsg( msg );
  883.        return;
  884.  
  885.     case SCR_WM:            /* Warning message */
  886.        sprintf( msg, "Warning: %s", s);
  887.        errmsg( msg );
  888.        return;
  889.  
  890.     case SCR_TU:            /* Undelimited text */
  891.     case SCR_TN:            /* Text delimited at beginning */
  892.     case SCR_TZ: return;        /* Text delimited at end */
  893.     case SCR_QE: parm1.s = s; parm1.n = n;
  894.              format( PutFormat, "%s = %ld\xFF", &parm1 );
  895.              return;
  896.     default:
  897.        errmsg( "*** screen() called with bad object ***" );
  898.        return;
  899.       }
  900. }
  901.  
  902. /* F. da Cruz, Columbia University Center for Computing Activities */
  903. /* Modified for use with MS-DOS by: Jan A. van der Eijk, NUS Corp., July 1985 */
  904. /* ... and for the Amiga August 86 by Jeff Lydiatt, Vancouver, BC, Canada.
  905. /*
  906.  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
  907.  Permission is granted to any individual or institution to use, copy, or
  908.  redistribute this software so long as it is not sold for profit, provided this
  909.  copyright notice is retained.
  910. */
  911.  
  912. /*
  913.   Functions (n is one of the predefined file numbers from ckcker.h):
  914.  
  915.    zopeni(n,name)   -- Opens an existing file for input.
  916.    zopeno(n,name)   -- Opens a new file for output.
  917.    zclose(n)        -- Closes a file.
  918.    zchin(n,&c)        -- Gets the next character from an input file.
  919.    zsout(n,s)        -- Write a null-terminated string to output file, buffered.
  920.    zsoutl(n,s)        -- Like zsout, but appends a line terminator.
  921.    zsoutx(n,s,x)    -- Write x characters to output file, unbuffered.
  922.    zchout(n,c)        -- Add a character to an output file, unbuffered.
  923.    zchki(name)        -- Check if named file exists and is readable, return size.
  924.    zchko(name)        -- Check if named file can be created.
  925.    znewn(name,s)    -- Make a new unique file name based on the given name.
  926.    zdelet(name)     -- Delete the named file.
  927.    zxpand(string)   -- Expands the given wildcard string into a list of files.
  928.    znext(string)    -- Returns the next file from the list in "string".
  929.    zrtol(n1,n2)     -- Convert remote filename into local form.
  930.    zltor(n1,n2)     -- Convert local filename into remote form.
  931.  */
  932. /* Declarations */
  933.  
  934. static FILE *fp[ZNFILS] = {            /* File pointers */
  935.     NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  936.  
  937.  
  938. static int fcount;            /* Number of files in wild group */
  939. static CHAR *mtchs[MAXWLD],        /* Matches found for filename */
  940.      **mtchptr;             /* Pointer to current match */
  941.  
  942. /*  C H K F N  --  Internal function to verify file number is ok  */
  943.  
  944. /*
  945.  Returns:
  946.   -1: File number n is out of range
  947.    0: n is in range, but file is not open
  948.    1: n in range and file is open
  949. */
  950. static int chkfn(n) 
  951. int n; 
  952. {
  953.     switch (n) {
  954.     case ZCTERM:
  955.     case ZSTDIO:
  956.     case ZIFILE:
  957.     case ZOFILE:
  958.     case ZDFILE:
  959.     case ZTFILE:
  960.     case ZPFILE:
  961.     case ZSFILE: break;
  962.     default:
  963.         debug(F101,"chkfn: file number out of range","",n);
  964.         fprintf(stderr,"?File number out of range - %d\n",n);
  965.         return(-1);
  966.     }
  967.     return( (fp[n] == NULL) ? 0 : 1 );
  968. }
  969.  
  970. /*  Z O P E N I  --  Open an existing file for input. */
  971. /*             Return 1 if successful */
  972.  
  973. zopeni(n,name) 
  974. register int n;
  975. CHAR *name;
  976. {
  977.  
  978.     debug(F111," zopeni",name,n);
  979.     debug(F101,"  fp","",(int) fp[n]);
  980.     if (chkfn(n) != 0) return(0);
  981.     if (n == ZSTDIO) {            /* Standard input? */
  982.     fp[ZIFILE] = stdin;
  983.     return(1);
  984.     }
  985.     fp[n] = fopen(name,"r");            /* Real file. */
  986.     debug(F111," zopeni", name, (int) fp[n]);
  987.     if (fp[n] == NULL)
  988.        format(PutChar,"Can't open: %s\n\xFF", &name);
  989.     return((fp[n] != NULL) ? 1 : 0);
  990. }
  991.  
  992. /*  Z O P E N O  --  Open a new file for output.  */
  993. /*             Return 1 if successful */
  994.  
  995. zopeno(n,name)
  996. register int n;
  997. char *name; 
  998. {
  999.     char xname[50];   
  1000.  
  1001.     debug(F111," zopeno",name,n);
  1002.     if (chkfn(n) != 0) return(0);
  1003.     if ((n == ZCTERM) || (n == ZSTDIO)) {   /* Terminal or standard output */
  1004.     fp[ZOFILE] = stdout;
  1005.     debug(F101," fp[]=stdout", "", (int) fp[n]);
  1006.     return(1);
  1007.        }
  1008.  
  1009.     *xname = '\0';
  1010.     if ( n == ZOFILE && *dirname )
  1011.        strcpy( xname, dirname );
  1012.     strcat( xname, name );
  1013.  
  1014.     fp[n] = fopen(xname,"w");            /* Real file. */
  1015.     if (fp[n] == NULL)
  1016.       perror( "zopeno" ); 
  1017.     if (n == ZDFILE) setbuf(fp[n],NULL); /* Make debugging file unbuffered */
  1018.     debug(F101, " fp[n]", "", (int) fp[n]);
  1019.     return((fp[n] != NULL) ? 1 : 0);
  1020. }
  1021.  
  1022. /*  Z C L O S E  --  Close the given file.  */
  1023. /*             Return 1 if successful */
  1024.  
  1025. zclose(n) 
  1026. register int n; 
  1027. {
  1028.     if (chkfn(n) < 1) return(0);
  1029.     if ((fp[n] != stdout) && (fp[n] != stdin)) fclose(fp[n]);
  1030.     fp[n] = NULL;
  1031.     return(1);
  1032. }
  1033.  
  1034. /*  Z C H I N  --  Get a character from the input file.  */
  1035.  
  1036. /*  Returns -1 if EOF, 0 otherwise with character returned in argument    */
  1037.  
  1038. zchin(n,c) 
  1039. int n; 
  1040. CHAR *c; 
  1041. {
  1042.     register int a;
  1043.  
  1044.     a = getc(fp[n]);
  1045.     if (a == EOF) return(-1);
  1046.     *c = a & 0377;
  1047.     return(0);
  1048. }
  1049. #ifdef DEBUG
  1050. /*  Z S O U T  --  Write a string to the given file, buffered.    */
  1051. /*  Returns -1 if ERROR, 0 otherwise  */
  1052.  
  1053. zsout(n,s) 
  1054. register int n; 
  1055. CHAR *s; 
  1056. {
  1057.     if (chkfn(n) < 1) return(-1);
  1058.     fprintf(fp[n],s);
  1059.     return(0);
  1060. }
  1061. #endif
  1062.  
  1063. /*  Z S O U T L  --  Write string to file, with line terminator, buffered  */
  1064. /*  Returns -1 if ERROR, 0 otherwise  */
  1065.  
  1066. zsoutl(n,s) 
  1067. register int n; 
  1068. CHAR *s; 
  1069. {
  1070.     if (chkfn(n) < 1) return(-1);
  1071.     fprintf(fp[n],"%s\n",s);
  1072.     return(0);
  1073. }
  1074.  
  1075. #ifdef DEBUG
  1076. /*  Z S O U T X  --  Write x characters to file, unbuffered.  */
  1077. /*  Returns -1 if ERROR, 0 otherwise  */
  1078.  
  1079. zsoutx(n,s,x) 
  1080. register int n;
  1081. int x; 
  1082. CHAR *s; 
  1083. {
  1084.     if (chkfn(n) < 1) return(-1);
  1085.     return(write(fileno(fp[n]),s,x));
  1086. }
  1087. #endif
  1088.  
  1089. /*  Z C H O U T  --  Add a character to the given file.  */
  1090. /*  Returns -1 if ERROR, 0 otherwise  */
  1091.  
  1092. zchout(n,c) 
  1093. register int n; 
  1094. CHAR c; 
  1095. {
  1096.     FILE *f;
  1097.  
  1098.     if (chkfn(n) < 1) return(-1);
  1099.     f = fp[n];
  1100.     if (n == ZSFILE)
  1101.     return(write(fileno(f),&c,1)); /* Use unbuffered for session log */
  1102.     else  putc(c, f);           /* Buffered for everything else */
  1103.     if ( ferror(f) )
  1104.     return -1;
  1105.     return 0;
  1106. }
  1107.  
  1108. /*  Z C H K I  --  Check if input file exists and is readable  */
  1109.  
  1110. /*
  1111.   Returns:
  1112.    >= 0 if the file can be read (returns the size).
  1113.      -1 if file doesn't exist or can't be accessed,
  1114.      -2 if file exists but is not readable (e.g. a directory file).
  1115.      -3 if file exists but protected against read access.
  1116. */
  1117. /*
  1118.  Directory files, special files, and symbolic links are not readable.
  1119. */
  1120. long zchki(name) 
  1121. CHAR *name; 
  1122. {
  1123.    struct FileInfoBlock *FBlock;
  1124.    long         *FLock;
  1125.    long         result;
  1126.  
  1127.    if ( (FLock = (struct FileLock *) Lock(name, ACCESS_READ)) == NULL)
  1128.       return -1;
  1129.  
  1130.    if ( (FBlock = (struct FileInfoBlock *)
  1131.      AllocMem( (long)sizeof(struct FileInfoBlock), (long)(MEMF_CHIP))) != NULL)
  1132.    if ( FBlock == NULL )
  1133.       result = -1;
  1134.    else
  1135.      {
  1136.     if ( !Examine( FLock, FBlock) )
  1137.        result = -1;
  1138.     else
  1139.       {
  1140.          if ( FBlock->fib_DirEntryType > 0 )
  1141.         result = -2; /* It's a directory */
  1142.          else
  1143.         result = FBlock->fib_Size;
  1144.       }
  1145.     FreeMem( FBlock, (long)sizeof(struct FileInfoBlock) );
  1146.       }
  1147.  
  1148.    UnLock( FLock );
  1149.    return result;
  1150.  
  1151. }
  1152.  
  1153. #ifdef DEBUG /*----Not used by Kermit----*/
  1154.  
  1155. /*  Z C H K O  --  Check if output file can be created    */
  1156.  
  1157. /*
  1158.  Returns -1 if write permission for the file would be denied, 0 otherwise.
  1159. */
  1160. zchko(name) 
  1161. CHAR *name; 
  1162. {
  1163.     int x;
  1164.     extern int errno;                /* System error code     */
  1165.     extern int access();            /* Aztec Builtin Function*/
  1166.  
  1167.     x = access(name, 2);            /* Check access of path. */
  1168.  
  1169.     x = 0;          /* assume it is ok to open file under DOS */
  1170.     if (x != 0) {
  1171.     debug(F111,"zchko access failed:",name,errno);
  1172.     return(-1);
  1173.     } else {
  1174.     debug(F111,"zchko access ok:",name,x);
  1175.     return(0);
  1176.     }
  1177. }
  1178. #endif
  1179.  
  1180. /*  Z D E L E T  --  Delete the named file.  */
  1181.  
  1182. zdelet(name) 
  1183. CHAR *name; 
  1184. {
  1185.     unlink(name);
  1186. }
  1187.  
  1188.  
  1189. /*  Z R T O L  --  Convert remote filename into local form  */
  1190.  
  1191. /*  For Amiga, just return name2 as name. */
  1192.  
  1193. zrtol(name,name2) 
  1194. CHAR *name; 
  1195. CHAR *name2; 
  1196. {
  1197.     strcpy( name2, name );
  1198. }
  1199.  
  1200.  
  1201. /*  Z L T O R  --  Convert filename from local format to common form.    */
  1202.  
  1203. zltor(name,name2) 
  1204. CHAR *name; 
  1205. CHAR *name2; 
  1206. {
  1207.     CHAR work[100]; 
  1208.     register CHAR *cp;
  1209.     register CHAR *pp;
  1210.     register int dc = 0;
  1211.  
  1212.     strcpy(work,name);
  1213.     for (cp = pp = work; *cp != '\0'; cp++) 
  1214.       {   /* strip path name */
  1215.     if (*cp == '/' || *cp == ':') 
  1216.       {
  1217.          pp = cp;
  1218.          pp++;
  1219.        }
  1220.     else if (islower(*cp)) *cp = toupper(*cp); /* Uppercase letters */
  1221.     else if (*cp == '~') *cp = 'X'; /* Change tilde to 'X' */
  1222.     else if ((*cp == '.') && (++dc > 1)) *cp = 'X'; /* & extra dots */
  1223.       }
  1224.     cp = name2;             /* If nothing before dot, */
  1225.     if (*pp == '.') *cp++ = 'X';        /* insert 'X' */
  1226.     strcpy(cp,pp);
  1227. }
  1228.  
  1229. /*  Z N E X T  --  Get name of next file from list created by zxpand(). */
  1230. /*
  1231.  Returns >0 if there's another file, with its name copied into the arg string,
  1232.  or 0 if no more files in list.
  1233. */
  1234. znext(fn) 
  1235. CHAR *fn; 
  1236. {
  1237.     if (fcount-- > 0)  strcpy(fn,*mtchptr++);
  1238.     else *fn = '\0';
  1239.     debug(F111,"znext",fn,fcount+1);
  1240.     return(fcount+1);
  1241. }
  1242.  
  1243. /*  Z N E W N  --  Make a new name for the given file  */
  1244.  
  1245. znewn(fn,s) 
  1246. CHAR *fn, 
  1247. **s; 
  1248. {
  1249.     /* If you really need this function on the Amiga, you might try    */
  1250.     /* Aztec's mktemp, or concatenating "Temp"+TimeStamp        */
  1251.  
  1252.     static CHAR *buf = (CHAR *)"Kermit.NewFile";
  1253.  
  1254.     *s = buf;
  1255. }
  1256.  
  1257.  
  1258. /*  Z X P A N D  --  Expand a wildcard string into an array of strings    */
  1259. /*
  1260.   Returns the number of files that match fn1, with data structures set up
  1261.   so that first file (if any) will be returned by the next znext() call.
  1262. */
  1263.  
  1264. zxpand(fn) 
  1265. CHAR *fn; 
  1266. {
  1267.     static CHAR *notImplemented = (CHAR *)"NotImplemented!";
  1268.  
  1269.     fcount = 0;
  1270.     mtchs[0] = notImplemented;
  1271.     debug(F111,"zxpand",mtchs[0],fcount);
  1272.     return(fcount);
  1273. }
  1274.  
  1275. /*  Z F C D A T  --  Put file creation date/time in str.     */
  1276. /*             returns 1 if able to get date, 0 otherwise. */
  1277.  
  1278. zfcdat(fname,str) 
  1279. CHAR *fname,
  1280. *str; 
  1281. {
  1282.    strcpy( str, "<zfcdat: Not Implemented>" );
  1283.    return 0;
  1284. }
  1285.  
  1286.  
  1287. /* Z F R E E -- Return total number of free bytes on drive specified */
  1288.  
  1289. long zfree(drive)
  1290. CHAR *drive;
  1291. {
  1292.    return 0x7FFFFFFF;
  1293.  
  1294. }
  1295.  
  1296. /* Z F P D A T -- Stamp a given file name with the given date */
  1297.  
  1298. zfpdat(fname,dattim) 
  1299. CHAR *fname, 
  1300. *dattim;
  1301. {
  1302.     /* Null Function on the Amiga. */
  1303. }
  1304.  
  1305.  
  1306. /*  L C K T I O    module   */
  1307.  
  1308. /* C-Kermit interrupt, terminal control & i/o functions for Amiga. */
  1309.  
  1310. /* F. da Cruz, Columbia University Center for Computing Activities */
  1311. /* Modified for use with PC-DOS by: Jan A. van der Eijk, NUS Corp., July 1985 */
  1312. /* ... and for the Amiga August 1986 by Jeff Lydiatt, Vancouver, Canada. */
  1313.  
  1314. /*
  1315.  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
  1316.  Permission is granted to any individual or institution to use, copy, or
  1317.  redistribute this software so long as it is not sold for profit, provided this
  1318.  copyright notice is retained.
  1319. */
  1320.  
  1321. /*
  1322.  Variables available to outside world:
  1323.  
  1324.    dftty  -- Pointer to default tty name string, like "/dev/tty".
  1325.    dfloc  -- 0 if dftty is console, 1 if external line.
  1326.    dfprty -- Default parity
  1327.    dfflow -- Default flow control
  1328.    ckxech -- Flag for who echoes console typein:
  1329.      1 - The program (system echo is turned off)
  1330.      0 - The system (or front end, or terminal).
  1331.    functions that want to do their own echoing should check this flag
  1332.    before doing so.
  1333.  
  1334.  Functions for assigned communication line (either external or console tty):
  1335.  
  1336.    ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access.
  1337.    ttclos()           -- Close & reset the tty, releasing any access lock.
  1338.    ttpkt(speed,flow)       -- Put the tty in packet mode and set the speed.
  1339.    ttvt(speed,flow)       -- Put the tty in virtual terminal mode.
  1340.                 or in DIALING or CONNECTED modem control state.
  1341.    ttinl(dest,max,timo,eol)-- Timed read line from the tty.
  1342.  
  1343.    ttinc(timo)           -- Timed read character from tty.
  1344.    ttchk()           -- See how many characters in tty input buffer.
  1345.    ttol(string,length)       -- Write a string to the tty.
  1346.    ttoc(c)           -- Write a character to the tty.
  1347.    ttflui()           -- Flush tty input buffer.
  1348.  
  1349. */
  1350.  
  1351. /*
  1352. Functions for console terminal:
  1353.  
  1354.    conoc(c)  -- Unbuffered output, one character to console.
  1355.    conol(s)  -- Unbuffered output, null-terminated string to the console.
  1356.    conola(s) -- Unbuffered output, array of strings to the console.
  1357.    conxo(n,s) -- Unbuffered output, n characters to the console.
  1358.    conchk()  -- Check if characters available at console (bsd 4.2).
  1359.         Check if escape char (^\) typed at console (System III/V).
  1360.    coninc(timo)  -- Timed get a character from the console.
  1361.  
  1362. Time functions
  1363.  
  1364.    msleep(m) -- Millisecond sleep
  1365.    ztime(&s) -- Return pointer to date/time string
  1366. */
  1367.  
  1368. /*  T T O L  --  Similar to "ttinl", but for writing.  */
  1369. /*         returns number of characters writen to Com port */
  1370.  
  1371. ttol(s,n)
  1372. int n;
  1373. register CHAR *s;
  1374. {
  1375.     register int j = n;
  1376.  
  1377.     for(; j > 0; j--)
  1378.       SerIOWrite( *s++ );
  1379.     return n;
  1380. }
  1381.  
  1382. /*  T T I N C --  Read a character from the communication line    */
  1383. /*          return the character if possible otherwise -1 */
  1384.  
  1385. /*  Argument     timo, timout  in seconds */
  1386.  
  1387. ttinc(timo) 
  1388. int timo; 
  1389. {
  1390.    UBYTE ch;
  1391.    BOOL  timerOn = FALSE;
  1392.  
  1393.    do
  1394.      {      
  1395.     if ( CheckSerIO() )
  1396.        {
  1397.          ch = SerIORead();
  1398.          return (int)ch;
  1399.        }
  1400.     else if ( chkint() )
  1401.        timerOn = FALSE;
  1402.     if ( !timerOn )
  1403.       {
  1404.         StartTimer( (long)timo, 0L );
  1405.         timerOn = TRUE;
  1406.       }
  1407.     Wait( waitMask );
  1408.  
  1409.       } while( !TimerExpired() );
  1410.  
  1411.    /* if not the above, the timer must have timed out */
  1412.    return -1;
  1413. }
  1414.  
  1415. /*  T T I N L  --  Read a record (up to break character) from comm line.  */
  1416. /*
  1417.   If no break character encountered within "max", return "max" characters,
  1418.   with disposition of any remaining characters undefined.  Otherwise, return
  1419.   the characters that were read, including the break character, in "dest" and
  1420.   the number of characters read as the value of function, or 0 upon end of
  1421.   file, or -1 if an error occurred.  Times out & returns error if not completed
  1422.   within "timo" sconds.
  1423. */
  1424.  
  1425. ttinl(dest,maxnum,timo,eol)
  1426.  register int maxnum;
  1427.  int timo;
  1428.  CHAR eol;
  1429.  register CHAR *dest;
  1430.  {
  1431.  
  1432.     register int i;
  1433.     register int c;
  1434.     int timeOut = timo;
  1435.  
  1436.     if ( !(1 <= timeOut && timeOut <= URTIME) )
  1437.        timeOut = DMYTIM;
  1438.     for ( i = c = 0; (i < maxnum) && (c != eol) ; i++)
  1439.       {
  1440.     c = ttinc( timeOut );
  1441.     if ( c < 0 )
  1442.        break;
  1443.     dest[i] = c;           /* Store the character */
  1444.     if ( i == 0 )
  1445.        timeOut = 2;
  1446.       }
  1447.     return(i);                   /* Return the count. */
  1448. }
  1449.  
  1450. /* TTFLUI  --- Flush tty input buffer */
  1451.  
  1452. ttflui() {
  1453.  
  1454.     FlushSerIO();
  1455.     return 0;
  1456. }
  1457.  
  1458. /* TTFLUO  --- Flush tty output buffer */
  1459.  
  1460. ttfluo()
  1461. {
  1462.     return 0;        /* Should not do on the Amiga */
  1463. }
  1464.  
  1465. /*  T T S O M E     check if character available in receive buffer */
  1466.  
  1467. ttsome() 
  1468. {
  1469.      if ( !CheckSerIO() )
  1470.     return(0);
  1471.      return 1;
  1472. }
  1473. ttchk()            /* Same function as ttsome() */
  1474. {
  1475.      return ttsome();
  1476. }
  1477.  
  1478. /*  S L E E P    wait for m seconds */
  1479.  
  1480. sleep(m) 
  1481. int m; 
  1482. {
  1483.    if ( m )
  1484.      {
  1485.        StartTimer((long)m, 0L);
  1486.        Wait( (unsigned long)(1L << GetTimerSigBit()) );
  1487.      }
  1488. }
  1489.  
  1490. /*  Z T I M E  --  Return date/time string  */
  1491.  
  1492. ztime(s) 
  1493. CHAR **s; 
  1494. {
  1495.    static CHAR *notimp = (CHAR *)"<ztime: Not implemented>";
  1496.      /* Aterm Has it's own Clock */
  1497.    *s = notimp;   
  1498. }
  1499.