/* conv.c
 *
 * Reads a character set from stdin converts and outputs to stdout.
 */

#ifndef lint
static char *Rcsid = "@(#)$Header$";

#endif

/*
 *
 * $Log: conv.c,v $
 * Revision 1.4  1993-01-14 keld
 * Adapted to use the quoted-printable and base64 rutines.
 *
 * Revision 1.3  1991/04/05  17:06:30  paul
 * Eliminated constant strings passed as arguments.
 *
 * Revision 1.2  1991/04/05  15:56:39  paul
 * Adapted to use the new strcnv.c
 *
 */

/* #include "sendmail.h"  */

#include <stdio.h>
#include <errno.h>
#include "iso646.h"
#include "charset.h"

#define SLEN	256		/* max length in octets of images */
#define Char   unsigned char
static CHARSET *in;
static CHARSET *out;

/* FILE *dfopen(); TW */
char *xalloc();
int getopt(), bincl2base();
Char *bin2qp(), *bin2base(), *binc2base(), *qp2bin(), *base2bin();

int bopt=0, uopt= 0, qopt=0, popt=0, errflg=0, ic;
int ipos;
Char oc ARRAY(SLEN),*op;

extern	int atoi(char *);	/* 941114 / TW */
extern	CHAR8U * strncnv(CHARSET *, CHARSET *, CHAR8U *, CHAR8U *, int); /* 941114 / TW */

void
outqb(b,bm)
Char *b, *bm;
{
	Char *i=b;
	if (qopt) do {
            i= bin2qp(i,oc,bm); 
            fputs ((char *)oc, stdout); 
        } while (i<bm);
        else if (bopt) {
	    for (;i<bm;i++) if (!(op=binc2base(*i,op,ipos++)))
	    {
	        fputs ((char *)oc, stdout); 
                ipos=0; op=oc;
	    }
	} else fwrite ((char *)b, bm-b, 1, stdout); 
}


void
main (argc, argv)
	int	 argc;
	Char   **argv;
{
	Char s ARRAY(SLEN), r ARRAY(SLEN), *opt=NULL, *o=r, c;
	char dk ARRAY(3), us ARRAY(3);
	int len;

	op= oc; ipos= 0;
	(void) strcpy(dk, "DK");
	(void) strcpy(us, "us");

	while ((ic = getopt(argc, argv, "buqp")) != EOF) {
		c = ic & 0377;
		switch(c) {
		case 'b': bopt++; break; /* encode base64 */
		case 'u': uopt++; break; /* uncode base64 */
		case 'q': qopt++; break; /* quote - make qp */
		case 'p': popt++; break; /* print - unmake qp */
		default: errflg++;
		}
	}

	if (errflg) {
		fprintf(stderr, "Usage: conv -buqp chset1 chset2\n");
		exit(1);
	}
	switch (argc) {
	    case 1:
		in = getchset (dk, '&');
		out = getchset (us, DEFAULT_ESCAPE);
		break;

	    case 2: opt = *(argv+1) ; break;

	    case 3:
		in = getchset (*(argv+1), DEFAULT_ESCAPE);
		out = getchset (*(argv+2), DEFAULT_ESCAPE);
		break;

	    case 5:
		in = getchset (*(argv+1), (INT16S) atoi(*(argv+2)));
		out = getchset (*(argv+3), (INT16S) atoi(*(argv+4)));
		break;

	    default:
		printf ("\n\nUsage: %s charset-in   (esc-in)  charset-out  (esc-out)\n\n", *argv);
		exit (1);
	}

    if (not opt) {
	if (in == NULL or out == NULL) {
		printf ("\n\n*** Error: Unknown Charset/s\n\n");
		exit (1);
	}
	/*
	 * Should output records of unlimited length by outputting one part at
	 * a time.
	 */
	while (fgets ((char *)s, SLEN, stdin)) {
		strncnv (out, in, r, s, SLEN);
		fputs ((char *)r, stdout);
	}
    } else if (popt or uopt or qopt)
    while (fgets((char *)s, SLEN, stdin)) {
	len= strlen(s);
        if (popt) {
		*(s+len-1) = 0;
		o= qp2bin(s,o);
		if (! *o) {
		    outqb(r,o);
                    o= r;
		}
        } else if (uopt) {
		o= base2bin(s,o);
		if (! *o) {
		    outqb(r,o);
                    o= r;
		}
	} else outqb(s,s+len-1);
    } 
    else while ((len=fread((char *)s, 1, SLEN, stdin)) diff 0) outqb(s,s+len);
    if (uopt) outqb(r,o);
    if (bopt and ipos) {
        bincl2base(op,ipos);
        fputs ((char *)oc, stdout); 
    }

    exit (0);
}
