#ifdef	ournix
#include "ournix.h"
#endif
char sccsID[] = "@(#) cleanch.c V1.7 Copyright Julian H. Stacey, Munich, 31st August 1988.\n";

/* see manual */

#include	<stdio.h>
#include 	<stdlib.h>
#include	<sys/types.h>
#include 	<sys/stat.h>
#include <string.h>
#ifdef ns32000	/* { */
#define BSD
#endif		/* } */
#ifdef FreeBSD	/* { */
#define BSD
#endif		/* } */
#ifdef	BSD
#include 	<sys/uio.h>
#include 	<unistd.h>
#include	<sys/file.h>
#include	<sys/signal.h>
#else
#include	<signal.h>
#endif
#ifndef	BSD	/* { */
#include	<fcntl.h>
#endif		/* } */



#define	BELL	7
#define	SUB	0x1a	/* = ^Z	= MSDOS	EOF */
#define	FORMFEED 0xC
#define	BS	8

char	**ARGV;

#ifdef	MSDOS
#define MAXBUF	25000
#else
#define MAXBUF	250000
#endif

/*
 * output/tmpfile variables
 */
char	out_buf[MAXBUF];
int	tmp_fd;
char	*out_p = out_buf;

/*
 * input file variables
 */
unsigned char	in_buf[MAXBUF];
unsigned char	*in_end;
unsigned char	*in_p;

#ifdef scs	/* { */
extern char *mktemp() ;
#define TMP_NAME "clXXXXXX"
#else		/* }{ */
#include <unistd.h>
#ifdef MSDOS	/* { */
#define TMP_NAME "clXXXXXX"
#else		/* }{ */
#define TMP_NAME "cleanch.XXXXXX"
#endif		/* } */
#endif		/* } */
#include <sys/param.h>	/* for MAXPATHLEN */
char	tmp_name[MAXPATHLEN] ;		/* temporary file name */

typedef	char	FLAG ;
FLAG	verbose = 0 ;

int in_c(f)
	int	f;
	{
	int	i;

	i = read(f, (char *)in_buf, (int)MAXBUF);
	if(i <= 0) return(EOF);
	in_end = in_buf + i;
	in_p = in_buf;
	return(*in_p++);
	}

void clean()
	{
	if(tmp_fd > 0)
		{
		(void)close(tmp_fd);
		tmp_fd = 0;
		(void) unlink(tmp_name);
		}
	out_p = out_buf;
	}

void out_c(c)
	char	c ;
	{
	int	i;
	if(tmp_fd == 0)
		{
		/* no temporary file yet */
		tmp_fd = open(tmp_name,
#ifdef	MSDOS	/* { */
				O_BINARY |
#endif		/* } */
				O_CREAT | O_TRUNC | O_RDWR, 0200);
		if(tmp_fd < 0)
			{
			fprintf(stderr, "Cannot create temporary file '%s'\n",
								tmp_name);
			exit(3);
			}
		}
	i = out_p - out_buf;
	out_p = out_buf;
	if(write(tmp_fd, out_buf, i) != i)
		{
		fprintf(stderr, "Write failure on temporary file\n");
		clean();
		exit(4);
		}
	*out_p++ = c;
	}

#define IN_C(f) ((in_p < in_end) ? *in_p++ : in_c(f))
#define OUTC(c) ((out_p < &out_buf[MAXBUF] )? *out_p++ = c : out_c(c))

void copyback(f)
	int	f;
	{
	int	i;
	int	res = 1;

	if(tmp_fd == 0)
		{	/* no temporary file */
		i = out_p - out_buf;
		out_p = out_buf;
		if(i && write(f, out_buf, i) != i) res = -1;
		}
	else 
		{
		while((i = read(tmp_fd, out_buf, (int)MAXBUF)) > 0)
			if(write(f, out_buf, i) != i)
				{
				res = -1;
				break;
				}
		}
	if(res < 0)
		{
		fprintf(stderr, "Write failure on source file\n");
		clean();
		exit(2);
		}
	if (close(f) < 0)
		{
		perror(*ARGV) ;
		exit(1);
		}
	}

void zapname(name)
	char	*name;
	{
	register int	i, j;

	if (!verbose) return ;
	i = strlen(name);
	for(j = i ; j ; j--) putchar(BS);
	for(j = i ; j ; j--) putchar(' ');
	for(j = i ; j ; j--) putchar(BS);
	}

