00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #include <sys/types.h>
00078 #include <fcntl.h>
00079 #include <stdlib.h>
00080 #include <unistd.h>
00081
00082 #define BUFSZ 1024
00083 #define BUFSZ_2 (BUFSZ/2)
00084 #define DICTSZ (unsigned)13056
00085 #define EOF_INDEX (unsigned short)0xFFFF
00086 #define FALSE 0
00087 #define TRUE ~FALSE
00088
00089 int fdin, fdout, fderr;
00090 int ibufstart, obufind, ibufend;
00091 int ipbufind = BUFSZ_2;
00092 int opbufind = 0;
00093 int pnum = -1;
00094 unsigned short ipbuf[BUFSZ_2];
00095 unsigned short opbuf[BUFSZ_2];
00096 unsigned char *ibuf = (unsigned char *) ipbuf;
00097 unsigned char *obuf = (unsigned char *) opbuf;
00098
00099 unsigned short dindex[DICTSZ];
00100 unsigned short dchar[DICTSZ];
00101 unsigned iindex, tindex, tindex2;
00102 unsigned base;
00103 unsigned tbase;
00104 unsigned locend;
00105 unsigned curend = 256;
00106 unsigned maxend;
00107 int dcharp;
00108 int curbits;
00109 int maxbits;
00110 int clearflg;
00111 int inmod;
00112
00113 _PROTOTYPE(int main, (int argc, char **argv));
00114 _PROTOTYPE(void ffork, (void));
00115 _PROTOTYPE(void die, (char *s));
00116 _PROTOTYPE(void myputc, (unsigned c));
00117 _PROTOTYPE(unsigned mygetc, (void));
00118 _PROTOTYPE(void getbits, (void));
00119 _PROTOTYPE(void getpipe, (void));
00120 _PROTOTYPE(void putpipe, (unsigned u, int flag));
00121
00122 int main(argc, argv)
00123 int argc;
00124 char **argv;
00125 {
00126 char c, *cp;
00127 int j, k, fdtmp;
00128 unsigned int len;
00129
00130
00131 j = 0;
00132 while (argv[0][j] != '\0') j++;
00133 len = (unsigned int) j;
00134 while (j--)
00135 if (argv[0][j] == '/') break;
00136 if (argv[0][j] == '/') j++;
00137 cp = argv[0] + j;
00138 len -= j;
00139
00140
00141 for (k = 1; k < argc; k++) {
00142 if (argv[k][0] == '-') {
00143 c = argv[k][1];
00144 switch (c) {
00145 case '0':
00146 case '1':
00147 case '2':
00148 case '3':
00149 case '4': pnum = c - '0'; break;
00150 case 'd':
00151 break;
00152 default:
00153 (void) write(1, "Usage: ", 7);
00154 (void) write(1, cp, len);
00155 (void) write(1, " [-#] [in] [out]\n", 17);
00156 exit(0);
00157 break;
00158 }
00159
00160
00161 for (j = k; j < argc; j++) argv[j] = argv[j + 1];
00162 argc--;
00163 k--;
00164 }
00165 }
00166
00167
00168 fdin = 0;
00169 fdout = 1;
00170 fderr = 2;
00171
00172
00173 if (argc > 1) {
00174 if ((fdtmp = open(argv[1], 0)) == -1) die("input open failed");
00175 (void) close(0);
00176 if ((fdin = dup(fdtmp)) == -1) die("input dup failed\n");
00177 (void) close(fdtmp);
00178 }
00179 if (argc > 2) {
00180 (void) unlink(argv[2]);
00181 if ((fdtmp = creat(argv[2], 0666)) == -1) die("output creat failed");
00182 (void) close(1);
00183 if ((fdout = dup(fdtmp)) == -1) die("output dup failed\n");
00184 (void) close(fdtmp);
00185 }
00186
00187
00188 if (pnum == -1 || pnum == 4) {
00189
00190 if (mygetc() != 0x1F || mygetc() != 0x9D)
00191 die("not a compressed file\n");
00192 iindex = mygetc();
00193 } else
00194 getpipe();
00195
00196 maxbits = iindex & 0x1F;
00197 clearflg = ((iindex & 0x80) != 0) ? TRUE : FALSE;
00198 if (maxbits < 9 || maxbits > 16)
00199 die("can't decompress\n");
00200 if (pnum != -1 && pnum != 0)
00201 putpipe(iindex, 0);
00202
00203
00204 if (pnum == -1) {
00205 pnum = 0;
00206 if (pnum == 0) ffork();
00207 if (pnum == 1) ffork();
00208 if (pnum == 2) ffork();
00209 if (pnum == 3) ffork();
00210 }
00211
00212
00213
00214 base = DICTSZ * pnum + 256;
00215 locend = base + DICTSZ - 1;
00216 maxend = (1 << maxbits) - 1;
00217 if (maxend > locend) maxend = locend;
00218
00219 while (TRUE) {
00220 curend = 255 + (clearflg ? 1 : 0);
00221 dcharp = DICTSZ;
00222 curbits = 9;
00223 while (TRUE) {
00224 if (pnum == 4) {
00225 if (curbits < maxbits && (1 << curbits) <= curend) {
00226
00227
00228
00229
00230 while (inmod) getbits();
00231 curbits++;
00232 }
00233 getbits();
00234 } else
00235 getpipe();
00236
00237 if (iindex == 256 && clearflg) {
00238 if (pnum > 0) putpipe(iindex, 0);
00239
00240
00241 while (inmod) getbits();
00242 break;
00243 }
00244 tindex = iindex;
00245
00246 while (tindex >= base) tindex = dindex[tindex - base];
00247
00248 putpipe(tindex, 0);
00249
00250 if (dcharp < DICTSZ) dchar[dcharp++] = tindex;
00251 if (curend < maxend && ++curend > (base - 1))
00252 dindex[dcharp = (curend - base)] = iindex;
00253
00254
00255
00256
00257
00258 tbase = base;
00259 while ((tindex = iindex) >= tbase) {
00260 while ((tindex2 = dindex[tindex - base]) >= tbase)
00261 tindex = tindex2;
00262 putpipe(dchar[tindex-base], 1);
00263 tbase = tindex + 1;
00264 if (tbase == 0) break;
00265 }
00266 }
00267 }
00268 }
00269
00270
00271
00272
00273
00274
00275 void ffork()
00276 {
00277 int j, pfd[2];
00278
00279 if (pipe(pfd) == -1) die("pipe() error\n");
00280 if ((j = fork()) == -1) die("fork() error\n");
00281 if (j == 0) {
00282 if (close(1) == -1) die("close(1) error\n");
00283 if (dup(pfd[1]) != 1) die("dup(1) error\n");
00284 (void) close(pfd[0]);
00285 pnum++;
00286 } else {
00287 if (close(0) == -1) die("close(0) error\n");
00288 if (dup(pfd[0]) != 0) die("dup(0) error\n");
00289 (void) close(pfd[1]);
00290 }
00291 }
00292
00293
00294
00295
00296
00297
00298 void die(s)
00299 char *s;
00300 {
00301
00302 if (obufind != 0) {
00303 if (write(fdout, (char *) obuf, (unsigned) obufind) != obufind)
00304 s = "bad stdout write\n";
00305 obufind = 0;
00306 }
00307
00308
00309 do
00310 putpipe(EOF_INDEX, 0);
00311 while (opbufind);
00312
00313 if (s != (char *) NULL) {
00314 while (*s) (void) write(fderr, s++, 1);
00315 }
00316 exit((s == (char *) NULL) ? 0 : 1);
00317 }
00318
00319
00320
00321
00322
00323
00324 void myputc(c)
00325 unsigned c;
00326 {
00327 obuf[obufind++] = c;
00328 if (obufind >= BUFSZ) {
00329 if (write(fdout, (char *) obuf, BUFSZ) != BUFSZ)
00330 die("bad stdout write\n");
00331 obufind = 0;
00332 }
00333 }
00334
00335
00336
00337
00338
00339
00340 unsigned mygetc()
00341 {
00342 if (ibufstart >= ibufend) {
00343 if ((ibufend = read(fdin, (char *) ibuf, BUFSZ)) <= 0)
00344 die((char *) NULL);
00345 ibufstart = 0;
00346 }
00347 return(ibuf[ibufstart++] & 0xff);
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 void getbits()
00360 {
00361 int have;
00362 static unsigned curbyte;
00363 static int left;
00364
00365 inmod = (inmod + 1) & 7;
00366 iindex = curbyte;
00367 have = left;
00368 if (curbits - have > 8) {
00369 iindex |= mygetc() << have;
00370 have += 8;
00371 }
00372 iindex |= ((curbyte = mygetc()) << have) & ~((unsigned) 0xFFFF << curbits);
00373 curbyte >>= curbits - have;
00374 left = 8 - (curbits - have);
00375 }
00376
00377
00378
00379
00380
00381
00382 void getpipe()
00383 {
00384 static short flags;
00385 static int n = 0;
00386
00387 while (TRUE) {
00388 if (n <= 0) {
00389 if (ipbufind >= BUFSZ_2) {
00390
00391 if (read(fdin, (char *) ipbuf, BUFSZ) != BUFSZ)
00392 die("bad pipe read\n");
00393 ipbufind = 0;
00394 }
00395 flags = ipbuf[ipbufind++];
00396 n = 15;
00397 }
00398 iindex = ipbuf[ipbufind++];
00399 if (iindex > curend)
00400 die((iindex == EOF_INDEX) ? (char *) NULL : "invalid data\n");
00401 flags <<= 1;
00402 n--;
00403
00404 if (flags < 0) {
00405 while (iindex >= base) iindex = dindex[iindex - base];
00406 putpipe(iindex, 1);
00407 } else
00408 return;
00409 }
00410 }
00411
00412
00413
00414
00415
00416
00417 void putpipe(u, flag)
00418 unsigned u;
00419 int flag;
00420 {
00421 static unsigned short flags, *flagp;
00422 static int n = 0;
00423
00424 if (pnum == 0) {
00425 myputc(u);
00426 return;
00427 }
00428 if (n == 0) {
00429 flags = 0;
00430 flagp = opbuf + opbufind;
00431 opbufind++;
00432 }
00433 opbuf[opbufind++] = u;
00434 flags = (flags << 1) | flag;
00435 if (++n >= 15) {
00436 n = 0;
00437 *flagp = flags;
00438 if (opbufind >= BUFSZ_2) {
00439 opbufind = 0;
00440 if (write(fdout, (char *) opbuf, BUFSZ) != BUFSZ)
00441 die("bad pipe write\n");
00442 }
00443 }
00444 }