/* DOS-to-Unix / Unix-to-DOS text file translation utility.	 */
/*  This program takes parameters the same way as 'copy', except */
/*  that if no parameters are given it acts as a filter between  */
/*  stdin and stdout.						 */

/* Written by Richard Braun @ Kronos, 19 March 1991.		 */
/*   Comments and bugs to rbraun@spdcc.com.			 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#ifdef MSDOS
#include <sys/utime.h>
#else
#include <utime.h>
#endif

void usage (char *);
void addCR (char *, FILE *, FILE *);
void removeCR (char *, FILE *, FILE *);

extern int errno;

main (argc, argv)
int argc;
char *argv[];
{
    FILE *fpin, *fpout, *fopen();
    struct stat statbuf;
    struct utimbuf timebuf;
    char outdir[200];
    char **cur_file;

    outdir[0] = '\0';
    fpout = (argc == 1) ? stdout : NULL;
    fpin  = (argc == 1) ? stdin  : NULL;

    /* Get output directory, if given */

    if (argc >= 3) {
	if (stat (argv[argc-1], &statbuf) == 0 &&
	    statbuf.st_mode & S_IFDIR) {
	    strcpy (outdir, argv[argc-1]);
	    argc--;
        }
    }
    else if (argc == 2) {
	strcpy (outdir, ".");
    }
    cur_file = &argv[1];
    for (;;) {
	char outfile [200];

	if (fpin != stdin && (fpin = fopen (*cur_file, "r")) == NULL) {
	    fprintf (stderr, "%s: couldn't open input file '%s'\n",
		     argv[0], *cur_file);
	    usage (argv[0]);
	}

	if (fpout != stdout) {
	    struct stat instat, outstat;

	    if (outdir[0]) {
		char *ptr;

		strcpy (outfile, outdir);
		strcat (outfile, "/");
		strcat (outfile, (ptr = strrchr (*cur_file, '/')) ? ptr+1 :
			*cur_file);
	    }
	    else
	      strcpy (outfile, argv[2]);

	    /* Check to make sure we're not overwriting a file */
	    if (stat (*cur_file, &instat) == 0 &&
		stat (outfile, &outstat) == 0 &&
		outstat.st_dev == instat.st_dev &&
		outstat.st_ino == instat.st_ino) {
		fprintf (stderr, "%s error: input and output filespecs (%s) identical\n",
			 argv[0], *cur_file);
		usage (argv[0]);
	    }

	    /* Skip any directories in the input list, to make	 */
	    /* "d2x * outdir" behave as expected.		 */

	    if (instat.st_mode & S_IFDIR) {
		fclose (fpin);
		if (outdir[0] == '\0' || --argc == 1)
		  break;
		cur_file++;
		continue;
	    }

	    if ((fpout = fopen (outfile, "wb")) == NULL) {
		fprintf (stderr, "%s: couldn't open output file '%s'\n",
			 argv[0], argv[2]);
		usage (argv[0]);
	    }

	    /* Preserve the modification time of the input file. */
	    timebuf.modtime = instat.st_mtime;
	}

	addCR (argv[0], fpin, fpout);
	fclose (fpin);
	fclose (fpout);

	/* Set the file's access time to now and the modification time  */
	/* to that of the input file.					*/
	time (&timebuf.actime);
	(void) utime (outfile, &timebuf);

	if (outdir[0] == '\0' || --argc == 1)
	  break;
	cur_file++;
    }
    exit (1);
}


void usage (program)
char *program;
{
    fprintf (stderr, "Usage:  %s [infile [outfile]]\n", program);
    fprintf (stderr, "        %s infile1 ... infileN outdir\n", program);
    exit (1);
}


void addCR (program, fpin, fpout)
char *program;
FILE *fpin, *fpout;
{
    char str[500];

    /* Run a loop, appending "\r\n" to each line. */

    while (fgets (str, sizeof(str) - 1, fpin) != NULL) {
	int len;

	len = strlen (str);
	if (str[len-1] == '\n') {
	    str[len-1] = '\r';
	    str[len] = '\n';
	    str[len+1] = '\0';
	}
	if (fputs (str, fpout) == EOF) {
	    fprintf (stderr, "%s: error writing output\n", program);
	    usage (program);
	}
    }
}


void removeCR (program, fpin, fpout)
char *program;
FILE *fpin, *fpout;
{
    char str[500];

    /* Run a loop, stripping \r and ^Z characters */

    while (fgets (str, sizeof str, fpin) != NULL) {
	char *ptrin, *ptrout;

	ptrin = str; ptrout = str;
	while (*ptrin) {
	    if (*ptrin != '\032' && *ptrin != '\r')
	      *ptrout++ = *ptrin++;
	    else
	      ptrin++;
	}
	*ptrout = '\0';
	if (fputs (str, fpout) == EOF) {
	    fprintf (stderr, "%s: error writing output\n", program);
	    usage (program);
	}
    }
}
