xref: /csrg-svn/usr.bin/uudecode/uudecode.c (revision 34953)
1*34953Sbostic /*
2*34953Sbostic  * Copyright (c) 1983 Regents of the University of California.
3*34953Sbostic  * All rights reserved.
4*34953Sbostic  *
5*34953Sbostic  * Redistribution and use in source and binary forms are permitted
6*34953Sbostic  * provided that the above copyright notice and this paragraph are
7*34953Sbostic  * duplicated in all such forms and that any documentation,
8*34953Sbostic  * advertising materials, and other materials related to such
9*34953Sbostic  * distribution and use acknowledge that the software was developed
10*34953Sbostic  * by the University of California, Berkeley.  The name of the
11*34953Sbostic  * University may not be used to endorse or promote products derived
12*34953Sbostic  * from this software without specific prior written permission.
13*34953Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*34953Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*34953Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16*34953Sbostic  */
17*34953Sbostic 
1813681Ssam #ifndef lint
19*34953Sbostic static char sccsid[] = "@(#)uudecode.c	5.4 (Berkeley) 07/06/88";
20*34953Sbostic #endif /* not lint */
2113681Ssam 
2213681Ssam /*
2313681Ssam  * uudecode [input]
2413681Ssam  *
2513681Ssam  * create the specified file, decoding as you go.
2613681Ssam  * used with uuencode.
2713681Ssam  */
2813681Ssam #include <stdio.h>
2913681Ssam #include <pwd.h>
3013681Ssam #include <sys/types.h>
3113681Ssam #include <sys/stat.h>
3213681Ssam 
3313681Ssam /* single character decode */
3413681Ssam #define DEC(c)	(((c) - ' ') & 077)
3513681Ssam 
3613681Ssam main(argc, argv)
3713681Ssam char **argv;
3813681Ssam {
3913681Ssam 	FILE *in, *out;
4013681Ssam 	int mode;
4113681Ssam 	char dest[128];
4213681Ssam 	char buf[80];
4313681Ssam 
4413681Ssam 	/* optional input arg */
4513681Ssam 	if (argc > 1) {
4613681Ssam 		if ((in = fopen(argv[1], "r")) == NULL) {
4713681Ssam 			perror(argv[1]);
4813681Ssam 			exit(1);
4913681Ssam 		}
5013681Ssam 		argv++; argc--;
5113681Ssam 	} else
5213681Ssam 		in = stdin;
5313681Ssam 
5413681Ssam 	if (argc != 1) {
5513681Ssam 		printf("Usage: uudecode [infile]\n");
5613681Ssam 		exit(2);
5713681Ssam 	}
5813681Ssam 
5913681Ssam 	/* search for header line */
6013681Ssam 	for (;;) {
6113681Ssam 		if (fgets(buf, sizeof buf, in) == NULL) {
6213681Ssam 			fprintf(stderr, "No begin line\n");
6313681Ssam 			exit(3);
6413681Ssam 		}
6513681Ssam 		if (strncmp(buf, "begin ", 6) == 0)
6613681Ssam 			break;
6713681Ssam 	}
6813681Ssam 	sscanf(buf, "begin %o %s", &mode, dest);
6913681Ssam 
7013681Ssam 	/* handle ~user/file format */
7113681Ssam 	if (dest[0] == '~') {
7213681Ssam 		char *sl;
7313681Ssam 		struct passwd *getpwnam();
7413681Ssam 		char *index();
7513681Ssam 		struct passwd *user;
7613681Ssam 		char dnbuf[100];
7713681Ssam 
7813681Ssam 		sl = index(dest, '/');
7913681Ssam 		if (sl == NULL) {
8013681Ssam 			fprintf(stderr, "Illegal ~user\n");
8113681Ssam 			exit(3);
8213681Ssam 		}
8313681Ssam 		*sl++ = 0;
8413681Ssam 		user = getpwnam(dest+1);
8513681Ssam 		if (user == NULL) {
8613681Ssam 			fprintf(stderr, "No such user as %s\n", dest);
8713681Ssam 			exit(4);
8813681Ssam 		}
8913681Ssam 		strcpy(dnbuf, user->pw_dir);
9013681Ssam 		strcat(dnbuf, "/");
9113681Ssam 		strcat(dnbuf, sl);
9213681Ssam 		strcpy(dest, dnbuf);
9313681Ssam 	}
9413681Ssam 
9513681Ssam 	/* create output file */
9613681Ssam 	out = fopen(dest, "w");
9713681Ssam 	if (out == NULL) {
9813681Ssam 		perror(dest);
9913681Ssam 		exit(4);
10013681Ssam 	}
10113681Ssam 	chmod(dest, mode);
10213681Ssam 
10313681Ssam 	decode(in, out);
10413681Ssam 
10513681Ssam 	if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
10613681Ssam 		fprintf(stderr, "No end line\n");
10713681Ssam 		exit(5);
10813681Ssam 	}
10913681Ssam 	exit(0);
11013681Ssam }
11113681Ssam 
11213681Ssam /*
11313681Ssam  * copy from in to out, decoding as you go along.
11413681Ssam  */
11513681Ssam decode(in, out)
11613681Ssam FILE *in;
11713681Ssam FILE *out;
11813681Ssam {
11913681Ssam 	char buf[80];
12013681Ssam 	char *bp;
12113681Ssam 	int n;
12213681Ssam 
12313681Ssam 	for (;;) {
12413681Ssam 		/* for each input line */
12513681Ssam 		if (fgets(buf, sizeof buf, in) == NULL) {
12613681Ssam 			printf("Short file\n");
12713681Ssam 			exit(10);
12813681Ssam 		}
12913681Ssam 		n = DEC(buf[0]);
13013681Ssam 		if (n <= 0)
13113681Ssam 			break;
13213681Ssam 
13313681Ssam 		bp = &buf[1];
13413681Ssam 		while (n > 0) {
13513681Ssam 			outdec(bp, out, n);
13613681Ssam 			bp += 4;
13713681Ssam 			n -= 3;
13813681Ssam 		}
13913681Ssam 	}
14013681Ssam }
14113681Ssam 
14213681Ssam /*
14313681Ssam  * output a group of 3 bytes (4 input characters).
14413681Ssam  * the input chars are pointed to by p, they are to
14513681Ssam  * be output to file f.  n is used to tell us not to
14613681Ssam  * output all of them at the end of the file.
14713681Ssam  */
14813681Ssam outdec(p, f, n)
14913681Ssam char *p;
15013681Ssam FILE *f;
15113681Ssam {
15213681Ssam 	int c1, c2, c3;
15313681Ssam 
15413681Ssam 	c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
15513681Ssam 	c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
15613681Ssam 	c3 = DEC(p[2]) << 6 | DEC(p[3]);
15713681Ssam 	if (n >= 1)
15813681Ssam 		putc(c1, f);
15913681Ssam 	if (n >= 2)
16013681Ssam 		putc(c2, f);
16113681Ssam 	if (n >= 3)
16213681Ssam 		putc(c3, f);
16313681Ssam }
16413681Ssam 
16513681Ssam 
16613681Ssam /* fr: like read but stdio */
16713681Ssam int
16813681Ssam fr(fd, buf, cnt)
16913681Ssam FILE *fd;
17013681Ssam char *buf;
17113681Ssam int cnt;
17213681Ssam {
17313681Ssam 	int c, i;
17413681Ssam 
17513681Ssam 	for (i=0; i<cnt; i++) {
17613681Ssam 		c = getc(fd);
17713681Ssam 		if (c == EOF)
17813681Ssam 			return(i);
17913681Ssam 		buf[i] = c;
18013681Ssam 	}
18113681Ssam 	return (cnt);
18213681Ssam }
18313681Ssam 
18413681Ssam /*
18513681Ssam  * Return the ptr in sp at which the character c appears;
18613681Ssam  * NULL if not found
18713681Ssam  */
18813681Ssam 
18913681Ssam #define	NULL	0
19013681Ssam 
19113681Ssam char *
19213681Ssam index(sp, c)
19313681Ssam register char *sp, c;
19413681Ssam {
19513681Ssam 	do {
19613681Ssam 		if (*sp == c)
19713681Ssam 			return(sp);
19813681Ssam 	} while (*sp++);
19913681Ssam 	return(NULL);
20013681Ssam }
201