static char rcsid[] = "$Header: cat.c,v 800.0 85/07/30 14:12:43 root Exp $";
/*
 * Concatenate files. STANDALONE version.  Don't ask me why...
 */
static char sccsid[]="%W% %Y% %Q% %G%";

#ifdef	STANDALONE
#include "../h/param.h"
#include "../h/fs.h"
#include "../h/inode.h"
#include "../salib/saio.h"
#else	STANDALONE
#include <stdio.h>
#endif	STANDALONE
#include <sys/types.h>
#include <sys/stat.h>

#ifdef s32		/* XXX: should be VALID or similar, not s32! */
/*
 * This cat has two features: buffering, and meow.
 * Can turn off meow by undefing it.  Buffering is a generic win,
 * I think.
 */
char	stdbuf[16384];	/* 841208 sbs */


#else s32
char	stdbuf[BUFSIZ];
#endif s32
int	bflg, eflg, nflg, sflg, tflg, vflg;
int	spaced, col, lno, inline;

#ifdef STANDALONE
/*
 * Version string comes from vers.c -- created by vers.sh on the fly.
 */
extern char version[];
#endif STANDALONE

#ifndef STANDALONE
main(argc, argv)
char **argv;
#else   STANDALONE
main()
#endif  STANDALONE
{
	int fflg = 0;
#ifndef	STANDALONE
	register FILE *fi;
#else	STANDALONE
	register int outfile, fi;
#endif	STANDALONE
	register c;
	int dev, ino, mtime = -1;
	struct stat statb, statb1;
#ifdef STANDALONE
	char fname[1024];
	int argc;
	char **argv;

	printf(version);
#endif STANDALONE

	lno = 1;
#ifndef STANDALONE
	setbuf(stdout, stdbuf);
	for( ; argc>1 && argv[1][0]=='-'; argc--,argv++) {
		switch(argv[1][1]) {
		case 0:
			break;
		case 'u':
			setbuf(stdout, (char *)NULL);
			continue;
		case 'n':
			nflg++;
			continue;
		case 'b':
			bflg++;
			nflg++;
			continue;
		case 'v':
			vflg++;
			continue;
		case 's':
			sflg++;
			continue;
		case 'e':
			eflg++;
			vflg++;
			continue;
		case 't':
			tflg++;
			vflg++;
			continue;
		}
		break;
	}
	if (fstat(fileno(stdout), &statb) == 0) {
		statb.st_mode &= S_IFMT;
		if (statb.st_mode!=S_IFCHR && statb.st_mode!=S_IFBLK) {
			dev = statb.st_dev;
			ino = statb.st_ino;
			mtime = statb.st_mtime;
		}
	}
	if (argc < 2) {
		argc = 2;
		fflg++;
	}
#else STANDALONE
	argc = 2;
#endif STANDALONE
	while (--argc > 0) {
#ifndef STANDALONE
		if (fflg || (*++argv)[0]=='-' && (*argv)[1]=='\0')
			fi = stdin;
		else {
			if ((fi = fopen(*argv, "r")) == NULL) {
				fprintf(stderr, "cat: can't open %s\n", *argv);
				continue;
			}
		}
		if (fstat(fileno(fi), &statb) == 0) {
			if ((statb.st_mode & S_IFMT) == S_IFREG &&
			    statb.st_dev==dev 
			    && statb.st_ino==ino 
			    && statb.st_mtime==mtime) {
				fprintf(stderr, "cat: input %s is output\n",
				   fflg?"-": *argv);
				fclose(fi);
				continue;
			}
		}
		if (nflg||sflg||vflg)
			copyopt(fi);
#else   STANDALONE
getinput:
		printf("Input file? ");
		gets(fname);
		if ((fi = open(fname, 0)) < 0) {
			printf("cat: can't open %s\n", fname);
			goto getinput;
		}
getoutput:
		printf("Output file? ");
		gets(fname);
		if ((outfile = open(fname, 1)) < 0) {
			printf("cat: can't open %s\n", fname);
			goto getoutput;
		}
#endif  STANDALONE
		else {
#ifdef s32
			/*
			 * Doing read/write to this buffer size takes the
			 * user time to 0.
			 */
			register x;

#ifdef	STANDALONE
			if ((x = read(fi, stdbuf, sizeof(stdbuf)))
			   > 0) { /* fastidious: only test isalrm 1st time */
				write(outfile, stdbuf, x);
				while ((x = read(fi, stdbuf,
						sizeof(stdbuf))) > 0)
					write(outfile, stdbuf, x);
			}
#else	STANDALONE
			if ((x = read(fileno(fi), stdbuf, sizeof(stdbuf)))
			   > 0) { /* fastidious: only test isalrm 1st time */
				write(fileno(stdout), stdbuf, x);
				while ((x = read(fileno(fi), stdbuf,
						sizeof(stdbuf))) > 0)
					write(fileno(stdout), stdbuf, x);
			}
#endif	STANDALONE
#else s32
			while ((c = getc(fi)) != EOF)
				putchar(c);
#endif s32
		}
#ifdef	STANDALONE
		close(fi);
#else	STANDALONE
		if (fi!=stdin)
			fclose(fi);
#endif	STANDALONE
	}
#ifndef STANDALONE
	if (ferror(stdout))
		fprintf(stderr, "cat: output write error\n");
#endif  STANDALONE
	return(0);
}

#ifndef STANDALONE
copyopt(f)
	register FILE *f;
{
	register int c;

top:
	c = getc(f);
	if (c == EOF)
		return;
	if (c == '\n') {
		if (inline == 0) {
			if (sflg && spaced)
				goto top;
			spaced = 1;
		}
		if (nflg && bflg==0 && inline == 0)
			printf("%6d\t", lno++);
		if (eflg)
			putchar('$');
		putchar('\n');
		inline = 0;
		goto top;
	}
	if (nflg && inline == 0)
		printf("%6d\t", lno++);
	inline = 1;
	if (vflg) {
		if (tflg==0 && c == '\t')
			putchar(c);
		else {
			if (c > 0177) {
				printf("M-");
				c &= 0177;
			}
			if (c < ' ')
				printf("^%c", c+'@');
			else if (c == 0177)
				printf("^?");
			else
				putchar(c);
		}
	} else
		putchar(c);
	spaced = 0;
	goto top;
}
#endif STANDALONE

