comparison toys/pending/uudecode.c @ 834:1c61f2827bf8

Fix the USE() macro around NEWTOY, tweak help text, remove unnecessary wrapper, tweak whitespace and curly brackets.
author Rob Landley <rob@landley.net>
date Wed, 27 Mar 2013 00:10:58 -0500
parents 1fdaba9a7124
children 89c65a45245a
comparison
equal deleted inserted replaced
833:98dc18ed57a3 834:1c61f2827bf8
2 * 2 *
3 * Copyright 2013 Erich Plondke <toybox@erich.wreck.org> 3 * Copyright 2013 Erich Plondke <toybox@erich.wreck.org>
4 * 4 *
5 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/uudecode.html 5 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/uudecode.html
6 6
7 USE_UUENCODE(NEWTOY(uudecode, ">2o:", TOYFLAG_USR|TOYFLAG_BIN)) 7 USE_UUDECODE(NEWTOY(uudecode, ">2o:", TOYFLAG_USR|TOYFLAG_BIN))
8 8
9 config UUDECODE 9 config UUDECODE
10 bool "uudecode" 10 bool "uudecode"
11 default n 11 default n
12 help 12 help
13 usage: uudecode [-o outfile] [file] 13 usage: uudecode [-o OUTFILE] [INFILE]
14 14
15 Uudecode or base64-decode stdin or [file], sending output to outfile or 15 Decode file from stdin (or INFILE).
16 filename specified by input. 16
17 -o write to OUTFILE instead of filename in header
17 */ 18 */
18 19
19 #define FOR_uudecode 20 #define FOR_uudecode
20 #include "toys.h" 21 #include "toys.h"
21 22
28 * The smallest valid character is 0x2B ('+') 29 * The smallest valid character is 0x2B ('+')
29 * The biggest valid character is 0x7A ('z') 30 * The biggest valid character is 0x7A ('z')
30 * We can make a table of 16*5 entries to cover 0x2B - 0x7A 31 * We can make a table of 16*5 entries to cover 0x2B - 0x7A
31 */ 32 */
32 33
33 static inline int startswith(const char *a, const char *b)
34 {
35 return (0==strncmp(a,b,strlen(b)));
36 }
37
38 static inline signed char uudecode_b64_1byte(char in) 34 static inline signed char uudecode_b64_1byte(char in)
39 { 35 {
40 char ret; 36 char ret;
41 static const signed char table[16*5] = { 37 static const signed char table[16*5] = {
42 /* '+' (0x2B) is 62, '/'(0x2F) is 63, rest invalid */ 38 /* '+' (0x2B) is 62, '/'(0x2F) is 63, rest invalid */
48 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, 44 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
49 /* '`' is invalid, 'a'-'z' are values 26-51, 0x7B - 0x7F are invalid */ 45 /* '`' is invalid, 'a'-'z' are values 26-51, 0x7B - 0x7F are invalid */
50 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 46 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
51 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 47 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
52 }; 48 };
49
53 in &= 0x7f; 50 in &= 0x7f;
54 if (in < '+') return -1; 51 if (in < '+') return -1;
55 if (in > 'z') return -1; 52 if (in > 'z') return -1;
56 in -= '+'; 53 in -= '+';
57 ret = table[in]; 54 ret = table[in];
55
58 return ret; 56 return ret;
59 }; 57 };
60 58
61 59
62 /* Returns length put in out */ 60 /* Returns length put in out */
63 static int uudecode_b64_4bytes(char *out, const char *in) 61 static int uudecode_b64_4bytes(char *out, const char *in)
64 { 62 {
65 unsigned int i,x=0; 63 unsigned int i, x=0;
66 signed char b0,b1,b2,b3; 64 signed char b0, b1, b2, b3;
67 int len = 3; 65 int len = 3;
66
68 b0 = uudecode_b64_1byte(in[0]); 67 b0 = uudecode_b64_1byte(in[0]);
69 b1 = uudecode_b64_1byte(in[1]); 68 b1 = uudecode_b64_1byte(in[1]);
70 b2 = uudecode_b64_1byte(in[2]); 69 b2 = uudecode_b64_1byte(in[2]);
71 b3 = uudecode_b64_1byte(in[3]); 70 b3 = uudecode_b64_1byte(in[3]);
72 if ((b1 < 0) || (b0 < 0)) return 0; 71 if ((b1 < 0) || (b0 < 0)) return 0;
73 if (b3 < 0) len--; 72 if (b3 < 0) len--;
74 if (b2 < 0) len--; 73 if (b2 < 0) len--;
75 x = ((b0 & 0x3f)<<18) | ((b1 & 0x3f)<<12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); 74 x = ((b0 & 0x3f)<<18) | ((b1 & 0x3f)<<12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f);
76 for (i = 0; i < len; i++) { 75 for (i = 0; i < len; i++) *out++ = (x>>(8*(2-i))) & 0x0ff;
77 *out++ = (x>>(8*(2-i))) & 0x0ff; 76
78 }
79 return len; 77 return len;
80 } 78 }
81 79
82 static void uudecode_b64_line(int ofd, const char *in, int ilen) 80 static void uudecode_b64_line(int ofd, const char *in, int ilen)
83 { 81 {
84 int olen; 82 int olen;
85 char out[4]; 83 char out[4];
84
86 while (ilen >= 4) { 85 while (ilen >= 4) {
87 olen = uudecode_b64_4bytes(out,in); 86 olen = uudecode_b64_4bytes(out,in);
88 xwrite(ofd,out,olen); 87 xwrite(ofd,out,olen);
89 in += 4; 88 in += 4;
90 ilen -= 4; 89 ilen -= 4;
93 92
94 static void uudecode_b64(int ifd, int ofd) 93 static void uudecode_b64(int ifd, int ofd)
95 { 94 {
96 int len; 95 int len;
97 char *line; 96 char *line;
97
98 while ((line = get_line(ifd)) != NULL) { 98 while ((line = get_line(ifd)) != NULL) {
99 if (startswith(line,"====")) return; 99 if ((len = strlen(line)) < 4) continue;
100 if ((len = strlen(line)) < 4) continue; // skip empty lines 100 if (!strncmp(line, "====", 4)) return;
101 uudecode_b64_line(ofd,line,len); 101 uudecode_b64_line(ofd,line,len);
102 free(line); 102 free(line);
103 } 103 }
104 } 104 }
105 105
106 106
107 static void uudecode_uu_4bytes(char *out, const char *in, int len) 107 static void uudecode_uu_4bytes(char *out, const char *in, int len)
108 { 108 {
109 unsigned int i,x=0; 109 unsigned int i,x=0;
110 for (i = 0; i < 4; i++) { 110
111 x |= ((in[i] - 32) & 0x03f) << (6*(3-i)); 111 for (i = 0; i < 4; i++) x |= ((in[i] - 32) & 0x03f) << (6*(3-i));
112 }
113 if (len > 3) len = 3; 112 if (len > 3) len = 3;
114 for (i = 0; i < len; i++) { 113 for (i = 0; i < len; i++) *out++ = x >> (8*(2-i));
115 *out++ = x >> (8*(2-i));
116 }
117 } 114 }
118 115
119 static void uudecode_uu_line(int ofd, const char *in) 116 static void uudecode_uu_line(int ofd, const char *in)
120 { 117 {
121 int olen = in[0] - 32; 118 int olen = in[0] - 32;
122 char buf[4]; 119 char buf[4];
120
123 in++; 121 in++;
124 while (olen > 0) { 122 while (olen > 0) {
125 uudecode_uu_4bytes(buf,in,olen); 123 uudecode_uu_4bytes(buf,in,olen);
126 xwrite(ofd,buf,olen < 3 ? olen : 3); 124 xwrite(ofd,buf,olen < 3 ? olen : 3);
127 olen -= 3; 125 olen -= 3;
130 } 128 }
131 129
132 static void uudecode_uu(int ifd, int ofd) 130 static void uudecode_uu(int ifd, int ofd)
133 { 131 {
134 char *line = NULL; 132 char *line = NULL;
133
135 while ((line = get_line(ifd)) != NULL) { 134 while ((line = get_line(ifd)) != NULL) {
136 if (line[0] == '`') break; 135 if (line[0] == '`') break;
137 if (startswith(line,"end")) break; 136 if (!strncmp(line, "end", 3)) break;
138 if (strlen(line) < 1) break; 137 if (strlen(line) < 1) break;
139 uudecode_uu_line(ofd,line); 138 uudecode_uu_line(ofd,line);
140 free(line); 139 free(line);
141 } 140 }
142 } 141 }
143 142
144 void uudecode_main(void) 143 void uudecode_main(void)
145 { 144 {
146 char *out_filename = NULL; 145 int ifd = 0, ofd = 1;
147 int ifd = 0; /* STDIN */ 146 char *out_filename = NULL, *line, *p,*p2;
148 int ofd = 1; /* STDOUT */
149 char *line;
150 char *p,*p2;
151 void (*decoder)(int ifd, int ofd) = NULL; 147 void (*decoder)(int ifd, int ofd) = NULL;
152 long mode = 0744; 148 long mode = 0744;
153 if (toys.optc == 1) { 149
154 ifd = xopen(toys.optargs[0],O_RDONLY); // dies if error 150 if (toys.optc == 1) ifd = xopen(toys.optargs[0],O_RDONLY);
155 } 151
156 do { 152 do {
157 if ((line = get_line(ifd)) == NULL) perror_exit("empty file"); 153 if ((line = get_line(ifd)) == NULL) perror_exit("empty file");
158 } while (strlen(line) == 0); /* skip over empty lines */ 154 } while (strlen(line) == 0); /* skip over empty lines */
159 if (startswith(line,"begin ")) decoder = uudecode_uu; 155 if (!strncmp(line, "begin ", 6)) decoder = uudecode_uu;
160 else if (startswith(line,"begin-base64 ")) decoder = uudecode_b64; 156 else if (!strncmp(line, "begin-base64 ", 13)) decoder = uudecode_b64;
161 else perror_exit("not a valid uu- or base64-encoded file"); 157 else perror_exit("not a valid uu- or base64-encoded file");
162 for (p = line; !isspace(*p); p++) /* skip first part */; 158 for (p = line; !isspace(*p); p++) /* skip first part */;
163 for (; isspace(*p); p++) /* skip spaces */; 159 for (; isspace(*p); p++) /* skip spaces */;
164 mode = strtoul(p,&p2,8); 160 mode = strtoul(p,&p2,8);
165 p = p2 + 1; /* skip space */ 161 p = p2 + 1; /* skip space */
166 if (toys.optflags & FLAG_o) { 162 if (toys.optflags & FLAG_o) out_filename = TT.o;
167 out_filename = TT.o; 163 else out_filename = p;
168 } else { 164
169 out_filename = p;
170 }
171 ofd = xcreate(out_filename,O_WRONLY|O_CREAT|O_TRUNC,mode); 165 ofd = xcreate(out_filename,O_WRONLY|O_CREAT|O_TRUNC,mode);
172 free(line); 166 free(line);
173 decoder(ifd,ofd); 167 decoder(ifd,ofd);
174 if (TOYBOX_CLEANUP) close(ofd); 168 if (CFG_TOYBOX_FREE) close(ofd);
175 } 169 }