xref: /csrg-svn/old/pr/pr.c (revision 11274)
1*11274Slayer static char *sccsid = "@(#)pr.c	4.3 (Berkeley) 02/24/83";
28789Smckusick 
31063Sbill /*
41063Sbill  *   print file with headings
51063Sbill  *  2+head+2+page[56]+5
61063Sbill  */
71063Sbill 
81063Sbill #include <stdio.h>
91063Sbill #include <signal.h>
101063Sbill #include <sys/types.h>
111063Sbill #include <sys/stat.h>
121063Sbill 
131063Sbill /* Making putcp a macro sped things up by 14%. */
141063Sbill #define putcp(c)  if (page >= fpage) putchar(c)
151063Sbill 
161063Sbill int	ncol	= 1;
171063Sbill char	*header;
181063Sbill int	col;
191063Sbill int	icol;
201063Sbill FILE	*file;
211063Sbill char	*bufp;
221063Sbill #define	BUFS	6720
231063Sbill char	buffer[BUFS];	/* for multi-column output */
241063Sbill char	obuf[BUFSIZ];
251063Sbill #define	FF	014
261063Sbill int	line;
271063Sbill char	*colp[72];
281063Sbill int	nofile;
291063Sbill char	isclosed[10];
301063Sbill FILE	*ifile[10];
311063Sbill char	**lastarg;
321063Sbill int	peekc;
331063Sbill int	fpage;
341063Sbill int	page;
351063Sbill int	colw;
361063Sbill int	nspace;
371063Sbill int	width	= 72;
381063Sbill int	length	= 66;
391063Sbill int	plength = 61;
401063Sbill int	margin	= 10;
411063Sbill int	ntflg;
421063Sbill int	fflg;
431063Sbill int	mflg;
441063Sbill int	tabc;
451063Sbill char	*tty;
461063Sbill int	mode;
471063Sbill char	*ttyname();
481063Sbill char	*ctime();
491063Sbill 
501063Sbill main(argc, argv)
511063Sbill char **argv;
521063Sbill {
531063Sbill 	int nfdone;
541063Sbill 	int onintr();
551063Sbill 
561063Sbill 	setbuf(stdout, obuf);
571063Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
581063Sbill 		signal(SIGINT, onintr);
591063Sbill 	lastarg = &argv[argc-1];
601063Sbill 	fixtty();
611063Sbill 	for (nfdone=0; argc>1; argc--) {
621063Sbill 		argv++;
631063Sbill 		if (**argv == '-') {
641063Sbill 			switch (*++*argv) {
658789Smckusick 			case 'h':		/* define page header */
661063Sbill 				if (argc>=2) {
671063Sbill 					header = *++argv;
681063Sbill 					argc--;
691063Sbill 				}
701063Sbill 				continue;
711063Sbill 
728789Smckusick 			case 't':		/* don't print page headers */
731063Sbill 				ntflg++;
741063Sbill 				continue;
751063Sbill 
768789Smckusick 			case 'f':		/* use form feeds */
771063Sbill 				fflg++;
781063Sbill 				plength = 60;
791063Sbill 				continue;
801063Sbill 
818789Smckusick 			case 'l':		/* length of page */
821063Sbill 				length = atoi(++*argv);
831063Sbill 				continue;
841063Sbill 
858789Smckusick 			case 'w':		/* width of page */
861063Sbill 				width = atoi(++*argv);
871063Sbill 				continue;
881063Sbill 
898789Smckusick 			case 's':		/* col separator */
901063Sbill 				if (*++*argv)
911063Sbill 					tabc = **argv;
921063Sbill 				else
931063Sbill 					tabc = '\t';
941063Sbill 				continue;
951063Sbill 
968789Smckusick 			case 'm':		/* all files at once */
971063Sbill 				mflg++;
981063Sbill 				continue;
991063Sbill 
1001063Sbill 			default:
1018789Smckusick 				if (numeric(*argv)) {	/* # of cols */
1028789Smckusick 					if ((ncol = atoi(*argv)) == 0) {
1038789Smckusick 						fprintf(stderr, "can't print 0 cols, using 1 instead.\n");
1048789Smckusick 						ncol = 1;
1058789Smckusick 					}
1068789Smckusick 				} else {
1078789Smckusick 					fprintf(stderr, "pr: bad key %s\n", *argv);
1088789Smckusick 					exit(1);
1098789Smckusick 				}
1101063Sbill 				continue;
1111063Sbill 			}
1128789Smckusick 		} else if (**argv == '+') {	/* start at page ++*argv */
1131063Sbill 			fpage = atoi(++*argv);
1141063Sbill 		} else {
1151063Sbill 			print(*argv, argv);
1161063Sbill 			nfdone++;
1171063Sbill 			if (mflg)
1181063Sbill 				break;
1191063Sbill 		}
1201063Sbill 	}
1211063Sbill 	if (nfdone==0)
1221063Sbill 		print((char *)0, (char **)0);
1231063Sbill 	done();
1241063Sbill }
1251063Sbill 
1261063Sbill done()
1271063Sbill {
1281063Sbill 
1291063Sbill 	if (tty)
1301063Sbill 		chmod(tty, mode);
1311063Sbill 	exit(0);
1321063Sbill }
1331063Sbill 
1348789Smckusick /* numeric -- returns 1 if str is numeric, elsewise 0 */
1358789Smckusick numeric(str)
1368789Smckusick 	char	*str;
1378789Smckusick {
1388789Smckusick 	for (; *str ; str++) {
1398789Smckusick 		if (*str > '9' || *str < '0') {
1408789Smckusick 			return(0);
1418789Smckusick 		}
1428789Smckusick 	}
1438789Smckusick 	return(1);
1448789Smckusick }
1458789Smckusick 
1461063Sbill onintr()
1471063Sbill {
1481063Sbill 
1491063Sbill 	if (tty)
1501063Sbill 		chmod(tty, mode);
1511063Sbill 	_exit(1);
1521063Sbill }
1531063Sbill 
1541063Sbill fixtty()
1551063Sbill {
1561063Sbill 	struct stat sbuf;
1571063Sbill 
1581063Sbill 	tty = ttyname(1);
1591063Sbill 	if (tty == 0)
1601063Sbill 		return;
1611063Sbill 	stat(tty, &sbuf);
1621063Sbill 	mode = sbuf.st_mode&0777;
1631063Sbill 	chmod(tty, 0600);
1641063Sbill }
1651063Sbill 
1668789Smckusick /* print -- print file */
1671063Sbill print(fp, argp)
1681063Sbill char *fp;
1691063Sbill char **argp;
1701063Sbill {
1711063Sbill 	extern char *sprintf();
1721063Sbill 	struct stat sbuf;
1731063Sbill 	register sncol;
1741063Sbill 	register char *sheader;
1751063Sbill 	register char *cbuf;
1761063Sbill 	char linebuf[150], *cp;
1771063Sbill 
1781063Sbill 	if (ntflg)
1791063Sbill 		margin = 0;
1801063Sbill 	else
1811063Sbill 		margin = 10;
1821063Sbill 	if (length <= margin)
1831063Sbill 		length = 66;
1841063Sbill 	if (width <= 0)
1851063Sbill 		width = 72;
1861063Sbill 	if (ncol>72 || ncol>width) {
1871063Sbill 		fprintf(stderr, "pr: No room for columns.\n");
1881063Sbill 		done();
1891063Sbill 	}
1901063Sbill 	if (mflg) {
1911063Sbill 		mopen(argp);
1921063Sbill 		ncol = nofile;
1931063Sbill 	}
1941063Sbill 	colw = width/(ncol==0? 1 : ncol);
1951063Sbill 	sncol = ncol;
1961063Sbill 	sheader = header;
1971063Sbill 	plength = length-5;
1981063Sbill 	if (ntflg)
1991063Sbill 		plength = length;
2001063Sbill 	if (--ncol<0)
2011063Sbill 		ncol = 0;
2021063Sbill 	if (mflg)
2031063Sbill 		fp = 0;
2041063Sbill 	if (fp) {
2051063Sbill 		if((file=fopen(fp, "r"))==NULL) {
2061063Sbill 			if (tty==NULL)
2071063Sbill 				fprintf(stderr, "pr: can't open %s\n", fp);
2081063Sbill 			ncol = sncol;
2091063Sbill 			header = sheader;
2101063Sbill 			return;
2111063Sbill 		}
2121063Sbill 		stat(fp, &sbuf);
2131063Sbill 	} else {
2141063Sbill 		file = stdin;
2151063Sbill 		time(&sbuf.st_mtime);
2161063Sbill 	}
2171063Sbill 	if (header == 0)
2181063Sbill 		header = fp?fp:"";
2191063Sbill 	cbuf = ctime(&sbuf.st_mtime);
2201063Sbill 	cbuf[16] = '\0';
2211063Sbill 	cbuf[24] = '\0';
2221063Sbill 	page = 1;
2231063Sbill 	icol = 0;
2241063Sbill 	colp[ncol] = bufp = buffer;
2251063Sbill 	if (mflg==0)
2261063Sbill 		nexbuf();
2271063Sbill 	while (mflg&&nofile || (!mflg)&&tpgetc(ncol)>0) {
2281063Sbill 		if (mflg==0) {
2291063Sbill 			colp[ncol]--;
2301063Sbill 			if (colp[ncol] < buffer)
2311063Sbill 				colp[ncol] = &buffer[BUFS];
2321063Sbill 		}
2331063Sbill 		line = 0;
2341063Sbill 		if (ntflg==0) {
2351063Sbill 			if (fflg) {
2361063Sbill 				/* Assume a ff takes two blank lines at the
2371063Sbill 				   top of the page. */
2381063Sbill 				line = 2;
2391063Sbill 				sprintf(linebuf, "%s %s  %s Page %d\n\n\n",
2401063Sbill 					cbuf+4, cbuf+20, header, page);
2411063Sbill 			} else
2421063Sbill 				sprintf(linebuf, "\n\n%s %s  %s Page %d\n\n\n",
2431063Sbill 					cbuf+4, cbuf+20, header, page);
2441063Sbill 			for(cp=linebuf;*cp;) put(*cp++);
2451063Sbill 		}
2461063Sbill 		putpage();
2471063Sbill 		if (ntflg==0) {
2481063Sbill 			if (fflg)
2491063Sbill 				put('\f');
2501063Sbill 			else
2511063Sbill 				while(line<length)
2521063Sbill 					put('\n');
2531063Sbill 		}
2541063Sbill 		page++;
2551063Sbill 	}
2561063Sbill 	fclose(file);
2571063Sbill 	ncol = sncol;
2581063Sbill 	header = sheader;
2591063Sbill }
2601063Sbill 
2611063Sbill mopen(ap)
2621063Sbill char **ap;
2631063Sbill {
2641063Sbill 	register char **p, *p1;
2651063Sbill 
2661063Sbill 	p = ap;
2671063Sbill 	while((p1 = *p) && p++ <= lastarg) {
2681063Sbill 		if((ifile[nofile]=fopen(p1, "r")) == NULL){
2691063Sbill 			isclosed[nofile] = 1;
2701063Sbill 			nofile--;
2711063Sbill 		}
2721063Sbill 		else
2731063Sbill 			isclosed[nofile] = 0;
2741063Sbill 		if(++nofile>=10) {
2751063Sbill 			fprintf(stderr, "pr: Too many args\n");
2761063Sbill 			done();
2771063Sbill 		}
2781063Sbill 	}
2791063Sbill }
2801063Sbill 
2811063Sbill putpage()
2821063Sbill {
2831063Sbill 	register int lastcol, i, c;
2841063Sbill 	int j;
2851063Sbill 
2861063Sbill 	if (ncol==0) {
2871063Sbill 		while (line<plength) {
2881063Sbill 			while((c = tpgetc(0)) && c!='\n' && c!=FF)
2891063Sbill 				putcp(c);
290*11274Slayer 			if (c==0) break;
2911063Sbill 			putcp('\n');
2921063Sbill 			line++;
2931063Sbill 			if (c==FF)
2941063Sbill 				break;
2951063Sbill 		}
2961063Sbill 		return;
2971063Sbill 	}
2981063Sbill 	colp[0] = colp[ncol];
2991063Sbill 	if (mflg==0) for (i=1; i<=ncol; i++) {
3001063Sbill 		colp[i] = colp[i-1];
3011063Sbill 		for (j = margin; j<length; j++)
3021063Sbill 			while((c=tpgetc(i))!='\n')
3031063Sbill 				if (c==0)
3041063Sbill 					break;
3051063Sbill 	}
3061063Sbill 	while (line<plength) {
3071063Sbill 		lastcol = colw;
3081063Sbill 		for (i=0; i<ncol; i++) {
3091063Sbill 			while ((c=pgetc(i)) && c!='\n')
3101063Sbill 				if (col<lastcol || tabc!=0)
3111063Sbill 					put(c);
3121063Sbill 			if (c==0)
3131063Sbill 				continue;
3141063Sbill 			if (tabc)
3151063Sbill 				put(tabc);
3161063Sbill 			else while (col<lastcol)
3171063Sbill 				put(' ');
3181063Sbill 			lastcol += colw;
3191063Sbill 		}
3201063Sbill 		while ((c = pgetc(ncol)) && c!='\n')
3211063Sbill 			put(c);
3221063Sbill 		put('\n');
3231063Sbill 	}
3241063Sbill }
3251063Sbill 
3261063Sbill nexbuf()
3271063Sbill {
3281063Sbill 	register int n;
3291063Sbill 	register char *rbufp;
3301063Sbill 
3311063Sbill 	rbufp = bufp;
3321063Sbill 	n = &buffer[BUFS] - rbufp;
3331063Sbill 	if (n>512)
3341063Sbill 		n = 512;
3351063Sbill 	if((n=fread(rbufp,1,n,file)) <= 0){
3361063Sbill 		fclose(file);
3371063Sbill 		*rbufp = 0376;
3381063Sbill 	}
3391063Sbill 	else {
3401063Sbill 		rbufp += n;
3411063Sbill 		if (rbufp >= &buffer[BUFS])
3421063Sbill 			rbufp = buffer;
3431063Sbill 		*rbufp = 0375;
3441063Sbill 	}
3451063Sbill 	bufp = rbufp;
3461063Sbill }
3471063Sbill 
3481063Sbill tpgetc(ai)
3491063Sbill {
3501063Sbill 	register char **p;
3511063Sbill 	register int c, i;
3521063Sbill 
3531063Sbill 	i = ai;
3541063Sbill 	if (mflg) {
3551063Sbill 		if((c=getc(ifile[i])) == EOF) {
3561063Sbill 			if (isclosed[i]==0) {
3571063Sbill 				isclosed[i] = 1;
3581063Sbill 				if (--nofile <= 0)
3591063Sbill 					return(0);
3601063Sbill 			}
3611063Sbill 			return('\n');
3621063Sbill 		}
3631063Sbill 		if (c==FF && ncol>0)
3641063Sbill 			c = '\n';
3651063Sbill 		return(c);
3661063Sbill 	}
3671063Sbill loop:
3681063Sbill 	c = **(p = &colp[i]) & 0377;
3691063Sbill 	if (c == 0375) {
3701063Sbill 		nexbuf();
3711063Sbill 		c = **p & 0377;
3721063Sbill 	}
3731063Sbill 	if (c == 0376)
3741063Sbill 		return(0);
3751063Sbill 	(*p)++;
3761063Sbill 	if (*p >= &buffer[BUFS])
3771063Sbill 		*p = buffer;
3781063Sbill 	if (c==0)
3791063Sbill 		goto loop;
3801063Sbill 	return(c);
3811063Sbill }
3821063Sbill 
3831063Sbill pgetc(i)
3841063Sbill {
3851063Sbill 	register int c;
3861063Sbill 
3871063Sbill 	if (peekc) {
3881063Sbill 		c = peekc;
3891063Sbill 		peekc = 0;
3901063Sbill 	} else
3911063Sbill 		c = tpgetc(i);
3921063Sbill 	if (tabc)
3931063Sbill 		return(c);
3941063Sbill 	switch (c) {
3951063Sbill 
3961063Sbill 	case '\t':
3971063Sbill 		icol++;
3981063Sbill 		if ((icol&07) != 0)
3991063Sbill 			peekc = '\t';
4001063Sbill 		return(' ');
4011063Sbill 
4021063Sbill 	case '\n':
4031063Sbill 		icol = 0;
4041063Sbill 		break;
4051063Sbill 
4061063Sbill 	case 010:
4071063Sbill 	case 033:
4081063Sbill 		icol--;
4091063Sbill 		break;
4101063Sbill 	}
4111063Sbill 	if (c >= ' ')
4121063Sbill 		icol++;
4131063Sbill 	return(c);
4141063Sbill }
4151063Sbill put(ac)
4161063Sbill {
4171063Sbill 	register int ns, c;
4181063Sbill 
4191063Sbill 	c = ac;
4201063Sbill 	if (tabc) {
4211063Sbill 		putcp(c);
4221063Sbill 		if (c=='\n')
4231063Sbill 			line++;
4241063Sbill 		return;
4251063Sbill 	}
4261063Sbill 	switch (c) {
4271063Sbill 
4281063Sbill 	case ' ':
4291063Sbill 		nspace++;
4301063Sbill 		col++;
4311063Sbill 		return;
4321063Sbill 
4331063Sbill 	case '\n':
4341063Sbill 		col = 0;
4351063Sbill 		nspace = 0;
4361063Sbill 		line++;
4371063Sbill 		break;
4381063Sbill 
4391063Sbill 	case 010:
4401063Sbill 	case 033:
4411063Sbill 		if (--col<0)
4421063Sbill 			col = 0;
4431063Sbill 		if (--nspace<0)
4441063Sbill 			nspace = 0;
4451063Sbill 
4461063Sbill 	}
4471063Sbill 	while(nspace) {
4481063Sbill 		if (nspace>2 && col > (ns=((col-nspace)|07))) {
4491063Sbill 			nspace = col-ns-1;
4501063Sbill 			putcp('\t');
4511063Sbill 		} else {
4521063Sbill 			nspace--;
4531063Sbill 			putcp(' ');
4541063Sbill 		}
4551063Sbill 	}
4561063Sbill 	if (c >= ' ')
4571063Sbill 		col++;
4581063Sbill 	putcp(c);
4591063Sbill }
460