uuencode.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       uuencode.c (3015B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include <sys/stat.h>
            3 
            4 #include <stdio.h>
            5 #include <string.h>
            6 
            7 #include "util.h"
            8 
            9 static unsigned int
           10 b64e(unsigned char *b)
           11 {
           12         unsigned int o, p = b[2] | (b[1] << 8) | (b[0] << 16);
           13         const char b64et[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
           14 
           15         o = b64et[p & 0x3f]; p >>= 6;
           16         o = (o << 8) | b64et[p & 0x3f]; p >>= 6;
           17         o = (o << 8) | b64et[p & 0x3f]; p >>= 6;
           18         o = (o << 8) | b64et[p & 0x3f];
           19 
           20         return o;
           21 }
           22 
           23 static void
           24 uuencodeb64(FILE *fp, const char *name, const char *s)
           25 {
           26         struct stat st;
           27         ssize_t n, m = 0;
           28         unsigned char buf[45], *pb;
           29         unsigned int out[sizeof(buf)/3 + 1], *po;
           30 
           31         if (fstat(fileno(fp), &st) < 0)
           32                 eprintf("fstat %s:", s);
           33         printf("begin-base64 %o %s\n", st.st_mode & 0777, name);
           34         /* write line by line */
           35         while ((n = fread(buf, 1, sizeof(buf), fp))) {
           36                 /* clear old buffer if converting with non-multiple of 3 */
           37                 if (n != sizeof(buf) && (m = n % 3) != 0) {
           38                         buf[n] = '\0'; /* m == 2 */
           39                         if (m == 1) buf[n+1] = '\0'; /* m == 1 */
           40                 }
           41                 for (pb = buf, po = out; pb < buf + n; pb += 3)
           42                         *po++ = b64e(pb);
           43                 if (m != 0) {
           44                         unsigned int mask = 0xffffffff, dest = 0x3d3d3d3d;
           45                         /* m==2 -> 0x00ffffff; m==1 -> 0x0000ffff */
           46                         mask >>= ((3-m) << 3);
           47                         po[-1] = (po[-1] & mask) | (dest & ~mask);
           48                 }
           49                 *po++ = '\n';
           50                 fwrite(out, 1, (po - out) * sizeof(unsigned int) - 3, stdout);
           51         }
           52         if (ferror(fp))
           53                 eprintf("'%s' read error:", s);
           54         puts("====");
           55 }
           56 
           57 static void
           58 uuencode(FILE *fp, const char *name, const char *s)
           59 {
           60         struct stat st;
           61         unsigned char buf[45], *p;
           62         ssize_t n;
           63         int ch;
           64 
           65         if (fstat(fileno(fp), &st) < 0)
           66                 eprintf("fstat %s:", s);
           67         printf("begin %o %s\n", st.st_mode & 0777, name);
           68         while ((n = fread(buf, 1, sizeof(buf), fp))) {
           69                 ch = ' ' + (n & 0x3f);
           70                 putchar(ch == ' ' ? '`' : ch);
           71                 for (p = buf; n > 0; n -= 3, p += 3) {
           72                         if (n < 3) {
           73                                 p[2] = '\0';
           74                                 if (n < 2)
           75                                         p[1] = '\0';
           76                         }
           77                         ch = ' ' + ((p[0] >> 2) & 0x3f);
           78                         putchar(ch == ' ' ? '`' : ch);
           79                         ch = ' ' + (((p[0] << 4) | ((p[1] >> 4) & 0xf)) & 0x3f);
           80                         putchar(ch == ' ' ? '`' : ch);
           81                         ch = ' ' + (((p[1] << 2) | ((p[2] >> 6) & 0x3)) & 0x3f);
           82                         putchar(ch == ' ' ? '`' : ch);
           83                         ch = ' ' + (p[2] & 0x3f);
           84                         putchar(ch == ' ' ? '`' : ch);
           85                 }
           86                 putchar('\n');
           87         }
           88         if (ferror(fp))
           89                 eprintf("'%s' read error:", s);
           90         printf("%c\nend\n", '`');
           91 }
           92 
           93 static void
           94 usage(void)
           95 {
           96         eprintf("usage: %s [-m] [file] name\n", argv0);
           97 }
           98 
           99 int
          100 main(int argc, char *argv[])
          101 {
          102         FILE *fp = NULL;
          103         void (*uuencode_f)(FILE *, const char *, const char *) = uuencode;
          104         int ret = 0;
          105 
          106         ARGBEGIN {
          107         case 'm':
          108                 uuencode_f = uuencodeb64;
          109                 break;
          110         default:
          111                 usage();
          112         } ARGEND
          113 
          114         if (!argc || argc > 2)
          115                 usage();
          116 
          117         if (argc == 1 || !strcmp(argv[0], "-")) {
          118                 uuencode_f(stdin, argv[0], "<stdin>");
          119         } else {
          120                 if (!(fp = fopen(argv[0], "r")))
          121                         eprintf("fopen %s:", argv[0]);
          122                 uuencode_f(fp, argv[1], argv[0]);
          123         }
          124 
          125         ret |= fp && fshut(fp, argv[0]);
          126         ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
          127 
          128         return ret;
          129 }