1 static char *sccsid = "@(#)pr.c 4.2 (Berkeley) 10/21/82"; 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 6720 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 extern char *sprintf(); 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 fprintf(stderr, "pr: can't open %s\n", 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]; 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 sprintf(linebuf, "%s %s %s Page %d\n\n\n", 240 cbuf+4, cbuf+20, header, page); 241 } else 242 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 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