zm.c

Go to the documentation of this file.
00001 /*
00002  *   Z M . C
00003  *    ZMODEM protocol primitives
00004  *    05-09-88  Chuck Forsberg Omen Technology Inc
00005  *
00006  * Entry point Functions:
00007  *      zsbhdr(type, hdr) send binary header
00008  *      zshhdr(type, hdr) send hex header
00009  *      zgethdr(hdr, eflag) receive header - binary or hex
00010  *      zsdata(buf, len, frameend) send data
00011  *      zrdata(buf, len) receive data
00012  *      stohdr(pos) store position data in Txhdr
00013  *      long rclhdr(hdr) recover position offset from header
00014  */
00015 
00016 #ifndef CANFDX
00017 #include "zmodem.h"
00018 #endif
00019 int Rxtimeout = 100;            /* Tenths of seconds to wait for something */
00020 
00021 #ifndef UNSL
00022 #define UNSL
00023 #endif
00024 
00025 
00026 /* Globals used by ZMODEM functions */
00027 int Rxframeind;         /* ZBIN ZBIN32, or ZHEX type of frame received */
00028 int Rxtype;             /* Type of header received */
00029 int Rxcount;            /* Count of data bytes received */
00030 char Rxhdr[4];          /* Received header */
00031 char Txhdr[4];          /* Transmitted header */
00032 long Rxpos;             /* Received file position */
00033 long Txpos;             /* Transmitted file position */
00034 int Txfcs32;            /* TURE means send binary frames with 32 bit FCS */
00035 int Crc32t;             /* Display flag indicating 32 bit CRC being sent */
00036 int Crc32;              /* Display flag indicating 32 bit CRC being received */
00037 int Znulls;             /* Number of nulls to send at beginning of ZDATA hdr */
00038 char Attn[ZATTNLEN+1];  /* Attention string rx sends to tx on err */
00039 
00040 static lastsent;        /* Last char we sent */
00041 static Not8bit;         /* Seven bits seen on header */
00042 
00043 static char *frametypes[] = {
00044         "Carrier Lost",         /* -3 */
00045         "TIMEOUT",              /* -2 */
00046         "ERROR",                /* -1 */
00047 #define FTOFFSET 3
00048         "ZRQINIT",
00049         "ZRINIT",
00050         "ZSINIT",
00051         "ZACK",
00052         "ZFILE",
00053         "ZSKIP",
00054         "ZNAK",
00055         "ZABORT",
00056         "ZFIN",
00057         "ZRPOS",
00058         "ZDATA",
00059         "ZEOF",
00060         "ZFERR",
00061         "ZCRC",
00062         "ZCHALLENGE",
00063         "ZCOMPL",
00064         "ZCAN",
00065         "ZFREECNT",
00066         "ZCOMMAND",
00067         "ZSTDERR",
00068         "xxxxx"
00069 #define FRTYPES 22      /* Total number of frame types in this array */
00070                         /*  not including psuedo negative entries */
00071 };
00072 
00073 static char badcrc[] = "Bad CRC";
00074 
00075 /* Send ZMODEM binary header hdr of type type */
00076 void zsbhdr(type, hdr)
00077 int type;
00078 register char *hdr;
00079 {
00080         register int n;
00081         register unsigned short crc;
00082 
00083         vfile("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
00084         if (type == ZDATA)
00085                 for (n = Znulls; --n >=0; )
00086                         xsendline(0);
00087 
00088         xsendline(ZPAD); xsendline(ZDLE);
00089 
00090         if (Crc32t=Txfcs32)
00091                 zsbh32(hdr, type);
00092         else {
00093                 xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
00094 
00095                 for (n=4; --n >= 0; ++hdr) {
00096                         zsendline(*hdr);
00097                         crc = updcrc((0377& *hdr), crc);
00098                 }
00099                 crc = updcrc(0,updcrc(0,crc));
00100                 zsendline(crc>>8);
00101                 zsendline(crc);
00102         }
00103         if (type != ZDATA)
00104                 flushmo();
00105 }
00106 
00107 
00108 /* Send ZMODEM binary header hdr of type type */
00109 void zsbh32(hdr, type)
00110 register char *hdr;
00111 int type;
00112 {
00113         register int n;
00114         register UNSL long crc;
00115 
00116         xsendline(ZBIN32);  zsendline(type);
00117         crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
00118 
00119         for (n=4; --n >= 0; ++hdr) {
00120                 crc = UPDC32((0377 & *hdr), crc);
00121                 zsendline(*hdr);
00122         }
00123         crc = ~crc;
00124         for (n=4; --n >= 0;) {
00125                 zsendline((int)crc);
00126                 crc >>= 8;
00127         }
00128 }
00129 
00130 /* Send ZMODEM HEX header hdr of type type */
00131 void zshhdr(type, hdr)
00132 int type;
00133 register char *hdr;
00134 {
00135         register int n;
00136         register unsigned short crc;
00137 
00138         vfile("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
00139         sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
00140         zputhex(type);
00141         Crc32t = 0;
00142 
00143         crc = updcrc(type, 0);
00144         for (n=4; --n >= 0; ++hdr) {
00145                 zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
00146         }
00147         crc = updcrc(0,updcrc(0,crc));
00148         zputhex(crc>>8); zputhex(crc);
00149 
00150         /* Make it printable on remote machine */
00151         sendline(015); sendline(0212);
00152         /*
00153          * Uncork the remote in case a fake XOFF has stopped data flow
00154          */
00155         if (type != ZFIN && type != ZACK)
00156                 sendline(021);
00157         flushmo();
00158 }
00159 
00160 /*
00161  * Send binary array buf of length length, with ending ZDLE sequence frameend
00162  */
00163 static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
00164 
00165 void zsdata(buf, length, frameend)
00166 register char *buf;
00167 int length;
00168 int frameend;
00169 {
00170         register unsigned short crc;
00171 
00172         vfile("zsdata: %d %s", length, Zendnames[(frameend-ZCRCE)&3]);
00173         if (Crc32t)
00174                 zsda32(buf, length, frameend);
00175         else {
00176                 crc = 0;
00177                 for (;--length >= 0; ++buf) {
00178                         zsendline(*buf); crc = updcrc((0377 & *buf), crc);
00179                 }
00180                 xsendline(ZDLE); xsendline(frameend);
00181                 crc = updcrc(frameend, crc);
00182 
00183                 crc = updcrc(0,updcrc(0,crc));
00184                 zsendline(crc>>8); zsendline(crc);
00185         }
00186         if (frameend == ZCRCW) {
00187                 xsendline(XON);  flushmo();
00188         }
00189 }
00190 
00191 void zsda32(buf, length, frameend)
00192 register char *buf;
00193 int length;
00194 int frameend;
00195 {
00196         register int c;
00197         register UNSL long crc;
00198 
00199         crc = 0xFFFFFFFFL;
00200         for (;--length >= 0; ++buf) {
00201                 c = *buf & 0377;
00202                 if (c & 0140)
00203                         xsendline(lastsent = c);
00204                 else
00205                         zsendline(c);
00206                 crc = UPDC32(c, crc);
00207         }
00208         xsendline(ZDLE); xsendline(frameend);
00209         crc = UPDC32(frameend, crc);
00210 
00211         crc = ~crc;
00212         for (length=4; --length >= 0;) {
00213                 zsendline((int)crc);  crc >>= 8;
00214         }
00215 }
00216 
00217 /*
00218  * Receive array buf of max length with ending ZDLE sequence
00219  *  and CRC.  Returns the ending character or error code.
00220  *  NB: On errors may store length+1 bytes!
00221  */
00222 int zrdata(buf, length)
00223 register char *buf;
00224 int length;
00225 {
00226         register int c;
00227         register unsigned short crc;
00228         register char *end;
00229         register int d;
00230 
00231         if (Rxframeind == ZBIN32)
00232                 return zrdat32(buf, length);
00233 
00234         crc = Rxcount = 0;  end = buf + length;
00235         while (buf <= end) {
00236                 if ((c = zdlread()) & ~0377) {
00237 crcfoo:
00238                         switch (c) {
00239                         case GOTCRCE:
00240                         case GOTCRCG:
00241                         case GOTCRCQ:
00242                         case GOTCRCW:
00243                                 crc = updcrc((d=c)&0377, crc);
00244                                 if ((c = zdlread()) & ~0377)
00245                                         goto crcfoo;
00246                                 crc = updcrc(c, crc);
00247                                 if ((c = zdlread()) & ~0377)
00248                                         goto crcfoo;
00249                                 crc = updcrc(c, crc);
00250                                 if (crc & 0xFFFF) {
00251                                         zperr(badcrc);
00252                                         return ERROR;
00253                                 }
00254                                 Rxcount = length - (end - buf);
00255                                 vfile("zrdata: %d  %s", Rxcount,
00256                                  Zendnames[(d-GOTCRCE)&3]);
00257                                 return d;
00258                         case GOTCAN:
00259                                 zperr("Sender Canceled");
00260                                 return ZCAN;
00261                         case TIMEOUT:
00262                                 zperr("TIMEOUT");
00263                                 return c;
00264                         default:
00265                                 zperr("Bad data subpacket");
00266                                 return c;
00267                         }
00268                 }
00269                 *buf++ = c;
00270                 crc = updcrc(c, crc);
00271         }
00272         zperr("Data subpacket too long");
00273         return ERROR;
00274 }
00275 
00276 int zrdat32(buf, length)
00277 register char *buf;
00278 int length;
00279 {
00280         register int c;
00281         register UNSL long crc;
00282         register char *end;
00283         register int d;
00284 
00285         crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
00286         while (buf <= end) {
00287                 if ((c = zdlread()) & ~0377) {
00288 crcfoo:
00289                         switch (c) {
00290                         case GOTCRCE:
00291                         case GOTCRCG:
00292                         case GOTCRCQ:
00293                         case GOTCRCW:
00294                                 d = c;  c &= 0377;
00295                                 crc = UPDC32(c, crc);
00296                                 if ((c = zdlread()) & ~0377)
00297                                         goto crcfoo;
00298                                 crc = UPDC32(c, crc);
00299                                 if ((c = zdlread()) & ~0377)
00300                                         goto crcfoo;
00301                                 crc = UPDC32(c, crc);
00302                                 if ((c = zdlread()) & ~0377)
00303                                         goto crcfoo;
00304                                 crc = UPDC32(c, crc);
00305                                 if ((c = zdlread()) & ~0377)
00306                                         goto crcfoo;
00307                                 crc = UPDC32(c, crc);
00308                                 if (crc != 0xDEBB20E3) {
00309                                         zperr(badcrc);
00310                                         return ERROR;
00311                                 }
00312                                 Rxcount = length - (end - buf);
00313                                 vfile("zrdat32: %d %s", Rxcount,
00314                                  Zendnames[(d-GOTCRCE)&3]);
00315                                 return d;
00316                         case GOTCAN:
00317                                 zperr("Sender Canceled");
00318                                 return ZCAN;
00319                         case TIMEOUT:
00320                                 zperr("TIMEOUT");
00321                                 return c;
00322                         default:
00323                                 zperr("Bad data subpacket");
00324                                 return c;
00325                         }
00326                 }
00327                 *buf++ = c;
00328                 crc = UPDC32(c, crc);
00329         }
00330         zperr("Data subpacket too long");
00331         return ERROR;
00332 }
00333 
00334 
00335 /*
00336  * Read a ZMODEM header to hdr, either binary or hex.
00337  *  eflag controls local display of non zmodem characters:
00338  *      0:  no display
00339  *      1:  display printing characters only
00340  *      2:  display all non ZMODEM characters
00341  *  On success, set Zmodem to 1, set Rxpos and return type of header.
00342  *   Otherwise return negative on error.
00343  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
00344  */
00345 int zgethdr(hdr, eflag)
00346 char *hdr;
00347 int eflag;
00348 {
00349         register int c, n, cancount;
00350 
00351         n = Zrwindow + Baudrate;        /* Max bytes before start of frame */
00352         Rxframeind = Rxtype = 0;
00353 
00354 startover:
00355         cancount = 5;
00356 again:
00357         /* Return immediate ERROR if ZCRCW sequence seen */
00358         switch (c = readline(Rxtimeout)) {
00359         case RCDO:
00360         case TIMEOUT:
00361                 goto fifi;
00362         case CAN:
00363 gotcan:
00364                 if (--cancount <= 0) {
00365                         c = ZCAN; goto fifi;
00366                 }
00367                 switch (c = readline(1)) {
00368                 case TIMEOUT:
00369                         goto again;
00370                 case ZCRCW:
00371                         c = ERROR;
00372                 /* **** FALL THRU TO **** */
00373                 case RCDO:
00374                         goto fifi;
00375                 default:
00376                         break;
00377                 case CAN:
00378                         if (--cancount <= 0) {
00379                                 c = ZCAN; goto fifi;
00380                         }
00381                         goto again;
00382                 }
00383         /* **** FALL THRU TO **** */
00384         default:
00385 agn2:
00386                 if ( --n == 0) {
00387                         zperr("Garbage count exceeded");
00388                         return(ERROR);
00389                 }
00390                 if (eflag && ((c &= 0177) & 0140))
00391                         bttyout(c);
00392                 else if (eflag > 1)
00393                         bttyout(c);
00394 #ifdef UNIX
00395                 fflush(stderr);
00396 #endif
00397                 goto startover;
00398         case ZPAD|0200:         /* This is what we want. */
00399                 Not8bit = c;
00400         case ZPAD:              /* This is what we want. */
00401                 break;
00402         }
00403         cancount = 5;
00404 splat:
00405         switch (c = noxrd7()) {
00406         case ZPAD:
00407                 goto splat;
00408         case RCDO:
00409         case TIMEOUT:
00410                 goto fifi;
00411         default:
00412                 goto agn2;
00413         case ZDLE:              /* This is what we want. */
00414                 break;
00415         }
00416 
00417         switch (c = noxrd7()) {
00418         case RCDO:
00419         case TIMEOUT:
00420                 goto fifi;
00421         case ZBIN:
00422                 Rxframeind = ZBIN;  Crc32 = FALSE;
00423                 c =  zrbhdr(hdr);
00424                 break;
00425         case ZBIN32:
00426                 Crc32 = Rxframeind = ZBIN32;
00427                 c =  zrbhdr32(hdr);
00428                 break;
00429         case ZHEX:
00430                 Rxframeind = ZHEX;  Crc32 = FALSE;
00431                 c =  zrhhdr(hdr);
00432                 break;
00433         case CAN:
00434                 goto gotcan;
00435         default:
00436                 goto agn2;
00437         }
00438         Rxpos = hdr[ZP3] & 0377;
00439         Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
00440         Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
00441         Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
00442 fifi:
00443         switch (c) {
00444         case GOTCAN:
00445                 c = ZCAN;
00446         /* **** FALL THRU TO **** */
00447         case ZNAK:
00448         case ZCAN:
00449         case ERROR:
00450         case TIMEOUT:
00451         case RCDO:
00452                 zperr("Got %s", frametypes[c+FTOFFSET]);
00453         /* **** FALL THRU TO **** */
00454         default:
00455                 if (c >= -3 && c <= FRTYPES)
00456                         vfile("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
00457                 else
00458                         vfile("zgethdr: %d %lx", c, Rxpos);
00459         }
00460         return c;
00461 }
00462 
00463 /* Receive a binary style header (type and position) */
00464 int zrbhdr(hdr)
00465 register char *hdr;
00466 {
00467         register int c, n;
00468         register unsigned short crc;
00469 
00470         if ((c = zdlread()) & ~0377)
00471                 return c;
00472         Rxtype = c;
00473         crc = updcrc(c, 0);
00474 
00475         for (n=4; --n >= 0; ++hdr) {
00476                 if ((c = zdlread()) & ~0377)
00477                         return c;
00478                 crc = updcrc(c, crc);
00479                 *hdr = c;
00480         }
00481         if ((c = zdlread()) & ~0377)
00482                 return c;
00483         crc = updcrc(c, crc);
00484         if ((c = zdlread()) & ~0377)
00485                 return c;
00486         crc = updcrc(c, crc);
00487         if (crc & 0xFFFF) {
00488                 zperr(badcrc);
00489                 return ERROR;
00490         }
00491 #ifdef ZMODEM
00492         Protocol = ZMODEM;
00493 #endif
00494         Zmodem = 1;
00495         return Rxtype;
00496 }
00497 
00498 /* Receive a binary style header (type and position) with 32 bit FCS */
00499 int zrbhdr32(hdr)
00500 register char *hdr;
00501 {
00502         register int c, n;
00503         register UNSL long crc;
00504 
00505         if ((c = zdlread()) & ~0377)
00506                 return c;
00507         Rxtype = c;
00508         crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
00509 #ifdef DEBUGZ
00510         vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
00511 #endif
00512 
00513         for (n=4; --n >= 0; ++hdr) {
00514                 if ((c = zdlread()) & ~0377)
00515                         return c;
00516                 crc = UPDC32(c, crc);
00517                 *hdr = c;
00518 #ifdef DEBUGZ
00519                 vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
00520 #endif
00521         }
00522         for (n=4; --n >= 0;) {
00523                 if ((c = zdlread()) & ~0377)
00524                         return c;
00525                 crc = UPDC32(c, crc);
00526 #ifdef DEBUGZ
00527                 vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
00528 #endif
00529         }
00530         if (crc != 0xDEBB20E3) {
00531                 zperr(badcrc);
00532                 return ERROR;
00533         }
00534 #ifdef ZMODEM
00535         Protocol = ZMODEM;
00536 #endif
00537         Zmodem = 1;
00538         return Rxtype;
00539 }
00540 
00541 
00542 /* Receive a hex style header (type and position) */
00543 int zrhhdr(hdr)
00544 char *hdr;
00545 {
00546         register int c;
00547         register unsigned short crc;
00548         register int n;
00549 
00550         if ((c = zgethex()) < 0)
00551                 return c;
00552         Rxtype = c;
00553         crc = updcrc(c, 0);
00554 
00555         for (n=4; --n >= 0; ++hdr) {
00556                 if ((c = zgethex()) < 0)
00557                         return c;
00558                 crc = updcrc(c, crc);
00559                 *hdr = c;
00560         }
00561         if ((c = zgethex()) < 0)
00562                 return c;
00563         crc = updcrc(c, crc);
00564         if ((c = zgethex()) < 0)
00565                 return c;
00566         crc = updcrc(c, crc);
00567         if (crc & 0xFFFF) {
00568                 zperr(badcrc); return ERROR;
00569         }
00570         switch ( c = readline(1)) {
00571         case 0215:
00572                 Not8bit = c;
00573                 /* **** FALL THRU TO **** */
00574         case 015:
00575                 /* Throw away possible cr/lf */
00576                 switch (c = readline(1)) {
00577                 case 012:
00578                         Not8bit |= c;
00579                 }
00580         }
00581 #ifdef ZMODEM
00582         Protocol = ZMODEM;
00583 #endif
00584         Zmodem = 1; return Rxtype;
00585 }
00586 
00587 /* Send a byte as two hex digits */
00588 void zputhex(c)
00589 register int c;
00590 {
00591         static char     digits[]        = "0123456789abcdef";
00592 
00593         if (Verbose>8)
00594                 vfile("zputhex: %02X", c);
00595         sendline(digits[(c&0xF0)>>4]);
00596         sendline(digits[(c)&0xF]);
00597 }
00598 
00599 /*
00600  * Send character c with ZMODEM escape sequence encoding.
00601  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
00602  */
00603 void zsendline(c)
00604 int c;
00605 {
00606 
00607         /* Quick check for non control characters */
00608         if (c & 0140)
00609                 xsendline(lastsent = c);
00610         else {
00611                 switch (c &= 0377) {
00612                 case ZDLE:
00613                         xsendline(ZDLE);
00614                         xsendline (lastsent = (c ^= 0100));
00615                         break;
00616                 case 015:
00617                 case 0215:
00618                         if (!Zctlesc && (lastsent & 0177) != '@')
00619                                 goto sendit;
00620                 /* **** FALL THRU TO **** */
00621                 case 020:
00622                 case 021:
00623                 case 023:
00624                 case 0220:
00625                 case 0221:
00626                 case 0223:
00627                         xsendline(ZDLE);
00628                         c ^= 0100;
00629         sendit:
00630                         xsendline(lastsent = c);
00631                         break;
00632                 default:
00633                         if (Zctlesc && ! (c & 0140)) {
00634                                 xsendline(ZDLE);
00635                                 c ^= 0100;
00636                         }
00637                         xsendline(lastsent = c);
00638                 }
00639         }
00640 }
00641 
00642 /* Decode two lower case hex digits into an 8 bit byte value */
00643 int zgethex()
00644 {
00645         register int c;
00646 
00647         c = zgeth1();
00648         if (Verbose>8)
00649                 vfile("zgethex: %02X", c);
00650         return c;
00651 }
00652 int zgeth1()
00653 {
00654         register int c, n;
00655 
00656         if ((c = noxrd7()) < 0)
00657                 return c;
00658         n = c - '0';
00659         if (n > 9)
00660                 n -= ('a' - ':');
00661         if (n & ~0xF)
00662                 return ERROR;
00663         if ((c = noxrd7()) < 0)
00664                 return c;
00665         c -= '0';
00666         if (c > 9)
00667                 c -= ('a' - ':');
00668         if (c & ~0xF)
00669                 return ERROR;
00670         c += (n<<4);
00671         return c;
00672 }
00673 
00674 /*
00675  * Read a byte, checking for ZMODEM escape encoding
00676  *  including CAN*5 which represents a quick abort
00677  */
00678 int zdlread()
00679 {
00680         register int c;
00681 
00682 again:
00683         /* Quick check for non control characters */
00684         if ((c = readline(Rxtimeout)) & 0140)
00685                 return c;
00686         switch (c) {
00687         case ZDLE:
00688                 break;
00689         case 023:
00690         case 0223:
00691         case 021:
00692         case 0221:
00693                 goto again;
00694         default:
00695                 if (Zctlesc && !(c & 0140)) {
00696                         goto again;
00697                 }
00698                 return c;
00699         }
00700 again2:
00701         if ((c = readline(Rxtimeout)) < 0)
00702                 return c;
00703         if (c == CAN && (c = readline(Rxtimeout)) < 0)
00704                 return c;
00705         if (c == CAN && (c = readline(Rxtimeout)) < 0)
00706                 return c;
00707         if (c == CAN && (c = readline(Rxtimeout)) < 0)
00708                 return c;
00709         switch (c) {
00710         case CAN:
00711                 return GOTCAN;
00712         case ZCRCE:
00713         case ZCRCG:
00714         case ZCRCQ:
00715         case ZCRCW:
00716                 return (c | GOTOR);
00717         case ZRUB0:
00718                 return 0177;
00719         case ZRUB1:
00720                 return 0377;
00721         case 023:
00722         case 0223:
00723         case 021:
00724         case 0221:
00725                 goto again2;
00726         default:
00727                 if (Zctlesc && ! (c & 0140)) {
00728                         goto again2;
00729                 }
00730                 if ((c & 0140) ==  0100)
00731                         return (c ^ 0100);
00732                 break;
00733         }
00734         if (Verbose>1)
00735                 zperr("Bad escape sequence %x", c);
00736         return ERROR;
00737 }
00738 
00739 /*
00740  * Read a character from the modem line with timeout.
00741  *  Eat parity, XON and XOFF characters.
00742  */
00743 int noxrd7()
00744 {
00745         register int c;
00746 
00747         for (;;) {
00748                 if ((c = readline(Rxtimeout)) < 0)
00749                         return c;
00750                 switch (c &= 0177) {
00751                 case XON:
00752                 case XOFF:
00753                         continue;
00754                 default:
00755                         if (Zctlesc && !(c & 0140))
00756                                 continue;
00757                 case '\r':
00758                 case '\n':
00759                 case ZDLE:
00760                         return c;
00761                 }
00762         }
00763 }
00764 
00765 /* Store long integer pos in Txhdr */
00766 void stohdr(pos)
00767 long pos;
00768 {
00769         Txhdr[ZP0] = pos;
00770         Txhdr[ZP1] = pos>>8;
00771         Txhdr[ZP2] = pos>>16;
00772         Txhdr[ZP3] = pos>>24;
00773 }
00774 
00775 /* Recover a long integer from a header */
00776 long
00777 rclhdr(hdr)
00778 register char *hdr;
00779 {
00780         register long l;
00781 
00782         l = (hdr[ZP3] & 0377);
00783         l = (l << 8) | (hdr[ZP2] & 0377);
00784         l = (l << 8) | (hdr[ZP1] & 0377);
00785         l = (l << 8) | (hdr[ZP0] & 0377);
00786         return l;
00787 }
00788 
00789 /* End of zm.c */

Generated on Fri Apr 14 22:57:14 2006 for minix by  doxygen 1.4.6