Annotation of researchv10no/cmd/pack/unpack.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *     Huffman decompressor
                      3:  *     Usage:  pcat filename...
                      4:  *     or      unpack filename...
                      5:  */
                      6: 
                      7: static char unpackvers[] = "@(#)unpack.c       1.10";
                      8: 
                      9: #include <stdio.h>
                     10: #include <setjmp.h>
                     11: #include <sys/types.h>
                     12: #include <sys/stat.h>
                     13: 
                     14: #define VOID (void)
                     15: 
                     16: jmp_buf env;
                     17: struct stat status;
                     18: char   *argv0, *argvk;
                     19: short  errorm;
                     20: 
                     21: #define NAMELEN 80
                     22: #define SUF0   '.'
                     23: #define SUF1   'z'
                     24: #define US     037
                     25: #define RS     036
                     26: 
                     27: #define        BLKSIZE BUFSIZ
                     28: 
                     29: 
                     30: /* variables associated with i/o */
                     31: char   filename[NAMELEN+2];
                     32: short  infile;
                     33: short  outfile;
                     34: short  inleft;
                     35: char   *inp;
                     36: char   *outp;
                     37: char   inbuff[BUFSIZ];
                     38: char   outbuff[BUFSIZ];
                     39: 
                     40: /* the dictionary */
                     41: long   origsize;
                     42: short  maxlev;
                     43: short  intnodes[25];
                     44: char   *tree[25];
                     45: char   characters[256];
                     46: char   *eof;
                     47: 
                     48: /* read in the dictionary portion and build decoding structures */
                     49: /* return 1 if successful, 0 otherwise */
                     50: getdict ()
                     51: {
                     52:        register int c, i, nchildren;
                     53: 
                     54:        /*
                     55:         * check two-byte header
                     56:         * get size of original file,
                     57:         * get number of levels in maxlev,
                     58:         * get number of leaves on level i in intnodes[i],
                     59:         * set tree[i] to point to leaves for level i
                     60:         */
                     61:        eof = &characters[0];
                     62: 
                     63:        inbuff[6] = 25;
                     64:        inleft = read (infile, &inbuff[0], BUFSIZ);
                     65:        if (inleft < 0) {
                     66:                eprintf (".z: read error");
                     67:                return (0);
                     68:        }
                     69:        if (inbuff[0] != US)
                     70:                goto goof;
                     71: 
                     72:        if (inbuff[1] == US) {          /* oldstyle packing */
                     73:                if (setjmp (env))
                     74:                        return (0);
                     75:                expand ();
                     76:                return (1);
                     77:        }
                     78:        if (inbuff[1] != RS)
                     79:                goto goof;
                     80: 
                     81:        inp = &inbuff[2];
                     82:        origsize = 0;
                     83:        for (i=0; i<4; i++)
                     84:                origsize = origsize*256 + ((*inp++) & 0377);
                     85:        maxlev = *inp++ & 0377;
                     86:        if (maxlev > 24) {
                     87: goof:          eprintf (".z: not in packed format");
                     88:                return (0);
                     89:        }
                     90:        for (i=1; i<=maxlev; i++)
                     91:                intnodes[i] = *inp++ & 0377;
                     92:        for (i=1; i<=maxlev; i++) {
                     93:                tree[i] = eof;
                     94:                for (c=intnodes[i]; c>0; c--) {
                     95:                        if (eof >= &characters[255])
                     96:                                goto goof;
                     97:                        *eof++ = *inp++;
                     98:                }
                     99:        }
                    100:        *eof++ = *inp++;
                    101:        intnodes[maxlev] += 2;
                    102:        inleft -= inp - &inbuff[0];
                    103:        if (inleft < 0)
                    104:                goto goof;
                    105: 
                    106:        /*
                    107:         * convert intnodes[i] to be number of
                    108:         * internal nodes possessed by level i
                    109:         */
                    110: 
                    111:        nchildren = 0;
                    112:        for (i=maxlev; i>=1; i--) {
                    113:                c = intnodes[i];
                    114:                intnodes[i] = nchildren /= 2;
                    115:                nchildren += c;
                    116:        }
                    117:        return (decode ());
                    118: }
                    119: 
                    120: /* unpack the file */
                    121: /* return 1 if successful, 0 otherwise */
                    122: decode ()
                    123: {
                    124:        register int bitsleft, c, i;
                    125:        int j, lev;
                    126:        char *p;
                    127: 
                    128:        outp = &outbuff[0];
                    129:        lev = 1;
                    130:        i = 0;
                    131:        while (1) {
                    132:                if (inleft <= 0) {
                    133:                        inleft = read (infile, inp = &inbuff[0], BUFSIZ);
                    134:                        if (inleft < 0) {
                    135:                                eprintf (".z: read error");
                    136:                                return (0);
                    137:                        }
                    138:                }
                    139:                if (--inleft < 0) {
                    140: uggh:                  if(origsize == 0) return 1;
                    141:                        eprintf (".z: unpacking error");
                    142:                        return (0);
                    143:                }
                    144:                c = *inp++;
                    145:                bitsleft = 8;
                    146:                while (--bitsleft >= 0) {
                    147:                        i *= 2;
                    148:                        if (c & 0200)
                    149:                                i++;
                    150:                        c <<= 1;
                    151:                        if ((j = i - intnodes[lev]) >= 0) {
                    152:                                p = &tree[lev][j];
                    153:                                if (p == eof) {
                    154:                                        c = outp - &outbuff[0];
                    155:                                        if (write (outfile, &outbuff[0], c) != c) {
                    156: wrerr:                                         eprintf (": write error");
                    157:                                                return (0);
                    158:                                        }
                    159:                                        origsize -= c;
                    160:                                        if (origsize != 0)
                    161:                                                goto uggh;
                    162:                                        return (1);
                    163:                                }
                    164:                                *outp++ = *p;
                    165:                                if (outp == &outbuff[BUFSIZ]) {
                    166:                                        if (write (outfile, outp = &outbuff[0], BUFSIZ) != BUFSIZ)
                    167:                                                goto wrerr;
                    168:                                        origsize -= BUFSIZ;
                    169:                                }
                    170:                                lev = 1;
                    171:                                i = 0;
                    172:                        } else
                    173:                                lev++;
                    174:                }
                    175:        }
                    176: }
                    177: 
                    178: main (argc, argv)
                    179:        char *argv[];
                    180: {
                    181:        register i, k;
                    182:        int sep, pcat = 0;
                    183:        register char *p1, *cp;
                    184:        int fcount = 0;         /* failure count */
                    185: 
                    186:        p1 = *argv;
                    187:        while(*p1++);           /* Point p1 to end of argv[0] string */
                    188:        while(--p1 >= *argv)
                    189:                if(*p1 == '/')break;
                    190:        *argv = p1 + 1;
                    191:        argv0 = argv[0];
                    192:        if(**argv == 'p')pcat++;        /* User entered pcat (or /xx/xx/pcat) */
                    193:        if(pcat && argc == 1){
                    194:                infile = 0;
                    195:                outfile = 1;
                    196:                return getdict();
                    197:        }
                    198:        for (k=1; k<argc; k++) {
                    199:                errorm = 0;
                    200:                sep = -1;
                    201:                cp = filename;
                    202:                argvk = argv[k];
                    203:                for (i=0; i < (NAMELEN-3) && (*cp = argvk[i]); i++)
                    204:                        if (*cp++ == '/')
                    205:                                sep = i;
                    206:                if (cp[-1] == SUF1 && cp[-2] == SUF0) {
                    207:                        argvk[i-2] = '\0'; /* Remove suffix and try again */
                    208:                        k--;
                    209:                        continue;
                    210:                }
                    211: 
                    212:                fcount++;       /* expect the worst */
                    213:                if (i >= (NAMELEN-3) || (i - sep) > 13) {
                    214:                        eprintf (": file name too long");
                    215:                        goto done;
                    216:                }
                    217:                *cp++ = SUF0;
                    218:                *cp++ = SUF1;
                    219:                *cp = '\0';
                    220:                if ((infile = open (filename, 0)) == -1) {
                    221:                        eprintf (".z: cannot open");
                    222:                        goto done;
                    223:                }
                    224: 
                    225:                if (pcat)
                    226:                        outfile = 1;    /* standard output */
                    227:                else {
                    228:                        if (stat (argvk, &status) != -1) {
                    229:                                eprintf (": already exists");
                    230:                                goto done;
                    231:                        }
                    232:                        VOID fstat (infile, &status);
                    233:                        if (status.st_nlink != 1)
                    234:                                eprintf (".z: Warning: file has links");
                    235:                        if ((outfile = creat (argvk, status.st_mode&07777)) == -1) {
                    236:                                eprintf (": cannot create");
                    237:                                goto done;
                    238:                        }
                    239: 
                    240:                        if (chmod (argvk, status.st_mode) != 0)
                    241:                            printf("can't change mode to %o\n", status.st_mode);
                    242:                        VOID chown (argvk, status.st_uid, status.st_gid);
                    243:                }
                    244: 
                    245:                if (getdict ()) {       /* unpack */
                    246:                        fcount--;       /* success after all */
                    247:                        if (!pcat) {
                    248:                                eprintf (": unpacked");
                    249:                                VOID unlink (filename);
                    250: 
                    251:                                /*
                    252:                                 * preserve acc & mod dates
                    253:                                 */
                    254:                                VOID utime (argvk, &status.st_atime);
                    255:                        }
                    256:                }
                    257:                else
                    258:                        if (!pcat)
                    259:                                VOID unlink (argvk);
                    260: done:          if (errorm)
                    261:                        VOID fprintf (stderr, "\n");
                    262:                VOID close (infile);
                    263:                if (!pcat)
                    264:                        VOID close (outfile);
                    265:        }
                    266:        return (fcount);
                    267: }
                    268: 
                    269: eprintf (s)
                    270:        char *s;
                    271: {
                    272:        if (!errorm) {
                    273:                errorm = 1;
                    274:                VOID fprintf (stderr, "%s: %s", argv0, argvk);
                    275:        }
                    276:        VOID fprintf (stderr, s);
                    277: }
                    278: 
                    279: /*
                    280:  * This code is for unpacking files that
                    281:  * were packed using the previous algorithm.
                    282:  */
                    283: 
                    284: int    Tree[1024];
                    285: 
                    286: expand ()
                    287: {
                    288:        register tp, bit;
                    289:        short word;
                    290:        int keysize, i, *t;
                    291: 
                    292:        outp = outbuff;
                    293:        inp = &inbuff[2];
                    294:        inleft -= 2;
                    295:        origsize = ((long) (unsigned) getwd ())*256*256;
                    296:        origsize += (unsigned) getwd ();
                    297:        t = Tree;
                    298:        for (keysize = getwd (); keysize--; ) {
                    299:                if ((i = getch ()) == 0377)
                    300:                        *t++ = getwd ();
                    301:                else
                    302:                        *t++ = i & 0377;
                    303:        }
                    304: 
                    305:        bit = tp = 0;
                    306:        for (;;) {
                    307:                if (bit <= 0) {
                    308:                        word = getwd ();
                    309:                        bit = 16;
                    310:                }
                    311:                tp += Tree[tp + (word<0)];
                    312:                word <<= 1;
                    313:                bit--;
                    314:                if (Tree[tp] == 0) {
                    315:                        putch (Tree[tp+1]);
                    316:                        tp = 0;
                    317:                        if ((origsize -= 1) == 0) {
                    318:                                write (outfile, outbuff, outp - outbuff);
                    319:                                return;
                    320:                        }
                    321:                }
                    322:        }
                    323: }
                    324: 
                    325: getch ()
                    326: {
                    327:        if (inleft <= 0) {
                    328:                inleft = read (infile, inp = inbuff, BUFSIZ);
                    329:                if (inleft < 0) {
                    330:                        eprintf (".z: read error");
                    331:                        longjmp (env, 1);
                    332:                }
                    333:        }
                    334:        inleft--;
                    335:        return (*inp++ & 0377);
                    336: }
                    337: 
                    338: getwd ()
                    339: {
                    340:        register char c;
                    341:        register d;
                    342:        c = getch ();
                    343:        d = getch ();
                    344:        d <<= 8;
                    345:        d |= c & 0377;
                    346:        return (d);
                    347: }
                    348: 
                    349: putch (c)
                    350:        char c;
                    351: {
                    352:        register n;
                    353: 
                    354:        *outp++ = c;
                    355:        if (outp == &outbuff[BUFSIZ]) {
                    356:                n = write (outfile, outp = outbuff, BUFSIZ);
                    357:                if (n < BUFSIZ) {
                    358:                        eprintf (": write error");
                    359:                        longjmp (env, 2);
                    360:                }
                    361:        }
                    362: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.