home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume6 / btoa < prev    next >
Text File  |  1989-02-03  |  10KB  |  431 lines

  1. Path: lll-winken!ncis.llnl.gov!helios.ee.lbl.gov!pasteur!agate!bionet!csd4.milw.wisc.edu!leah!itsgw!steinmetz!uunet!allbery
  2. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  3. Newsgroups: comp.sources.misc
  4. Subject: v06i001: btoa, tarmail
  5. Message-ID: <46897@uunet.UU.NET>
  6. Date: 21 Jan 89 20:19:33 GMT
  7. Sender: allbery@uunet.UU.NET
  8. Reply-To: per@philabs.Philips.Com (Paul E. Rutter)
  9. Lines: 419
  10. Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  11.  
  12. Posting-number: Volume 6, Issue 1
  13. Submitted-by: per@philabs.Philips.Com (Paul E. Rutter)
  14. Archive-name: btoa
  15.  
  16. [I thought this came with Usenet news sources?!  ++bsa]
  17.  
  18.   As I have seen a number of requests for btoa lately in comp.sources.wanted,
  19. and received a number of requests personally through round about email, it
  20. seems like it is time to repost sources to btoa/atob and tarmail/untarmail.
  21. A man page is included in the following shar file.  I am the original author
  22. of btoa.
  23.  
  24.                             Paul Rutter
  25.                             per@philabs.philips.com
  26.  
  27. #! /bin/sh
  28. # The rest of this file is a shell script which will extract:
  29. # Makefile atob.c btoa.c btoa.man tarmail untarmail
  30. # Suggested restore procedure:
  31. # Edit off anything above these comment lines,
  32. # save this file in an empty directory,
  33. # then say: sh < file
  34. echo x - Makefile
  35. cat >Makefile <<'!Funky!Stuff!'
  36. CC=cc -O -s
  37. BIN=/usr/local/bin
  38. MAN=/usr/man/manl
  39. L=l
  40.  
  41. install: atob btoa tarmail untarmail
  42.     rm -f $(BIN)/atob $(BIN)/btoa $(BIN)/tarmail $(BIN)/untarmail
  43.     cp atob btoa $(BIN)
  44.     cp tarmail untarmail $(BIN)
  45.     make man clean
  46.  
  47. man:    btoa.man
  48.     rm -f $(MAN)/btoa.$(L) $(MAN)/tarmail.$(L)
  49.     cp btoa.man $(MAN)/btoa.$(L)
  50.     cp btoa.man $(MAN)/tarmail.$(L)
  51.  
  52. atob:    atob.c
  53.     $(CC) atob.c -o atob
  54.  
  55. btoa:    btoa.c
  56.     $(CC) btoa.c -o btoa
  57.  
  58. clean:
  59.     rm -f *.o atob btoa
  60. !Funky!Stuff!
  61. echo x - atob.c
  62. cat >atob.c <<'!Funky!Stuff!'
  63. /* atob
  64.  * stream filter to change printable ascii from "btoa" back into 8 bit bytes
  65.  * if bad chars, or Csums do not match: exit(1) [and NO output]
  66.  *
  67.  * Paul Rutter Joe Orost
  68.  */
  69.  
  70. #include <stdio.h>
  71.  
  72. #define reg register
  73.  
  74. #define streq(s0, s1)  strcmp(s0, s1) == 0
  75.  
  76. #define times85(x)    ((((((x<<2)+x)<<2)+x)<<2)+x)
  77.  
  78. long int Ceor = 0;
  79. long int Csum = 0;
  80. long int Crot = 0;
  81. long int word = 0;
  82. long int bcount = 0;
  83.  
  84. fatal() {
  85.   fprintf(stderr, "bad format or Csum to atob\n");
  86.   exit(1);
  87. }
  88.  
  89. #define DE(c) ((c) - '!')
  90.  
  91. decode(c) reg c;
  92. {
  93.   if (c == 'z') {
  94.     if (bcount != 0) {
  95.       fatal();
  96.     } 
  97.     else {
  98.       byteout(0);
  99.       byteout(0);
  100.       byteout(0);
  101.       byteout(0);
  102.     }
  103.   } 
  104.   else if ((c >= '!') && (c < ('!' + 85))) {
  105.     if (bcount == 0) {
  106.       word = DE(c);
  107.       ++bcount;
  108.     } 
  109.     else if (bcount < 4) {
  110.       word = times85(word);
  111.       word += DE(c);
  112.       ++bcount;
  113.     } 
  114.     else {
  115.       word = times85(word) + DE(c);
  116.       byteout((int)((word >> 24) & 255));
  117.       byteout((int)((word >> 16) & 255));
  118.       byteout((int)((word >> 8) & 255));
  119.       byteout((int)(word & 255));
  120.       word = 0;
  121.       bcount = 0;
  122.     }
  123.   } 
  124.   else {
  125.     fatal();
  126.   }
  127. }
  128.  
  129. FILE *tmp_file;
  130.  
  131. byteout(c) reg c;
  132. {
  133.   Ceor ^= c;
  134.   Csum += c;
  135.   Csum += 1;
  136.   if ((Crot & 0x80000000)) {
  137.     Crot <<= 1;
  138.     Crot += 1;
  139.   } 
  140.   else {
  141.     Crot <<= 1;
  142.   }
  143.   Crot += c;
  144.   putc(c, tmp_file);
  145. }
  146.  
  147. main(argc, argv) char **argv;
  148. {
  149.   reg c;
  150.   reg long int i;
  151.   char tmp_name[100];
  152.   char buf[100];
  153.   long int n1, n2, oeor, osum, orot;
  154.  
  155.   if (argc != 1) {
  156.     fprintf(stderr,"bad args to %s\n", argv[0]);
  157.     exit(2);
  158.   }
  159.   sprintf(tmp_name, "/usr/tmp/atob.%x", getpid());
  160.   tmp_file = fopen(tmp_name, "w+");
  161.   if (tmp_file == NULL) {
  162.     fatal();
  163.   }
  164.   unlink(tmp_name); /* Make file disappear */
  165.   /*search for header line*/
  166.   for (;;) {
  167.     if (fgets(buf, sizeof buf, stdin) == NULL) {
  168.       fatal();
  169.     }
  170.     if (streq(buf, "xbtoa Begin\n")) {
  171.       break;
  172.     }
  173.   }
  174.  
  175.   while ((c = getchar()) != EOF) {
  176.     if (c == '\n') {
  177.       continue;
  178.     } 
  179.     else if (c == 'x') {
  180.       break;
  181.     } 
  182.     else {
  183.       decode(c);
  184.     }
  185.   }
  186.   if (scanf("btoa End N %ld %lx E %lx S %lx R %lx\n", &n1, &n2, &oeor, &osum, &
  187. orot) != 5) {
  188.     fatal();
  189.   }
  190.   if ((n1 != n2) || (oeor != Ceor) || (osum != Csum) || (orot != Crot)) {
  191.     fatal();
  192.   } 
  193.   else {
  194.     /* Now that we know everything is OK, copy tmp file to stdout */
  195.     fseek(tmp_file, 0L, 0);
  196.     for (i = n1; --i >= 0;) {
  197.       putchar(getc(tmp_file));
  198.     }
  199.   }
  200.   exit(0);
  201. }
  202. !Funky!Stuff!
  203. echo x - btoa.c
  204. cat >btoa.c <<'!Funky!Stuff!'
  205. /* btoa: version 4.0
  206.  * stream filter to change 8 bit bytes into printable ascii
  207.  * computes the number of bytes, and three kinds of simple checksums
  208.  * incoming bytes are collected into 32-bit words, then printed in base 85
  209.  * exp(85,5) > exp(2,32)
  210.  * the ASCII characters used are between '!' and 'u'
  211.  * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
  212.  *
  213.  * Paul Rutter Joe Orost
  214.  */
  215.  
  216. #include <stdio.h>
  217.  
  218. #define reg register
  219.  
  220. #define MAXPERLINE 78
  221.  
  222. long int Ceor = 0;
  223. long int Csum = 0;
  224. long int Crot = 0;
  225.  
  226. long int ccount = 0;
  227. long int bcount = 0;
  228. long int word;
  229.  
  230. #define EN(c)    (int) ((c) + '!')
  231.  
  232. encode(c) reg c;
  233. {
  234.   Ceor ^= c;
  235.   Csum += c;
  236.   Csum += 1;
  237.   if ((Crot & 0x80000000)) {
  238.     Crot <<= 1;
  239.     Crot += 1;
  240.   } 
  241.   else {
  242.     Crot <<= 1;
  243.   }
  244.   Crot += c;
  245.  
  246.   word <<= 8;
  247.   word |= c;
  248.   if (bcount == 3) {
  249.     wordout(word);
  250.     bcount = 0;
  251.   } 
  252.   else {
  253.     bcount += 1;
  254.   }
  255. }
  256.  
  257. wordout(word) reg long int word;
  258. {
  259.   if (word == 0) {
  260.     charout('z');
  261.   } 
  262.   else {
  263.     reg int tmp = 0;
  264.  
  265.     if (word < 0)
  266.     { /* Because some don't support unsigned long */
  267.       tmp = 32;
  268.       word = word - (long)(85L * 85 * 85 * 85 * 32);
  269.     }
  270.     if (word < 0) {
  271.       tmp = 64;
  272.       word = word - (long)(85L * 85 * 85 * 85 * 32);
  273.     }
  274.     charout(EN((word / (long)(85L * 85 * 85 * 85)) + tmp));
  275.     word %= (long)(85L * 85 * 85 * 85);
  276.     charout(EN(word / (85L * 85 * 85)));
  277.     word %= (85L * 85 * 85);
  278.     charout(EN(word / (85L * 85)));
  279.     word %= (85L * 85);
  280.     charout(EN(word / 85));
  281.     word %= 85;
  282.     charout(EN(word));
  283.   }
  284. }
  285.  
  286. charout(c) {
  287.   putchar(c);
  288.   ccount += 1;
  289.   if (ccount == MAXPERLINE) {
  290.     putchar('\n');
  291.     ccount = 0;
  292.   }
  293. }
  294.  
  295. main(argc,argv)
  296. char **argv;
  297. {
  298.   reg c;
  299.   reg long int n;
  300.  
  301.   if (argc != 1) {
  302.     fprintf(stderr,"bad args to %s\n", argv[0]);
  303.     exit(2);
  304.   }
  305.   printf("xbtoa Begin\n");
  306.   n = 0;
  307.   while ((c = getchar()) != EOF) {
  308.     encode(c);
  309.     n += 1;
  310.   }
  311.   while (bcount != 0) {
  312.     encode(0);
  313.   }
  314.   /* n is written twice as crude cross check*/
  315.   if (ccount == 0) /* ccount == 0 means '\n' just written in charout() */
  316.     ; /* this avoids bug in BITNET, which changes blank line to spaces */
  317.   else
  318.     putchar('\n');
  319.   printf("xbtoa End N %ld %lx E %lx S %lx R %lx\n", n, n, Ceor, Csum, Crot);
  320.   exit(0);
  321. }
  322. !Funky!Stuff!
  323. echo x - btoa.man
  324. cat >btoa.man <<'!Funky!Stuff!'
  325. .TH BTOA 1 local
  326. .SH NAME
  327. btoa, atob, tarmail, untarmail \- encode/decode binary to printable ASCII
  328. .SH SYNOPSIS
  329. .B btoa
  330. .br
  331. .B atob
  332. .br
  333. .B tarmail
  334. who files ...
  335. .br
  336. .B untarmail
  337. [ file ]
  338. .SH DESCRIPTION
  339. .I Btoa
  340. is a filter that reads anything from the standard input, and encodes it into
  341. printable ASCII on the standard output.  It also attaches a header and checksum
  342. information used by the reverse filter 
  343. .I atob 
  344. to find the start of the data and to check integrity.
  345. .PP
  346. .I Atob
  347. reads an encoded file, strips off any leading and trailing lines added by
  348. mailers, and recreates a copy of the original file on the standard output.
  349. .I Atob
  350. gives NO output (and exits with an error message) if its input is garbage or
  351. the checksums do not check.  (The checksum is at the end; giving no output on
  352. checksum error guarantees that no "partial things" will be created if there
  353. was an error in transit).
  354. .PP
  355. .I Tarmail
  356. is a shell script that tar's up all the given files, pipes them 
  357. through 
  358. .IR compress ","
  359. .IR btoa ","
  360. and mails them to the given person.  For
  361. example:
  362. .PP
  363. .in 1i
  364. tarmail ralph foo.c a.out
  365. .in -1i
  366. .PP
  367. Will package up files "foo.c" and "a.out" and mail them to "ralph".
  368. .PP
  369. .I Tarmail 
  370. with no args will print a short message reminding you what the required args 
  371. are.  When the mail is received at the other end, that person should use
  372. mail to save the message in some temporary file name (say "xx").
  373. Then saying "untarmail xx"
  374. will decode the message and untar it.  
  375. .I Untarmail 
  376. can also be used as a filter.  By using 
  377. .IR tarmail ","
  378. binary files and
  379. entire directory structures can be easily transmitted between machines.
  380. Naturally, you should understand what tar itself does before you use 
  381. .IR tarmail "."
  382. .PP
  383. Other uses:
  384. .PP
  385. compress < secrets | crypt | btoa | mail ralph
  386. .PP
  387. will mail the encrypted contents of the file "secrets" to ralph.  If ralph
  388. knows the encryption key, he can decode it by saving the mail (say in "xx"),
  389. and then running:
  390. .PP
  391. atob < xx | crypt | uncompress
  392. .PP
  393. (crypt requests the key from the terminal,
  394. and the "secrets" come out on the terminal).
  395. .SH AUTHOR
  396. Paul Rutter
  397. .SH FEATURES
  398. .I Btoa
  399. uses a compact base-85 encoding so that
  400. 4 bytes are encoded into 5 characters (file is expanded by 25%).
  401. As a special case, 32-bit zero is encoded as one character.  This encoding
  402. produces less output than
  403. .IR uuencode "(1)."
  404. .SH "SEE ALSO"
  405. compress(1), crypt(1), uuencode(1), mail(1)
  406. !Funky!Stuff!
  407. echo x - tarmail
  408. cat >tarmail <<'!Funky!Stuff!'
  409. if test $# -lt 2; then
  410.   echo "Usage: tarmail mailpath directory-or-file(s)"
  411.   exit
  412. else
  413.   mailpath=$1
  414.   echo "mailpath = $mailpath"
  415.   shift
  416.   echo files = $*
  417.   tar cvf - $* | compress | btoa | mail $mailpath
  418. fi
  419. !Funky!Stuff!
  420. echo x - untarmail
  421. cat >untarmail <<'!Funky!Stuff!'
  422. if test $# -ge 1; then
  423.    atob < $1 | uncompress | tar xvpf -
  424.    mv $1 /tmp/$1.$$
  425.    echo tarmail file moved to: /usr/tmp/$1.$$
  426. else
  427.    atob | uncompress | tar xvpf -
  428. fi
  429. !Funky!Stuff!
  430. exit 0
  431.