void do_it(src_fd)
	{
	register int old_ch, char_2;

	old_ch = '-';	
	while((char_2 = IN_C(src_fd)) != EOF)
		{
			/* cant	discard	parity as needed by ibm	umlauts	 */
		if ((char_2  ==	SUB) ||	(char_2	== '\0')) continue;
		switch(char_2) 
			{
		case 0x8E :	/* A umlaut (0x0e = ^N)	*/
			char_2 = 0x5b ;	/* '[' */
			break ;
		case 0x99 :	/* O umlaut (0x19 = ^Y)	*/
			char_2 = 0x5c ;	/* '\\'	*/
			break ;
		case 0x9A :	/* U umlaut (0x1a = ^Z = MSDOS EOF ) */
			char_2 = 0x5d ;	/* ']' */
			break ;
		case 0x84 :	/* a umlaut (0x04 = EOT) */
			char_2 = 0x7b ;	/* '{' */
			break ;
		case 0x94 :	/* o umlaut (0x14 = ^T)	*/
			char_2 = 0x7c ;	/* '|' */
			break ;
		case 0x81 :	/* u umlaut (0x01 == ^A) */
			char_2 = 0x7d ;	/* '}' */
			break ;
		case 0xE1 :	/* sharf ess (0x61 = 'a') */
			char_2 = 0x7e ;	/* '~' */
			break ;
		default	:
			/* discard parity for other characters */
			char_2 &= 0x7f ;
			break ;
			}
		switch(char_2)
			{
		case '\n':
		case '\t':
		case BELL:
		case FORMFEED:
		case BS:
			if(old_ch == '\r')
				{
				if(char_2 != '\n') OUTC('\n');
				}
			OUTC((char)char_2);
			break;
		case '\r': break;
		default:
			if(char_2 >= ' ' && char_2 < 0x7f)
				{
				if(old_ch == '\r') OUTC('\n') ;
				OUTC((char)char_2);
				break;
				}
			continue;
			}
		old_ch = char_2;
		}
	if(old_ch == '\r') OUTC('\n');
	}

void fls_tmp()
	{
	int	i, res;

	if(tmp_fd == 0) return;
	i = out_p - out_buf;
	if(i != 0) res = write(tmp_fd, out_buf, i);
	out_p = out_buf;
	if(i != res)
		{
		fprintf(stderr, "Write error on temporary file\n");
		if (close(tmp_fd) < 0)
			{
			perror(*ARGV) ;
			exit(1) ;
			}
		(void) unlink(tmp_name);
		exit(1);
		}
	/* go back to beginning */
	if (lseek(tmp_fd, (off_t)0, 0) < 0)
		{
		perror(*ARGV);
		exit(1) ;
		}
	}

void cleanup()
	{
	clean();
	exit(2);
	}

int main(argc, argv)	
	int argc;
	char **argv;
	{
	int	f;
	void	cleanup();
	int	errors = 0;

	ARGV = argv;
#ifdef	VSL	/* { */
#include	"../../include/vsl.h"
#endif		/* } */
#ifdef DEBUG
	printf("%s",sccsID);
#endif
	strcpy(tmp_name,TMP_NAME) ;
	(void) mktemp(tmp_name) ;

	if (argc == 1) /* no args; copy	standard input */
		{
		fprintf(stderr, "%s: Pipe usage not allowed.\n",*ARGV); 
		exit(1);
		}

	(void) signal(SIGINT, (void *)&cleanup);
	while(*++argv)
		{
		f = open(*argv,
#ifdef	MSDOS	/* { */
				O_BINARY |
#endif		/* } */
					O_RDONLY);
		if(f < 0)
			{
			fprintf(stderr, "Cannot open '%s'\n", *argv);
			errors++;
			continue;
			}
		if (verbose)
			{
			printf("%s", *argv);
			(void) fflush(stdout);
			}
		do_it(f);
		if (close(f) < 0)
			{
			perror(*ARGV) ;
			exit(1);
			}
		(void) fls_tmp();
		(void) signal(SIGINT, SIG_IGN);
		f = open(*argv, 
#ifdef	MSDOS	/* { */
				O_BINARY |
#endif		/* } */
				O_WRONLY | O_CREAT | O_TRUNC, 0200);
		if(f < 0)
			{
			(void) signal(SIGINT, (void *)&cleanup);
			fprintf(stderr, "Cannot recreate '%s'\n", *argv);
			errors++;
			clean();
			continue;
			}
		copyback(f);
		(void) signal(SIGINT, (void *)&cleanup);
		clean();
		zapname(*argv);
		}
	exit(errors);
	}




