Plan 9 from Bell Labs’s /usr/web/sources/contrib/steve/misc/uudecode.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/*
 * uudecode [input]
 *
 * create the specified file, decoding as you go.
 * used with uuencode.
 */
#include <u.h>
#include <libc.h>
#include <bio.h>

/* single character decode */
#define DEC(c)	(((c) - ' ') & 077)

static	void	decode(Biobuf*, Biobuf*);
static	void	outdec(char*, Biobuf*, int);

void
main(int argc, char **argv)
{
	int mode;
	int fd;
	char *line, *dest;
	static Biobuf bin, bout;

	/* optional input arg */
	if(argc > 1) {
		if((fd = open(argv[1], OREAD)) < 0) {
			fprint(2, "uudecode: can't open %s: %r\n", argv[1]);
			exits("open");
		}
		argc--; argv++;
		USED(argv);
	} else
		fd = 0;
	if(argc != 1) {
		fprint(2, "Usage: uudecode [infile]\n");
		exits("usage");
	}
	Binit(&bin, fd, OREAD);

	/* search for header line */
	do {
		if((line = Brdline(&bin, '\n')) == 0) {
			fprint(2, "uudecode: no begin line\n");
			exits("format");
		}
	} while(Blinelen(&bin) < 5 || strncmp(line, "begin", 5) != 0);
	line[Blinelen(&bin)-1] = 0;
	mode = strtoul(line+5, &dest, 8);
	while(*dest == ' ')
		dest++;
	if(*dest == 0) {
		fprint(2, "uudecode: bad header line\n");
		exits("format");
	}
	if(*dest == '~') {
		/* can't be bothered */
		fprint(2, "uudecode: ~user format not supported\n");
		exits("open");
	}

	fd = create(dest, OWRITE, mode);
	if(fd < 0) {
		fprint(2, "uudecode: can't create %s: %r\n", dest);
		exits("open");
	}
	Binit(&bout, fd, OWRITE);

	decode(&bin, &bout);

	if((line = Brdline(&bin, '\n')) == 0 || strncmp(line, "end\n", 4) != 0) {
		fprint(2, "uudecode: no end line\n");
		exits("format");
	}
	if(Bterm(&bout)) {
		fprint(2, "uudecode: error writing %s: %r\n", dest);
		exits("output");
	}
	exits(0);
}

/*
 * copy from in to out, decoding as you go along.
 */
static void
decode(Biobuf *in, Biobuf *out)
{
	char *lp;
	int n;

	for(;;) {
		/* for each input line */
		lp = Brdline(in, '\n');
		if(lp == 0) {
			fprint(2, "uudecode: unexpected end-of-file\n");
			exits("format");
		}
		n = DEC(*lp++);
		if(n <= 0)
			break;
		if(n >= Blinelen(in)) {
			fprint(2, "uudecode: corrupt input file\n");
			exits("format");
		}
		for(; n > 0; lp += 4, n -= 3)
			outdec(lp, out, n);
	}
}

/*
 * output a group of 3 bytes (4 input characters).
 * the input chars are pointed to by p, they are to
 * be output to file f.  n is used to tell us not to
 * output all of them at the end of the file.
 */
static void
outdec(char *p, Biobuf *f, int n)
{
	int c1, c2, c3;

	c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
	c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
	c3 = DEC(p[2]) << 6 | DEC(p[3]);
	if(n >= 1)
		BPUTC(f, c1);
	if(n >= 2)
		BPUTC(f, c2);
	if(n >= 3)
		BPUTC(f, c3);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.