home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!decvax!decwrl!purdue!umd5!ames!necntc!ncoast!allbery
- From: art@felix.UUCP (Art Dederick)
- Newsgroups: comp.sources.misc
- Subject: v03i051: comp.sources.misc posting request
- Message-ID: <8805222336.AA07991@fritz.UUCP>
- Date: 12 Jun 88 22:01:56 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: art@felix.UUCP (Art Dederick)
- Lines: 482
- Approved: allbery@ncoast.UUCP
-
- comp.sources.misc: Volume 3, Issue 51
- Submitted-By: "Art Dederick" <art@felix.UUCP>
- Archive-Name: nuudecode
-
- [I installed a patch and wrapped it in a shar. ++bsa]
-
- Here is the full source to the uudecode program last submitted
- with the best features I could find that have been posted for the
- last five years. I added the ability to process sectionized
- encoded files created by Richard Marks' v2.13 UUDECODE. He seems
- to be using a different checksum algorithm than the standard one
- so if I detect a sectioned encoded file I ignore the checksum. If
- I get the algorithm Richard is using I will add it to this version.
-
- If one wishes to decode one of Richard's sectioned postings, cat
- all the postings in the proper sequence and pipe to this version
- of uudecode. Alternatively, just cat all sections, again in the
- proper order, into a file then pass to uudecode. The former is
- easier on disk space.
-
- Art Dederick
- {trwrb,hplabs,oliveb}!felix!art
- FileNet Corp.
- 3565 Harbor Blvd.
- Costa Mesa, CA 92626
- (714) 966-3618
-
- #--------------------------------CUT HERE-------------------------------------
- #! /bin/sh
- #
- # This is a shell archive. Save this into a file, edit it
- # and delete all lines above this comment. Then give this
- # file to sh by executing the command "sh file". The files
- # will be extracted into the current directory owned by
- # you with default permissions.
- #
- # The files contained herein are:
- #
- # -rw-r--r-- 1 allbery System 10483 Jun 12 17:57 uudecode.c
- #
- echo 'x - uudecode.c'
- if test -f uudecode.c; then echo 'shar: not overwriting uudecode.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > uudecode.c
- X/* #ifndef lint
- Xstatic char sccsid[] = "@(#)uudecode.c 5.3-1 (Berkeley) 9/1/87";
- X#endif */
- X
- X/* Written by Mark Horton */
- X/* Modified by ajr (Alan J Rosenthatl,flaps@utcsri.UUCP) to use checksums */
- X/* Modified by fnf (Fred Fish,well!fnf) to use Keith Pyle's suggestion for
- X compatibility */
- X/* Modified by bcn (Bryce Nesbitt,ucbvax!cogsci!bryce) to fix a misleading
- X error message on the Amiga port, to fix a bug that prevented decoding
- X certain files, to work even if trailing spaces have been removed from a
- X file, to check the filesize (if present), to add some error checking, to
- X loop for multiple decodes from a single file, and to handle common
- X BITNET mangling. Also kludged around a missing string function in Aztec
- X C */
- X/* Modified by drw (Dale Worley, drw@math.mit.edu) to add the -f switch, which
- X forces the output to be on stdout. This makes uudecode into a filter, and
- X frees the user from perversions in the file name and mode given in the
- X input file. These changes Copyright (C) 1987 Dale R. Worley, and are hereby
- X put in the public domain. */
- X/* Modified by art (Art Dederick, {trwrb,oliveb,hplabs}!felix!art) to scan
- X for sectionized encoded files created by Richard Marks' v2.13 UUDECODE
- X program. Cat all sections in the proper order then pass to uudecode.
- X Added a more manageable method for assigning exit error codes. */
- X
- X/*
- X * uudecode [-f] [input]
- X *
- X * Decode a file encoded with uuencode. WIll extract multiple encoded
- X * modules from a single file. Can deal with most mangled files, including
- X * BITNET. Will handle sectioned encoded files also.
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X
- X#ifdef AMIGA
- X#define AMIGA_LATTICE /* Set for Amiga Lattice C */
- X#define MCH_AMIGA
- X#define MPU68000
- X#endif
- X
- X#ifdef unix
- X#include <pwd.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#endif
- X
- X/* Exit error codes */
- X#define err_ok 0
- X#define err_dest_open 1
- X#define err_dest_write 2
- X#define err_eof 3
- X#define err_in_open 4
- X#define err_no_begin 5
- X#define err_no_end 6
- X#define err_no_user 7
- X#define err_out_close 8
- X#define err_sect_seq 9
- X#define err_sect_size 10
- X#define err_size 11
- X#define err_tilda_user 12
- X#define err_usage 13
- X
- Xchar section_str[] = "======= [ remove this line";
- X#define section_str_sz (sizeof(section_str) - 1)
- X
- Xint section = 0; /* section flag and next section to get */
- Xlong written_size; /* number of bytes written to output, used instead of
- X ftell, because ftell doesn't work with -f */
- X
- X#define SUMSIZE 64
- X#define DEC(c) (((c) - ' ') & 077) /* single character decode */
- X
- Xmain(argc, argv)
- Xchar **argv;
- X{
- XFILE *in, *out;
- Xint through_loop=0; /* Dejavu indicator */
- Xint mode; /* file's mode (from header) */
- Xlong filesize; /* theoretical file size (from header) */
- Xchar dest[128];
- Xchar buf[80];
- Xint f_option = 0; /* set to 1 if -f option is present */
- X
- X#ifdef AMIGA_LATTICE
- Xextern int Enable_Abort;
- X Enable_Abort=1;
- X#endif
- X
- X /* First, check for the -f option */
- X if (argc >= 2 && strcmp(argv[1], "-f") == 0)
- X {
- X f_option = 1;
- X argc--; argv++;
- X }
- X
- X /* A filename can be specified to be uudecoded, or nothing can
- X be specified, and the input will come from STDIN */
- X
- X switch (argc)
- X {
- X case 1:
- X in=stdin;
- X break;
- X
- X case 2:
- X if ((in = fopen(argv[1], "r")) == NULL)
- X {
- X fprintf(stderr, "ERROR: can't find %s\n", argv[1]);
- X fprintf(stderr, "USAGE: uudecode [-f] [infile]\n");
- X exit(err_in_open);
- X }
- X break;
- X
- X default:
- X fprintf(stderr, "USAGE: uudecode [-f] [infile]\n");
- X exit(err_usage);
- X break;
- X }
- X
- X /* Loop through file, searching for headers. Decode anything with a
- X header, complain if there where no headers. */
- X
- Xfor (;;)
- X{
- X /* search file for header line */
- X for (;;)
- X {
- X if (fgets(buf, sizeof buf, in) == NULL)
- X {
- X if (!through_loop)
- X {
- X fprintf(stderr, "ERROR: no `begin' line!\n");
- X exit(err_no_begin);
- X }
- X else
- X {
- X exit(err_ok);
- X }
- X }
- X if (strncmp(buf, "section 1 of uuencode", 21) == 0)
- X section = 1;
- X else if (strncmp(buf, "begin ", 6) == 0)
- X break;
- X }
- X sscanf(buf, "begin %o %s", &mode, dest);
- X
- X /* set up the output file */
- X if (f_option)
- X {
- X /* the -f option is used, so use stdout */
- X out = stdout;
- X }
- X else
- X {
- X /* the -f option is not used, so use the filename (and mode) in the
- X * begin line */
- X#ifdef unix
- X /* handle ~user/file format */
- X if (dest[0] == '~')
- X {
- X char *sl;
- X struct passwd *getpwnam();
- X char *index();
- X struct passwd *user;
- X char dnbuf[100];
- X
- X sl = index(dest, '/');
- X if (sl == NULL)
- X {
- X fprintf(stderr, "Illegal ~user\n");
- X exit(err_tilda_user);
- X }
- X *sl++ = 0;
- X user = getpwnam(dest+1);
- X if (user == NULL)
- X {
- X fprintf(stderr, "No such user as %s\n", dest);
- X exit(err_no_user);
- X }
- X strcpy(dnbuf, user->pw_dir);
- X strcat(dnbuf, "/");
- X strcat(dnbuf, sl);
- X strcpy(dest, dnbuf);
- X }
- X#endif
- X
- X /* create output file */
- X if ((out = fopen(dest, "w")) == NULL)
- X {
- X fprintf(stderr, "ERROR: can't open output file %s\n", dest);
- X exit(err_dest_open);
- X }
- X#ifdef unix
- X chmod(dest, mode);
- X#endif
- X }
- X
- X /* actually decode the data */
- X decode(in, out, dest);
- X
- X if (fgets(buf, sizeof buf, in) == NULL || strncmp(buf,"end",3))
- X { /* don't be overly picky about newline ^ */
- X fprintf(stderr, "ERROR: no `end' line\n");
- X exit(err_no_end);
- X }
- X
- X if (section) {
- X /* suck up the section trailer before the size line */
- X if (fgets(buf,sizeof buf,in) == NULL) {
- X fprintf(stderr, "ERROR: input ended unexpectedly!\n");
- X exit(err_eof);
- X }
- X }
- X if (!(fgets(buf,sizeof buf,in) == NULL || strncmp(buf,"size ",3)))
- X {
- X sscanf(buf, "size %ld", &filesize);
- X if (written_size != filesize)
- X {
- X fprintf(stderr,
- X "ERROR: file should have been %ld bytes long but was %ld.\n",
- X filesize, written_size);
- X exit(err_size);
- X }
- X }
- X
- X /* close the output file */
- X if (!f_option)
- X if (fclose(out) != 0)
- X {
- X fprintf(stderr, "ERROR: error closing file %s.\n", dest);
- X exit(err_out_close);
- X }
- X
- X through_loop = 1;
- X} /* forever */
- X} /* main */
- X
- X/*
- X * Copy from in to out, decoding as you go.
- X * If a return or newline is encountered too early in a line, it is
- X * assumed that means that some editor has truncated trailing spaces.
- X */
- Xdecode(in, out, dest)
- XFILE *in;
- XFILE *out;
- Xchar *dest;
- X{
- Xchar buf[81];
- Xchar *bp;
- Xint nosum=0;
- X#ifndef unix
- Xextern errno;
- X#endif
- Xint j;
- Xregister int n;
- Xint checksum, line, section_size;
- X
- X /* zero the byte count and initial section size*/
- X section_size = written_size = 0;
- X
- X for (line = 1; ; line++) /* for each input line */
- X {
- X if (fgets(buf, sizeof buf, in) == NULL)
- X {
- X fprintf(stderr, "ERROR: input ended unexpectedly!\n");
- X exit(err_eof);
- X }
- X
- X /* Is this section finished? */
- X if (section &&
- X ((strncmp(buf, section_str, section_str_sz) == 0)
- X || buf[0] == '\n' || buf[0] == '\r')) {
- X long size;
- X
- X /* Scan for section size */
- X do {
- X line++;
- X if (fgets(buf, sizeof buf, in) == NULL) {
- X fprintf(stderr, "ERROR: input ended unexpectedly!\n");
- X exit(err_eof);
- X }
- X n = sscanf(buf, "section size %ld", &size);
- X } while (n != 1);
- X line++;
- X if (section_size != size) {
- X fprintf(stderr, "ERROR: section size wrong!\n");
- X exit(err_sect_size);
- X }
- X section_size = 0;
- X section++;
- X /* Scan for start of next section */
- X for (n = 0; n != 1;) {
- X line++;
- X if (fgets(buf, sizeof buf, in) == NULL) {
- X fprintf(stderr, "ERROR: input ended unexpectedly!\n");
- X exit(err_eof);
- X }
- X n = sscanf(buf, "section %d of uuencode", &j);
- X }
- X if (section != j) {
- X fprintf(stderr, "ERROR: section %d out of sequence!\n", j);
- X exit(err_sect_seq);
- X }
- X while (buf[0] != 'M') {
- X line++;
- X if (fgets(buf, sizeof buf, in) == NULL) {
- X fprintf(stderr, "ERROR: input ended unexpectedly!\n");
- X exit(err_eof);
- X }
- X }
- X }
- X /* Pad end of lines in case some editor truncated trailing
- X spaces */
- X
- X for (n=0;n<79;n++) /* search for first \r, \n or \000 */
- X {
- X if (buf[n]=='\176') /* If BITNET made a twiddle, */
- X buf[n]='\136'; /* we make a caret */
- X if (buf[n]=='\r'||buf[n]=='\n'||buf[n]=='\000')
- X break;
- X }
- X for (;n<79;n++) /* when found, fill rest of line with space */
- X {
- X buf[n]=' ';
- X }
- X buf[79]=0; /* terminate new string */
- X
- X checksum = 0;
- X n = DEC(buf[0]);
- X if (n <= 0)
- X break; /* 0 bytes on a line?? Must be the last line */
- X
- X bp = &buf[1];
- X
- X /* FOUR input characters go into each THREE output characters */
- X
- X while (n >= 4)
- X {
- X j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4;
- X putc(j, out);
- X checksum += j;
- X written_size++;
- X section_size++;
- X
- X j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2;
- X putc(j, out);
- X checksum += j;
- X written_size++;
- X section_size++;
- X
- X j = DEC(bp[2]) << 6 | DEC(bp[3]);
- X putc(j, out);
- X checksum += j;
- X written_size++;
- X section_size++;
- X
- X checksum = checksum % SUMSIZE;
- X bp += 4;
- X n -= 3;
- X }
- X
- X j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4;
- X checksum += j;
- X if (n >= 1)
- X {
- X putc(j, out);
- X written_size++;
- X section_size++;
- X }
- X j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2;
- X checksum += j;
- X if (n >= 2)
- X {
- X putc(j, out);
- X written_size++;
- X section_size++;
- X }
- X j = DEC(bp[2]) << 6 | DEC(bp[3]);
- X checksum += j;
- X if (n >= 3)
- X {
- X putc(j, out);
- X written_size++;
- X section_size++;
- X }
- X checksum = checksum % SUMSIZE;
- X bp += 4;
- X n -= 3;
- X
- X#ifndef unix
- X /* Error checking under UNIX??? You must be kidding... */
- X /* Check if an error occured while writing to that last line */
- X if (errno)
- X {
- X fprintf(stderr, "ERROR: error writing to %s\n",dest);
- X exit(err_dest_write);
- X }
- X#endif
- X
- X /* The line has been decoded; now check that sum */
- X
- X nosum |= !isspace(*bp);
- X if (nosum && !section) /* Is there a checksum at all?? */
- X {
- X if (checksum != DEC(*bp)) /* Does that checksum match? */
- X {
- X fprintf(stderr, "ERROR: checksum mismatch decoding %s, line %d.\n",dest, line);
- X }
- X } /* sum */
- X } /* line */
- X} /* function */
- X
- X#ifdef unix
- X/*
- X * Return the ptr in sp at which the character c appears;
- X * 0 if not found
- X */
- Xchar *
- Xindex(sp, c)
- Xregister char *sp, c;
- X{
- X do
- X {
- X if (*sp == c)
- X return(sp);
- X }
- X while (*sp++);
- X
- X return(0);
- X}
- X#endif unix
- ________This_Is_The_END________
- if test `wc -c < uudecode.c` -ne 10483; then
- echo 'shar: uudecode.c was damaged during transit (should have been 10483 bytes)'
- fi
- fi ; : end of overwriting check
- exit 0
-