home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol128 / umodem.lbr / UMODEM.C < prev   
Encoding:
C/C++ Source or Header  |  1985-02-10  |  34.3 KB  |  1,113 lines

  1. /*
  2.  *  UMODEM -- Implements the "CP/M User's Group XMODEM" protocol, 
  3.  *          the TERM II File Transfer Protocol (FTP) Number 1,
  4.  *          and the TERM II File Transfer Protocol Number 4 for
  5.  *            packetized file up/downloading.    
  6.  *
  7.  *    Note: UNIX System-Dependent values are indicated by the string [SD]
  8.  *          in a comment field on the same line as the values.
  9.  *
  10.  *
  11.  *         -- Lauren Weinstein, 6/81
  12.  *       -- (Version 2.0) Modified for JHU/UNIX by Richard Conn, 8/1/81
  13.  *       -- Version 2.1 Mods by Richard Conn, 8/2/81
  14.  *        . File Size Included on Send Option
  15.  *       -- Version 2.2 Mods by Richard Conn, 8/2/81
  16.  *        . Log File Generation and Option Incorporated
  17.  *       -- Version 2.3 Mods by Richard Conn, 8/3/81
  18.  *        . TERM II FTP 1 Supported
  19.  *        . Error Log Reports Enhanced
  20.  *        . CAN Function Added to FTP 3
  21.  *        . 'd' Option Added to Delete umodem.log File before starting
  22.  *       -- Version 2.4 Mods by Richard Conn, 8/4/81
  23.  *        . 16K-extent sector number check error corrected
  24.  *        . Count of number of received sectors added
  25.  *       -- Version 2.5 Mods by Richard Conn, 8/5/81
  26.  *        . ARPA Net Flag added
  27.  *        . ARPA Net parameter ('a') added to command line
  28.  *        . ARPA Net BIS, BIE, BOS, BOE added
  29.  *        . ARPA Net FFH escape added
  30.  *       -- Version 2.6 Mods by Bennett Marks, 8/21/81 (Bucky @ CCA-UNIX)
  31.  *        . mods for UNIX V7 (Note: for JHU compilation define
  32.  *          the variable JHU  during 'cc'
  33.  *        . added 'mungmode' flag to protect from inadvertant
  34.  *          overwrite on file receive
  35.  *        . changed timeout handling prior to issuing checksum
  36.  *       -- Version 2.7 Mods by Richard Conn, 8/25/81 (rconn @ BRL)
  37.  *        . correct minor "ifndef" error in which ifndef had no arg
  38.  *        . restructured "ifdef" references so that other versions
  39.  *          of UNIX than Version 7 and JHU can be easily incorporated;
  40.  *          previous ifdef references were for JHU/not JHU;
  41.  *          to compile under Version 7 or JHU UNIX, the following
  42.  *          command lines are recommended:
  43.  *            "cc umodem.c -o umodem -DVER7" for Version 7
  44.  *            "cc -7 umodem.c -o umodem -DJHU" for JHU
  45.  *        . added 'y' file status display option; this option gives
  46.  *          the user an estimate of the size of the target file to
  47.  *          send from the UNIX system in terms of CP/M records (128
  48.  *          bytes) and Kbytes (1024 byte units)
  49.  *        . added '7' option which modifies the transmission protocols
  50.  *          for 7 significant bits rather than 8; modifies both FTP 1
  51.  *          and FTP 3
  52.  *       -- Version 2.8 Mods by Richard Conn, 8/28/81
  53.  *        . corrected system-dependent reference to TIOCSSCR (for
  54.  *          disabling page mode) and created the PAGEMODE flag which
  55.  *          is to be set to TRUE to enable this
  56.  *        . added -4 option which engages TERM II, FTP 4 (new release)
  57.  *       -- Version 2.9 Mods by Richard Conn, 9/1/81
  58.  *        . internal documentation on ARPA Net protocols expanded
  59.  *        . possible operator precedence problem with BITMASK corrected
  60.  *          by redundant parentheses
  61.  *       -- Version 3.0 Mods by Lauren Weinstein, 9/14/81
  62.  *              . fixed bug in PAGEMODE defines (removed PAGEMODE define
  63.  *              line; now should be compiled with "-DPAGEMODE" if
  64.  *          Page Mode is desired)
  65.  *        . included forward declaration of ttyname() to avoid problems
  66.  *          with newer V7 C compilers
  67.  *         -- Version 3.1 Mods by Lauren Weinstein, 4/17/82
  68.  *        . avoids sending extraneous last sector when file EOF
  69.  *              occurs on an exact sector boundary
  70.  *       -- Version 3.2 Mods by Michael M Rubenstein, 5/26/83
  71.  *            . fixed bug in readbyte.  assumed that int's are ordered
  72.  *          from low significance to high
  73.  *        . added LOGDEFAULT define to allow default logging to be
  74.  *          off.  compile with -DLOGDEFAULT=0 to set default to no
  75.  *          no logging.
  76.  *
  77.  */
  78.  
  79. #include <stdio.h>
  80. #include <sys/types.h>
  81. #include <sys/stat.h>
  82.  
  83. /*  JHU UNIX tty parameter file  */
  84. #ifdef JHU
  85. #include <stty.h>
  86. #endif
  87.  
  88. /*  Version 7 UNIX tty parameter file  */
  89. #ifdef VER7
  90. #include <sgtty.h>
  91. #endif
  92.  
  93. /* log default define */
  94. #ifndef LOGDEFAULT
  95. #define LOGDEFAULT    1
  96. #endif
  97.  
  98. #include <signal.h>
  99.  
  100. #define         VERSION    32    /* Version Number */
  101. #define         TRUE    1        
  102. #define      FALSE      0
  103.  
  104. /*  Compile with "-DPAGEMODE" if Page Mode (TIOCSSCR) is supported on your
  105.  *  UNIX system.  If it is supported, make sure that TIOCSSCR is the
  106.  *  correct name for Page Mode engagement.
  107.  */
  108.  
  109. /*  ASCII Constants  */
  110. #define      SOH      001 
  111. #define         STX    002
  112. #define         ETX    003
  113. #define      EOT    004
  114. #define         ENQ    005
  115. #define      ACK      006
  116. #define         LF        012   /* Unix LF/NL */
  117. #define         CR        015  
  118. #define      NAK      025
  119. #define         SYN    026
  120. #define         CAN    030
  121. #define         ESC    033
  122. #define         CTRLZ    032   /* CP/M EOF for text (usually!) */
  123.  
  124. /*  UMODEM Constants  */
  125. #define      TIMEOUT      -1
  126. #define      ERRORMAX      10    /* maximum errors tolerated */
  127. #define      RETRYMAX      10    /* maximum retries to be made */
  128. #define         BBUFSIZ    128   /* buffer size -- do not change! */
  129.  
  130. /*  [SD] Mode for Created Files  */
  131. #define      CREATMODE    0644  /* mode for created files */
  132.  
  133. /*  ARPA Net Constants  */
  134. /*    The following constants are used to communicate with the ARPA
  135.  *    Net SERVER TELNET and TIP programs.  These constants are defined
  136.  *    as follows:
  137.  *        IAC            <-- Is A Command; indicates that
  138.  *                        a command follows
  139.  *        WILL/WONT        <-- Command issued to SERVER TELNET
  140.  *                        (Host); WILL issues command
  141.  *                        and WONT issues negative of
  142.  *                        the command
  143.  *        DO/DONT            <-- Command issued to TIP; DO issues
  144.  *                        command and DONT issues
  145.  *                        negative of the command
  146.  *        TRBIN            <-- Transmit Binary Command
  147.  *    Examples:
  148.  *        IAC WILL TRBIN    <-- Host is configured to transmit Binary
  149.  *        IAC WONT TRBIN    <-- Host is configured NOT to transmit binary
  150.  *        IAC DO TRBIN    <-- TIP is configured to transmit Binary
  151.  *        IAC DONT TRBIN    <-- TIP is configured NOT to transmit binary
  152.  */
  153. #define         IAC    0377    /* Is A Command */
  154. #define         DO        0375    /* Command to TIP */
  155. #define         DONT    0376    /* Negative of Command to TIP */
  156. #define         WILL    0373    /* Command to SERVER TELNET (Host) */
  157. #define         WONT    0374    /* Negative of Command to SERVER TELNET */
  158. #define         TRBIN    0    /* Transmit Binary Command */
  159.  
  160. /*  JHU UNIX structures  */
  161. #ifdef JHU
  162. struct sttybuf ttys, ttysnew, ttystemp;    /* for stty terminal mode calls */
  163. #endif
  164.  
  165. /*  Version 7 UNIX structures  */
  166. #ifdef VER7
  167. struct sgttyb  ttys, ttysnew, ttystemp;    /* for stty terminal mode calls */
  168. #endif
  169.  
  170. struct stat statbuf;      /* for terminal message on/off control */
  171. FILE *LOGFP, *fopen();
  172. char buff[BBUFSIZ];
  173.  
  174. #ifdef JHU
  175. int wason;
  176. #endif
  177.  
  178. #ifdef VER7
  179. int pagelen;
  180. char *ttyname();  /* forward declaration for C */
  181. #endif
  182.  
  183. char *tty;
  184. char XMITTYPE;
  185. int ARPA, RECVFLAG, SENDFLAG, FTP1, PMSG, DELFLAG, LOGFLAG, MUNGMODE;
  186. int STATDISP, BIT7, BITMASK;
  187. int delay;
  188.  
  189. alarmfunc();
  190.  
  191. main(argc, argv)
  192. int argc;
  193. char **argv;
  194. {
  195.     char *logfile;
  196.     int index;
  197.     char flag;
  198.  
  199.     logfile = "umodem.log";  /* Name of LOG File */
  200.  
  201.     printf("\nUMODEM Version %d.%d", VERSION/10, VERSION%10);
  202.     printf(" -- UNIX-Based Remote File Transfer Facility\n");
  203.  
  204.     if (argc < 3 || *argv[1] != '-')
  205.     {  printf("\nUsage:  \n\tumodem ");
  206.         printf("-[rb!rt!sb!st][p][l][1][a][m][d][y][7][4]");
  207.         printf(" filename\n");
  208.        printf("\n");
  209.        printf("\n\trb <-- Receive Binary");
  210.        printf("\n\trt <-- Receive Text");
  211.        printf("\n\tsb <-- Send Binary");
  212.        printf("\n\tst <-- Send Text");
  213.        printf("\n\tp  <-- Turn ON Parameter Display");
  214.  
  215. #if LOGDEFAULT
  216.        printf("\n\tl  <-- (ell) Turn OFF LOG File Entries");
  217. #else
  218.        printf("\n\tl  <-- (ell) Turn ON LOG File Entries");
  219. #endif
  220.  
  221.        printf("\n\t1  <-- (one) Employ TERM II FTP 1");
  222.        printf("\n\ta  <-- Turn ON ARPA Net Flag");
  223.        printf("\n\tm  <-- Allow file overwiting on receive");
  224.        printf("\n\td  <-- Delete umodem.log File before starting");
  225.        printf("\n\ty  <-- Display file status (size) information only");
  226.        printf("\n\t7  <-- Enable 7-bit transfer mask");
  227.        printf("\n\t4  <-- Enable TERM II FTP 4");
  228.        printf("\n");
  229.         exit(-1);
  230.     }
  231.  
  232.     index = 1;  /* set index for loop */
  233.     delay = 3;  /* assume FTP 3 delay */
  234.     PMSG = FALSE;  /* turn off flags */
  235.     FTP1 = FALSE;  /* assume FTP 3 (CP/M UG XMODEM2) */
  236.     RECVFLAG = FALSE;  /* not receive */
  237.     SENDFLAG = FALSE;  /* not send either */
  238.     XMITTYPE = 't';  /* assume text */
  239.     DELFLAG = FALSE;  /* do NOT delete log file before starting */
  240.     LOGFLAG = LOGDEFAULT;
  241.     ARPA = FALSE;  /* assume not on ARPA Net */
  242.     MUNGMODE = FALSE; /* protect files from overwriting */
  243.     STATDISP = FALSE;  /* assume not a status display */
  244.     BIT7 = FALSE;  /* assume 8-bit communication */
  245.     while ((flag = argv[1][index++]) != '\0')
  246.         switch (flag) {
  247.         case 'a' : ARPA = TRUE;  /* set ARPA Net */
  248.                break;
  249.         case 'p' : PMSG = TRUE;  /* print all messages */
  250.                break;
  251.         case '1' : FTP1 = TRUE;  /* select FTP 1 */
  252.                delay = 5;  /* FTP 1 delay constant */
  253.                printf("\nUMODEM:  TERM II FTP 1 Selected\n");
  254.                break;
  255.         case 'd' : DELFLAG = TRUE;  /* delete log file first */
  256.  
  257.                break;
  258.         case 'l' : LOGFLAG = ~LOGDEFAULT;  /* turn off log report */
  259.                break;
  260.         case 'r' : RECVFLAG = TRUE;  /* receive file */
  261.                XMITTYPE = gettype(argv[1][index++]);  /* get t/b */
  262.                break;
  263.         case 's' : SENDFLAG = TRUE;  /* send file */
  264.                XMITTYPE = gettype(argv[1][index++]);
  265.                break;
  266.         case 'm' : MUNGMODE = TRUE; /* allow overwriting of files */
  267.                break;
  268.         case 'y' : STATDISP = TRUE;  /* display file status */
  269.                break;
  270.         case '7' : BIT7 = TRUE;  /* transfer only 7 bits */
  271.                break;
  272.         case '4' : FTP1 = TRUE;  /* select FTP 1 (varient) */
  273.                BIT7 = TRUE;  /* transfer only 7 bits */
  274.                delay = 5;  /* FTP 1 delay constant */
  275.                printf("\nUMODEM:  TERM II FTP 4 Selected\n");
  276.                break;
  277.         default  : error("Invalid Flag", FALSE);
  278.         }
  279.  
  280.     if (BIT7 && (XMITTYPE == 'b'))
  281.     {  printf("\nUMODEM:  Fatal Error -- Both 7-Bit Transfer and ");
  282.        printf("Binary Transfer Selected");
  283.        exit(-1);  /* error exit to UNIX */
  284.     }
  285.  
  286.     if (BIT7)  /* set MASK value */
  287.        BITMASK = 0177;  /* 7 significant bits */
  288.     else
  289.        BITMASK = 0377;  /* 8 significant bits */
  290.  
  291.     if (PMSG)
  292.        { printf("\nSupported File Transfer Protocols:");
  293.          printf("\n\tTERM II FTP 1");
  294.          printf("\n\tCP/M UG XMODEM2 (TERM II FTP 3)");
  295.          printf("\n\tTERM II FTP 4");
  296.          printf("\n\n");
  297.        }
  298.  
  299.     if (LOGFLAG)
  300.        { if (!DELFLAG)
  301.         LOGFP = fopen(logfile, "a");  /* append to LOG file */
  302.          else
  303.         LOGFP = fopen(logfile, "w");  /* new LOG file */
  304.          fprintf(LOGFP,"\n\n++++++++\n");
  305.          fprintf(LOGFP,"\nUMODEM Version %d.%d\n", VERSION/10, VERSION%10);
  306.          printf("\nUMODEM:  LOG File '%s' is Open\n", logfile);
  307.        }
  308.  
  309.     if (STATDISP) yfile(argv[2]);  /* status of a file */
  310.  
  311.     if (RECVFLAG && SENDFLAG)
  312.         error("Both Send and Receive Functions Specified", FALSE);
  313.     if (!RECVFLAG && !SENDFLAG)
  314.         error("Neither Send nor Receive Functions Specified", FALSE);
  315.  
  316.     if (RECVFLAG)
  317.     {  if(open(argv[2], 0) != -1)  /* possible abort if file exists */
  318.        {    printf("\nUMODEM:  Warning -- Target File Exists\n");
  319.         if( MUNGMODE == FALSE )
  320.             error("Fatal - Can't overwrite file\n",FALSE);
  321.         printf("UMODEM:  Overwriting Target File\n");
  322.        }
  323.        rfile(argv[2]);  /* receive file */
  324.     }
  325.     else
  326.         sfile(argv[2]);  /* send file */
  327.  
  328. }
  329.  
  330. gettype(ichar)
  331. char ichar;
  332. {
  333.     if (ichar == 't') return(ichar);
  334.     if (ichar == 'b') return(ichar);
  335.     error("Invalid Send/Receive Parameter - not t or b", FALSE);
  336.     return;
  337. }
  338.  
  339. /* set tty modes for UMODEM transfers */
  340. setmodes()
  341. {
  342.  
  343. /*  Device characteristics for JHU UNIX  */
  344. #ifdef JHU    
  345.     if (gtty(0, &ttys) < 0)  /* get current tty params */
  346.         error("Can't get TTY Parameters", TRUE);
  347.  
  348.     tty = ttyname(0);  /* identify current tty */
  349.  
  350.     /* duplicate current modes in ttysnew structure */
  351.     ttysnew.ispeed = ttys.ispeed;    /* copy input speed */
  352.     ttysnew.ospeed = ttys.ospeed;    /* copy output speed */
  353.     ttysnew.xflags = ttys.xflags;    /* copy JHU/UNIX extended flags */
  354.     ttysnew.mode   = ttys.mode;    /* copy standard terminal flags */
  355.  
  356.     ttysnew.mode |= RAW;    /* set for RAW Mode */
  357.             /* This ORs in the RAW mode value, thereby
  358.                setting RAW mode and leaving the other
  359.                mode settings unchanged */
  360.     ttysnew.mode &= ~ECHO;  /* set for no echoing */
  361.             /* This ANDs in the complement of the ECHO
  362.                setting (for NO echo), thereby leaving all
  363.                current parameters unchanged and turning
  364.                OFF ECHO only */
  365.     ttysnew.mode &= ~XTABS;  /* set for no tab expansion */
  366.     ttysnew.mode &= ~LCASE;  /* set for no upper-to-lower case xlate */
  367.     ttysnew.mode |= ANYP;  /* set for ANY Parity */
  368.     ttysnew.mode &= ~NL3;  /* turn off ALL delays - new line */
  369.     ttysnew.mode &= ~TAB3; /* turn off tab delays */
  370.     ttysnew.mode &= ~CR3;  /* turn off CR delays */
  371.     ttysnew.mode &= ~FF1;  /* turn off FF delays */
  372.     ttysnew.mode &= ~BS1;  /* turn off BS delays */
  373.     /* the following are JHU/UNIX xflags settings; they are [SD] */
  374.     ttysnew.xflags &= ~PAGE;  /* turn off paging */
  375.     ttysnew.xflags &= ~STALL;  /* turn off ^S/^Q recognition */
  376.     ttysnew.xflags &= ~TAPE;  /* turn off ^S/^Q input control */
  377.     ttysnew.xflags &= ~FOLD;  /* turn off CR/LF folding at col 72 */
  378.     ttysnew.xflags |= NB8;  /* turn on 8-bit input/output */
  379.  
  380.     if (stty(0, &ttysnew) < 0)  /* set new params */
  381.         error("Can't set new TTY Parameters", TRUE);
  382.  
  383.     if (stat(tty, &statbuf) < 0)  /* get tty status */ 
  384.         error("Can't get your TTY Status", TRUE);
  385.  
  386.     if (statbuf.st_mode&011)  /* messages are on [SD] */
  387.     {    wason = TRUE;
  388.         if (chmod(tty, 020600) < 0)  /* turn off tty messages [SD] */
  389.             error("Can't change TTY Mode", TRUE);
  390.     }    
  391.     else
  392.         wason = FALSE;  /* messages are already off */
  393. #endif        
  394.  
  395. /*  Device characteristics for Version 7 UNIX  */
  396. #ifdef VER7
  397.     if (ioctl(0,TIOCGETP,&ttys)<0)  /* get tty params [V7] */
  398.         error("Can't get TTY Parameters", TRUE);
  399.     tty = ttyname(0);  /* identify current tty */
  400.     
  401.     /* transfer current modes to new structure */
  402.     ttysnew.sg_ispeed = ttys.sg_ispeed;    /* copy input speed */
  403.     ttysnew.sg_ospeed = ttys.sg_ospeed;    /* copy output speed */
  404.     ttysnew.sg_erase  = ttys.sg_erase;    /* copy erase flags */
  405.     ttysnew.sg_flags  = ttys.sg_flags;    /* copy flags */
  406.      ttysnew.sg_kill   = ttys.sg_kill;    /* copy std terminal flags */
  407.     
  408.  
  409.     ttysnew.sg_flags |= RAW;    /* set for RAW Mode */
  410.             /* This ORs in the RAW mode value, thereby
  411.                setting RAW mode and leaving the other
  412.                mode settings unchanged */
  413.     ttysnew.sg_flags &= ~ECHO;  /* set for no echoing */
  414.             /* This ANDs in the complement of the ECHO
  415.                setting (for NO echo), thereby leaving all
  416.                current parameters unchanged and turning
  417.                OFF ECHO only */
  418.     ttysnew.sg_flags &= ~XTABS;  /* set for no tab expansion */
  419.     ttysnew.sg_flags &= ~LCASE;  /* set for no upper-to-lower case xlate */
  420.     ttysnew.sg_flags |= ANYP;  /* set for ANY Parity */
  421.     ttysnew.sg_flags &= ~NL3;  /* turn off ALL delays - new line */
  422.     ttysnew.sg_flags &= ~TAB2; /* turn off tab delays */
  423.     ttysnew.sg_flags &= ~CR3;  /* turn off CR delays */
  424.     ttysnew.sg_flags &= ~FF1;  /* turn off FF delays */
  425.     ttysnew.sg_flags &= ~BS1;  /* turn off BS delays */
  426.     ttysnew.sg_flags &= ~TANDEM;  /* turn off flow control */
  427.  
  428. #ifdef PAGEMODE
  429.     /* make sure page mode is off */
  430.     ioctl(0,TIOCSSCR,&pagelen);    /*  [SD]  */
  431. #endif
  432.     
  433.     /* set new paramters */
  434.     if (ioctl(0,TIOCSETP,&ttysnew) < 0)
  435.         error("Can't set new TTY Parameters", TRUE);
  436.  
  437.     if (stat(tty, &statbuf) < 0)  /* get tty status */ 
  438.         error("Can't get your TTY Status", TRUE);
  439. #endif    
  440.  
  441.     if (PMSG)
  442.         { printf("\nUMODEM:  TTY Device Parameters Altered");
  443.           ttyparams();  /* print tty params */
  444.         }
  445.  
  446.     if (ARPA)  /* set 8-bit on ARPA Net */
  447.         setarpa();
  448.  
  449.     return;
  450. }
  451.  
  452. /*  set ARPA Net for 8-bit transfers  */
  453. setarpa()
  454. {
  455.     sendbyte(IAC);    /* Is A Command */
  456.     sendbyte(WILL);    /* Command to SERVER TELNET (Host) */
  457.     sendbyte(TRBIN);    /* Command is:  Transmit Binary */
  458.  
  459.     sendbyte(IAC);    /* Is A Command */
  460.     sendbyte(DO);    /* Command to TIP */
  461.     sendbyte(TRBIN);    /* Command is:  Transmit Binary */
  462.  
  463.     sleep(3);  /* wait for TIP to configure */
  464.  
  465.     return;
  466. }
  467.  
  468. /* restore normal tty modes */
  469. restoremodes(errcall)
  470. int errcall;
  471. {
  472.     if (ARPA)  /* if ARPA Net, reconfigure */
  473.         resetarpa();
  474.  
  475. /*  Device characteristic restoration for JHU UNIX  */
  476. #ifdef JHU
  477.     if (wason)  /* if messages were on originally */
  478.         if (chmod(tty, 020611) < 0)  /*  [SD]  */
  479.             error("Can't change TTY Mode", FALSE);
  480.  
  481.     if (stty(0, &ttys) < 0)  /* restore original tty modes */
  482.         { if (!errcall)
  483.            error("RESET - Can't restore normal TTY Params", FALSE);
  484.         else
  485.            { printf("UMODEM:  ");
  486.              printf("RESET - Can't restore normal TTY Params\n");
  487.            }
  488.         }
  489. #endif
  490.  
  491. /*  Device characteristic restoration for Version 7 UNIX  */
  492. #ifdef VER7
  493.     if (ioctl(0,TIOCSETP,&ttys) < 0)
  494.         { if (!errcall)
  495.            error("RESET - Can't restore normal TTY Params", FALSE);
  496.         else
  497.            { printf("UMODEM:  ");
  498.              printf("RESET - Can't restore normal TTY Params\n");
  499.            }
  500.         }
  501. #endif
  502.  
  503.     if (PMSG)
  504.         { printf("\nUMODEM:  TTY Device Parameters Restored");
  505.           ttyparams();  /* print tty params */
  506.         }
  507.  
  508.     return;
  509. }
  510.  
  511. /* reset the ARPA Net */
  512. resetarpa()
  513. {
  514.     sendbyte(IAC);    /* Is A Command */
  515.     sendbyte(WONT);    /* Negative Command to SERVER TELNET (Host) */
  516.     sendbyte(TRBIN);    /* Command is:  Don't Transmit Binary */
  517.  
  518.     sendbyte(IAC);    /* Is A Command */
  519.     sendbyte(DONT);    /* Negative Command to TIP */
  520.     sendbyte(TRBIN);    /* Command is:  Don't Transmit Binary */
  521.  
  522.     return;
  523. }
  524.  
  525. /* print error message and exit; if mode == TRUE, restore normal tty modes */
  526. error(msg, mode)
  527. char *msg;
  528. int mode;
  529. {
  530.     if (mode)
  531.         restoremodes(TRUE);  /* put back normal tty modes */
  532.     printf("UMODEM:  %s\n", msg);
  533.     if (LOGFLAG)
  534.     {   fprintf(LOGFP, "UMODEM Fatal Error:  %s\n", msg);
  535.         fclose(LOGFP);
  536.     }
  537.     exit(-1);
  538. }
  539.  
  540. /**  print status (size) of a file  **/
  541. yfile(name)
  542. char *name;
  543. {
  544.     printf("UMODEM File Status Display for %s\n", name);
  545.     if (LOGFLAG) fprintf(LOGFP,"UMODEM File Status Display for %s\n",
  546.       name);
  547.  
  548.     if (open(name,0) < 0)
  549.     {  printf("File %s does not exist\n", name);
  550.        if (LOGFLAG) fprintf(LOGFP,"File %s does not exist\n", name);
  551.        exit(-1);  /* error exit to UNIX */
  552.     }
  553.  
  554.     prfilestat(name);  /* print status */
  555.     printf("\n");
  556.     if (LOGFLAG)
  557.     {  fprintf(LOGFP,"\n");
  558.        fclose(LOGFP);
  559.     }
  560.  
  561.     exit(0);  /* exit to UNIX -- no error */
  562. }
  563.  
  564. /**  receive a file  **/
  565. rfile(name)
  566. char *name;
  567. {
  568.     char mode;
  569.     int fd, j, firstchar, sectnum, sectcurr, tmode;
  570.     int sectcomp, errors, errorflag, recfin;
  571.     register int bufctr, checksum;
  572.     register int c;
  573.     int errorchar, fatalerror, startstx, inchecksum, endetx, endenq;
  574.     long recvsectcnt;
  575.  
  576.     mode = XMITTYPE;  /* set t/b mode */
  577.     if ((fd = creat(name, CREATMODE)) < 0)
  578.           error("Can't create file for receive", FALSE);
  579.     setmodes();  /* setup tty modes for xfer */
  580.     printf("\r\nUMODEM:  File Name: %s", name);
  581.     if (LOGFLAG)
  582.     {    fprintf(LOGFP, "\n----\nUMODEM Receive Function\n");
  583.          fprintf(LOGFP, "File Name: %s\n", name);
  584.          if (FTP1)
  585.         if (!BIT7)
  586.              fprintf(LOGFP, "TERM II File Transfer Protocol 1 Selected\n");
  587.         else
  588.          fprintf(LOGFP, "TERM II File Transfer Protocol 4 Selected\n");
  589.          else
  590.         fprintf(LOGFP,
  591.           "TERM II File Transfer Protocol 3 (CP/M UG) Selected\n");
  592.          if (BIT7)
  593.         fprintf(LOGFP, "7-Bit Transmission Enabled\n");
  594.          else
  595.         fprintf(LOGFP, "8-Bit Transmission Enabled\n");
  596.     }
  597.     printf("\r\nUMODEM:  ");
  598.     if (BIT7)
  599.         printf("7-Bit");
  600.     else
  601.         printf("8-Bit");
  602.     printf(" Transmission Enabled");
  603.     printf("\r\nUMODEM:  Ready to RECEIVE File\r\n");
  604.  
  605.     recfin = FALSE;
  606.     sectnum = errors = 0;
  607.     fatalerror = FALSE;  /* NO fatal errors */
  608.     recvsectcnt = 0;  /* number of received sectors */
  609.  
  610.     if (mode == 't')
  611.         tmode = TRUE;
  612.     else
  613.         tmode = FALSE;
  614.  
  615.     if (FTP1)
  616.     {
  617.       while (readbyte(4) != SYN);
  618.       sendbyte(ACK);  /* FTP 1 Sync */
  619.     }
  620.     else sendbyte(NAK);  /* FTP 3 Sync */
  621.  
  622.         do
  623.         {   errorflag = FALSE;
  624.             do {
  625.                   firstchar = readbyte(6);
  626.             } while ((firstchar != SOH) && (firstchar != EOT) && (firstchar 
  627.              != TIMEOUT));
  628.             if (firstchar == TIMEOUT)
  629.         {  if (LOGFLAG)
  630.         fprintf(LOGFP, "Timeout on Sector %d\n", sectnum);
  631.                errorflag = TRUE;
  632.         }
  633.  
  634.             if (firstchar == SOH)
  635.         {  if (FTP1) readbyte(5);  /* discard leading zero */
  636.                sectcurr = readbyte(delay);
  637.                sectcomp = readbyte(delay);
  638.            if (FTP1) startstx = readbyte(delay);  /* get leading STX */
  639.                if ((sectcurr + sectcomp) == BITMASK)
  640.                {  if (sectcurr == ((sectnum+1)&BITMASK))
  641.           {  checksum = 0;
  642.              for (j = bufctr = 0; j < BBUFSIZ; j++)
  643.                    {  buff[bufctr] = c = readbyte(delay);
  644.                 checksum = ((checksum+c)&BITMASK);
  645.             if (!tmode)  /* binary mode */
  646.             {  bufctr++;
  647.                    continue;
  648.                 }
  649.             if (c == CR)
  650.                continue;  /* skip CR's */
  651.             if (c == CTRLZ)  /* skip CP/M EOF char */
  652.             {  recfin = TRUE;  /* flag EOF */
  653.                    continue;
  654.                 }
  655.                 if (!recfin)
  656.                bufctr++;
  657.              }
  658.              if (FTP1) endetx = readbyte(delay);  /* get ending ETX */
  659.              inchecksum = readbyte(delay);  /* get checksum */
  660.              if (FTP1) endenq = readbyte(delay); /* get ENQ */
  661.              if (checksum == inchecksum)  /* good checksum */
  662.              {  errors = 0;
  663.             recvsectcnt++;
  664.                 sectnum = sectcurr;  /* update sector counter */
  665.             if (write(fd, buff, bufctr) < 0)
  666.                error("File Write Error", TRUE);
  667.                 else
  668.             {  if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
  669.                sendbyte(ACK);
  670.             }
  671.              }
  672.              else
  673.              {  if (LOGFLAG)
  674.                 fprintf(LOGFP, "Checksum Error on Sector %d\n",
  675.                 sectnum);
  676.                 errorflag = TRUE;
  677.              }
  678.                   }
  679.                   else
  680.                   { if (sectcurr == sectnum)
  681.                     {  while(readbyte(3) != TIMEOUT);
  682.                if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
  683.                        sendbyte(ACK);
  684.                     }
  685.                     else
  686.             {  if (LOGFLAG)
  687.             { fprintf(LOGFP, "Phase Error - Received Sector is ");
  688.               fprintf(LOGFP, "%d while Expected Sector is %d\n",
  689.                sectcurr, ((sectnum+1)&BITMASK));
  690.             }
  691.             errorflag = TRUE;
  692.             fatalerror = TRUE;
  693.             if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
  694.             sendbyte(CAN);
  695.             }
  696.               }
  697.            }
  698.            else
  699.        {  if (LOGFLAG)
  700.         fprintf(LOGFP, "Header Sector Number Error on Sector %d\n",
  701.            sectnum);
  702.                errorflag = TRUE;
  703.        }
  704.         }
  705.     if (FTP1 && !errorflag)
  706.     {  if (startstx != STX)
  707.        {  errorflag = TRUE;  /* FTP 1 STX missing */
  708.           errorchar = STX;
  709.        }
  710.        if (endetx != ETX)
  711.        {  errorflag = TRUE;  /* FTP 1 ETX missing */
  712.           errorchar = ETX;
  713.        }
  714.        if (endenq != ENQ)
  715.        {  errorflag = TRUE;  /* FTP 1 ENQ missing */
  716.           errorchar = ENQ;
  717.        }
  718.        if (errorflag && LOGFLAG)
  719.        {  fprintf(LOGFP, "Invalid Packet-Control Character:  ");
  720.           switch (errorchar) {
  721.         case STX : fprintf(LOGFP, "STX"); break;
  722.         case ETX : fprintf(LOGFP, "ETX"); break;
  723.         case ENQ : fprintf(LOGFP, "ENQ"); break;
  724.         default  : fprintf(LOGFP, "Error"); break;
  725.           }
  726.           fprintf(LOGFP, "\n");
  727.        }
  728.     }
  729.         if (errorflag == TRUE)
  730.         {  errors++;
  731.        while (readbyte(3) != TIMEOUT);
  732.            sendbyte(NAK);
  733.         }
  734.   }
  735.   while ((firstchar != EOT) && (errors != ERRORMAX) && !fatalerror);
  736.   if ((firstchar == EOT) && (errors < ERRORMAX))
  737.   {  if (!FTP1) sendbyte(ACK);
  738.      close(fd);
  739.      restoremodes(FALSE);  /* restore normal tty modes */
  740.      if (FTP1)
  741.     while (readbyte(3) != TIMEOUT);  /* flush EOT's */
  742.      sleep(3);  /* give other side time to return to terminal mode */
  743.      if (LOGFLAG)
  744.      {  fprintf(LOGFP, "\nReceive Complete\n");
  745.     fprintf(LOGFP,"Number of Received CP/M Records is %ld\n", recvsectcnt);
  746.         fclose(LOGFP);
  747.      }
  748.      printf("\n");
  749.      exit(0);
  750.   }
  751.   else
  752.   {  if (LOGFLAG && FTP1 && fatalerror) fprintf(LOGFP,
  753.     "Synchronization Error");
  754.      error("TIMEOUT -- Too Many Errors", TRUE);
  755.   }
  756. }
  757.  
  758. /**  send a file  **/
  759. sfile(name)
  760. char *name;
  761. {
  762.     char mode;
  763.     int fd, charval, attempts;
  764.     int nlflag, sendfin, tmode;
  765.     register int bufctr, checksum, sectnum;
  766.     char c;
  767.     int sendresp;  /* response char to sent block */
  768.  
  769.     mode = XMITTYPE;  /* set t/b mode */
  770.     if ((fd = open(name, 0)) < 0)
  771.     {  if (LOGFLAG) fprintf(LOGFP, "Can't Open File\n");
  772.             error("Can't open file for send", FALSE);
  773.     }
  774.     setmodes();  /* setup tty modes for xfer */    
  775.     printf("\r\nUMODEM:  File Name: %s", name);
  776.     if (LOGFLAG)
  777.     {   fprintf(LOGFP, "\n----\nUMODEM Send Function\n");
  778.         fprintf(LOGFP, "File Name: %s\n", name);
  779.     }
  780.     prfilestat(name);  /* print file size statistics */
  781.     if (LOGFLAG)
  782.     {  if (FTP1)
  783.           if (!BIT7)
  784.         fprintf(LOGFP, "TERM II File Transfer Protocol 1 Selected\n");
  785.           else
  786.         fprintf(LOGFP, "TERM II File Transfer Protocol 4 Selected\n");
  787.        else
  788.         fprintf(LOGFP,
  789.            "TERM II File Transfer Protocol 3 (CP/M UG) Selected\n");
  790.        if (BIT7)
  791.         fprintf(LOGFP, "7-Bit Transmission Enabled\n");
  792.        else
  793.         fprintf(LOGFP, "8-Bit Transmission Enabled\n");
  794.     }
  795.     printf("\r\nUMODEM:  ");
  796.     if (BIT7)
  797.         printf("7-Bit");
  798.     else
  799.         printf("8-Bit");
  800.     printf(" Transmission Enabled");
  801.     printf("\r\nUMODEM:  Ready to SEND File\r\n");
  802.  
  803.     if (mode == 't')
  804.        tmode = TRUE;
  805.     else
  806.        tmode = FALSE;
  807.  
  808.         sendfin = nlflag = FALSE;
  809.       attempts = 0;
  810.  
  811.     if (FTP1)
  812.     {  sendbyte(SYN);  /* FTP 1 Synchronize with Receiver */
  813.        while (readbyte(5) != ACK)
  814.        {  if(++attempts > RETRYMAX*6) error("Remote System Not Responding",
  815.         TRUE);
  816.           sendbyte(SYN);
  817.        }
  818.     }
  819.     else
  820.     {  while (readbyte(30) != NAK)  /* FTP 3 Synchronize with Receiver */
  821.        if (++attempts > RETRYMAX) error("Remote System Not Responding",
  822.         TRUE);
  823.     }
  824.  
  825.     sectnum = 1;  /* first sector number */
  826.     attempts = 0;
  827.  
  828.         do 
  829.     {   for (bufctr=0; bufctr < BBUFSIZ;)
  830.         {   if (nlflag)
  831.             {  buff[bufctr++] = LF;  /* leftover newline */
  832.                nlflag = FALSE;
  833.             }
  834.             if ((charval = read(fd, &c, 1)) < 0)
  835.            error("File Read Error", TRUE);
  836.         if (charval == 0)  /* EOF for read */    
  837.         {  sendfin = TRUE;  /* this is the last sector */
  838.            if (!bufctr)  /* if EOF on sector boundary */
  839.               break;  /* avoid sending extra sector */
  840.            if (tmode)
  841.               buff[bufctr++] = CTRLZ;  /* Control-Z for CP/M EOF */
  842.                else
  843.               bufctr++;
  844.            continue;
  845.             }
  846.         if (tmode && c == LF)  /* text mode & Unix newline? */
  847.             {  if (c == LF)  /* Unix newline? */
  848.            {  buff[bufctr++] = CR;  /* insert carriage return */
  849.               if (bufctr < BBUFSIZ)
  850.                      buff[bufctr++] = LF;  /* insert Unix newline */
  851.                else
  852.                  nlflag = TRUE;  /* insert newline on next sector */
  853.            }
  854.            continue;
  855.            }    
  856.         buff[bufctr++] = c;  /* copy the char without change */
  857.         }
  858.             attempts = 0;
  859.     
  860.         if (!bufctr)  /* if EOF on sector boundary */
  861.               break;  /* avoid sending empty sector */
  862.  
  863.             do
  864.             {   sendbyte(SOH);  /* send start of packet header */
  865.         if (FTP1) sendbyte(0);  /* FTP 1 Type 0 Packet */
  866.                 sendbyte(sectnum);  /* send current sector number */
  867.                 sendbyte(-sectnum-1);  /* and its complement */
  868.         if (FTP1) sendbyte(STX);  /* send STX */
  869.                 checksum = 0;  /* init checksum */
  870.                 for (bufctr=0; bufctr < BBUFSIZ; bufctr++)
  871.                 {  sendbyte(buff[bufctr]);  /* send the byte */
  872.            if (ARPA && (buff[bufctr]==0xff))  /* ARPA Net FFH esc */
  873.             sendbyte(buff[bufctr]);  /* send 2 FFH's for one */
  874.                    checksum = ((checksum+buff[bufctr])&BITMASK);
  875.             }
  876. /*        while (readbyte(3) != TIMEOUT);   flush chars from line */
  877.         if (FTP1) sendbyte(ETX);  /* send ETX */
  878.                 sendbyte(checksum);  /* send the checksum */
  879.         if (FTP1) sendbyte(ENQ);  /* send ENQ */
  880.                 attempts++;
  881.         if (FTP1)
  882.         {  sendresp = NAK;  /* prepare for NAK */
  883.            if (readbyte(10) == ESC) sendresp = readbyte(10);
  884.         }
  885.         else
  886.            sendresp = readbyte(10);  /* get response */
  887.         if ((sendresp != ACK) && LOGFLAG)
  888.            { fprintf(LOGFP, "Non-ACK Received on Sector %d\n",
  889.               sectnum);
  890.              if (sendresp == TIMEOUT)
  891.             fprintf(LOGFP, "This Non-ACK was a TIMEOUT\n");
  892.            }
  893.             }   while((sendresp != ACK) && (attempts != RETRYMAX));
  894.             sectnum++;  /* increment to next sector number */
  895.     }  while (!sendfin && (attempts != RETRYMAX));
  896.  
  897.     if (attempts == RETRYMAX)
  898.     error("Remote System Not Responding", TRUE);
  899.  
  900.     attempts = 0;
  901.     if (FTP1)
  902.     while (attempts++ < 10) sendbyte(EOT);
  903.     else
  904.     {    sendbyte(EOT);  /* send 1st EOT */
  905.     while ((readbyte(15) != ACK) && (attempts++ < RETRYMAX))
  906.        sendbyte(EOT);
  907.     if (attempts >= RETRYMAX)
  908.        error("Remote System Not Responding on Completion", TRUE);
  909.     }
  910.  
  911.     close(fd);
  912.     restoremodes(FALSE);  
  913.     sleep(5);  /* give other side time to return to terminal mode */
  914.     if (LOGFLAG)
  915.     {  fprintf(LOGFP, "\nSend Complete\n");
  916.        fclose(LOGFP);
  917.     }
  918.     printf("\n");
  919.     exit(0);
  920.  
  921. }
  922.  
  923. /*  print file size status information  */
  924. prfilestat(name)
  925. char *name;
  926. {
  927.     struct stat filestatbuf; /* file status info */
  928.  
  929.     stat(name, &filestatbuf);  /* get file status bytes */
  930.     printf("\r\nUMODEM:  Estimated File Size %ldK, %ld Records, %ld Bytes",
  931.       (filestatbuf.st_size/1024)+1, (filestatbuf.st_size/128)+1,
  932.       filestatbuf.st_size);
  933.     if (LOGFLAG)
  934.       fprintf(LOGFP,"Estimated File Size %ldK, %ld Records, %ld Bytes\n",
  935.       (filestatbuf.st_size/1024)+1, (filestatbuf.st_size/128)+1,
  936.       filestatbuf.st_size);
  937.     return;
  938. }
  939.  
  940. /* get a byte from data stream -- timeout if "seconds" elapses */
  941. readbyte(seconds)
  942. unsigned seconds;
  943. {
  944.     char c;
  945.     
  946.     signal(SIGALRM,alarmfunc);  /* catch alarms */    
  947.     alarm(seconds);  /* set the alarm clock */
  948.     if (read(0, &c, 1) < 0)  /* get a char; error means we timed out */
  949.       {
  950.          return(TIMEOUT);
  951.       }
  952.     alarm(0);  /* turn off the alarm */
  953.     return((c&BITMASK));  /* return the char */
  954. }
  955.  
  956. /* send a byte to data stream */
  957. sendbyte(data)
  958. char data;
  959. {
  960.     char dataout;
  961.     dataout = (data&BITMASK);  /* mask for 7 or 8 bits */
  962.     write(1, &dataout, 1);  /* write the byte */
  963.     return;
  964. }
  965.  
  966. /* function for alarm clock timeouts */
  967. alarmfunc()
  968. {
  969.     return;  /* this is basically a dummy function to force error */
  970.          /* status return on the "read" call in "readbyte"    */
  971. }
  972.  
  973. /* print data on TTY setting */
  974. ttyparams()
  975. {
  976.     
  977. /*  Obtain TTY parameters for JHU UNIX  */
  978. #ifdef JHU    
  979.     gtty(0, &ttystemp);  /* get current tty params */
  980. #endif
  981.  
  982. /*  Obtain TTY parameters for Version 7 UNIX  */
  983. #ifdef VER7
  984.     ioctl(0,TIOCGETP,&ttystemp);
  985. #endif
  986.  
  987.     tty = ttyname(0);  /* get name of tty */
  988.     stat(tty, &statbuf);  /* get more tty params */
  989.  
  990.     printf("\r\n\nTTY Device Parameter Display");
  991.       printf("\r\n\tTTY Device Name is %s\r\n\n", tty);
  992.       printf("\tAny Parity Allowed "); pryn(ANYP);
  993.       printf("\tEven Parity Allowed"); pryn(EVENP);
  994.       printf("\tOdd Parity Allowed "); pryn(ODDP);
  995.       printf("\tEcho Enabled       "); pryn(ECHO);
  996.       printf("\tLower Case Map     "); pryn(LCASE);
  997.       printf("\tTabs Expanded      "); pryn(XTABS);
  998.       printf("\tCR Mode Enabled    "); pryn(CRMOD);
  999.       printf("\tRAW Mode Enabled   "); pryn(RAW);
  1000.  
  1001. /*  Print extended terminal characteristics for JHU UNIX  */
  1002. #ifdef JHU
  1003.       printf("\tBinary Mode Enabled"); pryn1(NB8);
  1004.       printf("\tCR/LF in Col 72    "); pryn1(FOLD);
  1005.       printf("\tRecognize ^S/^Q    "); pryn1(STALL);
  1006.       printf("\tSend ^S/^Q         "); pryn1(TAPE);
  1007.       printf("\tTerminal can BS    "); pryn1(SCOPE);
  1008.       printf("\r\n");  /* New line to separate topics */
  1009.       printf("\tTerminal Paging is "); pryn1(PAGE);
  1010.         if (ttystemp.xflags&PAGE)
  1011.         printf("\t  Lines/Page is %d\r\n", ttystemp.xflags&PAGE);
  1012.       printf("\r\n");  /* New line to separate topics */
  1013.       printf("\tTTY Input Rate     :   ");
  1014.         prbaud(ttystemp.ispeed);  /* print baud rate */
  1015.       printf("\tTTY Output Rate    :   ");
  1016.         prbaud(ttystemp.ospeed);  /* print output baud rate */
  1017.       printf("\r\n");  /* New line to separate topics */
  1018.       printf("\tMessages Enabled   ");
  1019.         if (statbuf.st_mode&011)
  1020.            printf(":   Yes\r\n");
  1021.         else
  1022.            printf(":   No\r\n");
  1023. #endif
  1024.  
  1025. /*  Print extended characteristics for Version 7 UNIX  */
  1026. #ifdef VER7
  1027.       printf("\tTTY Input Rate     :   ");
  1028.         prbaud(ttystemp.sg_ispeed);
  1029.       printf("\tTTY Output Rate    :   ");
  1030.         prbaud(ttystemp.sg_ospeed);  /* print output baud rate */
  1031. #endif
  1032.  
  1033. }
  1034.  
  1035. pryn(iflag)
  1036. int iflag;
  1037. {
  1038.  
  1039. /*  JHU UNIX flag test  */
  1040. #ifdef JHU
  1041.     if (ttystemp.mode&iflag)
  1042. #endif
  1043.  
  1044. /*  Version 7 UNIX flag test  */
  1045. #ifdef VER7
  1046.     if (ttystemp.sg_flags&iflag)
  1047. #endif
  1048.  
  1049.        printf(":   Yes\r\n");
  1050.     else
  1051.        printf(":   No\r\n");
  1052. }
  1053.  
  1054. /*  Extended flag test for JHU UNIX only  */
  1055. #ifdef JHU
  1056. pryn1(iflag)
  1057. int iflag;
  1058. {
  1059.     if (ttystemp.xflags&iflag)
  1060.        printf(":   Yes\r\n");
  1061.     else
  1062.        printf(":   No\r\n");
  1063. }
  1064. #endif
  1065.  
  1066. prbaud(speed)
  1067. char speed;
  1068. {
  1069.     switch (speed) {
  1070.  
  1071. /*  JHU UNIX speed flag cases  */
  1072. #ifdef JHU        
  1073.         case B0050 : printf("50"); break;
  1074.         case B0075 : printf("75"); break;
  1075.         case B0110 : printf("110"); break;
  1076.         case B0134 : printf("134.5"); break;
  1077.         case B0150 : printf("150"); break;
  1078.         case B0200 : printf("200"); break;
  1079.         case B0300 : printf("300"); break;
  1080.         case B0600 : printf("600"); break;
  1081.         case B1200 : printf("1200"); break;
  1082.         case B1800 : printf("1800"); break;
  1083.         case B2400 : printf("2400"); break;
  1084.         case B4800 : printf("4800"); break;
  1085.         case B9600 : printf("9600"); break;
  1086.         case EXT_A : printf("External A"); break;
  1087.         case EXT_B : printf("External B"); break;
  1088. #endif
  1089.  
  1090. /*  Version 7 UNIX speed flag cases  */
  1091. #ifdef VER7
  1092.         case B50 : printf("50"); break;
  1093.         case B75 : printf("75"); break;
  1094.         case B110 : printf("110"); break;
  1095.         case B134 : printf("134.5"); break;
  1096.         case B150 : printf("150"); break;
  1097.         case B200 : printf("200"); break;
  1098.         case B300 : printf("300"); break;
  1099.         case B600 : printf("600"); break;
  1100.         case B1200 : printf("1200"); break;
  1101.         case B1800 : printf("1800"); break;
  1102.         case B2400 : printf("2400"); break;
  1103.         case B4800 : printf("4800"); break;
  1104.         case B9600 : printf("9600"); break;
  1105.         case EXTA : printf("External A"); break;
  1106.         case EXTB : printf("External B"); break;
  1107. #endif
  1108.  
  1109.         default    : printf("Error"); break;
  1110.     }
  1111.     printf(" Baud\r\n");
  1112. }
  1113.