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 9 char 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 15 static char sccsid[] = "@(#)pr.c 4.9 (Berkeley) 04/18/91"; 16 #endif /* not lint */ 17 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 31 int ncol = 1; 32 char *header; 33 int col; 34 int icol; 35 FILE *file; 36 char *bufp; 37 #define BUFS 9000 /* at least 66 * 132 */ 38 char buffer[BUFS]; /* for multi-column output */ 39 char obuf[BUFSIZ]; 40 #define FF 014 41 int line; 42 char *colp[72]; 43 int nofile; 44 char isclosed[10]; 45 FILE *ifile[10]; 46 char **lastarg; 47 int peekc; 48 int fpage; 49 int page; 50 int colw; 51 int nspace; 52 int width = 72; 53 int length = 66; 54 int plength = 61; 55 int margin = 10; 56 int ntflg; 57 int fflg; 58 int mflg; 59 int tabc; 60 char *tty; 61 int mode; 62 char *ttyname(); 63 char *ctime(); 64 65 main(argc, argv) 66 char **argv; 67 { 68 int nfdone; 69 void onintr(); 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) { 80 case 'h': /* define page header */ 81 if (argc>=2) { 82 header = *++argv; 83 argc--; 84 } 85 continue; 86 87 case 't': /* don't print page headers */ 88 ntflg++; 89 continue; 90 91 case 'f': /* use form feeds */ 92 fflg++; 93 plength = 60; 94 continue; 95 96 case 'l': /* length of page */ 97 length = atoi(++*argv); 98 continue; 99 100 case 'w': /* width of page */ 101 width = atoi(++*argv); 102 continue; 103 104 case 's': /* col separator */ 105 if (*++*argv) 106 tabc = **argv; 107 else 108 tabc = '\t'; 109 continue; 110 111 case 'm': /* all files at once */ 112 mflg++; 113 continue; 114 115 default: 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 } 125 continue; 126 } 127 } else if (**argv == '+') { /* start at page ++*argv */ 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 141 done() 142 { 143 144 if (tty) 145 chmod(tty, mode); 146 exit(0); 147 } 148 149 /* numeric -- returns 1 if str is numeric, elsewise 0 */ 150 numeric(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 161 void 162 onintr() 163 { 164 165 if (tty) 166 chmod(tty, mode); 167 _exit(1); 168 } 169 170 fixtty() 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 182 /* print -- print file */ 183 print(fp, argp) 184 char *fp; 185 char **argp; 186 { 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) 222 perror(fp); 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) 246 colp[ncol] = &buffer[BUFS - 1]; 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; 254 (void)sprintf(linebuf, "%s %s %s Page %d\n\n\n", 255 cbuf+4, cbuf+20, header, page); 256 } else 257 (void)sprintf(linebuf, "\n\n%s %s %s Page %d\n\n\n", 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 276 mopen(ap) 277 char **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 296 putpage() 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); 305 if (c==0) break; 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 341 nexbuf() 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 363 tpgetc(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 } 382 loop: 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 398 pgetc(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 } 430 put(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 } 475