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