xref: /csrg-svn/old/pr/pr.c (revision 1063)
1*1063Sbill static char *sccsid = "@(#)pr.c	4.1 (Berkeley) 10/01/80";
2*1063Sbill /*
3*1063Sbill  *   print file with headings
4*1063Sbill  *  2+head+2+page[56]+5
5*1063Sbill  */
6*1063Sbill 
7*1063Sbill #include <stdio.h>
8*1063Sbill #include <signal.h>
9*1063Sbill #include <sys/types.h>
10*1063Sbill #include <sys/stat.h>
11*1063Sbill 
12*1063Sbill /* Making putcp a macro sped things up by 14%. */
13*1063Sbill #define putcp(c)  if (page >= fpage) putchar(c)
14*1063Sbill 
15*1063Sbill int	ncol	= 1;
16*1063Sbill char	*header;
17*1063Sbill int	col;
18*1063Sbill int	icol;
19*1063Sbill FILE	*file;
20*1063Sbill char	*bufp;
21*1063Sbill #define	BUFS	6720
22*1063Sbill char	buffer[BUFS];	/* for multi-column output */
23*1063Sbill char	obuf[BUFSIZ];
24*1063Sbill #define	FF	014
25*1063Sbill int	line;
26*1063Sbill char	*colp[72];
27*1063Sbill int	nofile;
28*1063Sbill char	isclosed[10];
29*1063Sbill FILE	*ifile[10];
30*1063Sbill char	**lastarg;
31*1063Sbill int	peekc;
32*1063Sbill int	fpage;
33*1063Sbill int	page;
34*1063Sbill int	colw;
35*1063Sbill int	nspace;
36*1063Sbill int	width	= 72;
37*1063Sbill int	length	= 66;
38*1063Sbill int	plength = 61;
39*1063Sbill int	margin	= 10;
40*1063Sbill int	ntflg;
41*1063Sbill int	fflg;
42*1063Sbill int	mflg;
43*1063Sbill int	tabc;
44*1063Sbill char	*tty;
45*1063Sbill int	mode;
46*1063Sbill char	*ttyname();
47*1063Sbill char	*ctime();
48*1063Sbill 
49*1063Sbill main(argc, argv)
50*1063Sbill char **argv;
51*1063Sbill {
52*1063Sbill 	int nfdone;
53*1063Sbill 	int onintr();
54*1063Sbill 
55*1063Sbill 	setbuf(stdout, obuf);
56*1063Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
57*1063Sbill 		signal(SIGINT, onintr);
58*1063Sbill 	lastarg = &argv[argc-1];
59*1063Sbill 	fixtty();
60*1063Sbill 	for (nfdone=0; argc>1; argc--) {
61*1063Sbill 		argv++;
62*1063Sbill 		if (**argv == '-') {
63*1063Sbill 			switch (*++*argv) {
64*1063Sbill 			case 'h':
65*1063Sbill 				if (argc>=2) {
66*1063Sbill 					header = *++argv;
67*1063Sbill 					argc--;
68*1063Sbill 				}
69*1063Sbill 				continue;
70*1063Sbill 
71*1063Sbill 			case 't':
72*1063Sbill 				ntflg++;
73*1063Sbill 				continue;
74*1063Sbill 
75*1063Sbill 			case 'f':
76*1063Sbill 				fflg++;
77*1063Sbill 				plength = 60;
78*1063Sbill 				continue;
79*1063Sbill 
80*1063Sbill 			case 'l':
81*1063Sbill 				length = atoi(++*argv);
82*1063Sbill 				continue;
83*1063Sbill 
84*1063Sbill 			case 'w':
85*1063Sbill 				width = atoi(++*argv);
86*1063Sbill 				continue;
87*1063Sbill 
88*1063Sbill 			case 's':
89*1063Sbill 				if (*++*argv)
90*1063Sbill 					tabc = **argv;
91*1063Sbill 				else
92*1063Sbill 					tabc = '\t';
93*1063Sbill 				continue;
94*1063Sbill 
95*1063Sbill 			case 'm':
96*1063Sbill 				mflg++;
97*1063Sbill 				continue;
98*1063Sbill 
99*1063Sbill 			default:
100*1063Sbill 				ncol = atoi(*argv);
101*1063Sbill 				continue;
102*1063Sbill 			}
103*1063Sbill 		} else if (**argv == '+') {
104*1063Sbill 			fpage = atoi(++*argv);
105*1063Sbill 		} else {
106*1063Sbill 			print(*argv, argv);
107*1063Sbill 			nfdone++;
108*1063Sbill 			if (mflg)
109*1063Sbill 				break;
110*1063Sbill 		}
111*1063Sbill 	}
112*1063Sbill 	if (nfdone==0)
113*1063Sbill 		print((char *)0, (char **)0);
114*1063Sbill 	done();
115*1063Sbill }
116*1063Sbill 
117*1063Sbill done()
118*1063Sbill {
119*1063Sbill 
120*1063Sbill 	if (tty)
121*1063Sbill 		chmod(tty, mode);
122*1063Sbill 	exit(0);
123*1063Sbill }
124*1063Sbill 
125*1063Sbill onintr()
126*1063Sbill {
127*1063Sbill 
128*1063Sbill 	if (tty)
129*1063Sbill 		chmod(tty, mode);
130*1063Sbill 	_exit(1);
131*1063Sbill }
132*1063Sbill 
133*1063Sbill fixtty()
134*1063Sbill {
135*1063Sbill 	struct stat sbuf;
136*1063Sbill 
137*1063Sbill 	tty = ttyname(1);
138*1063Sbill 	if (tty == 0)
139*1063Sbill 		return;
140*1063Sbill 	stat(tty, &sbuf);
141*1063Sbill 	mode = sbuf.st_mode&0777;
142*1063Sbill 	chmod(tty, 0600);
143*1063Sbill }
144*1063Sbill 
145*1063Sbill print(fp, argp)
146*1063Sbill char *fp;
147*1063Sbill char **argp;
148*1063Sbill {
149*1063Sbill 	extern char *sprintf();
150*1063Sbill 	struct stat sbuf;
151*1063Sbill 	register sncol;
152*1063Sbill 	register char *sheader;
153*1063Sbill 	register char *cbuf;
154*1063Sbill 	char linebuf[150], *cp;
155*1063Sbill 
156*1063Sbill 	if (ntflg)
157*1063Sbill 		margin = 0;
158*1063Sbill 	else
159*1063Sbill 		margin = 10;
160*1063Sbill 	if (length <= margin)
161*1063Sbill 		length = 66;
162*1063Sbill 	if (width <= 0)
163*1063Sbill 		width = 72;
164*1063Sbill 	if (ncol>72 || ncol>width) {
165*1063Sbill 		fprintf(stderr, "pr: No room for columns.\n");
166*1063Sbill 		done();
167*1063Sbill 	}
168*1063Sbill 	if (mflg) {
169*1063Sbill 		mopen(argp);
170*1063Sbill 		ncol = nofile;
171*1063Sbill 	}
172*1063Sbill 	colw = width/(ncol==0? 1 : ncol);
173*1063Sbill 	sncol = ncol;
174*1063Sbill 	sheader = header;
175*1063Sbill 	plength = length-5;
176*1063Sbill 	if (ntflg)
177*1063Sbill 		plength = length;
178*1063Sbill 	if (--ncol<0)
179*1063Sbill 		ncol = 0;
180*1063Sbill 	if (mflg)
181*1063Sbill 		fp = 0;
182*1063Sbill 	if (fp) {
183*1063Sbill 		if((file=fopen(fp, "r"))==NULL) {
184*1063Sbill 			if (tty==NULL)
185*1063Sbill 				fprintf(stderr, "pr: can't open %s\n", fp);
186*1063Sbill 			ncol = sncol;
187*1063Sbill 			header = sheader;
188*1063Sbill 			return;
189*1063Sbill 		}
190*1063Sbill 		stat(fp, &sbuf);
191*1063Sbill 	} else {
192*1063Sbill 		file = stdin;
193*1063Sbill 		time(&sbuf.st_mtime);
194*1063Sbill 	}
195*1063Sbill 	if (header == 0)
196*1063Sbill 		header = fp?fp:"";
197*1063Sbill 	cbuf = ctime(&sbuf.st_mtime);
198*1063Sbill 	cbuf[16] = '\0';
199*1063Sbill 	cbuf[24] = '\0';
200*1063Sbill 	page = 1;
201*1063Sbill 	icol = 0;
202*1063Sbill 	colp[ncol] = bufp = buffer;
203*1063Sbill 	if (mflg==0)
204*1063Sbill 		nexbuf();
205*1063Sbill 	while (mflg&&nofile || (!mflg)&&tpgetc(ncol)>0) {
206*1063Sbill 		if (mflg==0) {
207*1063Sbill 			colp[ncol]--;
208*1063Sbill 			if (colp[ncol] < buffer)
209*1063Sbill 				colp[ncol] = &buffer[BUFS];
210*1063Sbill 		}
211*1063Sbill 		line = 0;
212*1063Sbill 		if (ntflg==0) {
213*1063Sbill 			if (fflg) {
214*1063Sbill 				/* Assume a ff takes two blank lines at the
215*1063Sbill 				   top of the page. */
216*1063Sbill 				line = 2;
217*1063Sbill 				sprintf(linebuf, "%s %s  %s Page %d\n\n\n",
218*1063Sbill 					cbuf+4, cbuf+20, header, page);
219*1063Sbill 			} else
220*1063Sbill 				sprintf(linebuf, "\n\n%s %s  %s Page %d\n\n\n",
221*1063Sbill 					cbuf+4, cbuf+20, header, page);
222*1063Sbill 			for(cp=linebuf;*cp;) put(*cp++);
223*1063Sbill 		}
224*1063Sbill 		putpage();
225*1063Sbill 		if (ntflg==0) {
226*1063Sbill 			if (fflg)
227*1063Sbill 				put('\f');
228*1063Sbill 			else
229*1063Sbill 				while(line<length)
230*1063Sbill 					put('\n');
231*1063Sbill 		}
232*1063Sbill 		page++;
233*1063Sbill 	}
234*1063Sbill 	fclose(file);
235*1063Sbill 	ncol = sncol;
236*1063Sbill 	header = sheader;
237*1063Sbill }
238*1063Sbill 
239*1063Sbill mopen(ap)
240*1063Sbill char **ap;
241*1063Sbill {
242*1063Sbill 	register char **p, *p1;
243*1063Sbill 
244*1063Sbill 	p = ap;
245*1063Sbill 	while((p1 = *p) && p++ <= lastarg) {
246*1063Sbill 		if((ifile[nofile]=fopen(p1, "r")) == NULL){
247*1063Sbill 			isclosed[nofile] = 1;
248*1063Sbill 			nofile--;
249*1063Sbill 		}
250*1063Sbill 		else
251*1063Sbill 			isclosed[nofile] = 0;
252*1063Sbill 		if(++nofile>=10) {
253*1063Sbill 			fprintf(stderr, "pr: Too many args\n");
254*1063Sbill 			done();
255*1063Sbill 		}
256*1063Sbill 	}
257*1063Sbill }
258*1063Sbill 
259*1063Sbill putpage()
260*1063Sbill {
261*1063Sbill 	register int lastcol, i, c;
262*1063Sbill 	int j;
263*1063Sbill 
264*1063Sbill 	if (ncol==0) {
265*1063Sbill 		while (line<plength) {
266*1063Sbill 			while((c = tpgetc(0)) && c!='\n' && c!=FF)
267*1063Sbill 				putcp(c);
268*1063Sbill 			putcp('\n');
269*1063Sbill 			line++;
270*1063Sbill 			if (c==FF)
271*1063Sbill 				break;
272*1063Sbill 		}
273*1063Sbill 		return;
274*1063Sbill 	}
275*1063Sbill 	colp[0] = colp[ncol];
276*1063Sbill 	if (mflg==0) for (i=1; i<=ncol; i++) {
277*1063Sbill 		colp[i] = colp[i-1];
278*1063Sbill 		for (j = margin; j<length; j++)
279*1063Sbill 			while((c=tpgetc(i))!='\n')
280*1063Sbill 				if (c==0)
281*1063Sbill 					break;
282*1063Sbill 	}
283*1063Sbill 	while (line<plength) {
284*1063Sbill 		lastcol = colw;
285*1063Sbill 		for (i=0; i<ncol; i++) {
286*1063Sbill 			while ((c=pgetc(i)) && c!='\n')
287*1063Sbill 				if (col<lastcol || tabc!=0)
288*1063Sbill 					put(c);
289*1063Sbill 			if (c==0)
290*1063Sbill 				continue;
291*1063Sbill 			if (tabc)
292*1063Sbill 				put(tabc);
293*1063Sbill 			else while (col<lastcol)
294*1063Sbill 				put(' ');
295*1063Sbill 			lastcol += colw;
296*1063Sbill 		}
297*1063Sbill 		while ((c = pgetc(ncol)) && c!='\n')
298*1063Sbill 			put(c);
299*1063Sbill 		put('\n');
300*1063Sbill 	}
301*1063Sbill }
302*1063Sbill 
303*1063Sbill nexbuf()
304*1063Sbill {
305*1063Sbill 	register int n;
306*1063Sbill 	register char *rbufp;
307*1063Sbill 
308*1063Sbill 	rbufp = bufp;
309*1063Sbill 	n = &buffer[BUFS] - rbufp;
310*1063Sbill 	if (n>512)
311*1063Sbill 		n = 512;
312*1063Sbill 	if((n=fread(rbufp,1,n,file)) <= 0){
313*1063Sbill 		fclose(file);
314*1063Sbill 		*rbufp = 0376;
315*1063Sbill 	}
316*1063Sbill 	else {
317*1063Sbill 		rbufp += n;
318*1063Sbill 		if (rbufp >= &buffer[BUFS])
319*1063Sbill 			rbufp = buffer;
320*1063Sbill 		*rbufp = 0375;
321*1063Sbill 	}
322*1063Sbill 	bufp = rbufp;
323*1063Sbill }
324*1063Sbill 
325*1063Sbill tpgetc(ai)
326*1063Sbill {
327*1063Sbill 	register char **p;
328*1063Sbill 	register int c, i;
329*1063Sbill 
330*1063Sbill 	i = ai;
331*1063Sbill 	if (mflg) {
332*1063Sbill 		if((c=getc(ifile[i])) == EOF) {
333*1063Sbill 			if (isclosed[i]==0) {
334*1063Sbill 				isclosed[i] = 1;
335*1063Sbill 				if (--nofile <= 0)
336*1063Sbill 					return(0);
337*1063Sbill 			}
338*1063Sbill 			return('\n');
339*1063Sbill 		}
340*1063Sbill 		if (c==FF && ncol>0)
341*1063Sbill 			c = '\n';
342*1063Sbill 		return(c);
343*1063Sbill 	}
344*1063Sbill loop:
345*1063Sbill 	c = **(p = &colp[i]) & 0377;
346*1063Sbill 	if (c == 0375) {
347*1063Sbill 		nexbuf();
348*1063Sbill 		c = **p & 0377;
349*1063Sbill 	}
350*1063Sbill 	if (c == 0376)
351*1063Sbill 		return(0);
352*1063Sbill 	(*p)++;
353*1063Sbill 	if (*p >= &buffer[BUFS])
354*1063Sbill 		*p = buffer;
355*1063Sbill 	if (c==0)
356*1063Sbill 		goto loop;
357*1063Sbill 	return(c);
358*1063Sbill }
359*1063Sbill 
360*1063Sbill pgetc(i)
361*1063Sbill {
362*1063Sbill 	register int c;
363*1063Sbill 
364*1063Sbill 	if (peekc) {
365*1063Sbill 		c = peekc;
366*1063Sbill 		peekc = 0;
367*1063Sbill 	} else
368*1063Sbill 		c = tpgetc(i);
369*1063Sbill 	if (tabc)
370*1063Sbill 		return(c);
371*1063Sbill 	switch (c) {
372*1063Sbill 
373*1063Sbill 	case '\t':
374*1063Sbill 		icol++;
375*1063Sbill 		if ((icol&07) != 0)
376*1063Sbill 			peekc = '\t';
377*1063Sbill 		return(' ');
378*1063Sbill 
379*1063Sbill 	case '\n':
380*1063Sbill 		icol = 0;
381*1063Sbill 		break;
382*1063Sbill 
383*1063Sbill 	case 010:
384*1063Sbill 	case 033:
385*1063Sbill 		icol--;
386*1063Sbill 		break;
387*1063Sbill 	}
388*1063Sbill 	if (c >= ' ')
389*1063Sbill 		icol++;
390*1063Sbill 	return(c);
391*1063Sbill }
392*1063Sbill put(ac)
393*1063Sbill {
394*1063Sbill 	register int ns, c;
395*1063Sbill 
396*1063Sbill 	c = ac;
397*1063Sbill 	if (tabc) {
398*1063Sbill 		putcp(c);
399*1063Sbill 		if (c=='\n')
400*1063Sbill 			line++;
401*1063Sbill 		return;
402*1063Sbill 	}
403*1063Sbill 	switch (c) {
404*1063Sbill 
405*1063Sbill 	case ' ':
406*1063Sbill 		nspace++;
407*1063Sbill 		col++;
408*1063Sbill 		return;
409*1063Sbill 
410*1063Sbill 	case '\n':
411*1063Sbill 		col = 0;
412*1063Sbill 		nspace = 0;
413*1063Sbill 		line++;
414*1063Sbill 		break;
415*1063Sbill 
416*1063Sbill 	case 010:
417*1063Sbill 	case 033:
418*1063Sbill 		if (--col<0)
419*1063Sbill 			col = 0;
420*1063Sbill 		if (--nspace<0)
421*1063Sbill 			nspace = 0;
422*1063Sbill 
423*1063Sbill 	}
424*1063Sbill 	while(nspace) {
425*1063Sbill 		if (nspace>2 && col > (ns=((col-nspace)|07))) {
426*1063Sbill 			nspace = col-ns-1;
427*1063Sbill 			putcp('\t');
428*1063Sbill 		} else {
429*1063Sbill 			nspace--;
430*1063Sbill 			putcp(' ');
431*1063Sbill 		}
432*1063Sbill 	}
433*1063Sbill 	if (c >= ' ')
434*1063Sbill 		col++;
435*1063Sbill 	putcp(c);
436*1063Sbill }
437