comparison toys/pending/uudecode.c @ 839:a315fb343e2b

More uudecode cleanup.
author Rob Landley <rob@landley.net>
date Thu, 28 Mar 2013 23:33:27 -0500
parents a60c572a8218
children
comparison
equal deleted inserted replaced
4:a5b2a1aa2c42 5:1644cacb0cc0
22 22
23 GLOBALS( 23 GLOBALS(
24 char *o; 24 char *o;
25 ) 25 )
26 26
27 static inline signed char uudecode_b64_1byte(char in)
28 {
29 if (in >= 'A' && in <= 'Z') return in-'A';
30 if (in >= 'a' && in <= 'z') return in-'a'+26;
31 if (in >= '0' && in <= '9') return in-'0'+52;
32 if (in == '+') return 62;
33 if (in == '/') return 63;
34
35 return -1;
36 };
37
38
39 static int uudecode_b64_4bytes(char *out, char *in) 27 static int uudecode_b64_4bytes(char *out, char *in)
40 { 28 {
41 int i, len = 3; 29 int i, len = 3;
42 unsigned x = 0; 30 unsigned x = 0;
43 31
44 for (i=0; i<4; i++) { 32 for (i=0; i<4; i++) {
45 int c = in[i]; 33 int c = in[i];
46 34
47 if (c == '=') len--; 35 if (c == '=') {
48 else if (len != 3) len = 0; 36 len--;
49 if (!len) error_exit("bad input"); 37 c = 'A';
38 } else if (len != 3) len = 0;
39 if (!len) goto bad;
50 40
51 x |= uudecode_b64_1byte(c) << (6*(3-i)); 41 if (c >= 'A' && c <= 'Z') c -= 'A';
42 else if (c >= 'a' && c <= 'z') c += 26 - 'a';
43 else if (c >= '0' && c <= '9') c += 52 - '0';
44 else if (c == '+') c = 62;
45 else if (c == '/') c =63;
46 else goto bad;
47
48 x |= c << (6*(3-i));
52 if (i && i <= len) *(out++) = (x>>(8*(3-i))) & 0xff; 49 if (i && i <= len) *(out++) = (x>>(8*(3-i))) & 0xff;
53 } 50 }
54 51
55 return len; 52 return len;
53
54 bad:
55 error_exit("bad input");
56 } 56 }
57 57
58 static void uudecode_b64_line(int ofd, char *in, int ilen) 58 static void uudecode_b64_line(int ofd, char *in, int ilen)
59 { 59 {
60 int olen; 60 int olen;
66 in += 4; 66 in += 4;
67 ilen -= 4; 67 ilen -= 4;
68 }; 68 };
69 } 69 }
70 70
71 static void uudecode_b64(int ifd, int ofd)
72 {
73 int len;
74 char *line;
75
76 while ((line = get_line(ifd)) != NULL) {
77 if ((len = strlen(line)) < 4) continue;
78 if (!strncmp(line, "====", 4)) return;
79 uudecode_b64_line(ofd,line,len);
80 free(line);
81 }
82 }
83
84
85 static void uudecode_uu_4bytes(char *out, char *in, int len) 71 static void uudecode_uu_4bytes(char *out, char *in, int len)
86 { 72 {
87 unsigned int i,x=0; 73 unsigned int i,x=0;
88 74
89 for (i = 0; i < 4; i++) x |= ((in[i] - 32) & 0x03f) << (6*(3-i)); 75 for (i = 0; i < 4; i++) x |= ((in[i] - 32) & 0x03f) << (6*(3-i));
91 for (i = 0; i < len; i++) *out++ = x >> (8*(2-i)); 77 for (i = 0; i < len; i++) *out++ = x >> (8*(2-i));
92 } 78 }
93 79
94 static void uudecode_uu_line(int ofd, char *in) 80 static void uudecode_uu_line(int ofd, char *in)
95 { 81 {
96 int olen = in[0] - 32; 82 int olen = (in[0] - 32) & 0x3f;
97 char buf[4]; 83 char buf[4];
98 84
99 in++; 85 in++;
100 while (olen > 0) { 86 while (olen > 0) {
101 uudecode_uu_4bytes(buf,in,olen); 87 uudecode_uu_4bytes(buf,in,olen);
103 olen -= 3; 89 olen -= 3;
104 in += 4; 90 in += 4;
105 } 91 }
106 } 92 }
107 93
108 static void uudecode_uu(int ifd, int ofd)
109 {
110 char *line = NULL;
111
112 for (;;) {
113 if (!(line = get_line(ifd))) break;
114 if (*line) {
115 if (!strncmp(line, "end", 3)) {
116 free(line);
117 break;
118 }
119 uudecode_uu_line(ofd,line);
120 }
121 free(line);
122 }
123 }
124
125 void uudecode_main(void) 94 void uudecode_main(void)
126 { 95 {
127 int ifd = 0, ofd, idx = 0; 96 int ifd = 0, ofd, idx = 0, m;
128 char *line; 97 char *line = 0,
129 void (*decoder)(int ifd, int ofd) = NULL; 98 *class[] = {"begin%*[ ]%15s%*[ ]%n", "begin-base64%*[ ]%15s%*[ ]%n"};
99
130 100
131 if (toys.optc) ifd = xopen(*toys.optargs, O_RDONLY); 101 if (toys.optc) ifd = xopen(*toys.optargs, O_RDONLY);
132 102
133 for (;;) { 103 for (;;) {
134 char mode[16]; 104 char mode[16];
135 105
136 if (!(line = get_line(ifd))) error_exit("no header"); 106 free(line);
137 sscanf(line, "begin%*[ ]%15s%*[ ]%n", mode, &idx); 107 if (!(line = get_line(ifd))) error_exit("bad EOF");
138 if (idx) decoder = uudecode_uu; 108 for (m=0; m < 2; m++) {
139 else { 109 sscanf(line, class[m], mode, &idx);
140 sscanf(line, "begin-base64%*[ ]%15s%*[ ]%n", mode, &idx); 110 if (idx) break;
141 if (idx) decoder = uudecode_b64;
142 } 111 }
143 112
144 if (!idx) { 113 if (!idx) continue;
145 free(line);
146 continue;
147 }
148 114
149 ofd = xcreate(TT.o ? TT.o : line+idx, O_WRONLY|O_CREAT|O_TRUNC, 115 ofd = xcreate(TT.o ? TT.o : line+idx, O_WRONLY|O_CREAT|O_TRUNC,
150 string_to_mode(mode, 0777^toys.old_umask)); 116 string_to_mode(mode, 0777^toys.old_umask));
151 free(line); 117 free(line);
152 decoder(ifd,ofd);
153 break; 118 break;
119 }
120
121 while ((line = get_line(ifd)) != NULL) {
122 if (strcmp(line, m ? "====" : "end")) {
123 if (m) uudecode_b64_line(ofd, line, strlen(line));
124 else uudecode_uu_line(ofd, line);
125 } else m = 2;
126 free(line);
127 if (m == 2) break;
154 } 128 }
155 129
156 if (CFG_TOYBOX_FREE) { 130 if (CFG_TOYBOX_FREE) {
157 if (ifd) close(ifd); 131 if (ifd) close(ifd);
158 close(ofd); 132 close(ofd);