|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.