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