File: uufilter.c

package info (click to toggle)
xloadimage 4.1-25
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 4,820 kB
  • sloc: ansic: 36,084; asm: 284; makefile: 282; sh: 280
file content (217 lines) | stat: -rw-r--r-- 5,042 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/* uufilter.c:
 *
 * "smart" uudecode function that skips junk lines and outputs data to
 * stdout rather than a filename.
 *
 * jim frost 10.21.93
 *
 * 10.27.93 fixed a bug where short uuencoded lines were stripped out
 *          due to a bad "short length" calculation.  added -v flag at
 *          the same time.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(argc, argv)
     int argc;
     char **argv;
{
  FILE *inf, *outf;
  char *infilename = NULL;
  char *outfilename = NULL;
  int dump_to_file = 1; /* true if we're outputting to a file */
  int stringent = 1; /* true if we're really stringent about data lines */
  int verbose = 0; /* true if we're babbling about what we're skipping */
  char buf[1024];
  int i, len;
  int phase = 0;
  unsigned char outchar;

  for (i = 1; i < argc; i++) {
    if (!strcmp(argv[i], "-s")) /* output to stdout */
      dump_to_file = 0;
    else if (!strcmp(argv[i], "-l")) /* lenient mode */
      stringent = 0;
    else if (!strcmp(argv[i], "-f")) { /* output to named file */
      dump_to_file = 1;
      outfilename = argv[++i];
    }
    else if (!strcmp(argv[i], "-v")) /* verbose output */
      verbose = 1;
    else {
      infilename = argv[i];
      break;
    }
  }
  if (infilename == NULL) {
    inf = stdin;
    infilename = "stdin";
  }
  else {
    inf = fopen(infilename, "r");
    if (inf == NULL) {
      perror(infilename);
      exit(1);
    }
  }

  /* scan for "begin" line
   */
  while (fgets(buf, 1024, inf) != NULL) {
    if (!strncmp(buf, "begin ", 6))
      break;
    if (verbose)
      fprintf(stderr, "Ignoring header line: %s\n", buf);
  }
  if (feof(inf)) {
    fprintf(stderr, "%s: No 'begin' line, sorry.\n", infilename);
    exit(1);
  }

  if (dump_to_file) {
    int mode; /* ignored */
    char tmp[1024];

    if (!outfilename) {
      if (sscanf(buf, "begin %o %s", &mode, tmp) != 2) {
	fprintf(stderr, "%s: Bad format for 'begin' line (can't dump to file)\n", infilename);
	exit(1);
      }
      outfilename = tmp;
    }
    fprintf(stderr, "Decoding into file %s\n", outfilename);
    outf = fopen(outfilename, "w");
    if (outf == NULL) {
      perror(outfilename);
      exit(1);
    }
  }
  else
    outf = stdout;

  for (;;) {
    char *bp;

    if (fgets(buf, 1024, inf) == NULL) {
      fprintf(stderr, "%s: Missing 'end' line.\n", infilename);
      break;
    }
	
    if (!strncmp(buf, "end", 3))
      break; /* end of data */

    /* strip off trailing characters
     */
    len = strlen(buf) - 1;
    while ((buf[len] == '\n') || (buf[len] == '\r'))
      buf[len--] = '\0';

    /* character conversion and "obvious" filtering
     */
    for (; len >= 0; len--) {
      if ((buf[len] >= 'a') || (buf[len] < ' '))
	break; /* garbage character seen */

      if (buf[len] == '`')
	buf[len] = ' ';
    }
    if (len >= 0) {
      if (verbose)
	fprintf(stderr, "Ignoring garbage line: %s\n", buf);
      continue; /* line had garbage, ignore it */
    }

    if (buf[0] == '\0')
      continue; /* line is blank, ignore it */

    len = buf[0] - ' ';

    /* ok, see if the line length looks sane.
     */
    {
      int line_len = strlen(buf) - 1;
      int allow_len;

      /* if the line is shorter than the absolute minimum
       * allowable then we're sure this is not a valid line.
       */
      allow_len = ((len * 4) / 3) + ((len * 4) % 3);
      if (line_len < allow_len) {
	if (verbose)
	  fprintf(stderr, "Ignoring short line: %s\n", buf);
	continue;
      }

      /* if we're being really stringent about the lines we allow
       * this filters out any lines that are too long, too.  note
       * that this is still fairly lenient; it allows uuencode
       * programs to pad the line length out to a multiple of
       * 3 bytes.
       */
      if (stringent) {
	allow_len = ((len + 2) * 4) / 3;
	if (line_len > allow_len) {
	  if (verbose)
	    fprintf(stderr, "Ignoring long line: %s\n", buf);
	  continue;
	}
      }
    }

    /* ok, we have some characters -- process them!
     */
    bp = &buf[1];
    phase = 0;
    outchar = 0;
    while (len > 0) {
      unsigned char c;

      c = (unsigned char)*(bp++) - ' ';
      switch (phase) {
      case 0: /* 1st 6 bits */
	outchar = (c << 2);
	break;
      case 1: /* last 2 bits, 1st 4 bits */
	outchar |= (c >> 4);
	fputc(outchar, outf);
	len--;
	outchar = (c & 0xf) << 4;
	break;
      case 2: /* last 4 bits, 1st 2 bits */
	outchar |= (c >> 2);
	fputc(outchar, outf);
	len--;
	outchar = (c & 0x3) << 6;
	break;
      case 3: /* last 6 bits */
	outchar |= c;
	fputc(outchar, outf);
	len--;
	phase = 0;
	continue;
      }
      phase++;
    }
  }
  /* flush output
   */
  if (outf == stdout)
    fflush(outf);
  else
    fclose(outf);

  /* suck up the rest of the input file.  this avoids "broken pipe"
   * errors if reading from stdin.
   */
  if (inf == stdin) {
    while (fgets(buf, 1024, inf) != NULL)
      if (verbose)
	fprintf(stderr, "Ignoring trailing line: %s\n", buf);
  }
  else
    fclose(inf);

  exit(0);
}