#ifndef lint static char sccsid[] = "@(#)uudecode.c 5.1 (Berkeley) 7/2/83"; #endif /* * uudecode [input] * * create the specified file, decoding as you go. * used with uuencode. * * Modified: * PDM 29-Nov-1994 Added support for stripping out a lot of intermediate * garbage when UU Decoding appended files. * */ #include #include #include #ifndef vms #include #include #else #include #endif #ifdef VMS #define index strchr #endif int decode(FILE *in, FILE *out); void outdec(char *p, FILE *f, int n); int checkline(char *p, int n); /* single character decode */ #define DEC(c) (((c) - ' ') & 077) #define BUFSIZE 80 #define MAXBYTES 45 int endflag = 0; /* For filtering out junk */ main(argc, argv) char **argv; { FILE *in, *out; struct stat sbuf; int mode; char dest[128]; char buf[BUFSIZE]; int status; /* optional input arg */ 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); } /* search for header line */ for (;;) { if (fgets(buf, sizeof(buf), in) == NULL) { fprintf(stderr, "No begin line\n"); exit(3); } if (strncmp(buf, "begin ", 6) == 0) break; } sscanf(buf, "begin %o %s", &mode, dest); #ifndef vms /* handle ~user/file format */ 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 */ #ifndef vms out = fopen(dest, "w"); #else out = fopen(dest, "w", "alq=300", "deq=100", "fop=tef"); #endif if (out == NULL) { perror(dest); exit(4); } chmod(dest, mode); status = decode(in, out); switch (status) { case 0: break; case -1: fprintf(stderr, "No end line\n"); break; case -2: exit(11); default: if (fgets(buf, sizeof(buf), in) == NULL || strcmp(buf, "end\n")) { fprintf(stderr, "No end line\n"); exit(5); } } exit(0); } /* * copy from in to out, decoding as you go along. */ int decode(FILE *in, FILE *out) { char buf[BUFSIZE]; char *bp; int n; int status = 1; int linelen; for (;;) { /* for each input line */ if (fgets(buf, sizeof(buf), in) == NULL) { printf("Short file\n"); status = -2; break; } n = ((buf[0]) - ' '); /* Don't make it special */ if (DEC(buf[0]) <= 0) { /* Check the next line */ if (fgets(buf, sizeof(buf), in) == NULL) { status = -1; break; } if (strcmp(buf, "end\n") == 0) { status = 0; break; } else { n = ((buf[0]) - ' '); } } bp = &buf[1]; if (checkline(buf, n) == 1) { while (n > 0) { outdec(bp, out, n); bp += 4; n -= 3; } } } return(status); } /* * Check that the line is valid before processing it */ int checkline(char *lbuf, int n) { int buflen; int retval = 1; buflen = strlen(lbuf); if((strncmp(lbuf, "BEGIN", 5) == 0) && (endflag == 1)) { endflag = 0; return(0); } if(endflag == 1) { return(0); } if(strncmp(lbuf, "END", 3) == 0) { endflag = 1; return(0); } if(((n + 1)/3)*4 > (buflen - 1)) { /* If line too short */ return(0); } if(n > MAXBYTES) { /* Line cannot be any longer than this */ return(0); } if(n <= 0) { return(0); } return(retval); } /* * 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. */ void outdec(char *p, FILE *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) putc(c1, f); if (n >= 2) putc(c2, f); if (n >= 3) putc(c3, f); } /* If your library already has this function, use it */ #ifdef noindex /* * Return the ptr in sp at which the character c appears; * NULL if not found */ #define NULL 0 char * index(sp, c) register char *sp, c; { do { if (*sp == c) return(sp); } while (*sp++); return(NULL); } #endif