Annotation of researchv10no/cmd/pack/unpack.c, revision 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.