home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1996 October / PCO_10.ISO / filesbbs / bsrc_260.arj / SRC.ZIP / zmisc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-20  |  18.6 KB  |  753 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software, Co.                       */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          Freely Available<tm> Software.                 */
  7. /*        \ 1011 /                                                          */
  8. /*         ------                                                           */
  9. /*                                                                          */
  10. /*              (C) Copyright 1987-96, Bit Bucket Software Co.              */
  11. /*                                                                          */
  12. /*                                                                          */
  13. /*                                                                          */
  14. /*                 Zmodem routines used by Zsend and Zreceive               */
  15. /*                                                                          */
  16. /*                                                                          */
  17. /*    For complete  details  of the licensing restrictions, please refer    */
  18. /*    to the License  agreement,  which  is published in its entirety in    */
  19. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.260.    */
  20. /*                                                                          */
  21. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  22. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  23. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  24. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  25. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  26. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  27. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  28. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  29. /*                                                                          */
  30. /*                                                                          */
  31. /* You can contact Bit Bucket Software Co. at any one of the following      */
  32. /* addresses:                                                               */
  33. /*                                                                          */
  34. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
  35. /* P.O. Box 460398                AlterNet 7:42/1491                        */
  36. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  37. /*                                Internet f491.n343.z1.fidonet.org         */
  38. /*                                                                          */
  39. /* Please feel free to contact us at any time to share your comments about  */
  40. /* our software and/or licensing policies.                                  */
  41. /*                                                                          */
  42. /*                                                                          */
  43. /*  This module is based largely on a similar module in OPUS-CBCS V1.03b.   */
  44. /*  The original work is (C) Copyright 1986, Wynn Wagner III. The original  */
  45. /*  authors have graciously allowed us to use their code in this work.      */
  46. /*                                                                          */
  47. /*--------------------------------------------------------------------------*/
  48.  
  49. /* Include this file before any other includes or defines! */
  50.  
  51. #include "includes.h"
  52.  
  53. static int Rxtype;                /* Type of header received                 */
  54.  
  55. static char hex[] = "0123456789abcdef";
  56.  
  57. /* Send a byte as two hex digits */
  58. #define Z_PUTHEX(i,c) {i=(c);SENDBYTE(hex[((i)&0xF0)>>4]);SENDBYTE(hex[(i)&0xF]);}
  59.  
  60. /*--------------------------------------------------------------------------*/
  61. /* Private routines                                                         */
  62. /*--------------------------------------------------------------------------*/
  63.  
  64. static int LOCALFUNC _Z_GetBinaryHeader (unsigned char *);
  65. static int LOCALFUNC _Z_32GetBinaryHeader (unsigned char *);
  66. static int LOCALFUNC _Z_GetHexHeader (unsigned char *);
  67. static int LOCALFUNC _Z_GetHex (void);
  68. static int LOCALFUNC _Z_TimedRead (void);
  69. static long LOCALFUNC _Z_PullLongFromHeader (unsigned char *);
  70.  
  71. void 
  72. z_message (char *s)
  73. {
  74.     if (fullscreen && un_attended)
  75.     {
  76.         if (s)
  77.         {
  78.             sb_move (filewin, 2, 27);
  79.             sb_puts (filewin, s);
  80.         }
  81.         sb_puts (filewin, "              ");
  82.         sb_show ();
  83.     }
  84.     else
  85.     {
  86.         gotoxy (locate_x + 20, locate_y);
  87.         if (s)
  88.         {
  89.             (void) cputs (s);
  90.         }
  91.         (void) cputs ("               ");
  92.     }
  93. }
  94.  
  95. void 
  96. z_log (char *s)
  97. {
  98.     word x, y;
  99.  
  100.     z_message (s);
  101.  
  102.     x = locate_x;
  103.     y = locate_y;
  104.     status_line (s);            /* also does disk file logging */
  105.     locate_x = x;
  106.     locate_y = y;
  107. }
  108.  
  109. void 
  110. show_loc (unsigned long l, unsigned int w)
  111. {
  112.     char j[100];
  113.  
  114.     if (fullscreen && un_attended)
  115.     {
  116.  
  117.         (void) sprintf (j, "Ofs=%ld Retries=%d        ", l, w);
  118.         sb_move (filewin, 2, 37);
  119.         sb_puts (filewin, j);
  120.         sb_show ();
  121.     }
  122.     else
  123.     {
  124.         gotoxy (locate_x + 35, locate_y);
  125.         (void) printf ("Ofs=%ld Retries=%d        ", l, w);
  126.     }
  127. }
  128.  
  129. /*--------------------------------------------------------------------------*/
  130. /* Z GET BYTE                                                               */
  131. /* Get a byte from the modem;                                               */
  132. /* return TIMEOUT if no read within timeout tenths,                         */
  133. /* return RCDO if carrier lost                                              */
  134. /*--------------------------------------------------------------------------*/
  135.  
  136. int 
  137. Z_GetByte (int tenths)
  138. {
  139.     long timeout;
  140.  
  141.     if (PEEKBYTE () >= 0)
  142.         return (MODEM_IN ());
  143.  
  144.     timeout = timerset (tenths * 10);
  145.  
  146.     do
  147.     {
  148.         if (PEEKBYTE () >= 0)
  149.             return MODEM_IN ();
  150.  
  151.         if (!CARRIER)
  152.             return RCDO;
  153.  
  154.         if (got_ESC ())
  155.             return -1;
  156.  
  157.         time_release ();
  158.     }
  159.     while (!timeup (timeout));
  160.  
  161.     return TIMEOUT;
  162. }
  163.  
  164. /*--------------------------------------------------------------------------*/
  165. /* Z PUT STRING                                                             */
  166. /* Send a string to the modem, processing for \336 (sleep 1 sec)            */
  167. /* and \335 (break signal, ignored)                                         */
  168. /*--------------------------------------------------------------------------*/
  169.  
  170. void 
  171. Z_PutString (register unsigned char *s)
  172. {
  173.     register unsigned c;
  174.  
  175.     while (*s)
  176.     {
  177.         switch (c = *s++)
  178.         {
  179.         case (unsigned int) '\336':
  180.  
  181.             big_pause (2);
  182.             break;
  183.  
  184.         case (unsigned int) '\335':
  185.  
  186.             /* Should send a break on this */
  187.             break;
  188.  
  189.         default:
  190.  
  191.             SENDBYTE ((unsigned char) c);
  192.         }                            /* switch */
  193.  
  194.     }                                /* while */
  195.  
  196.     Z_UncorkTransmitter ();
  197. }                                    /* Z_PutString */
  198.  
  199. /*--------------------------------------------------------------------------*/
  200. /* Z SEND HEX HEADER                                                        */
  201. /* Send ZMODEM HEX header hdr of type type                                  */
  202. /*--------------------------------------------------------------------------*/
  203.  
  204. void 
  205. Z_SendHexHeader (unsigned int type, register unsigned char *hdr)
  206. {
  207.     register int n;
  208.     register int i;
  209.     register word crc;
  210.  
  211.     Z_UncorkTransmitter ();        /* Get our transmitter going */
  212.  
  213. #ifdef DEBUG
  214.     show_debug_name ("Z_SendHexHeader");
  215. #endif
  216.  
  217.     SENDBYTE (ZPAD);
  218.     SENDBYTE (ZPAD);
  219.     SENDBYTE (ZDLE);
  220.     SENDBYTE (ZHEX);
  221.  
  222.     Z_PUTHEX (i, type);
  223.  
  224.     Crc32t = 0;
  225.     crc = Z_UpdateCRC (type, 0);
  226.  
  227.     for (n = 4; --n >= 0;)
  228.     {
  229.         Z_PUTHEX (i, (*hdr));
  230.         crc = Z_UpdateCRC (((unsigned short) (*hdr++)), crc);
  231.     }
  232.     Z_PUTHEX (i, (crc >> 8));
  233.     Z_PUTHEX (i, crc);
  234.  
  235.     /* Make it printable on remote machine */
  236.  
  237.     SENDBYTE ('\r');
  238.     SENDBYTE ('\n');
  239.  
  240.     /* Uncork the remote in case a fake XOFF has stopped data flow */
  241.  
  242.     if (type != ZFIN && type != ZACK)
  243.         SENDBYTE (021);
  244.  
  245.     if (!CARRIER)
  246.         CLEAR_OUTBOUND ();
  247.  
  248. }                                /* Z_SendHexHeader */
  249.  
  250. /*--------------------------------------------------------------------------*/
  251. /* Z UNCORK TRANSMITTER                                                     */
  252. /* Wait a reasonable amount of time for transmitter buffer to clear.        */
  253. /*   When it does, or when time runs out, turn XON/XOFF off then on.        */
  254. /*   This should release a transmitter stuck by line errors.                */
  255. /*--------------------------------------------------------------------------*/
  256.  
  257. void 
  258. Z_UncorkTransmitter ()
  259. {
  260.     long t;
  261.  
  262. #ifdef DEBUG
  263.     show_debug_name ("Z_UncorkTransmitter");
  264. #endif
  265.  
  266.     if (!OUT_EMPTY () && CARRIER)
  267.     {
  268.         t = timerset (5 * Rxtimeout);    /* Wait for silence */
  269.  
  270.         while (!timeup (t) && !OUT_EMPTY () && CARRIER)
  271.             time_release ();                /* Give up slice while waiting  */
  272.     }
  273.  
  274.     com_kick ();
  275. }
  276.  
  277. /*--------------------------------------------------------------------------*/
  278. /* Z GET HEADER                                                             */
  279. /* Read a ZMODEM header to hdr, either binary or hex.                       */
  280. /*   On success, set Zmodem to 1 and return type of header.                 */
  281. /*   Otherwise return negative on error                                     */
  282. /*--------------------------------------------------------------------------*/
  283.  
  284. int 
  285. Z_GetHeader (byte * hdr)
  286. {
  287.     register int c;
  288.     unsigned long n;
  289.     int cancount;
  290.  
  291. #ifdef DEBUG
  292.     show_debug_name ("Z_GetHeader");
  293. #endif
  294.  
  295.     n = (unsigned long) cur_baud.rate_value;    /* Max characters before
  296.                                                   * start of frame */
  297.     cancount = 5;
  298.  
  299. Again:
  300.  
  301.     if (got_ESC ())
  302.     {
  303.         send_can ();
  304.         z_log (MSG_TXT (M_KBD_MSG));
  305.         return ZCAN;
  306.     }
  307.  
  308.     Rxframeind = Rxtype = 0;
  309.  
  310.     switch (c = _Z_TimedRead ())
  311.     {
  312.     case ZPAD:
  313.     case ZPAD | 0200:
  314.  
  315.         /*-----------------------------------------------*/
  316.         /* This is what we want.                         */
  317.         /*-----------------------------------------------*/
  318.  
  319.         break;
  320.  
  321.     case RCDO:
  322.     case TIMEOUT:
  323.  
  324.         goto Done;
  325.  
  326.     case CAN:
  327.  
  328. GotCan:
  329.  
  330.         if (--cancount <= 0)
  331.         {
  332.             c = ZCAN;
  333.             goto Done;
  334.         }
  335.         switch (c = Z_GetByte (1))
  336.         {
  337.         case TIMEOUT:
  338.  
  339.             goto Again;
  340.  
  341.         case ZCRCW:
  342.  
  343.             c = ERROR;
  344.  
  345.             /* fallthrough... */
  346.  
  347.         case RCDO:
  348.  
  349.             goto Done;
  350.  
  351.         case CAN:
  352.  
  353.             if (--cancount <= 0)
  354.             {
  355.                 c = ZCAN;
  356.                 goto Done;
  357.             }
  358.             goto Again;
  359.         }
  360.  
  361.         /* fallthrough... */
  362.  
  363.     default:
  364.  
  365. Agn2:
  366.  
  367.         if (--n <= 0)
  368.         {
  369.             z_log (MSG_TXT (M_FUBAR_MSG));
  370.             return ERROR;
  371.         }
  372.  
  373.         if (c != CAN)
  374.             cancount = 5;
  375.         goto Again;
  376.  
  377.     }                            /* switch */
  378.  
  379.     cancount = 5;
  380.  
  381. Splat:
  382.  
  383.     switch (c = _Z_TimedRead ())
  384.     {
  385.     case ZDLE:
  386.  
  387.         /*-----------------------------------------------*/
  388.         /* This is what we want.                         */
  389.         /*-----------------------------------------------*/
  390.  
  391.         break;
  392.  
  393.     case ZPAD:
  394.  
  395.         goto Splat;
  396.  
  397.     case RCDO:
  398.     case TIMEOUT:
  399.  
  400.         goto Done;
  401.  
  402.     default:
  403.  
  404.         goto Agn2;
  405.  
  406.     }                            /* switch */
  407.  
  408.     switch (c = _Z_TimedRead ())
  409.     {
  410.     case ZBIN:
  411.  
  412.         Rxframeind = ZBIN;
  413.         Crc32 = 0;
  414.         c = _Z_GetBinaryHeader (hdr);
  415.         break;
  416.  
  417.     case ZBIN32:
  418.  
  419.         Crc32 = Rxframeind = ZBIN32;
  420.         c = _Z_32GetBinaryHeader (hdr);
  421.         break;
  422.  
  423.     case ZHEX:
  424.  
  425.         Rxframeind = ZHEX;
  426.         Crc32 = 0;
  427.         c = _Z_GetHexHeader (hdr);
  428.         break;
  429.  
  430.     case CAN:
  431.  
  432.         goto GotCan;
  433.  
  434.     case RCDO:
  435.     case TIMEOUT:
  436.  
  437.         goto Done;
  438.  
  439.     default:
  440.  
  441.         goto Agn2;
  442.  
  443.     }                            /* switch */
  444.  
  445.     Rxpos = _Z_PullLongFromHeader (hdr);
  446.  
  447. Done:
  448.  
  449.     return c;
  450. }                                /* Z_GetHeader */
  451.  
  452. /*--------------------------------------------------------------------------*/
  453. /* Z GET BINARY HEADER                                                      */
  454. /* Receive a binary style header (type and position)                        */
  455. /*--------------------------------------------------------------------------*/
  456.  
  457. static int LOCALFUNC 
  458. _Z_GetBinaryHeader (register unsigned char *hdr)
  459. {
  460.     register int c;
  461.     register word crc;
  462.     register int n;
  463.  
  464. #ifdef DEBUG
  465.     show_debug_name ("Z_GetBinaryHeader");
  466. #endif
  467.  
  468.     if ((c = Z_GetZDL ()) & ~0xFF)
  469.         return c;
  470.     Rxtype = c;
  471.     crc = Z_UpdateCRC (c, 0);
  472.  
  473.     for (n = 4; --n >= 0;)
  474.     {
  475.         if ((c = Z_GetZDL ()) & ~0xFF)
  476.             return c;
  477.         crc = Z_UpdateCRC (c, crc);
  478.         *hdr++ = (unsigned char) (c & 0xff);
  479.     }
  480.     if ((c = Z_GetZDL ()) & ~0xFF)
  481.         return c;
  482.  
  483.     crc = Z_UpdateCRC (c, crc);
  484.     if ((c = Z_GetZDL ()) & ~0xFF)
  485.         return c;
  486.  
  487.     crc = Z_UpdateCRC (c, crc);
  488.     if (crc & 0xFFFF)
  489.     {
  490.         z_message (MSG_TXT (M_CRC_MSG));
  491.         return ERROR;
  492.     }
  493.  
  494.     return Rxtype;
  495. }                                /* _Z_GetBinaryHeader */
  496.  
  497. /*--------------------------------------------------------------------------*/
  498. /* Z GET BINARY HEADER with 32 bit CRC                                      */
  499. /* Receive a binary style header (type and position)                        */
  500. /*--------------------------------------------------------------------------*/
  501.  
  502. static int LOCALFUNC 
  503. _Z_32GetBinaryHeader (register unsigned char *hdr)
  504. {
  505.     register int c;
  506.     register unsigned long crc;
  507.     register int n;
  508.  
  509. #ifdef DEBUG
  510.     show_debug_name ("Z_32GetBinaryHeader");
  511. #endif
  512.  
  513.     if ((c = Z_GetZDL ()) & ~0xFF)
  514.         return c;
  515.     Rxtype = c;
  516.     crc = 0xFFFFFFFF;
  517.     crc = Z_32UpdateCRC (c, crc);
  518.  
  519.     for (n = 4; --n >= 0;)
  520.     {
  521.         if ((c = Z_GetZDL ()) & ~0xFF)
  522.             return c;
  523.         crc = Z_32UpdateCRC (c, crc);
  524.         *hdr++ = (unsigned char) (c & 0xff);
  525.     }
  526.  
  527.     for (n = 4; --n >= 0;)
  528.     {
  529.         if ((c = Z_GetZDL ()) & ~0xFF)
  530.             return c;
  531.  
  532.         crc = Z_32UpdateCRC (c, crc);
  533.     }
  534.  
  535.     if (crc != 0xDEBB20E3)
  536.     {
  537.         z_message (MSG_TXT (M_CRC_MSG));
  538.         return ERROR;
  539.     }
  540.  
  541.     return Rxtype;
  542. }                                /* _Z_32GetBinaryHeader */
  543.  
  544. /*--------------------------------------------------------------------------*/
  545. /* Z GET HEX HEADER                                                         */
  546. /* Receive a hex style header (type and position)                           */
  547. /*--------------------------------------------------------------------------*/
  548.  
  549. static int LOCALFUNC 
  550. _Z_GetHexHeader (register unsigned char *hdr)
  551. {
  552.     register int c;
  553.     register word crc;
  554.     register int n;
  555.  
  556. #ifdef DEBUG
  557.     show_debug_name ("Z_GetHexHeader");
  558. #endif
  559.  
  560.     if ((c = _Z_GetHex ()) < 0)
  561.         return c;
  562.     Rxtype = c;
  563.     crc = Z_UpdateCRC (c, 0);
  564.  
  565.     for (n = 4; --n >= 0;)
  566.     {
  567.         if ((c = _Z_GetHex ()) < 0)
  568.             return c;
  569.         crc = Z_UpdateCRC (c, crc);
  570.         *hdr++ = (unsigned char) c;
  571.     }
  572.  
  573.     if ((c = _Z_GetHex ()) < 0)
  574.         return c;
  575.     crc = Z_UpdateCRC (c, crc);
  576.     if ((c = _Z_GetHex ()) < 0)
  577.         return c;
  578.     crc = Z_UpdateCRC (c, crc);
  579.     if (crc & 0xFFFF)
  580.     {
  581.         z_message (MSG_TXT (M_CRC_MSG));
  582.         return ERROR;
  583.     }
  584.     if (Z_GetByte (1) == '\r')
  585.         (void) Z_GetByte (1);    /* Throw away possible cr/lf */
  586.  
  587.     return Rxtype;
  588. }
  589.  
  590. /*--------------------------------------------------------------------------*/
  591. /* Z GET HEX                                                                */
  592. /* Decode two lower case hex digits into an 8 bit byte value                */
  593. /*--------------------------------------------------------------------------*/
  594.  
  595. static int LOCALFUNC 
  596. _Z_GetHex ()
  597. {
  598.     register int c, n;
  599.  
  600. #ifdef DEBUG
  601.     show_debug_name ("Z_GetHex");
  602. #endif
  603.  
  604.     if ((n = _Z_TimedRead ()) < 0)
  605.         return n;
  606.     n -= '0';
  607.     if (n > 9)
  608.         n -= ('a' - ':');
  609.     if (n & ~0xF)
  610.         return ERROR;
  611.  
  612.     if ((c = _Z_TimedRead ()) < 0)
  613.         return c;
  614.     c -= '0';
  615.     if (c > 9)
  616.         c -= ('a' - ':');
  617.     if (c & ~0xF)
  618.         return ERROR;
  619.  
  620.     return ((n << 4) | c);
  621. }
  622.  
  623. /*--------------------------------------------------------------------------*/
  624. /* Z GET ZDL                                                                */
  625. /* Read a byte, checking for ZMODEM escape encoding                         */
  626. /* including CAN*5 which represents a quick abort                           */
  627. /*--------------------------------------------------------------------------*/
  628.  
  629. int 
  630. Z_GetZDL ()
  631. {
  632.     register int c;
  633.  
  634.     if ((c = Z_GetByte (Rxtimeout)) != ZDLE)
  635.         return c;
  636.  
  637.     switch (c = Z_GetByte (Rxtimeout))
  638.     {
  639.     case CAN:
  640.  
  641.         return ((c = Z_GetByte (Rxtimeout)) < 0) ? c :
  642.             ((c == CAN) && ((c = Z_GetByte (Rxtimeout)) < 0)) ? c :
  643.             ((c == CAN) && ((c = Z_GetByte (Rxtimeout)) < 0)) ? c : (GOTCAN);
  644.  
  645.     case ZCRCE:
  646.     case ZCRCG:
  647.     case ZCRCQ:
  648.     case ZCRCW:
  649.  
  650.         return (c | GOTOR);
  651.  
  652.     case ZRUB0:
  653.  
  654.         return 0x7F;
  655.  
  656.     case ZRUB1:
  657.  
  658.         return 0xFF;
  659.  
  660.     default:
  661.  
  662.         return (c < 0) ? c :
  663.             ((c & 0x60) == 0x40) ? (c ^ 0x40) : ERROR;
  664.  
  665.     }                            /* switch */
  666. }                                /* Z_GetZDL */
  667.  
  668. /*--------------------------------------------------------------------------*/
  669. /* Z TIMED READ                                                             */
  670. /* Read a character from the modem line with timeout.                       */
  671. /*  Eat parity, XON and XOFF characters.                                    */
  672. /*--------------------------------------------------------------------------*/
  673.  
  674. static int LOCALFUNC 
  675. _Z_TimedRead ()
  676. {
  677.     register int c;
  678.  
  679. #ifdef DEBUG
  680.     show_debug_name ("Z_TimedRead");
  681. #endif
  682.  
  683.     for (;;)
  684.     {
  685.         if ((c = Z_GetByte (Rxtimeout)) < 0)
  686.             return c;
  687.  
  688.         switch (c &= 0x7F)
  689.         {
  690.         case XON:
  691.         case XOFF:
  692.  
  693.             continue;
  694.  
  695.         default:
  696.  
  697.             if (!(c & 0x60))
  698.                 continue;
  699.  
  700.             /* Else fall through */
  701.  
  702.         case '\r':
  703.         case '\n':
  704.         case ZDLE:
  705.  
  706.             return c;
  707.         }                        /* switch */
  708.  
  709.     }                            /* for */
  710. }                                /* _Z_TimedRead */
  711.  
  712. /*--------------------------------------------------------------------------*/
  713. /* Z LONG TO HEADER                                                         */
  714. /* Store long integer pos in Txhdr                                          */
  715. /*--------------------------------------------------------------------------*/
  716.  
  717. void 
  718. Z_PutLongIntoHeader (long pos)
  719. {
  720. #ifndef GENERIC
  721.     *((long *) Txhdr) = pos;
  722. #else
  723.     Txhdr[ZP0] = pos;
  724.     Txhdr[ZP1] = pos >> 8;
  725.     Txhdr[ZP2] = pos >> 16;
  726.     Txhdr[ZP3] = pos >> 24;
  727. #endif
  728. }                                /* Z_PutLongIntoHeader */
  729.  
  730. /*--------------------------------------------------------------------------*/
  731. /* Z PULL LONG FROM HEADER                                                  */
  732. /* Recover a long integer from a header                                     */
  733. /*--------------------------------------------------------------------------*/
  734.  
  735. static long LOCALFUNC 
  736. _Z_PullLongFromHeader (unsigned char *hdr)
  737. {
  738. #ifndef GENERIC
  739.     return (*((long *) hdr));    /*PLF Fri  05-05-1989  06:42:41 */
  740. #else
  741.  
  742.     long l;
  743.  
  744.     l = hdr[ZP3];
  745.     l = (l << 8) | hdr[ZP2];
  746.     l = (l << 8) | hdr[ZP1];
  747.     l = (l << 8) | hdr[ZP0];
  748.     return l;
  749. #endif
  750. }                                /* _Z_PullLongFromHeader */
  751.  
  752. /* END OF FILE: zmisc.c */
  753.