home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3190 < prev    next >
Encoding:
Internet Message Format  |  1991-04-14  |  26.1 KB

  1. From: ralph@laas.fr (Ralph P. Sobek)
  2. Newsgroups: alt.sources,alt.sex.pictures.d
  3. Subject: UUD/UUE (was Re: uuencode.c request)
  4. Message-ID: <RALPH.91Apr13152954@orion.laas.fr>
  5. Date: 13 Apr 91 13:29:54 GMT
  6.  
  7. Submitted-by: ralph@orion.laas.fr
  8. Archive-name: uux/part01
  9.  
  10. I have been enjoying the manual uudecoding of these files ;-(
  11.  
  12. So herewith I post a better version.  UUE can automatically encode and
  13. split a file into n parts.  It also provides for better error-checking
  14. and it includes an ASCII table in case the message might traverse
  15. certain BITNET sites.  UUD can automatically decode multipart files
  16. created by UUE.
  17.  
  18. UUD/UUE compile on Unix, VAX, MSDOS, and GEMDOS.  Updates and comments
  19. are appreciated.
  20.  
  21.  
  22. #!/bin/sh
  23. # This is uux, a shell archive (shar 3.32)
  24. # made 04/13/1991 13:24 UTC by ralph@orion
  25. #
  26. # existing files will NOT be overwritten
  27. #
  28. # This shar contains:
  29. # length  mode       name
  30. # ------ ---------- ------------------------------------------
  31. #  11741 -rw-r--r-- uud.c
  32. #   4186 -rw-r--r-- uue.c
  33. #   7035 -rw-r--r-- uux.doc
  34. #
  35. if touch 2>&1 | fgrep 'amc' > /dev/null
  36.  then TOUCH=touch
  37.  else TOUCH=true
  38. fi
  39. # ============= uud.c ==============
  40. if test X"$1" != X"-c" -a -f 'uud.c'; then
  41.     echo "File already exists: skipping 'uud.c'"
  42. else
  43. echo "x - extracting uud.c (Text)"
  44. sed 's/^X//' << 'SHAR_EOF' > uud.c &&
  45. X/*
  46. X * Uud -- decode a uuencoded file back to binary form.
  47. X *
  48. X * From the Berkeley original, modified by MSD, RDR, JPHD & WLS.
  49. X * The Atari GEMDOS version compiled with MWC 2.x.
  50. X * The MSDOS version with TurboC.
  51. X * The Unix version with cc.
  52. X * this version is made: 25 Nov 1988.
  53. X */
  54. X
  55. X/*
  56. X * Be sure to have the proper symbol at this point. (GEMDOS, MSDOS, UNIX...)
  57. X */
  58. X/*
  59. X#ifndef GEMDOS
  60. X#define GEMDOS 1
  61. X#endif
  62. X */
  63. X#ifndef UNIX
  64. X#define UNIX 1
  65. X#endif
  66. X/*
  67. X#ifndef MSDOS
  68. X#define MSDOS 1
  69. X#endif
  70. X */
  71. X
  72. X#ifdef GEMDOS
  73. X#define SYSNAME "gemdos"
  74. X#define SMALL 1
  75. X#endif
  76. X#ifdef MSDOS
  77. X#define SYSNAME "msdos"
  78. X#define SMALL 1
  79. X#endif
  80. X#ifdef UNIX
  81. X#define SYSNAME "unix"
  82. X#endif
  83. X
  84. X#include <stdio.h>
  85. X
  86. X#ifdef GEMDOS
  87. X#include <osbind.h>
  88. X#define Error(n)  { Bconin(2); exit(n); }
  89. X#define WRITE      "wb"
  90. X#else
  91. X#define Error(n)  exit(n)
  92. X#define WRITE      "w"
  93. X#endif
  94. X
  95. X#define loop    while (1)
  96. X
  97. Xextern FILE *fopen();
  98. Xextern char *strcpy();
  99. Xextern char *strcat();
  100. X
  101. Xchar *getnword();
  102. X
  103. X#define MAXCHAR 256
  104. X#define LINELEN 256
  105. X#define FILELEN 64
  106. X#define NORMLEN 60    /* allows for 80 encoded chars per line */
  107. X
  108. X#define SEQMAX 'z'
  109. X#define SEQMIN 'a'
  110. Xchar seqc;
  111. Xint first, secnd, check, numl;
  112. X
  113. XFILE *in, *out;
  114. Xchar *pos;
  115. Xchar ifname[FILELEN], ofname[FILELEN];
  116. Xchar *source = NULL, *target = NULL;
  117. Xchar blank, part = '\0';
  118. Xint partn, lens;
  119. Xint debug = 0, nochk = 0, onedone = 0;
  120. Xint chtbl[MAXCHAR], cdlen[NORMLEN + 3];
  121. X
  122. Xmain(argc, argv) int argc; char *argv[];
  123. X{
  124. X    int mode;
  125. X    register int i, j;
  126. X    char *curarg;
  127. X    char dest[FILELEN], buf[LINELEN];
  128. X
  129. X    if (argc < 2) {
  130. X        format("Almost foolproof uudecode v3.4 (%s) 25-Nov-88\n",
  131. X            SYSNAME);
  132. X        format("\n");
  133. X        format("Usage: uud [-n] [-d] [-s dir] [-t dir] input-file\n");
  134. X        format("\n");
  135. X        format("Option: -n -> No line sequence check\n");
  136. X        format("Option: -d -> Debug/verbose mode\n");
  137. X        format("Option: -s + Source directory for all input files\n");
  138. X        format("  (MUST be terminated by directory separator)\n");
  139. X        format("Option: -t + Target directory for all output files\n");
  140. X        format("  (MUST be terminated by directory separator)\n");
  141. X        format("If input-file is - then stdin is used as input-file\n");
  142. X        Error(1);
  143. X    }
  144. X
  145. X    curarg = argv[1];
  146. X    
  147. X    while (curarg[0] == '-') {
  148. X        if (((curarg[1] == 'd') || (curarg[1] == 'D')) &&
  149. X            (curarg[2] == '\0')) {
  150. X            debug = 1;
  151. X        } else if (((curarg[1] == 'n') || (curarg[1] == 'N')) &&
  152. X               (curarg[2] == '\0')) {
  153. X            nochk = 1;
  154. X        } else if (((curarg[1] == 't') || (curarg[1] == 'T')) &&
  155. X               (curarg[2] == '\0')) {
  156. X            argv++;
  157. X            argc--;
  158. X            if (argc < 2) {
  159. X                format("uud: Missing target directory.\n");
  160. X                Error(15);
  161. X            }
  162. X            target = argv[1];
  163. X            if (debug)
  164. X                format("Target dir = %s\n",target);
  165. X        } else if (((curarg[1] == 's') || (curarg[1] == 'S')) &&
  166. X               (curarg[2] == '\0')) {
  167. X            argv++;
  168. X            argc--;
  169. X            if (argc < 2) {
  170. X                format("uud: Missing source directory.\n");
  171. X                Error(15);
  172. X            }
  173. X            source = argv[1];
  174. X            if (debug)
  175. X                format("Source dir = %s\n",source);
  176. X        } else if (curarg[1] != '\0') {
  177. X            format("uud: Unknown option <%s>\n", curarg);
  178. X            Error(15);
  179. X        } else
  180. X            break;
  181. X        argv++;
  182. X        argc--;
  183. X        if (argc < 2) {
  184. X            format("uud: Missing file name.\n");
  185. X            Error(15);
  186. X        }
  187. X        curarg = argv[1];
  188. X    }
  189. X
  190. X    if ((curarg[0] == '-') && (curarg[1] == '\0')) {
  191. X        in = stdin;
  192. X        strcpy(ifname, "<stdin>");
  193. X    } else {
  194. X        if (source != NULL) {
  195. X            strcpy(ifname, source);
  196. X            strcat(ifname, curarg);
  197. X        } else
  198. X            strcpy(ifname, curarg);
  199. X        if ((in = fopen(ifname, "r")) == NULL) {
  200. X            format("uud: Can't open %s\n", ifname);
  201. X            Error(2);
  202. X        }
  203. X        numl = 0;
  204. X    }
  205. X
  206. X/*
  207. X * Set up the default translation table.
  208. X */
  209. X    for (i = 0; i < ' '; i++) chtbl[i] = -1;
  210. X    for (i = ' ', j = 0; i < ' ' + 64; i++, j++) chtbl[i] = j;
  211. X    for (i = ' ' + 64; i < MAXCHAR; i++) chtbl[i] = -1;
  212. X    chtbl['`'] = chtbl[' '];    /* common mutation */
  213. X    chtbl['~'] = chtbl['^'];    /* an other common mutation */
  214. X    blank = ' ';
  215. X/*
  216. X * set up the line length table, to avoid computing lotsa * and / ...
  217. X */
  218. X    cdlen[0] = 1;
  219. X    for (i = 1, j = 5; i <= NORMLEN; i += 3, j += 4)
  220. X        cdlen[i] = (cdlen[i + 1] = (cdlen[i + 2] = j));
  221. X/*
  222. X * search for header or translation table line.
  223. X */
  224. X    loop {    /* master loop for multiple decodes in one file */
  225. X        partn = 'a';
  226. X        loop {
  227. X            if (fgets(buf, sizeof buf, in) == NULL) {
  228. X                if (onedone) {
  229. X                    if (debug) format("End of file.\n");
  230. X                    exit(0);
  231. X                } else {
  232. X                    format("uud: No begin line.\n");
  233. X                    Error(3);
  234. X                }
  235. X            }
  236. X            numl++;
  237. X            if (strncmp(buf, "table", 5) == 0) {
  238. X                gettable();
  239. X                continue;
  240. X            }
  241. X            if (strncmp(buf, "begin", 5) == 0) {
  242. X                break;
  243. X            }
  244. X        }
  245. X        lens = strlen(buf);
  246. X        if (lens) buf[--lens] = '\0';
  247. X#ifdef SMALL
  248. X        if ((pos = getnword(buf, 3))) {
  249. X            strcpy(dest, pos);
  250. X        } else
  251. X#else
  252. X        if(sscanf(buf,"begin%o%s", &mode, dest) != 2)
  253. X#endif
  254. X        {
  255. X            format("uud: Missing filename in begin line.\n");
  256. X            Error(10);
  257. X        }
  258. X
  259. X        if (target != NULL) {
  260. X            strcpy(ofname, target);
  261. X            strcat(ofname, dest);
  262. X        } else
  263. X            strcpy(ofname, dest);
  264. X
  265. X        if((out = fopen(ofname, WRITE)) == NULL) {
  266. X            format("uud: Cannot open output file: %s\n", ofname);
  267. X            Error(4);
  268. X        }
  269. X        if (debug) format("Begin uudecoding: %s\n", ofname);
  270. X        seqc = SEQMAX;
  271. X        check = nochk ? 0 : 1;
  272. X        first = 1;
  273. X        secnd = 0;
  274. X        decode();
  275. X        fclose(out);
  276. X#ifdef UNIX
  277. X        chmod(ofname, mode);
  278. X#endif
  279. X        onedone = 1;
  280. X        if (debug) format("End uudecoding: %s\n", ofname);
  281. X    }    /* master loop for multiple decodes in one file */
  282. X}
  283. X
  284. X/*
  285. X * Bring back a pointer to the start of the nth word.
  286. X */
  287. Xchar *getnword(str, n) register char *str; register int n;
  288. X{
  289. X    while((*str == '\t') || (*str == ' ')) str++;
  290. X    if (! *str) return NULL;
  291. X    while(--n) {
  292. X        while ((*str != '\t') && (*str != ' ') && (*str)) str++;
  293. X        if (! *str) return NULL;
  294. X        while((*str == '\t') || (*str == ' ')) str++;
  295. X        if (! *str) return NULL;
  296. X    }
  297. X    return str;
  298. X}
  299. X
  300. X/*
  301. X * Install the table in memory for later use.
  302. X */
  303. Xgettable()
  304. X{
  305. X    char buf[LINELEN];
  306. X    register int c, n = 0;
  307. X    register char *cpt;
  308. X
  309. X    for (c = 0; c <= MAXCHAR; c++) chtbl[c] = -1;
  310. X
  311. Xagain:    if (fgets(buf, sizeof buf, in) == NULL) {
  312. X        format("uud: EOF while in translation table.\n");
  313. X        Error(5);
  314. X    }
  315. X    numl++;
  316. X    if (strncmp(buf, "begin", 5) == 0) {
  317. X        format("uud: Incomplete translation table.\n");
  318. X        Error(6);
  319. X    }
  320. X    cpt = buf + strlen(buf) - 1;
  321. X    *cpt = ' ';
  322. X    while (*(cpt) == ' ') {
  323. X        *cpt = 0;
  324. X        cpt--;
  325. X    }
  326. X    cpt = buf;
  327. X    while (c = *cpt) {
  328. X        if (chtbl[c] != -1) {
  329. X            format("uud: Duplicate char in translation table.\n");
  330. X            Error(7);
  331. X        }
  332. X        if (n == 0) blank = c;
  333. X        chtbl[c] = n++;
  334. X        if (n >= 64) return;
  335. X        cpt++;
  336. X    }
  337. X    goto again;
  338. X}
  339. X
  340. X/*
  341. X * copy from in to out, decoding as you go along.
  342. X */
  343. X
  344. Xdecode()
  345. X{
  346. X    char buf[LINELEN], outl[LINELEN];
  347. X    register char *bp, *ut;
  348. X    register int *trtbl = chtbl;
  349. X    register int n, c, rlen;
  350. X    register unsigned int len;
  351. X
  352. X    loop {
  353. X        if (fgets(buf, sizeof buf, in) == NULL) {
  354. X            format("uud: EOF before end.\n");
  355. X            fclose(out);
  356. X            Error(8);
  357. X        }
  358. X        numl++;
  359. X        len = strlen(buf);
  360. X        if (len) buf[--len] = '\0';
  361. X/*
  362. X * Is it an unprotected empty line before the end line ?
  363. X */
  364. X        if (len == 0) continue;
  365. X/*
  366. X * Get the binary line length.
  367. X */
  368. X        n = trtbl[*buf];
  369. X        if (n >= 0) goto decod;
  370. X/*
  371. X * end of uuencoded file ?
  372. X */
  373. X        if (strncmp(buf, "end", 3) == 0) return;
  374. X/*
  375. X * end of current file ? : get next one.
  376. X */
  377. X        if (strncmp(buf, "include", 7) == 0) {
  378. X            getfile(buf);
  379. X            continue;
  380. X        }
  381. X        format("uud: Bad prefix line %d in file: %s\n",numl, ifname);
  382. X        if (debug) format("Bad line =%s\n",buf);
  383. X        Error(11);
  384. X/*
  385. X * Sequence checking ?
  386. X */
  387. Xdecod:        rlen = cdlen[n];
  388. X/*
  389. X * Is it the empty line before the end line ?
  390. X */
  391. X        if (n == 0) continue;
  392. X/*
  393. X * Pad with blanks.
  394. X */
  395. X        for (bp = &buf[c = len];
  396. X            c < rlen; c++, bp++) *bp = blank;
  397. X/*
  398. X * Verify if asked for.
  399. X */
  400. X        if (debug) {
  401. X            for (len = 0, bp = buf; len < rlen; len++) {
  402. X                if (trtbl[*bp] < 0) {
  403. X                    format(
  404. X    "Non uuencoded char <%c>, line %d in file: %s\n", *bp, numl, ifname);
  405. X                    format("Bad line =%s\n",buf);
  406. X                    Error(16);
  407. X                }
  408. X                bp++;
  409. X            }
  410. X        }
  411. X/*
  412. X * All this just to check for uuencodes that append a 'z' to each line....
  413. X */
  414. X        if (secnd && check) {
  415. X            secnd = 0;
  416. X            if (buf[rlen] == SEQMAX) {
  417. X                check = 0;
  418. X                if (debug) format("Sequence check turned off (2).\n");
  419. X            } else
  420. X                if (debug) format("Sequence check on (2).\n");
  421. X        } else if (first && check) {
  422. X            first = 0;
  423. X            secnd = 1;
  424. X            if (buf[rlen] != SEQMAX) {
  425. X                check = 0;
  426. X                if (debug) format("No sequence check (1).\n");
  427. X            } else
  428. X                if (debug) format("Sequence check on (1).\n");
  429. X        }
  430. X/*
  431. X * There we check.
  432. X */
  433. X        if (check) {
  434. X            if (buf[rlen] != seqc) {
  435. X                format("uud: Wrong sequence line %d in %s\n",
  436. X                    numl, ifname);
  437. X                if (debug)
  438. X                    format(
  439. X    "Sequence char is <%c> instead of <%c>.\n", buf[rlen], seqc);
  440. X                Error(18);
  441. X            }
  442. X            seqc--;
  443. X            if (seqc < SEQMIN) seqc = SEQMAX;
  444. X        }
  445. X/*
  446. X * output a group of 3 bytes (4 input characters).
  447. X * the input chars are pointed to by p, they are to
  448. X * be output to file f.n is used to tell us not to
  449. X * output all of them at the end of the file.
  450. X */
  451. X        ut = outl;
  452. X        len = n;
  453. X        bp = &buf[1];
  454. X        while (n > 0) {
  455. X            *(ut++) = trtbl[*bp] << 2 | trtbl[bp[1]] >> 4;
  456. X            n--;
  457. X            if (n) {
  458. X                *(ut++) = (trtbl[bp[1]] << 4) |
  459. X                      (trtbl[bp[2]] >> 2);
  460. X                n--;
  461. X            }
  462. X            if (n) {
  463. X                *(ut++) = trtbl[bp[2]] << 6 | trtbl[bp[3]];
  464. X                n--;
  465. X            }
  466. X            bp += 4;
  467. X        }
  468. X        if ((n = fwrite(outl, 1, len, out)) <= 0) {
  469. X            format("uud: Error on writing decoded file.\n");
  470. X            Error(18);
  471. X        }
  472. X    }
  473. X}
  474. X
  475. X/*
  476. X * Find the next needed file, if existing, otherwise try further
  477. X * on next file.
  478. X */
  479. Xgetfile(buf) register char *buf;
  480. X{
  481. X    if ((pos = getnword(buf, 2)) == NULL) {
  482. X        format("uud: Missing include file name.\n");
  483. X        Error(17);
  484. X    } else
  485. X        if (source != NULL) {
  486. X            strcpy(ifname, source);
  487. X            strcat(ifname, pos);
  488. X        } else
  489. X            strcpy(ifname, pos);
  490. X#ifdef GEMDOS
  491. X    if (Fattrib(ifname, 0, 0) < 0)
  492. X#else
  493. X    if (access(ifname, 04))
  494. X#endif
  495. X    {
  496. X        if (debug) {
  497. X            format("Cant find: %s\n", ifname);
  498. X            format("Continuing to read same file.\n");
  499. X        }
  500. X    }
  501. X    else {
  502. X        if (freopen(ifname, "r", in) == in) {
  503. X            numl = 0;
  504. X            if (debug) 
  505. X                format("Reading next section from: %s\n", ifname);
  506. X        } else {
  507. X            format("uud: Freopen abort: %s\n", ifname);
  508. X            Error(9);
  509. X        }
  510. X    }
  511. X    loop {
  512. X        if (fgets(buf, LINELEN, in) == NULL) {
  513. X            format("uud: No begin line after include: %s\n", ifname);
  514. X            Error(12);
  515. X        }
  516. X        numl++;
  517. X        if (strncmp(buf, "table", 5) == 0) {
  518. X            gettable();
  519. X            continue;
  520. X        }
  521. X        if (strncmp(buf, "begin", 5) == 0) break;
  522. X    }
  523. X    lens = strlen(buf);
  524. X    if (lens) buf[--lens] = '\0';
  525. X/*
  526. X * Check the part suffix.
  527. X */
  528. X    if ((pos = getnword(buf, 3)) == NULL ) {
  529. X        format("uud: Missing part name, in included file: %s\n", ifname);
  530. X        Error(13);
  531. X    } else {
  532. X        part = *pos;
  533. X        partn++;
  534. X        if (partn > 'z') partn = 'a';
  535. X        if (part != partn) {
  536. X            format("uud: Part suffix mismatch: <%c> instead of <%c>.\n",
  537. X                part, partn);
  538. X            Error(14);
  539. X        }
  540. X        if (debug) format("Reading part %c\n", *pos);
  541. X    }
  542. X}
  543. X
  544. X/*
  545. X * Printf style formatting. (Borrowed from MicroEmacs by Dave Conroy.) 
  546. X * A lot smaller than the full fledged printf.
  547. X */
  548. X/* VARARGS1 */
  549. Xformat(fp, args) char *fp;
  550. X{
  551. X    doprnt(fp, (char *)&args);
  552. X}
  553. X
  554. Xdoprnt(fp, ap)
  555. Xregister char    *fp;
  556. Xregister char    *ap;
  557. X{
  558. X    register int    c, k;
  559. X    register char    *s;
  560. X
  561. X    while ((c = *fp++) != '\0') {
  562. X        if (c != '%')
  563. X            outc(c);
  564. X        else {
  565. X            c = *fp++;
  566. X            switch (c) {
  567. X            case 'd':
  568. X                puti(*(int *)ap, 10);
  569. X                ap += sizeof(int);
  570. X                break;
  571. X
  572. X            case 's':
  573. X                s = *(char **)ap;
  574. X                while ((k = *s++) != '\0')
  575. X                    outc(k);
  576. X                ap += sizeof(char *);
  577. X                break;
  578. X
  579. X            case 'c':
  580. X                outc(*(int *)ap);
  581. X                ap += sizeof(int);
  582. X                break;
  583. X
  584. X            default:
  585. X                outc(c);
  586. X            }
  587. X        }
  588. X    }
  589. X}
  590. X
  591. X/*
  592. X * Put integer, in radix "r".
  593. X */
  594. Xputi(i, r)
  595. Xregister unsigned int    i;
  596. Xregister unsigned int    r;
  597. X{
  598. X    register unsigned int    q, s;
  599. X
  600. X    if ((q = i / r) != 0)
  601. X        puti(q, r);
  602. X    s = i % r;
  603. X    if (s <= 9)
  604. X        outc(s + '0');
  605. X    else
  606. X        outc(s - 10 + 'A');
  607. X}
  608. Xoutc(c) register char c;
  609. X{
  610. X#ifdef GEMDOS
  611. X    if (c == '\n') Bconout(2, '\r');
  612. X    Bconout(2, c);
  613. X#else
  614. X    putchar(c);
  615. X#endif
  616. X}
  617. SHAR_EOF
  618. $TOUCH -am 0113121589 uud.c &&
  619. chmod 0644 uud.c ||
  620. echo "restore of uud.c failed"
  621. set `wc -c uud.c`;Wc_c=$1
  622. if test "$Wc_c" != "11741"; then
  623.     echo original size 11741, current size $Wc_c
  624. fi
  625. fi
  626. # ============= uue.c ==============
  627. if test X"$1" != X"-c" -a -f 'uue.c'; then
  628.     echo "File already exists: skipping 'uue.c'"
  629. else
  630. echo "x - extracting uue.c (Text)"
  631. sed 's/^X//' << 'SHAR_EOF' > uue.c &&
  632. X/*
  633. X *
  634. X * Uue -- encode a file so that it's printable ascii, short lines
  635. X *
  636. X * Slightly modified from a version posted to net.sources a while back,
  637. X * and suitable for compilation on the IBM PC
  638. X *
  639. X * modified for Lattice C on the ST - 11.05.85 by MSD
  640. X * modified for ALCYON on the ST -    10-24-86 by RDR
  641. X * modified a little more for MWC...  02/09/87 by JPHD
  642. X * (An optional first argument of the form: -nnumber (e.g. -500), will
  643. X * produce a serie of files that long, linked by the include statement,
  644. X * such files are automatically uudecoded by the companion program.)
  645. X * More mods, - ...           05/06/87 by jphd
  646. X * Mods for TOPS 20, and more.     08/06/87 by jphd
  647. X *     (remove freopen and rindex...change filename generation...)
  648. X * (A lot more to do about I/O speed, avoiding completely the stdio.h...)
  649. X *
  650. X */
  651. X
  652. X
  653. X#include <stdio.h>
  654. X#include <ctype.h>
  655. X
  656. X#define USAGE 
  657. X
  658. X/* ENC is the basic 1 character encoding function to make a char printing */
  659. X#define ENC(c) (((c) & 077) + ' ')
  660. X
  661. Xextern FILE  *fopen();
  662. XFILE *fp, *outp;
  663. Xchar ofname[80];
  664. Xint lenofname;
  665. Xint stdo = 0;
  666. X
  667. X#ifdef ST
  668. X#define READ "rb"
  669. X#else
  670. X#define READ "r"
  671. X#endif
  672. X
  673. Xint part = 'a', chap = 'a';
  674. X#define SEQMAX 'z'
  675. X#define SEQMIN 'a'
  676. Xchar seqc = SEQMAX;
  677. X
  678. Xint split = 0; fileln = 32000;
  679. X
  680. Xmain(argc, argv)
  681. Xint argc; char *argv[];
  682. X{
  683. X    char *fname;
  684. X
  685. X    if (argc < 2) {
  686. X        fprintf(stderr, "Almost foolproof uuencode v3.1 06 Aug 1987\n");
  687. X        fprintf(stderr, "Usage: uue [-n] inputfile [-]\n");
  688. X        exit(2);
  689. X        }
  690. X    if (argv[1][0] == '-') {
  691. X        fileln = -atoi(argv[1]);
  692. X        if (fileln <= 0) {
  693. X            fprintf(stderr, "Wrong file length arg.\n");
  694. X            exit();
  695. X        }
  696. X        split = 1;
  697. X        argv++;
  698. X        argc--;
  699. X    }
  700. X    if ((fp=fopen(argv[1], READ))==NULL) {  /* binary input !!! */
  701. X        fprintf(stderr,"Cannot open %s\n",argv[1]);
  702. X        exit(1);
  703. X    }
  704. X    strcpy(ofname, argv[1]);
  705. X    fname = ofname;
  706. X    do {
  707. X        if (*fname == '.')
  708. X            *fname = '\0';
  709. X    } while (*fname++);
  710. X        /* 8 char prefix + .uue -> 12 chars MAX */
  711. X    lenofname = strlen(ofname);
  712. X    if (lenofname > 8) ofname[8] = '\0';
  713. X    strcat(ofname,".uue");
  714. X    lenofname = strlen(ofname);
  715. X    if (!split && (argc > 2) && (argv[2][0] == '-')) {
  716. X        stdo = 1;
  717. X        outp = stdout;
  718. X     } else {
  719. X         makename();
  720. X         if((outp = fopen(ofname, "w")) == NULL) {
  721. X             fprintf(stderr,"Cannot open %s\n", ofname);
  722. X             exit(1);
  723. X             }
  724. X    }
  725. X    maketable();
  726. X    fprintf(outp,"begin %o %s\n", 0644, argv[1]);
  727. X    encode();
  728. X    fprintf(outp,"end\n");
  729. X    fclose(outp);
  730. X    exit(0);
  731. X}
  732. X
  733. X/* create ASCII table so a mailer can screw it up and the decode
  734. X * program can restore the error.
  735. X */
  736. Xmaketable()
  737. X{
  738. X    register int i, j;
  739. X
  740. X    fputs("table\n", outp);
  741. X    for(i = ' ', j = 0; i < '`' ; j++) {
  742. X        if (j == 32)
  743. X            putc('\n', outp);
  744. X        fputc(i++, outp);
  745. X    }
  746. X    putc('\n', outp);
  747. X}
  748. X
  749. X/*
  750. X * Generate the names needed for single and multiple part encoding.
  751. X */
  752. Xmakename()
  753. X{
  754. X    if (split) {
  755. X        ofname[lenofname - 1] = part;
  756. X        ofname[lenofname - 2] = chap;
  757. X    }
  758. X}
  759. X
  760. X/*
  761. X * copy from in to out, encoding as you go along.
  762. X */
  763. Xencode()
  764. X{
  765. X    char buf[80];
  766. X    register int i, n;
  767. X    register int lines;
  768. X    lines = 6;
  769. X
  770. X    for (;;) {
  771. X        n = fr(buf, 45);
  772. X        putc(ENC(n), outp);
  773. X        for (i = 0; i < n; i += 3)
  774. X              outdec(&buf[i]);
  775. X        putc(seqc, outp);
  776. X        seqc--;
  777. X        if (seqc < SEQMIN) seqc = SEQMAX;
  778. X        putc('\n', outp);
  779. X        ++lines;
  780. X        if (split && (lines > fileln)) {
  781. X            part++;
  782. X            if (part > 'z') {
  783. X                part = 'a';
  784. X                if (chap == 'z')
  785. X                    chap = 'a'; /* loop ... */
  786. X                else
  787. X                    chap++;
  788. X            }
  789. X            makename();
  790. X            fprintf(outp,"include %s\n",ofname);
  791. X            fclose(outp);
  792. X            if((outp = fopen(ofname, "w")) == NULL) {
  793. X                fprintf(stderr,"Cannot open %s\n",ofname);
  794. X                exit(1);
  795. X            }
  796. X            maketable();
  797. X            fprintf(outp,"begin part %c %s\n",part,ofname);
  798. X            lines = 6;
  799. X        }
  800. X        if (n <= 0)
  801. X            break;
  802. X    }
  803. X}
  804. X
  805. X/*
  806. X * output one group of 3 bytes, pointed at by p, on file f.
  807. X */
  808. Xoutdec(p)
  809. Xregister char *p;
  810. X{
  811. X    register int c1, c2, c3, c4;
  812. X
  813. X    c1 = *p >> 2;
  814. X    c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
  815. X    c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
  816. X    c4 = p[2] & 077;
  817. X    putc(ENC(c1), outp);
  818. X    putc(ENC(c2), outp);
  819. X    putc(ENC(c3), outp);
  820. X    putc(ENC(c4), outp);
  821. X}
  822. X
  823. X/* fr: like read but stdio */
  824. Xint fr(buf, cnt)
  825. Xregister char *buf;
  826. Xregister int cnt;
  827. X{
  828. X    register int c, i;
  829. X    for (i = 0; i < cnt; i++) {
  830. X        c = fgetc(fp);
  831. X        if (feof(fp))
  832. X            return(i);
  833. X        buf[i] = c;
  834. X    }
  835. X    return (cnt);
  836. X}
  837. SHAR_EOF
  838. $TOUCH -am 0113121789 uue.c &&
  839. chmod 0644 uue.c ||
  840. echo "restore of uue.c failed"
  841. set `wc -c uue.c`;Wc_c=$1
  842. if test "$Wc_c" != "4186"; then
  843.     echo original size 4186, current size $Wc_c
  844. fi
  845. fi
  846. # ============= uux.doc ==============
  847. if test X"$1" != X"-c" -a -f 'uux.doc'; then
  848.     echo "File already exists: skipping 'uux.doc'"
  849. else
  850. echo "x - extracting uux.doc (Text)"
  851. sed 's/^X//' << 'SHAR_EOF' > uux.doc &&
  852. X
  853. X            *** UUE ***
  854. X
  855. Xuue filename
  856. Xuue -n filename
  857. Xuue filename -
  858. X
  859. XIf given no args, uue will tells you what version is this, and the usage.
  860. XThe filename arg will be uuencoded.
  861. Xthe -n option will yield several files, each n lines long.
  862. Xuue -500 niceprog.ttp will give:
  863. Xniceprog.uaa niceprog.uab ... niceprog.uaz (!!! that would be a lot),
  864. Xeach (except the last) will be 500 lines long.
  865. XIf given, the final - character (not valid if -n is present) will send
  866. Xthe output to stdout rather than a disk file.
  867. XThe filenames synthetized by uue will be at most 8 chars + .uue (or .uxx)
  868. Xto be in the accepted pattern for GEMDOS, MS/DOS, UN*X and TOPS20.
  869. X================================================================================
  870. X
  871. XThis is the v3.3 19-Apr-88 version of uud.ttp (and v3.1 of uue.ttp too)
  872. XIt is named uud instead of uudecode, to avoid confusion between different
  873. Ximplementations of the uudecoding functionnality.
  874. XIdem for uue.
  875. X
  876. XThese versions have the following capabilities:
  877. X1- Missing trailing blanks are still OK. (I am on EARN/BITNET ...)
  878. X   Absolutely no need for any procedure to restore 61 chars a line...
  879. X2- **Some** common internetwork transpositions are OK (e.g. 
  880. X   tilde instead of circonflex...but not coma instead of circonflex!) 
  881. X   (I am still on EARN/BITNET)
  882. X   No need to edit the file to change chars...
  883. X   Note: I have been told that the substitution of blanks by grave
  884. X   accent is not a gateway/network bug, but a feature of some recent
  885. X   UN*X uuencode, to avoid the blank compression by some protocols.
  886. X   Note: It is *NOT* BITNET/EARN that damage the files, we transfert non
  887. X   encoded binaries on this network, but put the blame on some brain damaged
  888. X   gateways. (One of them, between Usenet and Bitnet, is really ruining
  889. X   files... Totally wrong ASCII -> EBCDIC table)
  890. X3- Multi-file decoding is OK, by the 'include xxx' and 'begin part n' lines.
  891. X   To allow for identififation of the original file in the parts, the file
  892. X   name is now provided in the 'begin part n' line.
  893. X4- If the included files do not exist, uud.ttp will attempt to go on with the
  894. X   same file, in case the multiple files have just been concatenated upon
  895. X   reception.
  896. X5- There is a line sequence checking possible, allowing the detection of
  897. X   missing, duplicate, corrupted lines or files. (I have sloppy fingers when
  898. X   editing ...)
  899. X   This feature is enabled if the first line of the 1st uuencoded file
  900. X   is postfixed with a 'z', this is done automatically by the uue.ttp
  901. X   companion program.
  902. X   Note: a bug of the previous version is fixed.
  903. X6- A complete check of the uudecoding process is possible, by use of the
  904. X   -d flag. This will tell you about all whats going on in there, plus
  905. X   this is enabling a complete character by character check of the file
  906. X   while decoding. This should make some subtle file corruptions pop up,
  907. X   as all the uudecode do not check whats in a line before doing their job.
  908. X   If this option detect an error, then the file produced will not be
  909. X   correct (uud stops at the first error detected, and close the file).
  910. X7- If there is a character table present before each file, it will be used,
  911. X   this table is produced by the companion uue.
  912. X   The use of this table allows for some incredible recovery of files that
  913. X   went through some really brain damage gateway. No sweat.
  914. X8- You can decode a single file contaning several uuencoded files, at once;
  915. X   You give a complete month of INFO-ATARI16 digest, and voila all the
  916. X   nice PD .prg's, no editing, no sweat. (To be true, it's been a long time
  917. X   without *.prg in the digests..., but you should try it.)
  918. X9- The files are completely compatible with true UN*X uudecode/uuencode.
  919. X   As long as you do not use the multiple part option of uue.ttp.
  920. X10- Compile on the ST, using MWC, on UN*X System V and on TOPS20 using cc.
  921. X
  922. X
  923. XEn resume: get the mail file containing what you want to decode, on the
  924. XAtari ST, and apply uud.ttp on it, without any editing of any sort, including
  925. Xremoving mail header. (except for multiple parts, where the file names must be
  926. Xcorrect, but no need to edit individual files).
  927. X
  928. X
  929. Xuud v3.3 is the result of:
  930. X1. fixing a bug (nobody, but me, complained about it)
  931. X2. Having a source that compile and run successfully on
  932. X   Atari ST, MS-DOS and UNIX. (Nobody got an Amiga around here)
  933. X   I did the coding/compiling/testing for all 3 systems;
  934. X   For UNIX, it is done using cc on a real/certified SystemVr2
  935. X   For Atari, it is done using MWC 2.x.
  936. X   For the PC, it is done with MSC 4.0. (An attempt with
  937. X   Turbo C did not give me any thing that run correctly)
  938. X   (I discovered a slight bug in MSC 4.0 too, but no big deal.)
  939. X3. Adding some requested features:
  940. X   A. The -t option to allow for a full disk/directory target
  941. X      specification, on which the uuencoded filename is appended.
  942. X      The resulting pathname is where the result of the decoding
  943. X      will be written.
  944. X   B. The -s option: idem -t, but for the source file.
  945. X   C. the -n option to disable the line sequence checking, in case
  946. X      of uue'ed files, for any good/bad reason.
  947. X
  948. X
  949. X   The maximum command line can thus be like:
  950. X   uud -d -n -t c:^binaries^ -s d:^encoded^ file.uue
  951. X   -d : enable the verbose/debugging option, telling you what
  952. X      uud is doing, and sometimes even why...
  953. X   -n : suppress the line sequence checking. (Totally useless option)
  954. X      (The line checking is turned off automagically for files
  955. X      that where not uuencoded by uue, even now for the files with
  956. X      lines terminated by the 'z' char... no more fuzz about them...)
  957. X   -t directory : where the output file(s) will be written, in this case
  958. X      must be terminated by the directory separator character;
  959. X   -s directory : where uud is going to find the file(s) to
  960. X      decode.
  961. X4. This uud can decode line with 80 uuencoded char, instead of the
  962. X   usual 60, the next generation of uue will take advantage of that.
  963. X5. If the file name on the command line,
  964. X   is replaced by the character '-' then
  965. X   standard input will be read, instead of a named file.
  966. X   (For the heavy UNIX news reader...)
  967. X6. typing uud alone on a line, or invoking it without arguments
  968. X   from the desktop, will give you the usage with a reminder
  969. X   about the options.
  970. X
  971. XBig news for Atari/PC users with only restricted disks,
  972. Xyou can decode now much larger files, as the uud.ttp, source
  973. Xand destination files can all be on separate disks.
  974. X
  975. XIf given no args, uud will tells you what version is this, and the usage.
  976. XWith the -d option, a whole lot of checking is done, and it is telling
  977. Xyou all that it is doing.
  978. XIn all case if there is anything else that a perfect decoding, you will
  979. Xhave some message and you'll need to press any key to exit. (I anybody
  980. Xtell me how to tell if we are working from the desktop, or from a shell,
  981. XI will make the pause valid only if run from the desktop. Some kind soul
  982. Xwith an exemple ? I suppose I have to look into the base page...)
  983. XIn case of any error, the produced file is not valid.
  984. X
  985. X==============================================================================
  986. SHAR_EOF
  987. $TOUCH -am 0629144590 uux.doc &&
  988. chmod 0644 uux.doc ||
  989. echo "restore of uux.doc failed"
  990. set `wc -c uux.doc`;Wc_c=$1
  991. if test "$Wc_c" != "7035"; then
  992.     echo original size 7035, current size $Wc_c
  993. fi
  994. fi
  995. exit 0
  996. --
  997. Ralph P. Sobek              Disclaimer: The above ruminations are my own.
  998. ralph@laas.fr                   Addresses are ordered by importance.
  999. ralph@laas.uucp, or ...!uunet!laas!ralph        
  1000. If all else fails, try:                      sobek@eclair.Berkeley.EDU
  1001. ===============================================================================
  1002. THINK: Due to IMF & World Bank policies 100 million Latin American children are
  1003. living, eating, and sleeping in the streets -- Le Monde Diplomatique
  1004.