/* bituudec.c */ /* Exit status values: 1 Unable to open input file. 2 Removed, used to indicate more than one argument. 3 No begin line, probably not a uuencoded file. 4 Unable to write output file. 5 Missing an end line, file may be truncated? 10 Short file, EOF reached while decoding. */ /* Modified version of uudecode by Mark S. Zinzow in IBM C or MSC V. 2 use clink bituudec ssetargv; to get DOS command line wildcard processing */ #ifndef lint static char sccsid[] = "@(#)bituudecode.c 6.0 (Berkeley & M.S.Z.) 3/22/87" #endif /* * uudecode [input] * * create the specified file, decoding as you go. * used with uuencode. */ #include #ifndef MSDOS #include #endif #include #include /* single character decode */ #define DEC(c) (((c) - ' ') & 077) main(argc, argv) char **argv; { FILE *in; /* M.S.Z. 3/22/87 The following code block was deleted to support decoding of multiple files with the use of wild cards or several command line filenames. Part of the main line was moved to the function uufile with the appropriate changes for repeating for several files. */ /* optional input arg M.S.Z why only one file? if (argc > 1) { if ((in = fopen(argv[1], "r")) == NULL) { perror(argv[1]); exit(1); } argv++; argc--; } else in = stdin; if (argc != 1) { printf("Usage: uudecode [infile]\n"); exit(2); } */ if (argc == 1) /* no args; copy standard input */ uufile(stdin); else while (--argc > 0) if ((in = fopen(*++argv, "r")) == NULL) { perror(*argv); exit(1); } else { uufile(in); fclose(in); } exit(0); } uufile(in) /* Process one input file M.S.Z. */ FILE *in; { FILE *out; struct stat sbuf; int mode, filect=0; char dest[128]; char buf[80]; while ( !feof(in) ) { /* added while and filect for status */ /* search for header line */ for (;;) { if (fgets(buf, sizeof buf, in) == NULL) { if (filect < 1) { fprintf(stderr, "No begin line\n"); exit(3); } else return; } if (strncmp(buf, "begin ", 6) == 0) break; } sscanf(buf, "begin %o %s", &mode, dest); fprintf(stderr, "Processing file %d \"%s\", in current source file.\n", ++filect,dest); /* handle ~user/file format */ #ifndef MSDOS if (dest[0] == '~') { char *sl; struct passwd *getpwnam(); char *index(); struct passwd *user; char dnbuf[100]; sl = index(dest, '/'); if (sl == NULL) { fprintf(stderr, "Illegal ~user\n"); exit(3); } *sl++ = 0; user = getpwnam(dest+1); if (user == NULL) { fprintf(stderr, "No such user as %s\n", dest); exit(4); } strcpy(dnbuf, user->pw_dir); strcat(dnbuf, "/"); strcat(dnbuf, sl); strcpy(dest, dnbuf); } #endif /* create output file */ #ifdef MSDOS /* binary output file */ out = fopen(dest, "wb"); #else out = fopen(dest, "w"); #endif if (out == NULL) { perror(dest); exit(4); } chmod(dest, mode); decode(in, out); if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) { fprintf(stderr, "No end line\n"); exit(5); } fclose(out); } } /* * copy from in to out, decoding as you go along. */ decode(in, out) FILE *in; FILE *out; { char buf[80]; char *bp; int n,j,k,l; /* M.S.Z. added jkl for a counters in padding spaces */ for (;;) { /* for each input line */ if (fgets(buf, sizeof buf, in) == NULL) { printf("Short file\n"); exit(10); } n = DEC(buf[0]); /* was if (n <= 0) break; */ if (buf[0] <= ' ') break; /* M.S.Z. What good does it do to test n<0 when in DEC the sign bits are masked off? This seems to allow us to just ignore blank lines. A blank line (just \n) before the final end used to cause a short file error message, now that's not a problem. Next I'm adding a kludge to tack trailing spaces back on the input lines: */ j = strlen(buf); k = n*4/3 + 2 ; /* add 1 for \n and 1 for the first count char if ( j < k ) for( l=j-1 ; l < k && l < sizeof buf ; l++ ) buf[l] = ' /* Ignore that this changes the \n to a ' '; that doesn't hurt. M.S.Z. */ /* M.S.Z. end kludge */ bp = &buf[1]; while (n > 0) { outdec(bp, out, n); bp += 4; n -= 3; } } } /* * 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. */ outdec(p, f, n) char *p; FILE *f; { 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) putc(c1, f); if (n >= 2) putc(c2, f); if (n >= 3) putc(c3, f); /* M.S.Z. Another problem. Nobody notices when the disk is full! */ if (ferror(f)) { perror("Write error"); exit(4); } /* M.S.Z. end another hack */ } /* fr: like read but stdio */ int fr(fd, buf, cnt) FILE *fd; char *buf; int cnt; { int c, i; for (i=0; i