unstack, sort: cleanup and improvement
[minix.git] / commands / uue / uue.c
blob6bcf3440dcdf68687b8e8fe8b32ec78b53f46812
1 /* uue - bulletproof version of uuencode */
3 /* Uue -- encode a file so that it's printable ascii, short lines
5 * Slightly modified from a version posted to net.sources a while back,
6 * and suitable for compilation on the IBM PC
8 * modified for Lattice C on the ST - 11.05.85 by MSD
9 * modified for ALCYON on the ST - 10-24-86 by RDR
10 * modified a little more for MWC... 02/09/87 by JPHD
11 * (An optional first argument of the form: -nnumber (e.g. -500), will
12 * produce a serie of files that long, linked by the include statement,
13 * such files are automatically uudecoded by the companion program.)
14 * More mods, - ... 05/06/87 by jphd
15 * Mods for TOPS 20, and more. 08/06/87 by jphd
16 * (remove freopen and rindex...change filename generation...)
17 * (A lot more to do about I/O speed, avoiding completely the stdio.h...)
18 * May be called as uuencode. Oct 2 1993 by Kees J. Bot
23 #include <ctype.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
28 #define USAGE
29 #define FILE_NAME 10 /* affects how long names are truncated */
31 /* ENC is the basic 1 character encoding function to make a char printing */
32 #define ENC(c) (((c) & 077) + ' ')
34 FILE *fp, *outp;
35 char ofname[80];
36 int lenofname;
37 int stdo = 0;
39 #ifdef ST
40 #define READ "rb"
41 #else
42 #define READ "r"
43 #endif
45 int part = 'a', chap = 'a';
46 #define SEQMAX 'z'
47 #define SEQMIN 'a'
48 char seqc = SEQMAX;
50 int split = 0;
51 int fileln = 32000;
53 int main(int argc, char **argv);
54 void maketable(void);
55 void makename(void);
56 void encode(void);
57 void outdec(char *p);
58 int fr(char *buf, int cnt);
60 int main(argc, argv)
61 int argc;
62 char *argv[];
64 char *prog_name;
65 char *fname;
66 int filter;
68 prog_name = argv[0] + strlen(argv[0]);
69 while (prog_name > argv[0] && prog_name[-1] != '/') prog_name--;
70 filter = strcmp(prog_name, "uuencode") == 0;
72 if (argc < 2) {
73 fprintf(stderr, "Usage: %s [-n] inputfile [-]\n", prog_name);
74 exit(2);
76 if (argv[1][0] == '-') {
77 fileln = -atoi(argv[1]);
78 if (fileln <= 0) {
79 fprintf(stderr, "Wrong file length arg.\n");
80 exit(3);
82 split = 1;
83 argv++;
84 argc--;
86 if (filter) { /* old uuencode reads from standard input */
87 fp = stdin;
88 } else {
89 if ((fp = fopen(argv[1], READ)) == NULL) { /* binary input !!! */
90 fprintf(stderr, "Cannot open %s\n", argv[1]);
91 exit(1);
94 fname = argv[1] + strlen(argv[1]);
95 while (fname > argv[1] && fname[-1] != '/') fname--;
96 strcpy(ofname, fname);
97 fname = ofname;
98 do {
99 if (*fname == '.') *fname = '\0';
100 } while (*fname++);
101 /* 10 char prefix + .uue -> 14 chars MAX */
102 lenofname = strlen(ofname);
103 if (lenofname > FILE_NAME) ofname[FILE_NAME] = '\0';
104 strcat(ofname, ".uue");
105 lenofname = strlen(ofname);
106 if (!split && (filter || (argc > 2) && (argv[2][0] == '-'))) {
107 stdo = 1;
108 outp = stdout;
109 } else {
110 makename();
111 if ((outp = fopen(ofname, "w")) == NULL) {
112 fprintf(stderr, "Cannot open %s\n", ofname);
113 exit(1);
116 maketable();
117 fprintf(outp, "begin %o %s\n", 0644, argv[1]);
118 encode();
119 fprintf(outp, "end\n");
120 fclose(outp);
121 return(0);
124 /* Create ASCII table so a mailer can screw it up and the decode
125 * program can restore the error.
127 void maketable()
129 register int i, j;
131 fputs("table\n", outp);
132 for (i = ' ', j = 0; i < '`'; j++) {
133 if (j == 32) putc('\n', outp);
134 fputc(i++, outp);
136 putc('\n', outp);
139 /* Generate the names needed for single and multiple part encoding. */
140 void makename()
142 if (split) {
143 ofname[lenofname - 1] = part;
144 ofname[lenofname - 2] = chap;
148 /* Copy from in to out, encoding as you go along. */
149 void encode()
151 char buf[80];
152 register int i, n;
153 register int lines;
154 lines = 6;
156 for (;;) {
157 n = fr(buf, 45);
158 putc(ENC(n), outp);
159 for (i = 0; i < n; i += 3) outdec(&buf[i]);
160 putc(seqc, outp);
161 seqc--;
162 if (seqc < SEQMIN) seqc = SEQMAX;
163 putc('\n', outp);
164 ++lines;
165 if (split && (lines > fileln)) {
166 part++;
167 if (part > 'z') {
168 part = 'a';
169 if (chap == 'z')
170 chap = 'a'; /* loop ... */
171 else
172 chap++;
174 makename();
175 fprintf(outp, "include %s\n", ofname);
176 fclose(outp);
177 if ((outp = fopen(ofname, "w")) == NULL) {
178 fprintf(stderr, "Cannot open %s\n", ofname);
179 exit(1);
181 maketable();
182 fprintf(outp, "begin part %c %s\n", part, ofname);
183 lines = 6;
185 if (n <= 0) break;
189 /* Output one group of 3 bytes, pointed at by p, on file f. */
190 void outdec(p)
191 register char *p;
193 register int c1, c2, c3, c4;
195 c1 = *p >> 2;
196 c2 = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
197 c3 = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
198 c4 = p[2] & 077;
199 putc(ENC(c1), outp);
200 putc(ENC(c2), outp);
201 putc(ENC(c3), outp);
202 putc(ENC(c4), outp);
205 /* Fr: like read but stdio */
206 int fr(buf, cnt)
207 register char *buf;
208 register int cnt;
210 register int c, i;
211 for (i = 0; i < cnt; i++) {
212 c = fgetc(fp);
213 if (feof(fp)) return(i);
214 buf[i] = c;
216 return(cnt);