home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource3 / 169_01 / kermitpc.c < prev    next >
Text File  |  1984-07-29  |  31KB  |  974 lines

  1. /*
  2.  *    K e r m i t  File Transfer Utility
  3.  *
  4.  *    UNIX Kermit, Columbia University, 1981, 1982, 1983
  5.  *    Bill Catchings, Bob Cattani, Chris Maio, Frank da Cruz
  6.  *
  7.  *    usage: kermit [csr][dlbe line baud escapechar] [f1 f2 ...]
  8.  *
  9.  *    where c=connect, s=send [files], r=receive, d=debug,
  10.  *    l=tty line, b=baud rate, e=escape char (decimal ascii code).
  11.  *    For "host" mode Kermit, format is either "kermit r" to
  12.  *    receive files, or "kermit s f1 f2 ..." to send f1 .. fn.
  13.  *
  14.  *
  15.  *    Fixed up again for Unix, Jim Guyton 7/13/83 (Rand Corp)
  16.  */
  17.  
  18. #include <stdio.h>            /* Standard UNIX definitions */
  19. #include <sgtty.h>
  20. #include <signal.h>
  21. #include <setjmp.h>
  22.  
  23. /* Conditional Compilation: 0 means don't compile it, nonzero means do */
  24.  
  25. #define UNIX        1    /* Conditional compilation for UNIX */
  26. #define TOPS_20     0    /* Conditional compilation for TOPS-20 */
  27. #define VAX_VMS     0    /* Ditto for VAX/VMS */
  28. #define IBM_UTS     0    /* Ditto for Amdahl UTS on IBM systems */
  29.  
  30.  
  31. /* Symbol Definitions */
  32.  
  33. #define MAXPACK     94    /* Maximum packet size */
  34. #define SOH        1    /* Start of header */
  35. #define SP        32    /* ASCII space */
  36. #define CR        015    /* ASCII Carriage Return */
  37. #define DEL        127    /* Delete (rubout) */
  38. #define CTRLD        4
  39. #define BRKCHR        CTRLD    /* Default escape character for CONNECT */
  40.  
  41. #define MAXTRY        5    /* Times to retry a packet */
  42. #define MYQUOTE     '#'     /* Quote character I will use */
  43. #define MYPAD        0    /* Number of padding characters I will need */
  44. #define MYPCHAR     0    /* Padding character I need */
  45. #define MYEOL        '\n'    /* End-Of-Line character I need */
  46. #define MYTIME        5    /* Seconds after which I should be timed out */
  47. #define MAXTIM        20    /* Maximum timeout interval */
  48. #define MINTIM        2    /* Minumum timeout interval */
  49.  
  50. #define TRUE        -1    /* Boolean constants */
  51. #define FALSE        0
  52.  
  53.  
  54. /* Global Variables */
  55.  
  56. int    size,            /* Size of present data */
  57.     n,            /* Message number */
  58.     rpsiz,            /* Maximum receive packet size */
  59.     spsiz,            /* Maximum send packet size */
  60.     pad,            /* How much padding to send */
  61.     timint,         /* Timeout for foreign host on sends */
  62.     numtry,         /* Times this packet retried */
  63.     oldtry,         /* Times previous packet retried */
  64.     fd,            /* File pointer of file to read/write */
  65.     remfd,            /* File pointer of the host's tty */
  66.     image,            /* -1 means 8-bit mode */
  67.     remspd,         /* Speed of this tty */
  68.     host,            /* -1 means we're a host-mode kermit */
  69.     debug;            /* -1 means debugging */
  70.  
  71. char    state,            /* Present state of the automaton */
  72.     padchar,        /* Padding character to send */
  73.     eol,            /* End-Of-Line character to send */
  74.     escchr,         /* Connect command escape character */
  75.     quote,            /* Quote character in incoming data */
  76.     **filelist,        /* List of files to be sent */
  77.     *filnam,        /* Current file name */
  78.     recpkt[MAXPACK],    /* Receive packet buffer */
  79.     packet[MAXPACK];    /* Packet buffer */
  80.  
  81. struct sgttyb
  82.     rawmode,        /* Host tty "raw" mode */
  83.     cookedmode,        /* Host tty "normal" mode */
  84.     remttymode;        /* Assigned tty line "raw" mode */
  85.  
  86. jmp_buf env;            /* Environment ptr for timeout longjump */
  87.  
  88.  
  89. /*
  90.  *    m a i n
  91.  *
  92.  *    Main routine - parse command and options, set up the
  93.  *    tty lines, and dispatch to the appropriate routine.
  94.  */
  95.  
  96. main(argc,argv)
  97. int argc;                /* Character pointer for */
  98. char **argv;                /*  command line arguments */
  99. {
  100.   char *remtty,*cp;            /* tty for CONNECT, char pointer */
  101.   int speed, cflg, rflg, sflg;        /* speed of assigned tty, */
  102.                     /* flags for CONNECT, RECEIVE, SEND */
  103.   if (argc < 2) usage();        /* Make sure there's a command line. */
  104.  
  105.   cp = *++argv; argv++; argc -= 2;    /* Set up pointers to args */
  106.  
  107. /* Initialize this side's SEND-INIT parameters */
  108.  
  109.   eol = CR;                /* EOL for outgoing packets */
  110.   quote = MYQUOTE;            /* Standard control-quote char "#" */
  111.   pad = 0;                /* No padding */
  112.   padchar = NULL;            /* Use null if any padding wanted */
  113.  
  114.   speed = cflg = sflg = rflg = 0;    /* Turn off all parse flags */
  115.   remtty = 0;                /* Default is host (remote) mode */
  116.   image = FALSE;            /* Default to 7-bit mode */
  117.   escchr = BRKCHR;            /* Default escape character */
  118.  
  119.   while ((*cp) != NULL)         /* Get a character from the cmd line */
  120.     switch (*cp++)            /* Based on what the character is, */
  121.      {                    /*  do one of the folloing */
  122.       case '-': break;                  /* Ignore dash (UNIX style) */
  123.       case 'c': cflg++; break;          /* C = CONNECT command */
  124.       case 's': sflg++; break;          /* S = SEND command */
  125.       case 'r': rflg++; break;          /* R = RECEIVE command */
  126.       case 'e': if (argc--)             /* E = specify escape char */
  127.           escchr = atoi(*argv++); /*  as ascii decimal number */
  128.         else usage();
  129.         if (debug) fprintf(stderr,"escape char is ascii %d\n",escchr);
  130.         break;
  131.       case 'l': if (argc--)             /* L = specify tty line to use */
  132.           remtty = *argv++;
  133.         else usage();
  134.         if (debug) fprintf(stderr,"line %s\n",remtty);
  135.         break;
  136. #if UNIX                /* This part only for UNIX systems */
  137.       case 'b': if (argc--) speed = atoi(*argv++); /* Set baud rate */
  138.           else usage();
  139.         if (debug) fprintf(stderr,"speed %d\n",speed); break;
  140.  
  141.       case 'i': image = TRUE; break;    /* Image (8-bit) mode */
  142. #endif /* UNIX */
  143.  
  144.       case 'd': debug = TRUE; break;    /* Debug mode */
  145.      }
  146.  
  147. /* Done parsing */
  148.  
  149.   if ((cflg+sflg+rflg) != 1) usage();    /* Only one command allowed */
  150.  
  151.   remfd = 0;                /* Start out as a host (remote) */
  152.   host = TRUE;
  153.  
  154.   if (remtty)                /* If another tty was specified, */
  155.    {
  156.     remfd = open(remtty,2);        /*  open it */
  157.     if (remfd < 0)            /*  check for failure */
  158.      {
  159.       fprintf(stderr,"Kermit: cannot open %s\n",remtty);
  160.       exit(-1);             /*  Failed, quit. */
  161.      }
  162.     host = FALSE;            /* Opened OK, flag local (not host) */
  163.    }
  164.  
  165. /* Put the tty(s) into the correct modes */
  166.  
  167.   gtty(0,&cookedmode);            /* Save current mode for later */
  168.   gtty(0,&rawmode);
  169.   rawmode.sg_flags |= (RAW|TANDEM);
  170.   rawmode.sg_flags &= ~(ECHO|CRMOD);
  171.  
  172.   gtty(remfd,&remttymode);        /* If local kermit, get mode of */
  173.                     /*  assigned tty */
  174.   remttymode.sg_flags |= (RAW|TANDEM);
  175.   remttymode.sg_flags &= ~(ECHO|CRMOD);
  176.  
  177. #if UNIX                /* Speed changing for UNIX only */
  178.   if (speed)                /* User specified a speed? */
  179.    {
  180.     switch(speed)            /* Get internal system code */
  181.      {
  182.     case 110: speed = B110; break;
  183.     case 150: speed = B150; break;
  184.     case 300: speed = B300; break;
  185.     case 1200: speed = B1200; break;
  186.     case 2400: speed = B2400; break;
  187.     case 4800: speed = B4800; break;
  188.     case 9600: speed = B9600; break;
  189.     default: fprintf(stderr,"bad line speed\n");
  190.      }
  191.     remttymode.sg_ispeed = speed;
  192.     remttymode.sg_ospeed = speed;
  193.    }
  194. #endif /* UNIX */
  195.  
  196.   if (remfd) stty(remfd,&remttymode);    /* Put asg'd tty in raw mode */
  197.  
  198.  
  199. /* All set up, now execute the command that was given. */
  200.  
  201.   if (cflg) connect();            /* CONNECT command */
  202.  
  203.   if (sflg)                /* SEND command */
  204.    {
  205.     if (argc--) filnam = *argv++;    /* Get file to send */
  206.       else usage();
  207.     filelist = argv;
  208.     if (host) stty(0,&rawmode);     /* Put tty in raw mode if remote */
  209.     if (sendsw() == FALSE)        /* Send the file(s) */
  210.       printf("Send failed.\n");         /* Report failure */
  211.     else                /*  or */
  212.       printf("OK\n");                   /* success */
  213.     if (host) stty(0,&cookedmode);    /* Restore tty */
  214.    }
  215.  
  216.   if (rflg)                /* RECEIVE command */
  217.    {
  218.     if (host) stty(0,&rawmode);     /* Put tty in raw mode if remote */
  219.     if (recsw() == FALSE)        /* Receive the file */
  220.       printf("Receive failed.\n");      /* Report failure */
  221.     else                /*  or */
  222.       printf("OK\n");                   /* success */
  223.     if (host) stty(0,&cookedmode);    /* Restore tty */
  224.    }
  225.  }
  226.  
  227. usage()                 /* Give message if user makes */
  228. {                    /* a mistake in the command */
  229.   fprintf(stderr,
  230.      "usage: kermit [csr][di][lbe] [line] [baud] [esc char] [f1 f2 ...]\n");
  231.   exit();
  232. }
  233.  
  234. /*
  235.  *    s e n d s w
  236.  *
  237.  *    Sendsw is the state table switcher for sending
  238.  *    files.    It loops until either it finishes, or
  239.  *    an error is encountered.  The routines called by
  240.  *    sendsw are responsible for changing the state.
  241.  *
  242.  */
  243.  
  244. sendsw()
  245. {
  246.  char sinit(),sf