home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / honeywellgcosa / hd6ker.c < prev    next >
Text File  |  2020-01-01  |  59KB  |  1,492 lines

  1. /************************************************************************
  2.  *
  3.  *       HD6KER.C       Superkermit main source file and driver logic.
  4.  *
  5.  ***********************************************************************  
  6.  *
  7.  *  In ASCII mode only:
  8.  *
  9.  *                LF is converted to CR/LF in transmission
  10.  *                and CR, LF, CR/LF or LF/CR to LF on receipt.
  11.  *                This code is in the machine-dependent routines.
  12.  *
  13.  *   Following enhancements by:
  14.  *
  15.  *                    Frank Dreano (Code 431)
  16.  *
  17.  *   2403 Tarkington Ct.     or   Navy Management System Support Office
  18.  *   Chesapeake, Va. 23322        1441 Crossways Boulevard
  19.  *   (804) 421-3785               Chesapeake, Va. 23320-8915
  20.  *                                (804) 523-8190
  21.  *
  22.  *   Jun 1988 - binary transfers now supported by correcting two bugs in
  23.  *      bufill() and encode()...this Kermit now precreates the right type
  24.  *      file. The PC Kermit must NOT use CTRL-Z for end-of-file marker!
  25.  *
  26.  *   Jul 1988 - added routines to do type-1, type-2 and type-3 checksums
  27.  *      to support critical file transfers, typically binary. Also,
  28.  *      added routine to decode repeat-prefixed incoming filenames in
  29.  *      keeping with 'classic' Kermit. These routines are chk1(), chk2(),
  30.  *      chk3() and decfil() respectively.
  31.  *
  32.  *   Aug 1988 - long packets implemented if they can be negotiated with the
  33.  *      micro Kermit, otherwise 'classic' Kermit is used. If the other side
  34.  *      can use extended packets then the length is negotiated as follows:
  35.  *
  36.  *      If no remote extended packet length is specified but the CAPAS
  37.  *         extended bit is set then the default is 500.
  38.  *      If the remote's extended packet length is less than mine, then
  39.  *        that length is used, else mine (2000) is used.
  40.  *
  41.  *      Changed spack() and rpack() routines to use register variables
  42.  *      and address pointer arithmetic to improve efficiency since
  43.  *      CRC integrity checks are expensive. Added a 'generic' error message
  44.  *      routine, syserr(), to send error packets for either UNIX/Kermit
  45.  *      or MOD400 type errors.
  46.  *
  47.  *   Sep 1988 - implemented file attribute packets (definitely one of my
  48.  *      better efforts) to send file sizes back and forth for transfers; if
  49.  *      this capability is requested. This allows the user to see approximate
  50.  *      percentages of data transfered to the PC during file receives.
  51.  *      The MOD400 file size is determined by the fsize() routine and the file
  52.  *      size will NOT be estimated for variable-length record files as there
  53.  *      is NO way of knowing how many records/CI there are without reading
  54.  *      each record.  If this option produces ANY problems at all turn
  55.  *      off the file attributes on the PC Kermit and bypass this feature.
  56.  *      This capability allows binary files on the DPS-6 to be precreated at
  57.  *      the right size instead of growing all over the disk in 32 Control
  58.  *      Interval file management extents.  Also greatly simplified DPS-6
  59.  *      Superkermit command-line arguments and invocation.
  60.  *
  61.  *   Dec 1988 - added support for the 4.0 operating system...the SOH char
  62.  *      is ^F for 3.1 and ^A for the 4.0 operating systems. The PC Kermit
  63.  *      can use this info to take appropriate action (e.g. to not repeat
  64.  *      the outgoing 'hide' character in 4.0 ... see notes below).
  65.  *
  66.  *   Mar 1989 - due to Honeywell's Kermit having to run in an inefficient
  67.  *      MOD400 'swappool' under 4.0 operating system, Superkermit was made
  68.  *      more generic and now works with VIP3 and MOD400 4.0 ONLY!. The VIP3
  69.  *      Terminal Emulator must be configured for the '7-bit other host' Kermit
  70.  *      file transfer option. Although packet sizes are limited to 94 bytes
  71.  *      I feel that this is more than compensated for by Superkermit's fast
  72.  *      turn-around; no interpacket pacing delays. Superkermit also pre-
  73.  *      creates DPS-6 'fixed relative' files for binary transfers. VIP3
  74.  *      appends a ',I' string to incoming binary filenames and Superkermit
  75.  *      rips it out.  Added ability to date/time stamp debug file data via
  76.  *      the new get_time() routine.
  77.  *
  78.  *   Jan 1990 - MOD400 4.0 can now run terminal lines with eight bits of
  79.  *      data and no parity...therefore 8-bit 'binary-image' mode was
  80.  *      re-implemented for more efficient (no-prefixing) binary transfers.
  81.  *      Also made 2000-byte extended packets available for compatibility
  82.  *      with MSKermit 3.0 and up.
  83.  *
  84.  *   Aug 1990 - fixed a problem in the nextin() routine which caused a
  85.  *      coredump when the third level of debugging (-DDD) was turned on
  86.  *      when SUPERKERMIT was receiving a file as discovered by Tim Ewing
  87.  *      from Honeywell's Maclean office.
  88.  *
  89.  *   Sep 1990 - figured out a way to perform wild card 'sends' to a micro
  90.  *       while in server/send mode using the star_name() function.  This
  91.  *       will ship up to 100 files of the type specified in the command
  92.  *       line (e.g. ASCII or BINARY); other file types will be skipped.
  93.  *       File types are:   F_R = BINARY;  SEQ, S_R = ASCII.  This routine
  94.  *       uses the Honeywell 'heap' to build the filename list so the code
  95.  *       grew some and the compiler EC has changed (see below).  Also added
  96.  *       the ability to do many 'advanced' Kermit server commands; see the
  97.  *       internal documentation below.  It is strongly recommended that these
  98.  *       new capabilities only be used on a Honeywell 4.0 operating system 
  99.  *       (due to Superkermit's increased size) and with MSKermit 3.02 or
  100.  *       later (3.02 fixed many 'remote' command bugs).  Finally, (thanks
  101.  *       again to Tim Ewing of Honeywell Maclean) there is a way to store
  102.  *       all types of MSDOS files (e.g. text, *.COM, *.EXE, *.WKS, etc.) on 
  103.  *       the DPS-6 and bring them back alive to the PC using MSKermit.
  104.  *       A new Superkermit command line argument 'F' designates a 'foreign' 
  105.  *       (usually MSDOS) file type and invokes special Honeywell disk storage
  106.  *       methods.  Unfortunately, the MSKermit 'remote set file type' server 
  107.  *       command only has 'text' and 'binary' arguments, so to change the file
  108.  *       transfer mode to 'foreign' I have implemented a special Kermit
  109.  *       command on the micro: 'remote kermit foreign'.  Modified fsize() to
  110.  *       also determine if a sequential file is being used for foreign data
  111.  *       storage so wilcard gets work correctly.  Found and fixed more bugs
  112.  *       than I care to mention with fprintf() statements to the debug file.
  113.  *
  114.  *       Performed a much-needed reorganization of code; all possible 'C'
  115.  *       preprocessor and global/external variable/functions are now in
  116.  *       a separate hd6ker.h include file. With all of these changes, the
  117.  *       program has been given a new major release number of 2.00.
  118.  *
  119.  *   Dec 1990 - fixed a long-standing bug in binary file sending...the 
  120.  *       spar() routine defaulted to a 'Y' in the 8th-bit quoting field
  121.  *       of the send-init packet; this means that I (Superkermit) do not
  122.  *       require 8th-bit quoting - a usually false assumption.  Instead 
  123.  *       the usual default char of '&' is now the default if no character
  124.  *       is received from the other Kermit.
  125.  *
  126.  *   Apr 1991 - implemented the 'remote space' command as a MOD400 
  127.  *       STS -ALL command as MSKermit 3.10 fixed a bug in this function.
  128.  *
  129.  *     The above enhancements are per the Kermit Protocol Manual
  130.  *     as distributed from Columbia University, Frank da Cruz.
  131.  *
  132.  ***********************************************************************
  133.  *
  134.  *      Typical ASCII file transfer (7-bit only, extended packets):
  135.  *
  136.  *              SUPERKERM S/R/VA [file1 file2 etc.]
  137.  *
  138.  *    Typical binary file transfer (8-bit prefixed, extended packets):
  139.  *
  140.  *              SUPERKERM S/R/VB [file1 file2 etc.]
  141.  *
  142.  *     MOD400 'save' files may be shipped in binary mode if the save was
  143.  *     done to a pre-created 'fixed-relative' type file.
  144.  *
  145.  *     This Kermit has been successfully tested at speeds up to 19,200 bps
  146.  *     and also works on the Honeywell AP6 microcomputer.  HOWEVER, unless
  147.  *     you KNOW that your environment can handle extended packets, CRC-type
  148.  *     block checks etc., stick to 'classic' Kermit with 94-byte packets,
  149.  *     1-character block checks and speeds at or under 9600 bps.  The PC
  150.  *     Kermit used with the DPS-6 must be modified to deliver 2 backslash
  151.  *     (\) characters when one is desired in outgoing packets as the terminal
  152.  *     driver on the Honeywell consumes the first one even in 'raw' mode.
  153.  *     This extra char should not be figured in any checksum or length
  154.  *     computations. This is only necessary with the 3.1 operating system as
  155.  *     the 'hide' char in 4.0 is ^P. If extended packets over 127-bytes are
  156.  *     desired for either the 3.1 OR the 4.0 Honeywell operating system then
  157.  *     the PC Kermit must be modified to consume incoming LF (0AH) characters
  158.  *     in its rpack() routine, these should also not be figured into checksum
  159.  *     or length computations. This is necessary as the Honeywell sends a
  160.  *     post write-order LF char at the end of 134-byte buffer writes regard-
  161.  *     less of the packet length. If these mods only activate during DPS-6
  162.  *     file transfers then the PC Kermit is still generic for all other
  163.  *     systems. These two mods were implemented in the MSSCOM.ASM module
  164.  *     of MSKERMIT Ver. 3.00 (Columbia University). This Kermit requires the
  165.  *     DPS-6 Scientific Instruction Processor or an equivalent simulator.
  166.  *
  167.  *              WARNINGS / DISCLAIMERS / CAVEAT EMPTOR / ETC.
  168.  *              =============================================
  169.  *
  170.  *    NO warranty is expressed or implied and the suitability of this
  171.  *    product for a particular application must be determined by the user.
  172.  *
  173.  *     Kermit is a copyrighted product of Columbia University.  As always
  174.  *     it may be freely distributed and copied as long as it remains in
  175.  *     its complete form with these comments included.  This particular
  176.  *     Kermit was produced using U.S. Government time and materials.
  177.  *
  178.  *
  179.  *      An EC to build executable Superkermit is as follows:
  180.  *
  181.  *      &N
  182.  *      M4_CC HD6KER.C -OP -AS -SZ 32 -V
  183.  *      M4_CC HD6PRI.C -OP -AS -SZ 32 -V
  184.  *      LD SUPERKERM -LK HD6KER HD6PRI -SZ 32 -V -NL
  185.  *      &
  186.  *      &   The editor routine below saves about 9 Kwords
  187.  *      &   by nuking extra 'heap' space unused by Superkermit.
  188.  *      &       It also creates a more detailed link map by
  189.  *      &   using the MAP versus the MAPD linker directive.
  190.  *      &
  191.  *      &A
  192.  *      >SYSLIB2>ED?SILENT
  193.  *      R SUPERKERM.Q
  194.  *      /HSIZE/ S/X'./X'B/
  195.  *      /MAPD/ S/MAPD/MAP/
  196.  *      W
  197.  *      Q
  198.  *      &D
  199.  *      >SYSLIB2>LINKER SUPERKERM -IN SUPERKERM.Q -SZ 32
  200.  *      &F
  201.  *      &Q
  202.  *
  203.  *      If you want a 'shareable/reentrant' version append the '-R'
  204.  *      argument to the two 'M4_CC' lines and the 'LINKER' line
  205.  *      above.  It will then run only in a swappool however!
  206.  *
  207.  *********  End of introductory comments.....Frank Dreano  ************
  208.  */
  209.  
  210. #define MAINDEF         /* allows the inclusion of necessary global stuff */
  211. #include "hd6ker.h"
  212. /*
  213.  *     m a i n
  214.  *
  215.  *     main routine - parse command and options, set up the
  216.  *     tty lines, and dispatch to the appropriate routine.
  217.  *
  218.  */
  219.  
  220. main(argc,argv)
  221. int argc;                           /* Character pointers to and count of */
  222. char **argv;                            /* command line arguments */
  223. {
  224.     char *cp, **argv1;
  225.     int  argc1;
  226.  
  227.     unbuffer();                         /* unbuffer output */
  228.     printf("%s", ident);
  229.     aflg = sflg = rflg = 0;             /* Turn off all parse flags */
  230.     cp = *++argv;
  231.     argv1 = argv;                       /* remember argument pointers */
  232.     argv++;
  233.     argc1 = --argc;
  234.     --argc;                             /* pointers to args */
  235.  
  236. /*  Initialize these values and hope the first packet will get across OK */
  237.  
  238.     eol = CR;                           /* EOL for outgoing packets */
  239.     quote = '#';                        /* Standard control-quote char "#" */
  240.     pad = 0;                            /* No padding */
  241.     padchar = NULL;                     /* Use xnull if any padding wanted */
  242.     spsiz = 94;                         /* set up max packet length */
  243.     qu8 = 0;                            /*   Assume 7-bit                  */
  244.     image = -1;                         /*         ASCII file transfer     */
  245.     ofi = fileimage = ASCII;            /*                       at first. */
  246.     rptflg = TRUE;                      /* try for repeating    */
  247.     dlflag = TRUE;                      /* Overwrite incoming files */
  248.     filnamcnv = FALSE;                  /* conversion for UNIX systems */
  249.     sattrib = FALSE;                    /* attribute packets off */
  250.     senda = TRUE;                       /* I have attribute capability */
  251.     slongp = TRUE;                                  /* extended packets on */
  252.     dfp = 0;
  253.     dname = 0;                          /* clear debug file ptrs        */
  254. /*  signal(SIGALRM,timoex);               initialize signal catcher     */
  255.  
  256.     if (argc >= 0) while ((*cp) != NULL) switch (*cp++) {
  257.  
  258.      /* If command-line, parse characters in first arg. */
  259.               
  260.               case 'H':  case 'h':
  261.                     debug = 0;  help();     /* H = help messages */
  262.  
  263.               case 'V':  case 'v':
  264.                     aflg++;  break;         /* V = Server command */
  265.  
  266.               case 'I':  case 'i':          /* I = 8-bit image */
  267.                     image = 1;
  268.                         ++iflg; break;
  269.  
  270.               case 'R':  case 'r':
  271.                     rflg++;  break;         /* R = Receive command */
  272.  
  273.               case 'S':  case 's':
  274.                     sflg++;  break;         /* S = Send command */
  275.  
  276.               case 'F':  case 'f':
  277.                     ofi++; fileimage = FOREIGN; /* B = Foreign file type */
  278.                     break;
  279.                     
  280.               case 'B':  case 'b':
  281.                     ofi++; fileimage = BINARY; /* B = Binary transfer */
  282.                     break;
  283.                      
  284.               case 'A':  case 'a':
  285.                     image = 0;              /* 7 = Ascii 7-bit transfer */
  286.                     ++iflg; ofi++; 
  287.                     break;
  288.  
  289.               case 'C':  case 'c':
  290.                     dlflag = FALSE;        /* C = Concat to incoming files */
  291.                     break;
  292.  
  293.               case '-':
  294.                     break;                 /* - flag swallowed  */
  295.  
  296.               default:
  297.                     --cp;
  298.                     printmsg("Invalid char %c in command-line.",*cp);
  299.                     usage();
  300.           }
  301.  
  302. if (image == -1) {     /* default is 8-bit prefixed */
  303.    image = 2;
  304.    ++iflg;
  305.    }
  306.  
  307.     oimage = image;             /* remember tseting */
  308.     if (ofi > 1) {
  309.          printmsg("One only of \"A\", \"B\" or \"F\" arguments!");
  310.          usage();
  311.     }
  312.     ofi = fileimage;            /* remember filetype */
  313.  
  314. /* Flags parsed, check for debug filename                       */
  315.     cp = *argv;
  316.     if (*cp == '-') {
  317.           if (*++cp != 'D') {     /* invalid debug filename       */
  318.               printmsg("Debug filename <%s> must start with \"D\".",*--cp);
  319.               usage();
  320.           }
  321.           while (*cp == 'D') {    /* count the Ds                 */
  322.               ++debug;
  323.               ++cp;
  324.           }
  325.           if (debug > 3) usage();        /* no more than 3 'D's */
  326.                 
  327.           dname = cp;             /* filename starts after Ds     */
  328.           dfp = fopen(dname,"a");
  329.           ++argv;
  330.           --argc;
  331.     }
  332.  
  333.     if ((c = aflg+sflg+rflg) > 1) {         /* Only one command allowed */
  334.           printmsg("One only of Server OR Receive OR Send!");
  335.           usage();
  336.     }
  337.  
  338.     if (iflg > 1) {
  339.          printmsg("One only of \"I\" or \"A\" arguments!");
  340.          usage();
  341.     }
  342.  
  343.     if (c == 0) {               /* no action-flag       */
  344.           printf(crlf);
  345.  printmsg("No action on command-line; Server mode assumed;\n  For help type \"superkerm  h\".");
  346.           aflg = 1;
  347.     }
  348.  
  349.                /* Put the tty into the correct mode */
  350.  
  351.     rawtty();
  352.  
  353. /* All set up, now execute the command that was given. */
  354.  
  355.     if (debug) {
  356.           if (dfp != 0) {
  357.               printmsg("Debugging level = %d into file \"%s\";",debug,dname);
  358.               fprintf(dfp,"\n\n******** Superkermit Debug File ** next run starts here  **********\n");
  359.               fprintf(dfp,"%s", ident);
  360.               get_time();
  361.               fprintf(dfp,"\nDebugging level = %d into file \"%s\";\nCommand-line: <",debug,dname);
  362.               while (argc1-- > 0)
  363.                     fprintf(dfp,"  %s",*argv1++);
  364.               fprintf(dfp,"  >;");
  365.               if (aflg) fprintf(dfp,"\nServer Command\n");
  366.               if (sflg) fprintf(dfp,"\nSend Command\n");
  367.               if (rflg) fprintf(dfp,"\nReceive Command\n");
  368.           }
  369.           else {
  370.               printf("No valid debug file, debug switched off.\r\n");
  371.               debug = 0;
  372.           }
  373.     }
  374.     
  375.  /* ---  get BU size for operating system version and print time stanp  --- */
  376.     fsize(buname,3);
  377.  
  378.     if (sflg)                           /* Send command */
  379.     {
  380.           if (argc--) {
  381.               sysint = system(tset);
  382.               printmsg("Send Command; set your Kermit to receive files\n");
  383.               filnam = *argv++;   /* Get file to send */
  384.           }
  385.           else {
  386.               cooktty();                  /* restore tty to normal  */
  387.               printmsg("Send, but no filename given;\n");
  388.               usage();                    /* and give error */
  389.           }
  390.  
  391.         /*  check for wildcards else do the old stuff */
  392.         
  393.           if ((star_check(filnam)) == -1)  {
  394.                           fp = NULL;
  395.               filelist = argv;      /* Set up the rest of the file list */
  396.               filecount = argc;     /* Number of files left to send */
  397.               for (timflag=0; timflag<8; ++timflag) {sleep(1);}
  398.               if (sendsw() == FALSE)          /* Send the file(s) */
  399.                  printmsg("Send failed.");   /* Report failure */
  400.               } else {
  401.                      if (debug)
  402.                        fprintf(dfp,"\n Parsing wildcard name <%s>\n", filnam);
  403.                      wildname(filnam);
  404.                      filelist = filenames;
  405.                      if (filecount--) {
  406.                          filnam = *filelist++;
  407.                          fp = NULL;
  408.                          if (sendsw() == FALSE) {  /* send the files */
  409.                             if (fp != NULL) fclose(fp);
  410.                             printmsg("Send failed.");   /* Report failure */
  411.                             }
  412.                          }  /*  end if  */
  413.                      }   /*  end else */
  414.     }    /*  end sflag */
  415.  
  416.     else if (rflg) {                         /* Receive command */
  417.           sysint = system(tset);
  418.           if ((debug) && (m4_errno != 0))
  419.                 fprintf(dfp,"\nsystem call error = %d", m4_errno);
  420.           printmsg("Receive Command; set your Kermit to Send files\n");
  421.           for (timflag=0; timflag<5; ++timflag) {
  422.               sleep(1);}
  423.           timint = 20;
  424.           if (recsw() == FALSE)            /* Receive the file(s) */
  425.               printmsg("Receive failed.");
  426.     }
  427.  
  428.     else while (aflg) {                    /* server mode  */
  429.           sysint = system(tset);
  430.           printmsg("Server Command; set your Kermit to Send or Get files;");
  431.           getdir(attrib, -1);        /* get users home directory */
  432.           strcat(attrib,"/$KERMIT$.TMP");
  433.           pthto6(attrib, fo_name);
  434.           if (fileimage != ASCII) 
  435.              oimage = image;     /* keep ORIGINAL BINARY/FOREIGN image flag */
  436.              else oimage = 0;
  437.           if (autosw() ==  TRUE) {
  438.               printmsg("Server Send/Get complete");
  439.               sprintf(cmdstg, ">SYSLIB2>DL %s -BF", fo_name);
  440.               system(cmdstg);
  441.               } else {
  442.          /* ---  logout of the DPS-6 if user requested if  --- */
  443.                  printmsg("Server-mode cancelled");
  444.                  closeall();
  445.                  cooktty();
  446.                  sysint = system(tclr);
  447.                  printmsg("done.");
  448.                  system(byenow);           /* Log out of DPS-6 */
  449.                  exit(0);
  450.                  } /* end else */
  451.     }
  452.     closeall();
  453.     cooktty();
  454.     sysint = system(tclr);
  455.     printmsg("done.");
  456. /*    if (c == 'L') system(byenow);   Log out of DPS-6 if requested */
  457.     exit(0);
  458. }                       /* End main()                   */
  459.  
  460.  
  461. /*
  462.  *     a u t o s w
  463.  *
  464.  *     autosw is the state table switcher for automatic mode.  It loops
  465.  *     until it finishes or an error is encountered.  The called routines
  466.  *     are responsible for changing the state
  467.  *
  468.  */
  469.  
  470. autosw()                /* state switcher for automatic mode     */
  471. {
  472.     int   len, num;
  473.     char  c, *ap, *wild;
  474.  
  475.     forever {
  476.           timint = 40;           /* slow NAKs at first           */
  477.           bctu = 1;             /* assume type-1 blk chk at first */
  478.           senda = TRUE;
  479.           sattrib = FALSE;                /* attribute packets off */
  480.           if (debug) fprintf(dfp,
  481.  
  482. "\nServer setup: Fileimage: %d, image: %d, q_char: %c, rptflg: %s, bchk: %d.",
  483. fileimage,image,qu8,logicval[-rptflg],bctu);              
  484. /*
  485. "\nServersw() set: 8th-bit tseting is %d, char is %c, reptflag %s, chktype %d.",
  486. image,qu8,logicval[-rptflg],bctu); */
  487.           n = numtry = 0;
  488.           switch ( (type = rpack(&len,&num,recpkt)) ) {
  489.               /* decipher request from micro */
  490.  
  491.             case 'S':                                             /* SEND */
  492.          /* receive file(s) from local Kermit */
  493.               state = 'F';
  494.               bctu = 1;   /* assume type-1 blk-chk */
  495.               rpar(recpkt,len);
  496.               len = spar(packet);
  497.               spack('Y',n,len,packet);     /* ack parameters   */
  498.               n = (n+1)%64;
  499.               bctu = bctr; /* use agreed upon blk-check from now on */
  500.               while (state != 'C') {      /* until EoF            */
  501.                     if (debug == 1) fprintf(dfp," serversw state %c\n",state);
  502.                     switch(state) {
  503.                       case 'F':  state = rfile();  break;
  504.                       case 'D':  state = rdata();  break;
  505.                       case 'A':   /* upload aborted */
  506.                                  state = 'C';  break;
  507.                       case 'C':  break;
  508.               }   }                       /* end switch, while    */
  509.               fileimage = ofi;            
  510.  /*  If original BINARY/FOREIGN image never given default to prefixed !!!  */
  511.               if (fileimage == ASCII)
  512.                  image = 0;
  513.                  else {
  514.                    if (oimage == 0) 
  515.                       image = 2;
  516.                       else 
  517.                         image = oimage; 
  518.                        }     
  519.               break;                      /* end of reception     */
  520.  
  521.             case 'R':                                              /* GET */
  522.                 /* send file(s) to micro Kermit */
  523.              if (debug) fprintf(dfp,"\n  getting files <%s>, ", recpkt);
  524.              decfil(recpkt,getfiles,len);
  525. TYPE: 
  526.           /*  process wildcards if star name else do the old stuff  */
  527.  
  528.                       if ((star_check(getfiles)) == -1)
  529.                      filecount = decol8(getfiles,filenames,10);
  530.                      else 
  531.                        wildname(getfiles);
  532.  
  533.                filelist = filenames;
  534.                 if (debug > 1) {
  535.                 fprintf(dfp,"\n %d files, ",filecount);
  536.                 while (*filelist != 0)
  537.                          fprintf(dfp,"<%s> ",*filelist++);
  538.                 filelist = filenames;
  539.                         }
  540.  
  541.               if (filecount--) {          /* if any valid names   */
  542.                     filnam = *filelist++;
  543.                     fp = NULL;
  544.                     if (sendsw() == FALSE) {        /* Send the file(s) */
  545.                         if (fp != NULL) fclose(fp);
  546.                         printmsg("Send failed.");   /* Report failure */
  547.                         } /* end if */
  548.                     else
  549.                         printmsg("Files sent; still in server-mode.");
  550.               }
  551.               else                        /* if no names          */
  552.                 error(noname,prompt);
  553.                 fileimage = ofi;
  554.  /*  If original BINARY/FOREIGN image never given default to prefixed !!!  */
  555.                 if (fileimage == ASCII)
  556.                     image = 0;
  557.                     else {
  558.                       if (oimage == 0) 
  559.                          image = 2;
  560.                          else 
  561.                            image = oimage; 
  562.                        }     
  563.                 iflg = 0;          /* reset flag to xfer and not type files */
  564.                 break;
  565.                 
  566.             case 'I':                                      /* INFO PACKET */
  567.               bctu = 1;  /* use type-1 blk chk at first */
  568.               rpar(recpkt,len);
  569.               len = spar(packet);
  570.               spack('Y',n,len,packet);      /* ack the parameters   */
  571.               bctu = bctr;  /* its safe to use agreed blk chk now */
  572.               break;
  573.  
  574.             case 'E':                                     /* ERROR PACKET */
  575.               prerrpkt(recpkt);
  576.               aflg = 0;
  577.               error(goodbye,prompt);
  578.               return(FALSE);  
  579.               break;
  580.  
  581.             case 'N':                                              /* NAK */
  582.               error(amauto,prompt);
  583.               break;
  584.  
  585.             case FALSE:                               /* TIMEOUT ON MICRO */
  586.               printf(crlf);
  587.               printmsg("Please enter Kermit server command to micro Kermit,");
  588.               printf("\t(or send ESCAPE-C to cancel Superkermit) ...\n");
  589.               spack('N',0,0,xnull);
  590.               break;    
  591.  
  592.             case 'G':                             /* KERMIT SEVER COMMAND */
  593.             if (len > 1) {
  594.                decfil(&recpkt[1],attrib,(len-1));
  595.                strcpy(getfiles, &attrib[1]);
  596.                if (debug)
  597.                  fprintf(dfp,"\nDecoded server cmd argument: %s\n", getfiles); 
  598.                }
  599.             switch (c = *recpkt&0x5f)  {
  600.  
  601.             case 'F':                                          /*  FINISH */
  602.               len = strlen(goodbye);              
  603.               spack('Y',num,len,goodbye);
  604.               aflg = 0;
  605.               return(TRUE);
  606.               break;
  607.                            
  608.             case 'L':                                           /* LOGOUT */
  609.               len = strlen(logout);                
  610.               spack('Y',num,len,logout);
  611.               aflg = 0;
  612.               return(FALSE);
  613.               break;
  614.  
  615.  /* ---  Following routines implement advanced Kermit server features  --- */
  616.  /* ---  This stuff will only work right with MSKermit 3.02 or later.  --- */ 
  617.  /* ---  Short results are returned in a packet; long in a file xfer.  --- */
  618.  
  619.             case 'S':                             /* SERVER SET FUNCTION */
  620.   /*   The 'trick' string in the next line was obtained by logging
  621.              MSKermit 3.01/3.02 packets and not thru ANY documentation.  */
  622.                           if ((strncmp(getfiles, "300!", 4)) != 0) {
  623.                               len = strlen(hostng);
  624.                               spack('Y',num,len,hostng);
  625.                               }
  626.                               else {
  627.                                 len = strlen(hostok);
  628.                                                 spack('Y',num,len,hostok);
  629.                                 if(getfiles[4] == '0') {      /* Text mode */
  630.                                   ofi = fileimage = ASCII;
  631.                                   image = 0;
  632.                                   }
  633.                                 if(getfiles[4] == '1') {    /* Binary mode */
  634.                                    ofi = fileimage = BINARY;
  635.   /*  If original BINARY/FOREIGN image never given default to prefixed !!!  */
  636.                                    if (oimage == 0) 
  637.                                       image = 2;
  638.                                         else 
  639.                                          image = oimage; 
  640.                                   } }
  641.                                    break;       
  642.  
  643.             case 'M':                                /* OPERATOR MESSAGE */
  644.             case 'E':                                  /* DELETE FILE(S) */
  645.             case 'C':                              /* CHANGE WORKING DIR */
  646.                        if (c == 'C') {
  647.                            strcpy(cmdstg, getfiles);
  648.                            pthto6(cmdstg, getfiles);
  649.                            sprintf(cmdstg, ">SYSLIB2>CWD %s", getfiles);
  650.                            }
  651.                        if (c == 'E')    
  652.                            sprintf(cmdstg, ">SYSLIB2>DL %s -BF", getfiles);
  653.                        if (c == 'M')    
  654.                            sprintf(cmdstg, ">SYSLIB2>MSG \"%s\"", getfiles);
  655.                            cmdstat = 0;
  656.                            if ((cmdstat = system(cmdstg)) != 0) {
  657.                                           if (debug)
  658.                                  fprintf(dfp, 
  659.                "\nGeneric server cmd: %c, with arg: %s failed\n", c, getfiles);
  660.                               len = strlen(hostng);
  661.                               spack('Y',num,len,hostng);
  662.                               } else {
  663.                                              if (debug)
  664.                                                 fprintf(dfp,
  665.             "\nGeneric server cmd: %c, with arg: %s succeeded\n", c, getfiles);
  666.                                   if (c == 'C') 
  667.                                      getcwd(cmdstg, 80);
  668.                                   len = strlen(cmdstg);
  669.                                   spack('Y',num,len,cmdstg);       
  670.                                   } /* end else */
  671.                            break;
  672.  
  673.             case 'T':                                     /* TYPE A FILE */
  674.   /* set the unused iflg variable and jump upto the 'R' to send the file */
  675.                 fileimage = ASCII; iflg = 99; 
  676.                 if (debug) fprintf(dfp,"\n  Typing file <%s>, ", getfiles);
  677.                 goto TYPE;
  678.                 break;
  679.  
  680.             case 'D':                               /* DIRECTORY LISTING */
  681.                            sprintf(cmdstg,">SYSLIB2>LS %s", getfiles);
  682.                            goto WHO;
  683.                            break; 
  684.             case 'W':                                       /* WHO IS ON */
  685.                            sprintf(cmdstg,">SYSLIB2>VIDEO -G ALL -PAGES 1");
  686.                            goto WHO;
  687.                            break;           
  688.                            
  689.             case 'U':                                       /* DISK SPACE */
  690.                            sprintf(cmdstg,">SYSLIB2>STS -ALL");
  691.                            goto WHO;
  692.                            break;                                      
  693.                            
  694.             default :      error(onlyg,prompt);
  695.                            break;
  696.             }  /* end inner switch */
  697.             break;          /* break for outer switch */
  698.             
  699.             case 'K':                               /* SPECIAL KERMIT COMMAND */
  700.               decfil(recpkt, getfiles, len);
  701.               if (debug) fprintf(dfp,"\nKermit cmd: %s\n", getfiles);
  702.                  if ((strncmp("IMAGE",getfiles,5) == 0) ||
  703.                      (strncmp("image",getfiles,5) == 0)) {
  704.                                      oimage = 1;
  705.                                      if (fileimage != ASCII) image = 1;
  706.                                      len = strlen(hostok);
  707.                                      spack('Y',num,len,hostok);
  708.                                      } else
  709.                  if ((strncmp("PREFI",getfiles,5) == 0) ||
  710.                      (strncmp("prefi",getfiles,5) == 0)) {
  711.                                      oimage = 2;
  712.                                      if (fileimage != ASCII) image = 2;
  713.                                      len = strlen(hostok);
  714.                                      spack('Y',num,len,hostok);
  715.                                      } else
  716.                  if ((strncmp("FOREI",getfiles,5) == 0) || 
  717.                      (strncmp("forei",getfiles,5) == 0)) {
  718.                      ofi = fileimage = FOREIGN;
  719.                 /*  preserve ORIGINAL image mode!!!  */     
  720.                      if (oimage == 0) 
  721.                         image = 2;
  722.                         else 
  723.                           image = oimage; 
  724.                      len = strlen(hostok);
  725.                                      spack('Y',num,len,hostok);
  726.                                      } else 
  727.                          error(onlyg, prompt);
  728.                 break;
  729.  
  730.             case 'C':                                   /* MOD400 COMMAND */
  731.  
  732. /*  The safest way to do MOD400 commands is via I/O redirection...the DPS-6
  733.     command results are sent to a Honeywell file (named $KERMIT$.TMP) and this
  734.     file is then sent to the PC starting with an 'X' instead of an 'F' Kermit
  735.     packet.  This notifies MSKermit that the file should be typed to the
  736.     microcomputer screen and not stored on disk.  Unfortunately the DPS-6
  737.     directory delimiter char is '>' which is ALSO the MSDOS I/O redirection
  738.     symbol.  MSKermit host server commands doing DPS-6 directory stuff almost
  739.     never deliver proper directory names unless they operate only in the 
  740.     working directory. Therefore you must do things like:
  741.                         remote cwd /UDD/DREANO     { UNIX style ! }
  742.                         remote host CD MYDIR
  743.                and NOT  remote host CD >>UDD>DREANO>MYDIR    !!!
  744.                
  745.      This makes some things hard and others impossible, but thats life.
  746.                                                                                                                 Frank Dreano    */
  747.                                                                                                                 
  748.               decfil(recpkt, getfiles, len);
  749.               filecount = decol8(getfiles,filenames,10);
  750.               filelist = filenames;
  751.               filecount--;
  752.               filnam = *filelist++;
  753.               sprintf(cmdstg, "%s", filnam);
  754.               while (filecount-- > 0) {  /* add on any command arguments */
  755.                  strcat(cmdstg," ");
  756.                  filnam = *filelist++;
  757.                  strcat(cmdstg, filnam);
  758.                  } /* end while */
  759. WHO:
  760.               fileimage = ASCII; iflg = 100; /* load up the bound unit name */
  761.               sprintf(cmdstring, ">SYSLIB2>DL %s -BF", fo_name);
  762.               system(cmdstring); 
  763.               sleep(1);                                 
  764.               sprintf(cmdstring, ">SYSLIB2>FO %s", fo_name);
  765.               system(cmdstring);
  766.               sprintf(cmdstring, ">SYSLIB2>FO %s -EO", fo_name);
  767.               system(cmdstring);
  768.               if (debug) fprintf(dfp,"\nExecuting: %s \n", cmdstg);
  769.               cmdstat = system(cmdstg);
  770.               system(">SYSLIB2>FO -RESET -EO");
  771.               system(">SYSLIB2>FO -RESET");
  772.               sleep(1);
  773.               decfil(fo_name,getfiles,strlen(fo_name));
  774.               goto TYPE;
  775.               break;
  776.   /* ---                                                             --- */
  777.   /* ---            End of advanced Kermit server features           --- */ 
  778.   /* ---                                                             --- */
  779.    
  780.             default:                                        /* BAD PACKET */
  781.               error(badpack,prompt,type);
  782.               return(FALSE); 
  783.     }   }               /* end switch, forever                  */
  784. }               /* End autosw()                                 */
  785.  
  786. /*
  787.  *     b u f i l l
  788.  *
  789.  *     Get a bufferful of data from the file thats being sent
  790.  *
  791.  */
  792.  
  793. bufill(buffer)
  794. char *buffer;
  795. {
  796.     int t, i;
  797.     static  int  softeof= FALSE;
  798.  
  799.     if (softeof == TRUE) {
  800.           softeof = FALSE;
  801.           return(EOF);
  802.     }
  803.     rpt = sz = 0;                             /* Inits for encode()   */
  804.     dt = buffer;
  805.     oldt = -2;                                /* impossible last char */
  806.  
  807.     if (iflg == 100) {    /* skip encoding, packetizing and slew byte */
  808.         for (i=0; i < 132 && (t=fgetc(fp)) != EOF; ++i) {
  809.             if (i==0) continue;
  810.             t = ascedit(t);                 /*  edited if necessary */
  811.             encode(t);                      /*   to buffer          */
  812.             if (t == '\n') break;
  813.             }   /* end for */
  814.         if (sz==0) goto EOFPROC; else return(sz);
  815.         } else {
  816.           while((t = getc(fp)) != EOF) {      /* next character       */
  817.               t = ascedit(t);                 /*  edited if necessary */
  818.               encode(t);                      /*   to buffer          */
  819.               if (sz >= spsiz-(7+bctu))       /* Check length         */
  820.                  return(sz);
  821.               }  /* end while */
  822.           }  /* end else */
  823.  
  824.   /* reach here on (hard) EOF or error                          */
  825. EOFPROC:
  826.     if (sz==0)
  827.        return(EOF);
  828.        else {
  829.           softeof = TRUE;
  830.           return (sz);
  831.           }
  832. }                       /* end of bufill()                      */
  833.  
  834. /*
  835.  *     c l o s e a l l
  836.  *
  837.  *     Close both the input/output file and the debug file
  838.  *
  839.  */
  840.  
  841. closeall()
  842. {
  843.     if (fp != NULL)
  844.           fclose(fp);
  845.     if (dfp != NULL) {
  846.     get_time();    /* print stop time to debug file */
  847.     fprintf(dfp,"\n\n************************* End of Run ******************************\n\n");
  848.     fclose(dfp);
  849.     }
  850. }                       /* end of closeall()            */
  851.  
  852. /*
  853.  *     c r e a d
  854.  *
  855.  *     Gets the next character from the terminal line;
  856.  *     detects Kermit escape sequences; returns SOH and
  857.  *     printables, eats all other control characters
  858.  *
  859.  */
  860.  
  861. char  cread()
  862. {
  863.     char  c, t;
  864.     int   ex;
  865.  
  866.     ex =  0;
  867.     while (ex == 0) {
  868.           t = nextin();           /* get next char        */
  869. /*        if (timflag == 0)
  870.               return(0);             timeout occured      */
  871.           c = t&0x7f;
  872.           if (image != 1)
  873.               t = c;
  874.           if ( (c == CR) || (c == LF) || (c == SOH) || (c > 0x1f) )
  875.               return(t);
  876. /* left only with invalid controls */
  877.           if (c == ESC) {         /* process escape       */
  878.               printf("\nSuperkermit-ESC");
  879. Repeat:                         /* for ignoring "-"     */
  880.               t = nextin();
  881.               c = t&0x5f;
  882.               if (c == SOH) return(t);
  883.               switch(c) {
  884. /*             case  SOH:
  885.                     return(t);      */
  886.                 case  'C':
  887.                     cooktty();
  888.       printf("\nSuperkermit terminating by ESC-C from local station\n");
  889.                     closeall();
  890.                     sysint = system(tclr);
  891.                     exit(0);
  892.                     break;
  893.                 case 'H':
  894.             printf("\n\rSuperkermit is alive and well ....\n\r");
  895.                     break;
  896.                 case 'Q':
  897.                     cooktty();
  898.                     system(tclr);
  899.            printf("\n\rSuperkermit spawning command shell ... &Q to return\n");
  900.                     system(">SYSLIB2>EC ![TERM_ID]");
  901.                     system(tset);
  902.                     rawtty();
  903.                     break;
  904.                 case 0x1f:                /* ?            */
  905.                 case 0x0f:                /* /            */
  906.                     cooktty();
  907.                     system(tclr);
  908.                     help1();
  909.                     system(tset);
  910.                     rawtty();
  911.                     break;
  912.                 case '-':
  913.                     goto Repeat;
  914.                 default:
  915.                     printf("???");
  916.                     break;
  917.     }   }   }
  918.     return(0);
  919. }                       /* End of cread()               */
  920.  
  921. /*
  922.  *     d e c o d e
  923.  *
  924.  *     Routine to decode incoming packets, returns 0 or an error-code
  925.  *
  926.  */
  927.  
  928. decode(buf,len)
  929. char *buf;
  930. int  len;
  931. {
  932.     char  a, a7, b8, *end, rep;
  933.     int   flg8=0, error=0, r;
  934.  
  935.     end = buf + len;
  936.     while (buf < end) {
  937.           a = *buf++;
  938.           if ( rptflg && (a == '~') ) {   /* got a repeat prefix? */
  939.                     rep = unchar(*buf++);   /* Yes, get the repeat count, */
  940.                     a = *buf++;
  941.   /* and get the prefixed character. */
  942.           }
  943.           else
  944.               rep = 1;
  945.           b8 = 0;                         /* Check high order "8th" bit */
  946.           if ( (image == 2) && (a == qu8) ) {
  947.                     b8 = 0200;
  948.                     a = *buf++;
  949.   /* and get the prefixed character. */
  950.               }
  951.           if (a == quote) {               /* If control prefix, */
  952.               a  = *buf++;                /* get its operand. */
  953.               a7 = a & 0177;              /* Only look at low 7 bits. */
  954.               if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') /* Uncontrollify */
  955.               a = ctl(a);                 /* if in control range. */
  956.           }
  957.           a = a | b8;                        /* OR in the 8th bit */
  958.  
  959.           while (rep-- > 0) {
  960.               if (image == 0 || fileimage == ASCII) /*  if 7-bit            */
  961.                     r = ascout(a);
  962.               else {                       /*  prefixing / image   */
  963.                     r = putc(a,fp);
  964.               }
  965.               if (r == EOF)               /* if error             */
  966.                     error |= filerr();
  967.     }   }
  968.     return(error);
  969. }                       /* end of decode()                      */
  970.  
  971. /*
  972.  *     d e c o l 8
  973.  *
  974.  *     Splits up command line into sections delimited by blanks,
  975.  *     zeros all such chars & places start-addresses into array,
  976.  *     up to maximum of num entries; zeros rest of entries and
  977.  *     returns count of valid entries.
  978.  *
  979.  */
  980.  
  981. decol8(line,arr,num)
  982. char  *line, *arr[], num;
  983. {
  984.     char  c, count, *start;
  985.     int   i, j;
  986.  
  987.     j = count = 0;
  988.     start = line;
  989.     for (i=0; i<80, j<num; ++i) {
  990.           if ( (c = line[i]) <= SP) {     /* terminator   */
  991.               line[i] = 0;
  992.               if (count > 0) {
  993.                     arr[j++] = start;
  994.                     count = 0;
  995.               }
  996.               if (c == 0)
  997.                     break;          /* out of for           */
  998.           }
  999.           else if (count++ == 0)  /* printable            */
  1000.               start = &line[i];   /* start next parm      */
  1001.     }                           /* end else, for        */
  1002.     line[i] = 0;                /* terminate last parm  */
  1003.     i = j;                      /* number of parms      */
  1004.     while (j < num)
  1005.           arr[j++] = 0;           /* clear garbage        */
  1006.     return(i);
  1007. }                       /* End of decol8()              */
  1008.  
  1009. /*
  1010.  *     e n c o d e
  1011.  *
  1012.  *     Encode single character into packet for transmission
  1013.  *
  1014.  */
  1015.  
  1016. encode(a)
  1017. int a;                          /* char to be encoded           */
  1018. {
  1019.     int a7;                             /* Low order 7 bits     */
  1020.     int b8;                             /* 8th bit of character */
  1021.     int flg8 = 0;
  1022.     static  int  oldsz;
  1023.  
  1024.     if (image == 2)
  1025.           flg8 = -1;
  1026.  
  1027.     if (rptflg) {               /* repeat-count processing      */
  1028.      if ((a == oldt) && ((a & 0x00FF) != 0xFE)) { /* char is same and NOT -2 */
  1029.  
  1030.        /* This code is simple but relatively inefficient; it stores
  1031.           the repeat flag, count and character each time around so
  1032.           that when the run is broken the buffer is valid; also it
  1033.           treats a pair as a run, which requires 3 bytes not 2 unless
  1034.           the pair is control- or 8bit-prefixed; but it does not
  1035.           require lookahead logic from the data-read.             */
  1036.  
  1037.               sz = oldsz;                 /* wind back pointer    */
  1038.               dt[sz++] = '~';             /*  store prefix        */
  1039.               dt[sz++] = tochar(++rpt);   /*   & count            */
  1040.               if (rpt > 93)               /* force new start      */
  1041.                     oldt = -2;              /* impossible value     */
  1042.           } /* end inner if */
  1043.           else {                          /* not run, or end      */
  1044.               rpt = 1;
  1045.               oldt = a;                   /* save char            */
  1046.               oldsz = sz;
  1047.           }   /* end else */
  1048.     } /* end outer if */
  1049.  
  1050.     a7 = a & 0177;                      /* Isolate ASCII part */
  1051.     b8 = a & 0200;                      /* and 8th (parity) bit. */
  1052.  
  1053.     if (flg8 && b8) {                   /* Do 8th bit prefix if necessary. */
  1054.           dt[sz++] = qu8;
  1055.           a = a7;
  1056.     }
  1057.     if ((a7 < SP) || (a7==DEL)) {      /* Do control prefix if necessary */
  1058.           dt[sz++] = MYQUOTE;
  1059.           a = ctl(a);
  1060.     }
  1061.     if (a7 == MYQUOTE)                  /* Prefix the control prefix */
  1062.           dt[sz++] = MYQUOTE;
  1063.     else if (rptflg && (a7 == '~'))     /* If it's the repeat prefix, */
  1064.           dt[sz++] = MYQUOTE;
  1065.  /* quote it if doing repeat counts. */
  1066.     else if (flg8 && (a7 == qu8))               /* Prefix the 8th bit prefix */
  1067.           dt[sz++] = MYQUOTE;             /* if doing 8th-bit prefixes */
  1068.  
  1069.     dt[sz++] = a;                       /* Finally, insert the character */
  1070.     dt[sz] = '\0';                      /* itself, and mark the end. */
  1071.     return;
  1072. }                       /* end of encode()              */
  1073.  
  1074. /*
  1075.  *     g n x t f l
  1076.  *
  1077.  *     Get next file in a file group
  1078.  *
  1079.  */
  1080.  
  1081. gnxtfl()
  1082. {
  1083.     if (debug) fprintf(dfp,"\n   gnxtfl: filelist = \"%s\"",*filelist);
  1084.     filnam = *(filelist++);
  1085.     if (filecount-- == 0)
  1086.           return FALSE; /* If no more, fail */
  1087.     else
  1088.           return TRUE;                   /* else succeed */
  1089. }                       /* End gnxtfl()                 */
  1090.  
  1091. /*
  1092.  *     d e c f i l
  1093.  *
  1094.  *     This routine decodes repeat-prefixed, control-prefixed
  1095.  *     incoming filenames and Kermit server advanced commands.
  1096.  *     It assumes that such items are 7-bit ASCII ONLY !!!
  1097.  *                                             [FRANK DREANO]
  1098.  */
  1099.  
  1100. decfil(buf, to, len)
  1101. char *buf, *to;
  1102. int len;
  1103. {
  1104.            char a, *end, rep;
  1105.            end = buf + len;
  1106.            while (buf < end) {
  1107.  
  1108.                a = *buf++;
  1109.                if (a == '~') {
  1110.                    rep = unchar(*buf++);
  1111.                    a = *buf++;
  1112.                    } /* end if */
  1113.                    else
  1114.                      rep = 1;
  1115.  
  1116.                if (a == quote) {
  1117.                   a = *buf++;
  1118.                   a &= 0177;    
  1119.                   if ((a >= 0100 && a <= 0137) || a =='?')
  1120.                      a = ctl(a);
  1121.                   }  /* end if */
  1122.                
  1123.                while (rep-- > 0)
  1124.                   *to++ = a;
  1125.  
  1126.                } /* end outer while */
  1127.           *to = '\0';
  1128.           return;
  1129. } /* end decfil */
  1130.  
  1131. /*
  1132.  *     r e c s w
  1133.  *
  1134.  *     This is the state table switcher for receiving files
  1135.  *
  1136.  */
  1137.  
  1138. recsw()
  1139. {
  1140.     if (debug) fprintf(dfp,"Ready to receive file\n");
  1141.     state = 'R';                        /* Receive-Init is the start state */
  1142.     n = 0;                              /* Initialize message number */
  1143.     numtry = 0;                         /* Say no tries yet */
  1144.  
  1145.     forever {
  1146.           if (debug == 1) fprintf(dfp," recsw state: %c\n",state);
  1147.           switch(state)                   /* Do until done */
  1148.           {
  1149.               case 'R':   state = rinit(); break; /* Receive-Init */
  1150.               case 'F':   state = rfile(); break; /* Receive-File */
  1151.               case 'D':   state = rdata(); break; /* Receive-Data */
  1152.               case 'C':   return(TRUE);           /* Complete state */
  1153.               case 'A':   return(FALSE);          /* "Abort" state */
  1154.           }
  1155.     }
  1156. }                       /* End recsw()                          */
  1157.  
  1158. /*
  1159.  *     s e n d s w
  1160.  *
  1161.  *  Sendsw is the state table switcher for sending files.  It loops until
  1162.  *  either it finishes, or an error is encountered.  The routines called
  1163.  *  by sendsw are responsible for changing the state.
  1164.  */
  1165.  
  1166. sendsw()
  1167. {
  1168.     if (debug) {
  1169.           fprintf(dfp,"\nSendsw() sending file; ");
  1170.     }
  1171.     state = 'S';                        /* Send initiate is the start state */
  1172.     n = 0;                              /* Initialize message number */
  1173.     numtry = 0;                         /* Say no tries yet */
  1174.     forever {                           /* Do this as long as necessary */
  1175.           if (debug == 1) fprintf(dfp," sendsw state: %c\n",state);
  1176.           switch(state) {
  1177.       /*  'Q' state is for attributes ONLY! */
  1178.               case 'Q':   state = sattru(); break; /* Send-Attributes */
  1179.               case 'S':   state = sinit();  break; /* Send-Init */
  1180.               case 'F':   state = sfile();  break; /* Send-File */
  1181.               case 'D':   state = sdata();  break; /* Send-Data */
  1182.               case 'Z':   state = seof();   break; /* Send-End-of-File */
  1183.               case 'B':   state = sbreak(); break; /* Send-Break */
  1184.               case 'C':   return (TRUE);           /* Complete */
  1185.               case 'A':   return (FALSE);          /* "Abort" */
  1186.               default:    return (FALSE);          /* Unknown, fail */
  1187.           }
  1188.     }
  1189. }                       /* End sendsw()                         */
  1190.  
  1191. /*
  1192.  *     s y s e r r
  1193.  *
  1194.  *     Routine to provide generic error reporting of either
  1195.  *     UNIX or MOD400 type errors.       [FRANK DREANO]
  1196.  *
  1197.  */
  1198.  
  1199. syserr(msg)
  1200. char *msg;
  1201. {
  1202. char sherr[25], errstg1[50], errstg2[10];
  1203. int status;
  1204. extern int errno, sys_nerr;
  1205. extern char *sys_errlist[];
  1206.  
  1207. /* --- print MOD400 error if its a "system" ECL command request --- */
  1208.  
  1209. if ((status = strncmp(msg, "syst", 4)) == 0) {
  1210.  sprintf(errstg1, "%sError occurred in MOD400 command: 0%x",prompt,m4_errno);
  1211.   sprintf(sherr, ">SYSLIB2>DISPLAY 0%x", m4_errno);
  1212.   if ((status = system(sherr)) != 0)
  1213.       fprintf(stderr, "MOD400 error not in message library. \n");
  1214.   error(errstg1);               /* ship error packet out */
  1215.   } /* end if */
  1216.  
  1217. /* --- if its a UNIX type error print MOD400 equivalent, if
  1218.             possible, then print the UNIX version of the error --- */
  1219.  
  1220.       else  {
  1221.  if (((m4_errno - errno) != 0x1800) && (m4_errno > 0) && (m4_errno < 0x9999)) {
  1222.           fprintf(stderr, "Error occurred in MOD400 system service call. \n");
  1223.           sprintf(sherr, ">SYSLIB2>DISPLAY 0%x", m4_errno);
  1224.           if ((status = system(sherr)) != 0)
  1225.               fprintf(stderr, "Error not in message library. \n");
  1226.           } /* end if */
  1227.           sprintf(errstg1, "%sERROR: %s (%d",prompt, msg, errno);
  1228.           if (errno > 0 && errno < sys_nerr)
  1229.               sprintf(errstg2, ": %s)\n", sys_errlist[errno]);
  1230.               else
  1231.                  sprintf(errstg2,")\n");
  1232.           strcat(errstg1, errstg2);
  1233.           error(errstg1);          /* send error packet out */
  1234.           } /* end else */
  1235. } /* end syserr */
  1236.  
  1237.  
  1238. /*
  1239.  *     g e t _ t i m e
  1240.  *
  1241.  *     function to print start/stop time to debug file in the form:
  1242.  *                  Thu May 25 07:50:15 1989
  1243.  */
  1244.  
  1245. get_time()
  1246. {
  1247. struct tm { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon;
  1248.           int tm_year; int tm_wday; int tm_yday; int tm_isdst; } *localtime();
  1249. long time(), tloc;
  1250. char  *asctime(), *ltime;
  1251. tloc = time ( (long *) 0);
  1252. ltime = asctime(localtime(&tloc));
  1253. if (debug) fprintf(dfp,
  1254.           "\n\t Time stamp:  %s\n", ltime);
  1255. return(0);
  1256. } /* end get_time */
  1257.  
  1258.  
  1259. /*
  1260.  *     a s c e d i t
  1261.  *
  1262.  *     This routine converts unix LF end-of-line to CR/LF
  1263.  *     iff in 7-bit mode prior to sending the character.
  1264.  *     Returns the modified character.
  1265.  *
  1266.  */
  1267.  
  1268. char ascedit(c)
  1269. char    c;
  1270. {
  1271.     if (image == 0 || fileimage == ASCII) {
  1272.        /* only if 7-bit                */
  1273.           c &= 0x7f;
  1274.           if (c == LF)
  1275.               encode(CR);         /* CR of CR/LF;                 */
  1276.     }                           /*  bufill() adds the LF        */
  1277.     return(c);
  1278. }               /* End of ascedit()                             */
  1279.  
  1280. /*
  1281.  *     a s c o u t
  1282.  *
  1283.  *     This routine writes 7-bit data to file as it is received
  1284.  *     and is not used for 8-bit data, either image or 8-prefixing
  1285.  *
  1286.  */
  1287.  
  1288. char ascout(a)
  1289. char    a;
  1290. {
  1291.     char    ret;
  1292.     static  char  olda = 0;
  1293.  
  1294. /* for dps6, replace each CR, LF or CR/LF or LF/CR by a single LF */
  1295.     if (a == SUB) {
  1296.        ret = olda = 0;
  1297.        return (ret);
  1298.     }
  1299.     if ( ( (a == CR) && (olda == LF) )
  1300.       || ( (a == LF) && (olda == CR) ) )
  1301.           ret = olda = 0;
  1302.     else {                  /*  if not CR/LF pair   */
  1303.           olda = a;
  1304.           if (a == CR)
  1305.               a = LF;         /*  CR => LF for unix   */
  1306.           ret = putc(a,fp);
  1307.     }
  1308.     return (ret);
  1309. }                       /* End of ascout()                      */
  1310.  
  1311. /*
  1312.  *     f i l e r r
  1313.  *
  1314.  *     This routine is called when EOF is encountered reading or
  1315.  *     writing the data file, if truly and EOF it returns 0 or
  1316.  *     else a system error code
  1317.  *
  1318.  */
  1319.  
  1320. char  filerr()
  1321. {
  1322.     char    ret;
  1323.  
  1324.     ret = ferror(fp);
  1325.     clearerr(fp);
  1326.     return(ret);
  1327. }                       /* End of flerr()              */
  1328.  
  1329. /*
  1330.  *     f l u s h i n p u t
  1331.  *
  1332.  *     Dump all pending input to clear stacked up NAKs
  1333.  *
  1334.  */
  1335.  
  1336. flushinput()            /* DHS 1.0 version              */
  1337. {
  1338. /*     ioctl(0,TIOCFLUSH,0);   */
  1339.      return;
  1340. }                       /* End of flushinput()          */
  1341.  
  1342. /*
  1343.  *     c o o k t t y    /    r a w t t y
  1344.  *
  1345.  *  Routines to set terminal input into "raw" or "cooked" mode.
  1346.  *
  1347.  */
  1348.  
  1349. static  char  cookedok = 0;
  1350.  
  1351. cooktty()               /* restore terminal state       */
  1352. {
  1353. /*    if (cookedok != 0)              provided made raw   */
  1354. /*          stty(0,&cookedmode); */
  1355.     return;
  1356. }                       /* End of cooktty               */
  1357.  
  1358. rawtty()                /* set terminal raw             */
  1359. {
  1360.     if (cookedok == 0) {        /* first time only      */
  1361. /*          gtty(0,&cookedmode);               Save current mode so we can */
  1362. /*          gtty(0,&rawmode);                  restore it later */
  1363.           cookedok = 1;
  1364.           rawmode.sg_flags != (RAW|TANDEM);
  1365.           rawmode.sg_flags &= ~(ECHO|CRMOD);
  1366.     }
  1367. /*    stty(0,&rawmode);                  Put tty in raw mode */
  1368.     return;
  1369. }                       /* End of rawtty() */
  1370.  
  1371. /* end of tty cook/uncook routines                      */
  1372.  
  1373. /*
  1374.  *      n e x t i n
  1375.  *
  1376.  *      Timeouts are always accompanied by attempting to read
  1377.  *      the line.  Two situations are catered for: normally,
  1378.  *      if a timeout can be set which cancels a hanging
  1379.  *      read() call, then this is done; else if a test
  1380.  *      can be made as to whether chars are available AND
  1381.  *      a sleep() call is available, these are linked to
  1382.  *      provide a timeout based on decrementing after
  1383.  *      each sleep().
  1384.  */
  1385.  
  1386. char nextin()            /* read next char, checking time-flag  */
  1387. /* return char (or 0 if timer expired)                          */
  1388. {
  1389.     char   c;
  1390.     static char buff[2048];
  1391.     static int  count = 0, cmax =  0, ccnt = 0;
  1392.     long   lcount;
  1393.  
  1394.     if (count == 0)
  1395.         cmax = count = read(0, buff, 2047);
  1396.     c = buff[cmax - (count--)];
  1397.     if (debug > 2)  {
  1398.                   if (ccnt == 0) fprintf(dfp, "\n");
  1399.           if (ccnt > 15) {
  1400.                 fprintf(dfp," %x \n",((int)c)&0xff );
  1401.                 ccnt = 0;
  1402.                 }
  1403.                 else {
  1404.            fprintf(dfp," %x ",((int)c)&0xff );
  1405.            ++ccnt;
  1406.            }
  1407.           }
  1408.     return(c);
  1409. }                       /* end of nextin()              */
  1410.  
  1411.  
  1412.  
  1413. timoset(sex)            /* set timeout                  */
  1414. char  sex;                      /* # of seconds         */
  1415. {
  1416.     timflag = sex;
  1417. /*  signal(SIGALRM,timoex);
  1418.     alarm(timflag);    */
  1419.     return;
  1420. }                       /* End of timoset()             */
  1421.  
  1422. /* The routines which action and clear timeouts, timoex()
  1423.      and timocan() are not system-dependent; see above. */
  1424.  
  1425. /*
  1426.  *     u n b u f f e r
  1427.  *
  1428.  *     System-dependent action to do quick terminal writes
  1429.  *
  1430.  */
  1431.  
  1432. unbuffer()              /* unbuffer output              */
  1433. /* system-dependent action to write quickly to terminal */
  1434. {
  1435. /*    setbuf(stdout,0);             UNbuffer output!    */
  1436.     return;
  1437. }                       /* End of unbuffer()            */
  1438.  
  1439. /*
  1440.  *     w i l d n a m e  
  1441.  *
  1442.  *     Routine to retrieve Honeywell files using wildcards
  1443.  *
  1444.  */
  1445.  
  1446. wildname(line)
  1447.     char *line;
  1448.     {
  1449.     unsigned char *sn, *fsn;
  1450.     char fnamx[MOD4_NAME-1];
  1451.     int type = 0;
  1452.               fsn = sn = star_name(line, "\0");  /* file in working dir */
  1453.               filecount = 0;
  1454.                       if (*sn == 0) return(0);      /* no filenames given */
  1455.               while (*sn != 0)  {            /* loop through star name list */
  1456.                  type = *sn;                            /* MOD400 file type */
  1457.                  sprintf(fnamx, "%s", ++sn);  /* make file name into string */
  1458.                  switch(type) {    /* only ship files of the cmd line type! */
  1459.                       case F_R:
  1460.                                          if (fileimage == BINARY) {
  1461.                                     filenames[filecount] = sn;
  1462.                                     filecount += 1;
  1463.                                     }
  1464.                                  break;
  1465.                       case SEQ:
  1466.                       case SVQ:
  1467.                                      if ((fsize(sn,1) != 0) && 
  1468.                                         (fileimage == FOREIGN)) {
  1469.                                                 filenames[filecount] = sn;
  1470.                                                 filecount += 1;
  1471.                                                 }
  1472.                                              if ((fsize(sn,1) == 0) && 
  1473.                                         (fileimage == ASCII)) {
  1474.                                                 filenames[filecount] = sn;
  1475.                                                 filecount += 1;
  1476.                                                 }   
  1477.                                          break;
  1478.                       case S_R:
  1479.                                         if (fileimage == ASCII) {
  1480.                                            filenames[filecount] = sn;
  1481.                                            filecount += 1;
  1482.                                    }
  1483.                                          break;
  1484.                       default:   break;                  
  1485.                       }     /* end switch; fall through if not ASCII/BINARY */
  1486.                  sn += strlen(fnamx)+1;         /* point to next file name  */
  1487.                  }  /* end while */
  1488.               free(fsn);    /* star_name() uses the heap; give back the mem */
  1489. }               /*  end of wildname() */
  1490.  
  1491. /*********************  END of FILE  hd6ker.c  **************************/
  1492.