/* yenc file decoder * * Please read www.exit109.com/~jeremy/news/yenc.html * "Why Yenc is bad for Usenet" before adding an encoder. */ #include #include #include #include static int Verbose = 0; static ulong *Crctab; static Biobuf bout; int yydec(char *file, Biobuf *bi) { uchar c; char *name, *buf, *p; static int totgot = 0; static int nextpart = 1; unsigned long crc, ecrc; int got, part, size, esize, begin, end; got = 0; crc = 0; part = 0; name = 0; size = 0; begin = 0; end = 0; ecrc = 0; while((buf = Brdline(bi, '\n')) != nil){ if ((p = strchr(buf, '\n')) != nil) *p = 0; if ((p = strchr(buf, '\r')) != nil) *p = 0; if (strncmp(buf, "=ybegin ", 8)==0) { if ((p = strstr(buf,"name=")) == nil) sysfatal("%s - no name= in =ybegin\n", file); name = strdup(p+5); if ((p = strstr(buf,"size=")) == nil) sysfatal("%s - no size= in =ybegin\n", file); size = atoi(p+5); if ((p = strstr(buf,"part=")) != nil) part = atoi(p+5); break; } } if (part){ if ((buf = Brdline(bi, '\n')) == nil) sysfatal("%s - unexpected EOF\n", file); if ((p = strchr(buf, '\n')) != nil) *p = 0; if ((p = strchr(buf, '\r')) != nil) *p = 0; if (strncmp(buf, "=ypart ", 7) != 0) sysfatal("%s - no =ypart in multipart file\n", file); if ((p = strstr(buf, "end=")) == nil) sysfatal("%s - no end= in =ypart\n", file); end = atol(p+4); if ((p = strstr(buf, "begin=")) == nil) sysfatal("%s - no begin= in =ypart\n", file); begin = atol(p+6); } if (name == nil) sysfatal("%s - =ybegin not found\n", file); if (Verbose && part == 0 || part == 1) fprint(2, "%s %d bytes\n", name, size); if (part && part != nextpart) sysfatal("%s - got part=%d, wanted part=%d\n", file, part, nextpart); while (1){ if ((buf = Brdline(bi, '\n')) == nil) sysfatal("%s - unexpected EOF\n", file); if ((p = strchr(buf, '\n')) != nil) *p = 0; if ((p = strchr(buf, '\r')) != nil) *p = 0; if (strncmp(buf, "=yend ", 6) == 0) break; for (p = buf; *p;){ c = (uchar)*p++; if (c == '='){ if ((c = *p++) == 0) sysfatal("%s - Esc char (=) at end of line\n", file); c = (uchar)(c-64); } c = (uchar)(c-42); Bputc(&bout, c); crc = blockcrc(Crctab, crc, &c, 1); totgot++; got++; } } if ((p = strstr(buf, "size=")) != nil){ esize = atoi(p+5); if (esize != got) { fprint(2, "%s corrupted size=%d != %d\n", file, esize, got); return 0; } } if (! part){ if ((p = strstr(buf, "crc32=")) != nil) ecrc = strtoul((p+6), nil, 16); if (crc != ecrc) fprint(2, "%s: %s corrupt crc=%08lux != %08lux\n", argv0, file, crc, ecrc); return 0; } /* * multipart only from here on */ if ((p = strstr(buf, "pcrc32=")) != nil) ecrc = strtoul((p+7), nil, 16); if (crc != ecrc) fprint(2, "%s: %s corrupt part crc=%08lux != %08lux\n", argv0, file, crc, ecrc); if (got != (end - begin + 1)) sysfatal("%s part=%d wrong size\n", file, part); nextpart = part +1; return 0; } void usage(void) { fprint(2, "usage: %s [-v] [file...]\n", argv0); exits("usage"); } void main(int argc, char *argv[]) { Biobuf bin, *bi; Crctab = mkcrctab(0xedb88320UL); Binit(&bin, 0, OREAD); Binit(&bout, 1, OWRITE); argv0 = *argv; ARGBEGIN { case 'v': Verbose++; break; default: usage(); break; } ARGEND; if (argc == 0) yydec(*argv, &bin); for (; argc--; argv++){ if ((bi = Bopen(*argv, OREAD)) == nil){ fprint(2, "%s: %s - cannot read file %r\n", argv0, *argv); continue; } yydec(*argv, bi); Bterm(bi); } Bterm(&bout); exits(0); }