source: branches/2.2.2/mindi-busybox/coreutils/uudecode.c @ 1247

Last change on this file since 1247 was 821, checked in by Bruno Cornec, 14 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 4.2 KB
Line 
1/*
2 *  Copyright 2003, Glenn McGrath <bug1@iinet.net.au>
3 *
4 *  Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
5 *
6 *  Based on specification from
7 *  http://www.opengroup.org/onlinepubs/007904975/utilities/uuencode.html
8 *
9 *  Bugs: the spec doesn't mention anything about "`\n`\n" prior to the
10 *        "end" line
11 */
12
13
14#include <stdio.h>
15#include <errno.h>
16#include <getopt.h> /* optind */
17#include <string.h>
18#include <stdlib.h>
19#include "busybox.h"
20
21static int read_stduu(FILE *src_stream, FILE *dst_stream)
22{
23    char *line;
24
25    while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) {
26        int length;
27        char *line_ptr = line;
28
29        if (strcmp(line, "end") == 0) {
30            return(EXIT_SUCCESS);
31        }
32        length = ((*line_ptr - 0x20) & 0x3f)* 4 / 3;
33
34        if (length <= 0) {
35            /* Ignore the "`\n" line, why is it even in the encode file ? */
36            continue;
37        }
38        if (length > 60) {
39            bb_error_msg_and_die("Line too long");
40        }
41
42        line_ptr++;
43        /* Tolerate an overly long line to acomadate a possible exta '`' */
44        if (strlen(line_ptr) < (size_t)length) {
45            bb_error_msg_and_die("Short file");
46        }
47
48        while (length > 0) {
49            /* Merge four 6 bit chars to three 8 bit chars */
50            fputc(((line_ptr[0] - 0x20) & 077) << 2 | ((line_ptr[1] - 0x20) & 077) >> 4, dst_stream);
51            line_ptr++;
52            length--;
53            if (length == 0) {
54                break;
55            }
56
57            fputc(((line_ptr[0] - 0x20) & 077) << 4 | ((line_ptr[1] - 0x20) & 077) >> 2, dst_stream);
58            line_ptr++;
59            length--;
60            if (length == 0) {
61                break;
62            }
63
64            fputc(((line_ptr[0] - 0x20) & 077) << 6 | ((line_ptr[1] - 0x20) & 077), dst_stream);
65            line_ptr += 2;
66            length -= 2;
67        }
68        free(line);
69    }
70    bb_error_msg_and_die("Short file");
71}
72
73static int read_base64(FILE *src_stream, FILE *dst_stream)
74{
75    static const char base64_table[] =
76        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n";
77    char term_count = 0;
78
79    while (1) {
80        char translated[4];
81        int count = 0;
82
83        while (count < 4) {
84            char *table_ptr;
85            int ch;
86
87            /* Get next _valid_ character */
88            do {
89                ch = fgetc(src_stream);
90                if (ch == EOF) {
91                    bb_error_msg_and_die("Short file");
92                }
93            } while ((table_ptr = strchr(base64_table, ch)) == NULL);
94
95            /* Convert encoded charcter to decimal */
96            ch = table_ptr - base64_table;
97
98            if (*table_ptr == '=') {
99                if (term_count == 0) {
100                    translated[count] = 0;
101                    break;
102                }
103                term_count++;
104            }
105            else if (*table_ptr == '\n') {
106                /* Check for terminating line */
107                if (term_count == 5) {
108                    return(EXIT_SUCCESS);
109                }
110                term_count = 1;
111                continue;
112            } else {
113                translated[count] = ch;
114                count++;
115                term_count = 0;
116            }
117        }
118
119        /* Merge 6 bit chars to 8 bit */
120        fputc(translated[0] << 2 | translated[1] >> 4, dst_stream);
121        if (count > 2) {
122            fputc(translated[1] << 4 | translated[2] >> 2, dst_stream);
123        }
124        if (count > 3) {
125            fputc(translated[2] << 6 | translated[3], dst_stream);
126        }
127    }
128}
129
130int uudecode_main(int argc, char **argv)
131{
132    int (*decode_fn_ptr) (FILE * src, FILE * dst);
133    FILE *src_stream;
134    char *outname = NULL;
135    char *line;
136    int opt;
137
138    opt = bb_getopt_ulflags(argc, argv, "o:", &outname);
139
140    if (optind == argc) {
141        src_stream = stdin;
142    } else if (optind + 1 == argc) {
143        src_stream = bb_xfopen(argv[optind], "r");
144    } else {
145        bb_show_usage();
146    }
147
148    /* Search for the start of the encoding */
149    while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) {
150        char *line_ptr = NULL;
151
152        if (line == NULL) {
153            break;
154        } else if (strncmp(line, "begin-base64 ", 13) == 0) {
155            line_ptr = line + 13;
156            decode_fn_ptr = read_base64;
157        } else if (strncmp(line, "begin ", 6) == 0) {
158            line_ptr = line + 6;
159            decode_fn_ptr = read_stduu;
160        }
161
162        if (line_ptr) {
163            FILE *dst_stream;
164            int mode;
165            int ret;
166
167            mode = strtoul(line_ptr, NULL, 8);
168            if (outname == NULL) {
169                outname = strchr(line_ptr, ' ');
170                if ((outname == NULL) || (*outname == '\0')) {
171                    break;
172                }
173                outname++;
174            }
175            if (strcmp(outname, "-") == 0) {
176                dst_stream = stdout;
177            } else {
178                dst_stream = bb_xfopen(outname, "w");
179                chmod(outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO));
180            }
181            free(line);
182            ret = decode_fn_ptr(src_stream, dst_stream);
183            bb_fclose_nonstdin(src_stream);
184            return(ret);
185        }
186        free(line);
187    }
188    bb_error_msg_and_die("No `begin' line");
189}
Note: See TracBrowser for help on using the repository browser.