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