3 * Copyright 2003, Glenn McGrath <bug1@iinet.net.au>
4 * Copyright 2006, Pavel Roskin <proski@gnu.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation; either version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Library General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * Based on specification from
20 * http://www.opengroup.org/onlinepubs/007904975/utilities/uuencode.html
22 * Bugs: the spec doesn't mention anything about "`\n`\n" prior to the "end" line
32 #include <sys/fcntl.h>
35 static void uudecode_usage(void)
37 printf("Usage: uudecode [-o OUTFILE] [INFILE]\n");
40 static char *get_line_from_file(FILE *file
)
44 static char linebuf
[80];
46 while ((ch
= getc(file
)) != EOF
) {
47 linebuf
[idx
++] = (char)ch
;
54 /* Dumb overflow protection */
55 if (idx
>= (int)sizeof(linebuf
))
62 if (idx
> 0 && linebuf
[idx
- 1] == '\r')
68 #define char_val(n) ((line_ptr[n] - 0x20) & 0x3f)
70 static void read_stduu(FILE *src_stream
, FILE *dst_stream
)
74 while ((line
= get_line_from_file(src_stream
)) != NULL
) {
76 char *line_ptr
= line
;
78 if (strcmp(line
, "end") == 0)
80 length
= char_val(0) * 4 / 3;
82 /* Ignore the "`\n" line, why is it even in the encode file ? */
87 fprintf(stderr
, "uudecode: Line too long\n");
92 /* Tolerate an overly long line to accommodate an extra '`' */
93 if ((int)strlen(line_ptr
) < length
) {
94 fprintf(stderr
, "uudecode: Short line detected\n");
99 /* Merge four 6 bit chars to three 8 bit chars */
100 fputc(char_val(0) << 2 | char_val(1) >> 4, dst_stream
);
105 fputc(char_val(0) << 4 | char_val(1) >> 2, dst_stream
);
110 fputc(char_val(0) << 6 | char_val(1), dst_stream
);
115 fprintf(stderr
, "uudecode: no `end' found\n");
119 int main(int argc
, char **argv
)
122 FILE *dst_stream
= NULL
;
123 char *outname
= NULL
;
126 char *line_ptr
= NULL
;
128 int forced_output
= 0;
130 while ((c
= getopt (argc
, argv
, "o:")) != -1)
141 if (optind
== argc
) {
143 } else if (optind
+ 1 == argc
) {
144 src_stream
= fopen(argv
[optind
], "rt");
146 fprintf(stderr
, "uudecode: Cannot open \"%s\": %s\n",
147 argv
[optind
], strerror(errno
));
155 /* Search for the start of the encoding */
156 while ((line
= get_line_from_file(src_stream
)) != NULL
) {
157 if (strncmp(line
, "begin ", 6) == 0) {
164 fprintf(stderr
, "uudecode: No `begin' line\n");
168 mode
= strtoul(line_ptr
, NULL
, 8);
169 if (outname
== NULL
) {
170 outname
= strchr(line_ptr
, ' ');
171 if ((outname
== NULL
) || (*outname
== '\0')) {
172 fprintf(stderr
, "uudecode: No file name specified\n");
178 if (forced_output
&& (strcmp(outname
, "-") == 0)) {
182 int flags
= O_WRONLY
| O_CREAT
| O_TRUNC
;
184 /* don't clobber files without an explicit "-o" */
188 fd
= open(outname
, flags
,
189 mode
& (S_IRWXU
| S_IRWXG
| S_IRWXO
));
191 dst_stream
= fdopen(fd
, "wb");
192 if ((fd
== -1) || !dst_stream
) {
193 fprintf(stderr
, "uudecode: Cannot open \"%s\": %s\n",
194 outname
, strerror(errno
));
199 read_stduu(src_stream
, dst_stream
);
200 if (src_stream
!= stdin
)
202 if (dst_stream
!= stdout
)