00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #define UNIX 1
00016
00017 #ifdef GEMDOS
00018 #define SYSNAME "gemdos"
00019 #define SMALL 1
00020 #endif
00021 #ifdef MSDOS
00022 #define SYSNAME "msdos"
00023 #define SMALL 1
00024 #endif
00025 #ifdef UNIX
00026 #define SYSNAME "unix"
00027 #endif
00028
00029 #include <sys/types.h>
00030 #include <stdarg.h>
00031 #include <string.h>
00032 #include <stdlib.h>
00033 #include <unistd.h>
00034 #include <sys/stat.h>
00035 #include <stdio.h>
00036
00037 #ifdef GEMDOS
00038 #include <osbind.h>
00039 #define Error(n) { Bconin(2); exit(n); }
00040 #else
00041 #define Error(n) exit(n)
00042 #endif
00043 #ifdef UNIX
00044 #define WRITE "w"
00045 #else
00046 #define WRITE "wb"
00047 #endif
00048
00049 #define loop while (1)
00050
00051 #define NCHARS 256
00052 #define LINELEN 256
00053 #define FILELEN 64
00054 #define NORMLEN 60
00055
00056 #define SEQMAX 'z'
00057 #define SEQMIN 'a'
00058 char seqc;
00059 int first, secnd, check, numl;
00060
00061 FILE *in, *out;
00062 char *pos;
00063 char ifname[FILELEN], ofname[FILELEN];
00064 char *source = NULL, *target = NULL;
00065 char blank, part = '\0';
00066 int partn, lens;
00067 int debug = 0, nochk = 0, onedone = 0;
00068 int chtbl[NCHARS], cdlen[NORMLEN + 3];
00069
00070 _PROTOTYPE(int main, (int argc, char **argv));
00071 _PROTOTYPE(char *getnword, (char *str, int n));
00072 _PROTOTYPE(void gettable, (void));
00073 _PROTOTYPE(void decode, (void));
00074 _PROTOTYPE(void getfile, (char *buf));
00075 _PROTOTYPE(void format, (char *fp, ...));
00076 _PROTOTYPE(void doprnt, (char *fp, char *ap));
00077 _PROTOTYPE(void puti, (unsigned int i, unsigned int r));
00078 _PROTOTYPE(void outc, (int c));
00079
00080 int main(argc, argv) int argc; char *argv[];
00081 {
00082 int mode;
00083 register int i, j;
00084 char *curarg;
00085 char dest[FILELEN], buf[LINELEN];
00086
00087 while ((curarg = argv[1]) != NULL && curarg[0] == '-') {
00088 if (((curarg[1] == 'd') || (curarg[1] == 'D')) &&
00089 (curarg[2] == '\0')) {
00090 debug = 1;
00091 } else if (((curarg[1] == 'n') || (curarg[1] == 'N')) &&
00092 (curarg[2] == '\0')) {
00093 nochk = 1;
00094 } else if (((curarg[1] == 't') || (curarg[1] == 'T')) &&
00095 (curarg[2] == '\0')) {
00096 argv++;
00097 argc--;
00098 if (argc < 2) {
00099 format("uud: Missing target directory.\n");
00100 Error(15);
00101 }
00102 target = argv[1];
00103 if (debug)
00104 format("Target dir = %s\n",target);
00105 } else if (((curarg[1] == 's') || (curarg[1] == 'S')) &&
00106 (curarg[2] == '\0')) {
00107 argv++;
00108 argc--;
00109 if (argc < 2) {
00110 format("uud: Missing source directory.\n");
00111 Error(15);
00112 }
00113 source = argv[1];
00114 if (debug)
00115 format("Source dir = %s\n",source);
00116 } else if (curarg[1] != '\0') {
00117 format("Usage: uud [-n] [-d] [-s dir] [-t dir] [input-file]\n");
00118 Error(1);
00119 } else
00120 break;
00121 argv++;
00122 argc--;
00123 }
00124
00125 if (curarg == NULL || ((curarg[0] == '-') && (curarg[1] == '\0'))) {
00126 in = stdin;
00127 strcpy(ifname, "<stdin>");
00128 } else {
00129 if (source != NULL) {
00130 strcpy(ifname, source);
00131 strcat(ifname, curarg);
00132 } else
00133 strcpy(ifname, curarg);
00134 if ((in = fopen(ifname, "r")) == NULL) {
00135 format("uud: Can't open %s\n", ifname);
00136 Error(2);
00137 }
00138 numl = 0;
00139 }
00140
00141
00142
00143
00144 for (i = 0; i < ' '; i++) chtbl[i] = -1;
00145 for (i = ' ', j = 0; i < ' ' + 64; i++, j++) chtbl[i] = j;
00146 for (i = ' ' + 64; i < NCHARS; i++) chtbl[i] = -1;
00147 chtbl['`'] = chtbl[' '];
00148 chtbl['~'] = chtbl['^'];
00149 blank = ' ';
00150
00151
00152
00153 cdlen[0] = 1;
00154 for (i = 1, j = 5; i <= NORMLEN; i += 3, j += 4)
00155 cdlen[i] = (cdlen[i + 1] = (cdlen[i + 2] = j));
00156
00157
00158
00159 loop {
00160 partn = 'a';
00161 loop {
00162 if (fgets(buf, sizeof buf, in) == NULL) {
00163 if (onedone) {
00164 if (debug) format("End of file.\n");
00165 exit(0);
00166 } else {
00167 format("uud: No begin line.\n");
00168 Error(3);
00169 }
00170 }
00171 numl++;
00172 if (strncmp(buf, "table", (size_t)5) == 0) {
00173 gettable();
00174 continue;
00175 }
00176 if (strncmp(buf, "begin", (size_t)5) == 0) {
00177 break;
00178 }
00179 }
00180 lens = strlen(buf);
00181 if (lens) buf[--lens] = '\0';
00182 #ifdef SMALL
00183 if ((pos = getnword(buf, 3))) {
00184 strcpy(dest, pos);
00185 } else
00186 #else
00187 if(sscanf(buf,"begin%o%s", &mode, dest) != 2)
00188 #endif
00189 {
00190 format("uud: Missing filename in begin line.\n");
00191 Error(10);
00192 }
00193
00194 if (target != NULL) {
00195 strcpy(ofname, target);
00196 strcat(ofname, dest);
00197 } else
00198 strcpy(ofname, dest);
00199
00200 if((out = fopen(ofname, WRITE)) == NULL) {
00201 format("uud: Cannot open output file: %s\n", ofname);
00202 Error(4);
00203 }
00204 if (debug) format("Begin uudecoding: %s\n", ofname);
00205 seqc = SEQMAX;
00206 check = nochk ? 0 : 1;
00207 first = 1;
00208 secnd = 0;
00209 decode();
00210 fclose(out);
00211 #ifdef UNIX
00212 chmod(ofname, mode);
00213 #endif
00214 onedone = 1;
00215 if (debug) format("End uudecoding: %s\n", ofname);
00216 }
00217 }
00218
00219
00220
00221
00222 char *getnword(str, n) register char *str; register int n;
00223 {
00224 while((*str == '\t') || (*str == ' ')) str++;
00225 if (! *str) return NULL;
00226 while(--n) {
00227 while ((*str != '\t') && (*str != ' ') && (*str)) str++;
00228 if (! *str) return NULL;
00229 while((*str == '\t') || (*str == ' ')) str++;
00230 if (! *str) return NULL;
00231 }
00232 return str;
00233 }
00234
00235
00236
00237
00238 void gettable()
00239 {
00240 char buf[LINELEN];
00241 register int c, n = 0;
00242 register char *cpt;
00243
00244 for (c = 0; c < NCHARS; c++) chtbl[c] = -1;
00245
00246 again: if (fgets(buf, sizeof buf, in) == NULL) {
00247 format("uud: EOF while in translation table.\n");
00248 Error(5);
00249 }
00250 numl++;
00251 if (strncmp(buf, "begin", (size_t)5) == 0) {
00252 format("uud: Incomplete translation table.\n");
00253 Error(6);
00254 }
00255 cpt = buf + strlen(buf) - 1;
00256 *cpt = ' ';
00257 while (*(cpt) == ' ') {
00258 *cpt = 0;
00259 cpt--;
00260 }
00261 cpt = buf;
00262 while (c = *cpt) {
00263 if (chtbl[c] != -1) {
00264 format("uud: Duplicate char in translation table.\n");
00265 Error(7);
00266 }
00267 if (n == 0) blank = c;
00268 chtbl[c] = n++;
00269 if (n >= 64) return;
00270 cpt++;
00271 }
00272 goto again;
00273 }
00274
00275
00276
00277
00278
00279 void decode()
00280 {
00281 char buf[LINELEN], outl[LINELEN];
00282 register char *bp, *ut;
00283 register int *trtbl = chtbl;
00284 register int n, c, rlen;
00285 register unsigned int len;
00286
00287 loop {
00288 if (fgets(buf, sizeof buf, in) == NULL) {
00289 format("uud: EOF before end.\n");
00290 fclose(out);
00291 Error(8);
00292 }
00293 numl++;
00294 len = strlen(buf);
00295 if (len) buf[--len] = '\0';
00296
00297
00298
00299 if (len == 0) continue;
00300
00301
00302
00303 n = trtbl[*buf];
00304 if (n >= 0) goto decod;
00305
00306
00307
00308 if (strncmp(buf, "end", (size_t)3) == 0) return;
00309
00310
00311
00312 if (strncmp(buf, "include", (size_t)7) == 0) {
00313 getfile(buf);
00314 continue;
00315 }
00316 format("uud: Bad prefix line %d in file: %s\n",numl, ifname);
00317 if (debug) format("Bad line =%s\n",buf);
00318 Error(11);
00319
00320
00321
00322 decod: rlen = cdlen[n];
00323
00324
00325
00326 if (n == 0) continue;
00327
00328
00329
00330 for (bp = &buf[c = len];
00331 c < rlen; c++, bp++) *bp = blank;
00332
00333
00334
00335 if (debug) {
00336 for (len = 0, bp = buf; len < rlen; len++) {
00337 if (trtbl[*bp] < 0) {
00338 format(
00339 "Non uuencoded char <%c>, line %d in file: %s\n", *bp, numl, ifname);
00340 format("Bad line =%s\n",buf);
00341 Error(16);
00342 }
00343 bp++;
00344 }
00345 }
00346
00347
00348
00349 if (secnd && check) {
00350 secnd = 0;
00351 if (buf[rlen] == SEQMAX) {
00352 check = 0;
00353 if (debug) format("Sequence check turned off (2).\n");
00354 } else
00355 if (debug) format("Sequence check on (2).\n");
00356 } else if (first && check) {
00357 first = 0;
00358 secnd = 1;
00359 if (buf[rlen] != SEQMAX) {
00360 check = 0;
00361 if (debug) format("No sequence check (1).\n");
00362 } else
00363 if (debug) format("Sequence check on (1).\n");
00364 }
00365
00366
00367
00368 if (check) {
00369 if (buf[rlen] != seqc) {
00370 format("uud: Wrong sequence line %d in %s\n",
00371 numl, ifname);
00372 if (debug)
00373 format(
00374 "Sequence char is <%c> instead of <%c>.\n", buf[rlen], seqc);
00375 Error(18);
00376 }
00377 seqc--;
00378 if (seqc < SEQMIN) seqc = SEQMAX;
00379 }
00380
00381
00382
00383
00384
00385
00386 ut = outl;
00387 len = n;
00388 bp = &buf[1];
00389 while (n > 0) {
00390 *(ut++) = trtbl[*bp] << 2 | trtbl[bp[1]] >> 4;
00391 n--;
00392 if (n) {
00393 *(ut++) = (trtbl[bp[1]] << 4) |
00394 (trtbl[bp[2]] >> 2);
00395 n--;
00396 }
00397 if (n) {
00398 *(ut++) = trtbl[bp[2]] << 6 | trtbl[bp[3]];
00399 n--;
00400 }
00401 bp += 4;
00402 }
00403 if ((n = fwrite(outl, (size_t)1, (size_t)len, out)) <= 0) {
00404 format("uud: Error on writing decoded file.\n");
00405 Error(18);
00406 }
00407 }
00408 }
00409
00410
00411
00412
00413
00414 void getfile(buf) register char *buf;
00415 {
00416 if ((pos = getnword(buf, 2)) == NULL) {
00417 format("uud: Missing include file name.\n");
00418 Error(17);
00419 } else
00420 if (source != NULL) {
00421 strcpy(ifname, source);
00422 strcat(ifname, pos);
00423 } else
00424 strcpy(ifname, pos);
00425 #ifdef GEMDOS
00426 if (Fattrib(ifname, 0, 0) < 0)
00427 #else
00428 if (access(ifname, 04))
00429 #endif
00430 {
00431 if (debug) {
00432 format("Cant find: %s\n", ifname);
00433 format("Continuing to read same file.\n");
00434 }
00435 }
00436 else {
00437 if (freopen(ifname, "r", in) == in) {
00438 numl = 0;
00439 if (debug)
00440 format("Reading next section from: %s\n", ifname);
00441 } else {
00442 format("uud: Freopen abort: %s\n", ifname);
00443 Error(9);
00444 }
00445 }
00446 loop {
00447 if (fgets(buf, LINELEN, in) == NULL) {
00448 format("uud: No begin line after include: %s\n", ifname);
00449 Error(12);
00450 }
00451 numl++;
00452 if (strncmp(buf, "table", (size_t)5) == 0) {
00453 gettable();
00454 continue;
00455 }
00456 if (strncmp(buf, "begin", (size_t)5) == 0) break;
00457 }
00458 lens = strlen(buf);
00459 if (lens) buf[--lens] = '\0';
00460
00461
00462
00463 if ((pos = getnword(buf, 3)) == NULL ) {
00464 format("uud: Missing part name, in included file: %s\n", ifname);
00465 Error(13);
00466 } else {
00467 part = *pos;
00468 partn++;
00469 if (partn > 'z') partn = 'a';
00470 if (part != partn) {
00471 format("uud: Part suffix mismatch: <%c> instead of <%c>.\n",
00472 part, partn);
00473 Error(14);
00474 }
00475 if (debug) format("Reading part %c\n", *pos);
00476 }
00477 }
00478
00479
00480
00481
00482
00483 #ifdef __STDC__
00484 void format(char *fp, ...)
00485 {
00486 va_list args;
00487
00488 va_start (args, fp);
00489 doprnt(fp, (char *)&args);
00490 va_end(args);
00491 }
00492 #else
00493
00494 void format(fp, args) char *fp;
00495 {
00496 doprnt(fp, (char *)&args);
00497 }
00498 #endif
00499
00500 void doprnt(fp, ap)
00501 register char *fp;
00502 register char *ap;
00503 {
00504 register int c, k;
00505 register char *s;
00506
00507 while ((c = *fp++) != '\0') {
00508 if (c != '%')
00509 outc(c);
00510 else {
00511 c = *fp++;
00512 switch (c) {
00513 case 'd':
00514 puti(*(int *)ap, 10);
00515 ap += sizeof(int);
00516 break;
00517
00518 case 's':
00519 s = *(char **)ap;
00520 while ((k = *s++) != '\0')
00521 outc(k);
00522 ap += sizeof(char *);
00523 break;
00524
00525 case 'c':
00526 outc(*(int *)ap);
00527 ap += sizeof(int);
00528 break;
00529
00530 default:
00531 outc(c);
00532 }
00533 }
00534 }
00535 }
00536
00537
00538
00539
00540 void puti(i, r)
00541 register unsigned int i;
00542 register unsigned int r;
00543 {
00544 register unsigned int q, s;
00545
00546 if ((q = i / r) != 0)
00547 puti(q, r);
00548 s = i % r;
00549 if (s <= 9)
00550 outc(s + '0');
00551 else
00552 outc(s - 10 + 'A');
00553 }
00554 void outc(c) register char c;
00555 {
00556 #ifdef GEMDOS
00557 if (c == '\n') Bconout(2, '\r');
00558 Bconout(2, c);
00559 #else
00560 putchar(c);
00561 #endif
00562 }