/*
 *
 * Uue -- encode a file so that it's printable ascii, short lines
 *
 * Slightly modified from a version posted to net.sources a while back,
 * and suitable for compilation on the IBM PC
 *
 * modified for Lattice C on the ST - 11.05.85 by MSD
 * modified for ALCYON on the ST -    10-24-86 by RDR
 * modified a little more for MWC...  02/09/87 by JPHD
 * (An optional first argument of the form: -nnumber (e.g. -500), will
 * produce a serie of files that long, linked by the include statement,
 * such files are automatically uudecoded by the companion program.)
 * More mods, - ...                05/06/87 by jphd
 * Mods for TOPS 20, and more.     08/06/87 by jphd
 *     (remove freopen and rindex...change filename generation...)
 * (A lot more to do about I/O speed, avoiding completely the stdio.h...)
 *
 */


#include <stdio.h>
#include <ctype.h>

#define USAGE

/* ENC is the basic 1 character encoding function to make a char printing */
#define ENC(c) (((c) & 077) + ' ')

extern FILE  *fopen();
FILE *fp, *outp;
char ofname[80];
int lenofname;
int stdo = 0;

#ifdef ST
#define READ "rb"
#else
#define READ "r"
#endif

int part = 'a', chap = 'a';
#define SEQMAX 'z'
#define SEQMIN 'a'
char seqc = SEQMAX;

int split = 0; fileln = 32000;

main(argc, argv)
int argc; char *argv[];
{
        char *fname;

        if (argc < 2) {
                fprintf(stderr, "Almost foolproof uuencode v3.1 06 Aug 1987\n");
                fprintf(stderr, "Usage: uue [-n] inputfile [-]\n");
                exit(2);
                }
        if (argv[1][0] == '-') {
                fileln = -atoi(argv[1]);
                if (fileln <= 0) {
                        fprintf(stderr, "Wrong file length arg.\n");
                        exit();
                }
                split = 1;
                argv++;
                argc--;
        }
        if ((fp=fopen(argv[1], READ))==NULL) {  /* binary input !!! */
                fprintf(stderr,"Cannot open %s\n",argv[1]);
                exit(1);
        }
        strcpy(ofname, argv[1]);
        fname = ofname;
        do {
                if (*fname == '.')
                        *fname = '\0';
        } while (*fname++);
                /* 8 char prefix + .uue -> 12 chars MAX */
        lenofname = strlen(ofname);
        if (lenofname > 8) ofname[8] = '\0';
        strcat(ofname,".uue");
        lenofname = strlen(ofname);
        if (!split && (argc > 2) && (argv[2][0] == '-')) {
                stdo = 1;
                outp = stdout;
         } else {
                 makename();
                 if((outp = fopen(ofname, "w")) == NULL) {
                         fprintf(stderr,"Cannot open %s\n", ofname);
                         exit(1);
                         }
        }
        maketable();
        fprintf(outp,"begin %o %s\n", 0644, argv[1]);
        encode();
        fprintf(outp,"end\n");
        fclose(outp);
        exit(0);
}

/* create ASCII table so a mailer can screw it up and the decode
 * program can restore the error.
 */
maketable()
{
        register int i, j;

        fputs("table\n", outp);
        for(i = ' ', j = 0; i < '`' ; j++) {
                if (j == 32)
                        putc('\n', outp);
                fputc(i++, outp);
        }
        putc('\n', outp);
}

/*
 * Generate the names needed for single and multiple part encoding.
 */
makename()
{
        if (split) {
                ofname[lenofname - 1] = part;
                ofname[lenofname - 2] = chap;
        }
}

/*
 * copy from in to out, encoding as you go along.
 */
encode()
{
        char buf[80];
        register int i, n;
        register int lines;
        lines = 6;

        for (;;) {
                n = fr(buf, 45);
                putc(ENC(n), outp);
                for (i = 0; i < n; i += 3)
                      outdec(&buf[i]);
                putc(seqc, outp);
                seqc--;
                if (seqc < SEQMIN) seqc = SEQMAX;
                putc('\n', outp);
                ++lines;
                if (split && (lines > fileln)) {
                        part++;
                        if (part > 'z') {
                                part = 'a';
                                if (chap == 'z')
                                        chap = 'a'; /* loop ... */
                                else
                                        chap++;
                        }
                        makename();
                        fprintf(outp,"include %s\n",ofname);
                        fclose(outp);
                        if((outp = fopen(ofname, "w")) == NULL) {
                                fprintf(stderr,"Cannot open %s\n",ofname);
                                exit(1);
                        }
                        maketable();
                        fprintf(outp,"begin part %c %s\n",part,ofname);
                        lines = 6;
                }
                if (n <= 0)
                        break;
        }
}

/*
 * output one group of 3 bytes, pointed at by p, on file f.
 */
outdec(p)
register char *p;
{
        register int c1, c2, c3, c4;

        c1 = *p >> 2;
        c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
        c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
        c4 = p[2] & 077;
        putc(ENC(c1), outp);
        putc(ENC(c2), outp);
        putc(ENC(c3), outp);
        putc(ENC(c4), outp);
}

/* fr: like read but stdio */
int fr(buf, cnt)
register char *buf;
register int cnt;
{
        register int c, i;
        for (i = 0; i < cnt; i++) {
                c = fgetc(fp);
                if (feof(fp))
                        return(i);
                buf[i] = c;
        }
        return (cnt);
}
