Mercurial > hg > toybox
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 } |