xref: /csrg-svn/old/pr/pr.c (revision 48289)
1*48289Sbostic /*-
2*48289Sbostic  * Copyright (c) 1983 The Regents of the University of California.
3*48289Sbostic  * All rights reserved.
4*48289Sbostic  *
5*48289Sbostic  * %sccs.include.proprietary.c%
6*48289Sbostic  */
78789Smckusick 
8*48289Sbostic #ifndef lint
9*48289Sbostic char copyright[] =
10*48289Sbostic "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
11*48289Sbostic  All rights reserved.\n";
12*48289Sbostic #endif /* not lint */
13*48289Sbostic 
14*48289Sbostic #ifndef lint
15*48289Sbostic static char sccsid[] = "@(#)pr.c	4.9 (Berkeley) 04/18/91";
16*48289Sbostic #endif /* not lint */
17*48289Sbostic 
181063Sbill /*
191063Sbill  *   print file with headings
201063Sbill  *  2+head+2+page[56]+5
211063Sbill  */
221063Sbill 
231063Sbill #include <stdio.h>
241063Sbill #include <signal.h>
251063Sbill #include <sys/types.h>
261063Sbill #include <sys/stat.h>
271063Sbill 
281063Sbill /* Making putcp a macro sped things up by 14%. */
291063Sbill #define putcp(c)  if (page >= fpage) putchar(c)
301063Sbill 
311063Sbill int	ncol	= 1;
321063Sbill char	*header;
331063Sbill int	col;
341063Sbill int	icol;
351063Sbill FILE	*file;
361063Sbill char	*bufp;
3717505Sralph #define	BUFS	9000	/* at least 66 * 132 */
381063Sbill char	buffer[BUFS];	/* for multi-column output */
391063Sbill char	obuf[BUFSIZ];
401063Sbill #define	FF	014
411063Sbill int	line;
421063Sbill char	*colp[72];
431063Sbill int	nofile;
441063Sbill char	isclosed[10];
451063Sbill FILE	*ifile[10];
461063Sbill char	**lastarg;
471063Sbill int	peekc;
481063Sbill int	fpage;
491063Sbill int	page;
501063Sbill int	colw;
511063Sbill int	nspace;
521063Sbill int	width	= 72;
531063Sbill int	length	= 66;
541063Sbill int	plength = 61;
551063Sbill int	margin	= 10;
561063Sbill int	ntflg;
571063Sbill int	fflg;
581063Sbill int	mflg;
591063Sbill int	tabc;
601063Sbill char	*tty;
611063Sbill int	mode;
621063Sbill char	*ttyname();
631063Sbill char	*ctime();
641063Sbill 
main(argc,argv)651063Sbill main(argc, argv)
661063Sbill char **argv;
671063Sbill {
681063Sbill 	int nfdone;
6946845Sbostic 	void onintr();
701063Sbill 
711063Sbill 	setbuf(stdout, obuf);
721063Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
731063Sbill 		signal(SIGINT, onintr);
741063Sbill 	lastarg = &argv[argc-1];
751063Sbill 	fixtty();
761063Sbill 	for (nfdone=0; argc>1; argc--) {
771063Sbill 		argv++;
781063Sbill 		if (**argv == '-') {
791063Sbill 			switch (*++*argv) {
808789Smckusick 			case 'h':		/* define page header */
811063Sbill 				if (argc>=2) {
821063Sbill 					header = *++argv;
831063Sbill 					argc--;
841063Sbill 				}
851063Sbill 				continue;
861063Sbill 
878789Smckusick 			case 't':		/* don't print page headers */
881063Sbill 				ntflg++;
891063Sbill 				continue;
901063Sbill 
918789Smckusick 			case 'f':		/* use form feeds */
921063Sbill 				fflg++;
931063Sbill 				plength = 60;
941063Sbill 				continue;
951063Sbill 
968789Smckusick 			case 'l':		/* length of page */
971063Sbill 				length = atoi(++*argv);
981063Sbill 				continue;
991063Sbill 
1008789Smckusick 			case 'w':		/* width of page */
1011063Sbill 				width = atoi(++*argv);
1021063Sbill 				continue;
1031063Sbill 
1048789Smckusick 			case 's':		/* col separator */
1051063Sbill 				if (*++*argv)
1061063Sbill 					tabc = **argv;
1071063Sbill 				else
1081063Sbill 					tabc = '\t';
1091063Sbill 				continue;
1101063Sbill 
1118789Smckusick 			case 'm':		/* all files at once */
1121063Sbill 				mflg++;
1131063Sbill 				continue;
1141063Sbill 
1151063Sbill 			default:
1168789Smckusick 				if (numeric(*argv)) {	/* # of cols */
1178789Smckusick 					if ((ncol = atoi(*argv)) == 0) {
1188789Smckusick 						fprintf(stderr, "can't print 0 cols, using 1 instead.\n");
1198789Smckusick 						ncol = 1;
1208789Smckusick 					}
1218789Smckusick 				} else {
1228789Smckusick 					fprintf(stderr, "pr: bad key %s\n", *argv);
1238789Smckusick 					exit(1);
1248789Smckusick 				}
1251063Sbill 				continue;
1261063Sbill 			}
1278789Smckusick 		} else if (**argv == '+') {	/* start at page ++*argv */
1281063Sbill 			fpage = atoi(++*argv);
1291063Sbill 		} else {
1301063Sbill 			print(*argv, argv);
1311063Sbill 			nfdone++;
1321063Sbill 			if (mflg)
1331063Sbill 				break;
1341063Sbill 		}
1351063Sbill 	}
1361063Sbill 	if (nfdone==0)
1371063Sbill 		print((char *)0, (char **)0);
1381063Sbill 	done();
1391063Sbill }
1401063Sbill 
done()1411063Sbill done()
1421063Sbill {
1431063Sbill 
1441063Sbill 	if (tty)
1451063Sbill 		chmod(tty, mode);
1461063Sbill 	exit(0);
1471063Sbill }
1481063Sbill 
1498789Smckusick /* numeric -- returns 1 if str is numeric, elsewise 0 */
numeric(str)1508789Smckusick numeric(str)
1518789Smckusick 	char	*str;
1528789Smckusick {
1538789Smckusick 	for (; *str ; str++) {
1548789Smckusick 		if (*str > '9' || *str < '0') {
1558789Smckusick 			return(0);
1568789Smckusick 		}
1578789Smckusick 	}
1588789Smckusick 	return(1);
1598789Smckusick }
1608789Smckusick 
16146845Sbostic void
onintr()1621063Sbill onintr()
1631063Sbill {
1641063Sbill 
1651063Sbill 	if (tty)
1661063Sbill 		chmod(tty, mode);
1671063Sbill 	_exit(1);
1681063Sbill }
1691063Sbill 
fixtty()1701063Sbill fixtty()
1711063Sbill {
1721063Sbill 	struct stat sbuf;
1731063Sbill 
1741063Sbill 	tty = ttyname(1);
1751063Sbill 	if (tty == 0)
1761063Sbill 		return;
1771063Sbill 	stat(tty, &sbuf);
1781063Sbill 	mode = sbuf.st_mode&0777;
1791063Sbill 	chmod(tty, 0600);
1801063Sbill }
1811063Sbill 
1828789Smckusick /* print -- print file */
print(fp,argp)1831063Sbill print(fp, argp)
1841063Sbill char *fp;
1851063Sbill char **argp;
1861063Sbill {
1871063Sbill 	struct stat sbuf;
1881063Sbill 	register sncol;
1891063Sbill 	register char *sheader;
1901063Sbill 	register char *cbuf;
1911063Sbill 	char linebuf[150], *cp;
1921063Sbill 
1931063Sbill 	if (ntflg)
1941063Sbill 		margin = 0;
1951063Sbill 	else
1961063Sbill 		margin = 10;
1971063Sbill 	if (length <= margin)
1981063Sbill 		length = 66;
1991063Sbill 	if (width <= 0)
2001063Sbill 		width = 72;
2011063Sbill 	if (ncol>72 || ncol>width) {
2021063Sbill 		fprintf(stderr, "pr: No room for columns.\n");
2031063Sbill 		done();
2041063Sbill 	}
2051063Sbill 	if (mflg) {
2061063Sbill 		mopen(argp);
2071063Sbill 		ncol = nofile;
2081063Sbill 	}
2091063Sbill 	colw = width/(ncol==0? 1 : ncol);
2101063Sbill 	sncol = ncol;
2111063Sbill 	sheader = header;
2121063Sbill 	plength = length-5;
2131063Sbill 	if (ntflg)
2141063Sbill 		plength = length;
2151063Sbill 	if (--ncol<0)
2161063Sbill 		ncol = 0;
2171063Sbill 	if (mflg)
2181063Sbill 		fp = 0;
2191063Sbill 	if (fp) {
2201063Sbill 		if((file=fopen(fp, "r"))==NULL) {
2211063Sbill 			if (tty==NULL)
22212095Smckusick 				perror(fp);
2231063Sbill 			ncol = sncol;
2241063Sbill 			header = sheader;
2251063Sbill 			return;
2261063Sbill 		}
2271063Sbill 		stat(fp, &sbuf);
2281063Sbill 	} else {
2291063Sbill 		file = stdin;
2301063Sbill 		time(&sbuf.st_mtime);
2311063Sbill 	}
2321063Sbill 	if (header == 0)
2331063Sbill 		header = fp?fp:"";
2341063Sbill 	cbuf = ctime(&sbuf.st_mtime);
2351063Sbill 	cbuf[16] = '\0';
2361063Sbill 	cbuf[24] = '\0';
2371063Sbill 	page = 1;
2381063Sbill 	icol = 0;
2391063Sbill 	colp[ncol] = bufp = buffer;
2401063Sbill 	if (mflg==0)
2411063Sbill 		nexbuf();
2421063Sbill 	while (mflg&&nofile || (!mflg)&&tpgetc(ncol)>0) {
2431063Sbill 		if (mflg==0) {
2441063Sbill 			colp[ncol]--;
2451063Sbill 			if (colp[ncol] < buffer)
24630276Sbostic 				colp[ncol] = &buffer[BUFS - 1];
2471063Sbill 		}
2481063Sbill 		line = 0;
2491063Sbill 		if (ntflg==0) {
2501063Sbill 			if (fflg) {
2511063Sbill 				/* Assume a ff takes two blank lines at the
2521063Sbill 				   top of the page. */
2531063Sbill 				line = 2;
25432417Sbostic 				(void)sprintf(linebuf, "%s %s  %s Page %d\n\n\n",
2551063Sbill 					cbuf+4, cbuf+20, header, page);
2561063Sbill 			} else
25732417Sbostic 				(void)sprintf(linebuf, "\n\n%s %s  %s Page %d\n\n\n",
2581063Sbill 					cbuf+4, cbuf+20, header, page);
2591063Sbill 			for(cp=linebuf;*cp;) put(*cp++);
2601063Sbill 		}
2611063Sbill 		putpage();
2621063Sbill 		if (ntflg==0) {
2631063Sbill 			if (fflg)
2641063Sbill 				put('\f');
2651063Sbill 			else
2661063Sbill 				while(line<length)
2671063Sbill 					put('\n');
2681063Sbill 		}
2691063Sbill 		page++;
2701063Sbill 	}
2711063Sbill 	fclose(file);
2721063Sbill 	ncol = sncol;
2731063Sbill 	header = sheader;
2741063Sbill }
2751063Sbill 
mopen(ap)2761063Sbill mopen(ap)
2771063Sbill char **ap;
2781063Sbill {
2791063Sbill 	register char **p, *p1;
2801063Sbill 
2811063Sbill 	p = ap;
2821063Sbill 	while((p1 = *p) && p++ <= lastarg) {
2831063Sbill 		if((ifile[nofile]=fopen(p1, "r")) == NULL){
2841063Sbill 			isclosed[nofile] = 1;
2851063Sbill 			nofile--;
2861063Sbill 		}
2871063Sbill 		else
2881063Sbill 			isclosed[nofile] = 0;
2891063Sbill 		if(++nofile>=10) {
2901063Sbill 			fprintf(stderr, "pr: Too many args\n");
2911063Sbill 			done();
2921063Sbill 		}
2931063Sbill 	}
2941063Sbill }
2951063Sbill 
putpage()2961063Sbill putpage()
2971063Sbill {
2981063Sbill 	register int lastcol, i, c;
2991063Sbill 	int j;
3001063Sbill 
3011063Sbill 	if (ncol==0) {
3021063Sbill 		while (line<plength) {
3031063Sbill 			while((c = tpgetc(0)) && c!='\n' && c!=FF)
3041063Sbill 				putcp(c);
30511274Slayer 			if (c==0) break;
3061063Sbill 			putcp('\n');
3071063Sbill 			line++;
3081063Sbill 			if (c==FF)
3091063Sbill 				break;
3101063Sbill 		}
3111063Sbill 		return;
3121063Sbill 	}
3131063Sbill 	colp[0] = colp[ncol];
3141063Sbill 	if (mflg==0) for (i=1; i<=ncol; i++) {
3151063Sbill 		colp[i] = colp[i-1];
3161063Sbill 		for (j = margin; j<length; j++)
3171063Sbill 			while((c=tpgetc(i))!='\n')
3181063Sbill 				if (c==0)
3191063Sbill 					break;
3201063Sbill 	}
3211063Sbill 	while (line<plength) {
3221063Sbill 		lastcol = colw;
3231063Sbill 		for (i=0; i<ncol; i++) {
3241063Sbill 			while ((c=pgetc(i)) && c!='\n')
3251063Sbill 				if (col<lastcol || tabc!=0)
3261063Sbill 					put(c);
3271063Sbill 			if (c==0)
3281063Sbill 				continue;
3291063Sbill 			if (tabc)
3301063Sbill 				put(tabc);
3311063Sbill 			else while (col<lastcol)
3321063Sbill 				put(' ');
3331063Sbill 			lastcol += colw;
3341063Sbill 		}
3351063Sbill 		while ((c = pgetc(ncol)) && c!='\n')
3361063Sbill 			put(c);
3371063Sbill 		put('\n');
3381063Sbill 	}
3391063Sbill }
3401063Sbill 
nexbuf()3411063Sbill nexbuf()
3421063Sbill {
3431063Sbill 	register int n;
3441063Sbill 	register char *rbufp;
3451063Sbill 
3461063Sbill 	rbufp = bufp;
3471063Sbill 	n = &buffer[BUFS] - rbufp;
3481063Sbill 	if (n>512)
3491063Sbill 		n = 512;
3501063Sbill 	if((n=fread(rbufp,1,n,file)) <= 0){
3511063Sbill 		fclose(file);
3521063Sbill 		*rbufp = 0376;
3531063Sbill 	}
3541063Sbill 	else {
3551063Sbill 		rbufp += n;
3561063Sbill 		if (rbufp >= &buffer[BUFS])
3571063Sbill 			rbufp = buffer;
3581063Sbill 		*rbufp = 0375;
3591063Sbill 	}
3601063Sbill 	bufp = rbufp;
3611063Sbill }
3621063Sbill 
tpgetc(ai)3631063Sbill tpgetc(ai)
3641063Sbill {
3651063Sbill 	register char **p;
3661063Sbill 	register int c, i;
3671063Sbill 
3681063Sbill 	i = ai;
3691063Sbill 	if (mflg) {
3701063Sbill 		if((c=getc(ifile[i])) == EOF) {
3711063Sbill 			if (isclosed[i]==0) {
3721063Sbill 				isclosed[i] = 1;
3731063Sbill 				if (--nofile <= 0)
3741063Sbill 					return(0);
3751063Sbill 			}
3761063Sbill 			return('\n');
3771063Sbill 		}
3781063Sbill 		if (c==FF && ncol>0)
3791063Sbill 			c = '\n';
3801063Sbill 		return(c);
3811063Sbill 	}
3821063Sbill loop:
3831063Sbill 	c = **(p = &colp[i]) & 0377;
3841063Sbill 	if (c == 0375) {
3851063Sbill 		nexbuf();
3861063Sbill 		c = **p & 0377;
3871063Sbill 	}
3881063Sbill 	if (c == 0376)
3891063Sbill 		return(0);
3901063Sbill 	(*p)++;
3911063Sbill 	if (*p >= &buffer[BUFS])
3921063Sbill 		*p = buffer;
3931063Sbill 	if (c==0)
3941063Sbill 		goto loop;
3951063Sbill 	return(c);
3961063Sbill }
3971063Sbill 
pgetc(i)3981063Sbill pgetc(i)
3991063Sbill {
4001063Sbill 	register int c;
4011063Sbill 
4021063Sbill 	if (peekc) {
4031063Sbill 		c = peekc;
4041063Sbill 		peekc = 0;
4051063Sbill 	} else
4061063Sbill 		c = tpgetc(i);
4071063Sbill 	if (tabc)
4081063Sbill 		return(c);
4091063Sbill 	switch (c) {
4101063Sbill 
4111063Sbill 	case '\t':
4121063Sbill 		icol++;
4131063Sbill 		if ((icol&07) != 0)
4141063Sbill 			peekc = '\t';
4151063Sbill 		return(' ');
4161063Sbill 
4171063Sbill 	case '\n':
4181063Sbill 		icol = 0;
4191063Sbill 		break;
4201063Sbill 
4211063Sbill 	case 010:
4221063Sbill 	case 033:
4231063Sbill 		icol--;
4241063Sbill 		break;
4251063Sbill 	}
4261063Sbill 	if (c >= ' ')
4271063Sbill 		icol++;
4281063Sbill 	return(c);
4291063Sbill }
put(ac)4301063Sbill put(ac)
4311063Sbill {
4321063Sbill 	register int ns, c;
4331063Sbill 
4341063Sbill 	c = ac;
4351063Sbill 	if (tabc) {
4361063Sbill 		putcp(c);
4371063Sbill 		if (c=='\n')
4381063Sbill 			line++;
4391063Sbill 		return;
4401063Sbill 	}
4411063Sbill 	switch (c) {
4421063Sbill 
4431063Sbill 	case ' ':
4441063Sbill 		nspace++;
4451063Sbill 		col++;
4461063Sbill 		return;
4471063Sbill 
4481063Sbill 	case '\n':
4491063Sbill 		col = 0;
4501063Sbill 		nspace = 0;
4511063Sbill 		line++;
4521063Sbill 		break;
4531063Sbill 
4541063Sbill 	case 010:
4551063Sbill 	case 033:
4561063Sbill 		if (--col<0)
4571063Sbill 			col = 0;
4581063Sbill 		if (--nspace<0)
4591063Sbill 			nspace = 0;
4601063Sbill 
4611063Sbill 	}
4621063Sbill 	while(nspace) {
4631063Sbill 		if (nspace>2 && col > (ns=((col-nspace)|07))) {
4641063Sbill 			nspace = col-ns-1;
4651063Sbill 			putcp('\t');
4661063Sbill 		} else {
4671063Sbill 			nspace--;
4681063Sbill 			putcp(' ');
4691063Sbill 		}
4701063Sbill 	}
4711063Sbill 	if (c >= ' ')
4721063Sbill 		col++;
4731063Sbill 	putcp(c);
4741063Sbill }
475