#ifdef	ournix
#include "ournix.h"
#endif
#ifndef	LINT	/* { */
char sccsID[] = 
	"@(#) notrail.c V1.5 Copyright Julian H. Stacey, Munich, 25th January 1990.\n" ;
#endif		/* } */

/* strip trailing white space from lines terminating in \n 
	(note \r is considered as white space, 
	thus also converts \r\n to \n) */

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

#define BS 8

char	**ARGV ;

#ifdef	MSDOS
#define MAXBUF	25000
#else
#define MAXBUF	400000
#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, *in_p ;


#ifdef scs	/* { */
extern char *mktemp() ;
#define TMP_NAME "noXXXXXX"
#else		/* }{ */
#include <unistd.h>
#ifdef MSDOS	/* { */
#define TMP_NAME "no78XXXXXX"
#else		/* }{ */
#define TMP_NAME "notrail.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, 
				"%s: Cannot create temporary file '%s'\n",
							*ARGV, tmp_name) ;
			exit(3) ;
			}
		}
	i = out_p - out_buf ;
	out_p = out_buf ;
	if(write(tmp_fd, out_buf, i) != i)
		{
		fprintf(stderr, "%s: Write failure on temporary file.\n",
			*ARGV) ;
		clean() ;
		exit(4) ;
		}
	*out_p++ = c ;
	}

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

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,src_name)
	int	src_fd ;
	char	*src_name ;
	{
	register int ch ;
	char	*p_array ;
#define	MAX_LINE_BUF	50000
	char	array[MAX_LINE_BUF] ;

	p_array = array + 1 ;	/* 1 is for begin of segment */
	while((ch = IN_C(src_fd)) != EOF)
		{
		if (p_array - array >= MAX_LINE_BUF - 5 )
			{
			*p_array = '\0' ;
			fprintf(stderr,"%s: %s line too long %s\n",
				*ARGV,src_name,array+1) ;
			exit(1) ;
			}
		if ((*p_array++ = (char)ch) != '\n') continue ;
		/* scan back for spaces */
		p_array -= 2 ;
		while((p_array >= array + 1) && (((ch = *p_array) == ' ') ||
			(ch == '\t') || (ch == '\r') ) ) p_array-- ;
		*++p_array = '\n' ;
		*++p_array = '\0' ;
		p_array = array + 1 ;
		while ((ch = *p_array++) != '\0') OUTC((char)ch) ;
		p_array = array + 1 ;
		}
	/* allow for files not ending in \n */
	if (p_array > array + 1 )
		{
		*p_array = '\0' ;
		p_array = array + 1 ;
		while ((ch = *p_array++) != '\0') OUTC((char)ch) ;
		}
	}

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

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, "%s: Write error on temporary file\n",*ARGV) ;
		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) ;
		}
	}

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, "%s: Write failure on source file\n",*ARGV) ;
		clean() ;
		exit(2) ;
		}
	if (close(f) < 0)
		{
		perror(*ARGV) ;
		exit(1) ;
		}
	}


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

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