1 static char *sccsid = "@(#)pr.c 4.7 (Berkeley) 10/22/87"; 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 int 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 onintr() 147 { 148 149 if (tty) 150 chmod(tty, mode); 151 _exit(1); 152 } 153 154 fixtty() 155 { 156 struct stat sbuf; 157 158 tty = ttyname(1); 159 if (tty == 0) 160 return; 161 stat(tty, &sbuf); 162 mode = sbuf.st_mode&0777; 163 chmod(tty, 0600); 164 } 165 166 /* print -- print file */ 167 print(fp, argp) 168 char *fp; 169 char **argp; 170 { 171 struct stat sbuf; 172 register sncol; 173 register char *sheader; 174 register char *cbuf; 175 char linebuf[150], *cp; 176 177 if (ntflg) 178 margin = 0; 179 else 180 margin = 10; 181 if (length <= margin) 182 length = 66; 183 if (width <= 0) 184 width = 72; 185 if (ncol>72 || ncol>width) { 186 fprintf(stderr, "pr: No room for columns.\n"); 187 done(); 188 } 189 if (mflg) { 190 mopen(argp); 191 ncol = nofile; 192 } 193 colw = width/(ncol==0? 1 : ncol); 194 sncol = ncol; 195 sheader = header; 196 plength = length-5; 197 if (ntflg) 198 plength = length; 199 if (--ncol<0) 200 ncol = 0; 201 if (mflg) 202 fp = 0; 203 if (fp) { 204 if((file=fopen(fp, "r"))==NULL) { 205 if (tty==NULL) 206 perror(fp); 207 ncol = sncol; 208 header = sheader; 209 return; 210 } 211 stat(fp, &sbuf); 212 } else { 213 file = stdin; 214 time(&sbuf.st_mtime); 215 } 216 if (header == 0) 217 header = fp?fp:""; 218 cbuf = ctime(&sbuf.st_mtime); 219 cbuf[16] = '\0'; 220 cbuf[24] = '\0'; 221 page = 1; 222 icol = 0; 223 colp[ncol] = bufp = buffer; 224 if (mflg==0) 225 nexbuf(); 226 while (mflg&&nofile || (!mflg)&&tpgetc(ncol)>0) { 227 if (mflg==0) { 228 colp[ncol]--; 229 if (colp[ncol] < buffer) 230 colp[ncol] = &buffer[BUFS - 1]; 231 } 232 line = 0; 233 if (ntflg==0) { 234 if (fflg) { 235 /* Assume a ff takes two blank lines at the 236 top of the page. */ 237 line = 2; 238 (void)sprintf(linebuf, "%s %s %s Page %d\n\n\n", 239 cbuf+4, cbuf+20, header, page); 240 } else 241 (void)sprintf(linebuf, "\n\n%s %s %s Page %d\n\n\n", 242 cbuf+4, cbuf+20, header, page); 243 for(cp=linebuf;*cp;) put(*cp++); 244 } 245 putpage(); 246 if (ntflg==0) { 247 if (fflg) 248 put('\f'); 249 else 250 while(line<length) 251 put('\n'); 252 } 253 page++; 254 } 255 fclose(file); 256 ncol = sncol; 257 header = sheader; 258 } 259 260 mopen(ap) 261 char **ap; 262 { 263 register char **p, *p1; 264 265 p = ap; 266 while((p1 = *p) && p++ <= lastarg) { 267 if((ifile[nofile]=fopen(p1, "r")) == NULL){ 268 isclosed[nofile] = 1; 269 nofile--; 270 } 271 else 272 isclosed[nofile] = 0; 273 if(++nofile>=10) { 274 fprintf(stderr, "pr: Too many args\n"); 275 done(); 276 } 277 } 278 } 279 280 putpage() 281 { 282 register int lastcol, i, c; 283 int j; 284 285 if (ncol==0) { 286 while (line<plength) { 287 while((c = tpgetc(0)) && c!='\n' && c!=FF) 288 putcp(c); 289 if (c==0) break; 290 putcp('\n'); 291 line++; 292 if (c==FF) 293 break; 294 } 295 return; 296 } 297 colp[0] = colp[ncol]; 298 if (mflg==0) for (i=1; i<=ncol; i++) { 299 colp[i] = colp[i-1]; 300 for (j = margin; j<length; j++) 301 while((c=tpgetc(i))!='\n') 302 if (c==0) 303 break; 304 } 305 while (line<plength) { 306 lastcol = colw; 307 for (i=0; i<ncol; i++) { 308 while ((c=pgetc(i)) && c!='\n') 309 if (col<lastcol || tabc!=0) 310 put(c); 311 if (c==0) 312 continue; 313 if (tabc) 314 put(tabc); 315 else while (col<lastcol) 316 put(' '); 317 lastcol += colw; 318 } 319 while ((c = pgetc(ncol)) && c!='\n') 320 put(c); 321 put('\n'); 322 } 323 } 324 325 nexbuf() 326 { 327 register int n; 328 register char *rbufp; 329 330 rbufp = bufp; 331 n = &buffer[BUFS] - rbufp; 332 if (n>512) 333 n = 512; 334 if((n=fread(rbufp,1,n,file)) <= 0){ 335 fclose(file); 336 *rbufp = 0376; 337 } 338 else { 339 rbufp += n; 340 if (rbufp >= &buffer[BUFS]) 341 rbufp = buffer; 342 *rbufp = 0375; 343 } 344 bufp = rbufp; 345 } 346 347 tpgetc(ai) 348 { 349 register char **p; 350 register int c, i; 351 352 i = ai; 353 if (mflg) { 354 if((c=getc(ifile[i])) == EOF) { 355 if (isclosed[i]==0) { 356 isclosed[i] = 1; 357 if (--nofile <= 0) 358 return(0); 359 } 360 return('\n'); 361 } 362 if (c==FF && ncol>0) 363 c = '\n'; 364 return(c); 365 } 366 loop: 367 c = **(p = &colp[i]) & 0377; 368 if (c == 0375) { 369 nexbuf(); 370 c = **p & 0377; 371 } 372 if (c == 0376) 373 return(0); 374 (*p)++; 375 if (*p >= &buffer[BUFS]) 376 *p = buffer; 377 if (c==0) 378 goto loop; 379 return(c); 380 } 381 382 pgetc(i) 383 { 384 register int c; 385 386 if (peekc) { 387 c = peekc; 388 peekc = 0; 389 } else 390 c = tpgetc(i); 391 if (tabc) 392 return(c); 393 switch (c) { 394 395 case '\t': 396 icol++; 397 if ((icol&07) != 0) 398 peekc = '\t'; 399 return(' '); 400 401 case '\n': 402 icol = 0; 403 break; 404 405 case 010: 406 case 033: 407 icol--; 408 break; 409 } 410 if (c >= ' ') 411 icol++; 412 return(c); 413 } 414 put(ac) 415 { 416 register int ns, c; 417 418 c = ac; 419 if (tabc) { 420 putcp(c); 421 if (c=='\n') 422 line++; 423 return; 424 } 425 switch (c) { 426 427 case ' ': 428 nspace++; 429 col++; 430 return; 431 432 case '\n': 433 col = 0; 434 nspace = 0; 435 line++; 436 break; 437 438 case 010: 439 case 033: 440 if (--col<0) 441 col = 0; 442 if (--nspace<0) 443 nspace = 0; 444 445 } 446 while(nspace) { 447 if (nspace>2 && col > (ns=((col-nspace)|07))) { 448 nspace = col-ns-1; 449 putcp('\t'); 450 } else { 451 nspace--; 452 putcp(' '); 453 } 454 } 455 if (c >= ' ') 456 col++; 457 putcp(c); 458 } 459