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