home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume23 / xmodem3.9 / part02 / getput.c next >
C/C++ Source or Header  |  1991-01-08  |  12KB  |  463 lines

  1. /*
  2.  * Contains system routines to get and put bytes, change tty modes, etc
  3.  * Most of the routines are VERY 4.2BSD Specific!!!
  4.  */
  5.  
  6. #include "xmodem.h"
  7.  
  8. /*
  9.  *
  10.  *    Get a byte from the specified file.  Buffer the read so we don't
  11.  *    have to use a system call for each character.
  12.  *
  13.  */
  14. getbyte(fildes, ch)                /* Buffered disk read */
  15. int fildes;
  16. char *ch;
  17.  
  18.     {
  19.     static char buf[BUFSIZ];    /* Remember buffer */
  20.     static char *bufp = buf;    /* Remember where we are in buffer */
  21.     
  22.     if (nbchr == 0)            /* Buffer exausted; read some more */
  23.         {
  24.         if ((nbchr = read(fildes, buf, BUFSIZ)) < 0)
  25.             error("File Read Error", TRUE);
  26.         bufp = buf;        /* Set pointer to start of array */
  27.         }
  28.     if (--nbchr >= 0)
  29.         {
  30.         *ch = *bufp++;
  31.         return(0);
  32.         }
  33.     else
  34.         {
  35.         return(EOF);
  36.         }
  37.     }
  38.  
  39. /* Count the number of newlines in a file so we know the REAL file size */
  40.  
  41. long
  42. countnl(fd)
  43. int fd;
  44. {
  45.     char buf[BUFSIZ];
  46.     char *bufp;
  47.     long nltot = 0;
  48.     int numchar;
  49.     long lseek();
  50.  
  51.     while (numchar = read(fd, buf, BUFSIZ))        /* cycle through file */
  52.         for (bufp=buf; numchar--; bufp++)
  53.             if (*bufp == '\n')
  54.                 nltot++;
  55.  
  56.     (void) lseek (fd, 0l, 0);            /* rewind file */
  57.     if (DEBUG)
  58.         fprintf(LOGFP, "DEBUG: countnl--%ld newlines counted\n", nltot);
  59.     return (nltot);
  60. }
  61.  
  62. /*   CRC-16 constant array...
  63.      from Usenet contribution by Mark G. Mendel, Network Systems Corp.
  64.      (ihnp4!umn-cs!hyper!mark)
  65. */
  66.  
  67. /* crctab as calculated by initcrctab() */
  68. unsigned short crctab[1<<B] = { 
  69.     0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
  70.     0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
  71.     0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
  72.     0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
  73.     0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
  74.     0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
  75.     0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
  76.     0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
  77.     0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
  78.     0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
  79.     0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
  80.     0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
  81.     0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
  82.     0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
  83.     0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
  84.     0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
  85.     0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
  86.     0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
  87.     0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
  88.     0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
  89.     0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
  90.     0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
  91.     0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
  92.     0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
  93.     0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
  94.     0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
  95.     0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
  96.     0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
  97.     0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
  98.     0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
  99.     0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
  100.     0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
  101.     };
  102.  
  103. /* get a byte from data stream -- timeout if "seconds" elapses */
  104. /* This routine is VERY 4.2 specific */
  105.  
  106. int
  107. readbyte(seconds)
  108. int seconds;
  109.     {
  110.     int readfd;
  111.     char c;
  112.     struct timeval tmout;
  113.  
  114.     tmout.tv_sec = seconds;
  115.     tmout.tv_usec = 0;
  116.  
  117.     readfd = 1<<0;
  118.  
  119.     if ((select(1, &readfd, (int *)0, (int *)0, &tmout)) == 0)
  120.         {
  121.         if (DEBUG)
  122.             fprintf(LOGFP, "DEBUG: readbyte TIMEOUT\n");
  123.         return(TIMEOUT);
  124.         }
  125.  
  126.     read(0, &c, 1);
  127.  
  128.     if (DEBUG)
  129.         fprintf(LOGFP, "DEBUG: readbyte %02xh\n", c & 0xff);
  130.  
  131.     return(c & 0xff);  /* return the char */
  132.     }
  133.  
  134. /* flush input stream by reading pending characters */
  135.  
  136. flushin()
  137.     {
  138.     int readfd;
  139.     char inbuf[BBUFSIZ];
  140.     struct timeval tmout;
  141.  
  142.     /* set up a usec timeout on stdin */
  143.     tmout.tv_sec = 0;
  144.     tmout.tv_usec = 1;
  145.     readfd = 1<<0;
  146.  
  147.     /* any characters pending?; return if none */
  148.     if ((select(1, &readfd, (int *)0, (int *)0, &tmout)) == 0)
  149.         return;
  150.  
  151.     /* read the characters to flush them (assume there are fewer than BBUFSIZ */
  152.     (void) read(0, inbuf, BBUFSIZ);
  153.     }
  154.  
  155. /* 
  156.  get a buffer (length bufsize) from data stream -- timeout if "seconds" elapses.
  157.  Read bunches of characters to save system overhead;
  158.  Further process data while kernel is reading stream (calculating "checksum").
  159.  Try to nap long enough so kernel collects 100 characters or so until we wake up
  160.  unless TOOBUSY is set.
  161. */
  162.  
  163. /* This routine is VERY 4.2 specific */
  164.  
  165. int
  166. readbuf(bufsize, seconds, tmode, amode, recvsectcnt, checksum, bufctr)
  167.  
  168. int bufsize,    /* number of chars to be read */
  169. seconds,     /* timeout period for each read */
  170. tmode,         /* transmission mode: TRUE if text */
  171. amode,         /* transmission mode: TRUE if apple macintosh */
  172. *checksum,     /* pointer to checksum value */
  173. *bufctr;    /* length of actual data string in buffer */
  174. long recvsectcnt;    /* running sector count (128 byte sectors) */
  175.  
  176. {
  177.     int readfd;        /* mask for select call */
  178.     struct timeval tmout;    /* timeout structure for select */
  179.     int numread;        /* number of chars read */
  180.     int left;        /* number of chars left to read */
  181.     int recfin = FALSE;        /* flag that EOF read */
  182.     char inbuf[BBUFSIZ];    /* buffer for incoming packet */
  183.     register unsigned char c;    /* character being processed */
  184.     register unsigned short chksm;    /* working copy of checksum */
  185.     register int bfctr;    /* working copy of bufctr */
  186.     int j;            /* loop index */
  187.     char *sectdisp();
  188.  
  189.     tmout.tv_sec = seconds;
  190.     tmout.tv_usec = 0;
  191.     readfd = 1<<0;
  192.     chksm = 0;
  193.     bfctr = 0;
  194.  
  195.     for (left = bufsize; left > 0;) {
  196.  
  197.         /* read however many chars are waiting */
  198.  
  199.         if ((select(1, &readfd, (int *)0, (int *)0, &tmout)) == 0)
  200.             return(TIMEOUT);
  201.  
  202.         numread = read(0, inbuf, left);
  203.         left -= numread;
  204.  
  205.         if (DEBUG)
  206.             fprintf(LOGFP, "DEBUG: readbuf--read %d characters\n", numread);
  207.  
  208.         /* now process part of packet we just read */
  209.  
  210.         for (j =  0; j < numread; j++) 
  211.             {  
  212.                 buff[bfctr] = c = inbuf[j] & 0xff;
  213.                 fileread++;
  214.  
  215.                 if (CRCMODE)  /* CRC */
  216.                     chksm = (chksm<<B) ^ crctab[(chksm>>(W-B)) ^ c];
  217.  
  218.                 else        /* checksum */
  219.                            chksm = ((chksm+c) & 0xff);
  220.  
  221.                 if (CHECKLENGTH && fileread > filelength)    /* past EOF ? */
  222.                     continue;
  223.  
  224.                 if (tmode)         /* text mode processing */
  225.                     {
  226.                     buff[bfctr] &= 0x7f;    /* nuke bit 8 */
  227.                     if (c == CR || c == 0)    /* skip CRs and nulls */
  228.                         continue;
  229.                     else if (c == CTRLZ)    /* CP/M EOF char */
  230.                         {  
  231.                         recfin = TRUE;
  232.                                continue;
  233.                                }
  234.                            else if (!recfin)    /* don't increment if past EOF */
  235.                         bfctr++;
  236.                     }
  237.                 else if (amode)     /* Apple macintosh text mode processing */
  238.                     {
  239.                     buff[bfctr] &= 0x7f;    /* nuke bit 8 */
  240.                     if (c == 0)        /* skip nulls */
  241.                         continue;
  242.                     else if (c == CR)    /* translate CR to LF */
  243.                         buff[bfctr] = LF;
  244.                     else if (c == CTRLZ)    /* CP/M EOF char */
  245.                         {  
  246.                         recfin = TRUE;
  247.                                continue;
  248.                                }
  249.                            if (!recfin)        /* don't increment if past EOF */
  250.                         bfctr++;
  251.                     }
  252.                 else            /* binary */
  253.                     bfctr++;
  254.  
  255.                  }    
  256.  
  257.         /* go to sleep to save uneeded system calls while kernel
  258.            is reading data from serial line; 
  259.            fudge constant from 10000 to 9000 to avoid sleeping too long.
  260.         */
  261.         if (left && !TOOBUSY)
  262.             napms( (left<SLEEPNUM ? left:SLEEPNUM) * 9000/ttyspeed);
  263.  
  264.     }
  265.  
  266.     if (CHECKLENGTH && fileread >= filelength)
  267.         logitarg("File end from YMODEM length found in sector %s\n",
  268.           sectdisp(recvsectcnt,bufsize,1));
  269.     *checksum = chksm;
  270.     *bufctr = bfctr;
  271.     return(0);
  272. }
  273.  
  274. /* send a byte to data stream */
  275.  
  276. sendbyte(data)
  277. char data;
  278.     {
  279.     if (DEBUG)
  280.         fprintf(LOGFP, "DEBUG: sendbyte %02xh\n", data & 0xff);
  281.  
  282.     if (write(1, &data, 1) != 1)      /* write the byte (assume it goes NOW; no flushing needed) */
  283.         error ("Write error on stream", TRUE);
  284.     return;
  285.     }
  286.  
  287. /* send a buffer to data stream */
  288.  
  289. writebuf(buffer, nbytes)
  290. char *buffer;
  291. int  nbytes;
  292.     {
  293.     if (DEBUG)
  294.         fprintf(LOGFP, "DEBUG: writebuf (%d bytes)\n", nbytes);
  295.  
  296.     if (write(1, buffer, nbytes) != nbytes)        /* write the buffer (assume no TIOCFLUSH needed) */
  297.         error ("Write error on stream", TRUE);
  298.     return;
  299.     }
  300.  
  301. /*
  302.  * "nap" for specified time -- VERY 4.2BSD specific
  303.  */
  304.  
  305. napms (milliseconds)
  306. int    milliseconds;
  307. {
  308.     struct    timeval    timeout;
  309.     int readfd;
  310.  
  311.     if (milliseconds == 0)
  312.         return;
  313.     if (DEBUG)
  314.         fprintf (LOGFP, "DEBUG: napping for %d ms\n", milliseconds);
  315.     timeout.tv_sec = 0;
  316.     timeout.tv_usec = milliseconds * 1000;
  317.     readfd = 0;
  318.  
  319.     (void) select(1, &readfd, (int *)0, (int *)0, &timeout);
  320. }
  321.  
  322.  
  323. /* set and restore tty modes for XMODEM transfers */
  324. /* These routines are 4.2/v7(?) specific */
  325.  
  326. struct sgttyb ttys, ttysnew;    /* for stty terminal mode calls */
  327. struct stat statbuf;        /* for terminal message on/off control */
  328.  
  329. int wason;            /* holds status of tty read write/modes */
  330. char *tty;            /* current tty name */
  331.  
  332.  
  333. setmodes()
  334.     {
  335.     char *ttyname();
  336.  
  337.     int n;
  338.  
  339.     extern onintr();
  340.  
  341.     sleep(2);            /* let the output appear */
  342.     if (ioctl(0,TIOCGETP,&ttys)<0)  /* get tty params [V7] */
  343.         error("Can't get TTY Parameters", TRUE);
  344.  
  345.     tty = ttyname(0);  /* identify current tty */
  346.     
  347.     ttysnew.sg_ispeed = ttys.sg_ispeed;    /* copy input speed */
  348.     ttysnew.sg_ospeed = ttys.sg_ospeed;    /* copy input speed */
  349.     ttysnew.sg_flags |= RAW;    /* set for RAW Mode */
  350.     ttysnew.sg_flags &= ~ECHO;    /* set for no echoing */
  351.     ttysnew.sg_flags &= ~TANDEM;    /* turn off flow control */
  352.  
  353.     /* set new paramters */
  354.     if (ioctl(0,TIOCSETP,&ttysnew) < 0)
  355.         error("Can't set new TTY Parameters", TRUE);
  356.  
  357.     /* Flush characters waiting for read or write */
  358.     n = 0;
  359.     if (ioctl(0,TIOCFLUSH,&n) < 0)
  360.         error("Can't flush terminal queue", TRUE);
  361.  
  362.     if (stat(tty, &statbuf) < 0)    /* get tty modes */ 
  363.         {
  364.         logit("Can't get your TTY Status\n");
  365.         tlogit("Can't get your TTY Status\n");
  366.         wason = FALSE;
  367.         }
  368.     else
  369.         {
  370.         if (statbuf.st_mode & 022)
  371.             {
  372.             if (chmod(tty, (int)statbuf.st_mode & ~022) < 0)
  373.                 {
  374.                 logit("Can't change TTY mode\n");
  375.                 tlogit("Can't change TTY mode\n");
  376.                 wason = FALSE;
  377.                 }
  378.             else 
  379.                 wason = TRUE;
  380.             }
  381.         else 
  382.             wason = FALSE;
  383.         }
  384.  
  385.     /* set up signal catcher to restore tty state if we are KILLed */
  386.  
  387.     if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
  388.         signal(SIGTERM, onintr);
  389.     }
  390.  
  391. /* restore normal tty modes */
  392.  
  393. restoremodes(errcall)
  394. int errcall;
  395.     {
  396.     if (wason)
  397.         if (chmod(tty, (int)statbuf.st_mode | 022) < 0)
  398.             error("Can't change TTY mode", FALSE);
  399.     if (ioctl(0,TIOCSETP,&ttys) < 0)
  400.         { if (!errcall)
  401.            error("RESET - Can't restore normal TTY Params", FALSE);
  402.         else
  403.              printf("RESET - Can't restore normal TTY Params\n");
  404.         }
  405.     if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
  406.         signal(SIGTERM, SIG_DFL);
  407.     return;
  408.     }
  409.  
  410.  
  411.  
  412.  
  413. /* signal catcher */
  414. onintr()
  415.     {
  416.     error("Kill signal; bailing out", TRUE);
  417.     }
  418.  
  419. /* create string with a timestamp for log file */
  420.  
  421. char *stamptime()
  422. {
  423.     char *asctime();        /* stuff to get timestamp */
  424.     struct tm *localtime(), *tp;
  425.     struct timeval tv;
  426.     struct timezone tz;
  427.  
  428.     gettimeofday (&tv, &tz);        /* fill in timestamp */
  429.     tp = localtime ((time_t *)&tv.tv_sec);
  430.     return(asctime(tp));
  431. }
  432.  
  433.  
  434.  
  435. /* get tty speed for time estimates */
  436.  
  437. getspeed()
  438.     {
  439.     static int speedtbl[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 
  440.        1200, 1800, 2400, 4800, 9600, 19200, 0};
  441.     if (ioctl(0,TIOCGETP,&ttys) < 0)    /* get tty structure */
  442.         error("Can't get TTY parameters", FALSE);
  443.  
  444.     if (ttys.sg_ispeed >= 0 && ttys.sg_ispeed <= 14)
  445.         {
  446.         ttyspeed = speedtbl[ttys.sg_ispeed];
  447.         logitarg ("Line speed = %d bits per second\n", ttyspeed);
  448.         }
  449.     else
  450.         {
  451.         ttyspeed = 1200;
  452.         logit ("Can't determine line speed; assuming 1200 bps\n");
  453.         }
  454.     }
  455.  
  456.  
  457. /* turn off keyboard stop signal so stray ^X don't put us in background */
  458.  
  459. stopsig()
  460.     {
  461.     signal(SIGTSTP, SIG_IGN);
  462.     }
  463.