Annotation of src/usr.bin/pr/pr.c, Revision 1.1
1.1 ! deraadt 1: /*-
! 2: * Copyright (c) 1991 Keith Muller.
! 3: * Copyright (c) 1993
! 4: * The Regents of the University of California. All rights reserved.
! 5: *
! 6: * This code is derived from software contributed to Berkeley by
! 7: * Keith Muller of the University of California, San Diego.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. All advertising materials mentioning features or use of this software
! 18: * must display the following acknowledgement:
! 19: * This product includes software developed by the University of
! 20: * California, Berkeley and its contributors.
! 21: * 4. Neither the name of the University nor the names of its contributors
! 22: * may be used to endorse or promote products derived from this software
! 23: * without specific prior written permission.
! 24: *
! 25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 35: * SUCH DAMAGE.
! 36: */
! 37:
! 38: #ifndef lint
! 39: static char copyright[] =
! 40: "@(#) Copyright (c) 1993\n\
! 41: The Regents of the University of California. All rights reserved.\n";
! 42: #endif /* not lint */
! 43:
! 44: #ifndef lint
! 45: /* from: static char sccsid[] = "@(#)pr.c 8.1 (Berkeley) 6/6/93"; */
! 46: static char *rcsid = "$Id: pr.c,v 1.3 1995/06/07 16:10:11 cgd Exp $";
! 47: #endif /* not lint */
! 48:
! 49: #include <sys/types.h>
! 50: #include <sys/time.h>
! 51: #include <sys/stat.h>
! 52:
! 53: #include <ctype.h>
! 54: #include <errno.h>
! 55: #include <signal.h>
! 56: #include <stdio.h>
! 57: #include <stdlib.h>
! 58: #include <string.h>
! 59: #include <unistd.h>
! 60:
! 61: #include "pr.h"
! 62: #include "extern.h"
! 63:
! 64: /*
! 65: * pr: a printing and pagination filter. If multiple input files
! 66: * are specified, each is read, formatted, and written to standard
! 67: * output. By default, input is seperated into 66-line pages, each
! 68: * with a header that includes the page number, date, time and the
! 69: * files pathname.
! 70: *
! 71: * Complies with posix P1003.2/D11
! 72: */
! 73:
! 74: /*
! 75: * parameter variables
! 76: */
! 77: int pgnm; /* starting page number */
! 78: int clcnt; /* number of columns */
! 79: int colwd; /* column data width - multiple columns */
! 80: int across; /* mult col flag; write across page */
! 81: int dspace; /* double space flag */
! 82: char inchar; /* expand input char */
! 83: int ingap; /* expand input gap */
! 84: int formfeed; /* use formfeed as trailer */
! 85: char *header; /* header name instead of file name */
! 86: char ochar; /* contract output char */
! 87: int ogap; /* contract output gap */
! 88: int lines; /* number of lines per page */
! 89: int merge; /* merge multiple files in output */
! 90: char nmchar; /* line numbering append char */
! 91: int nmwd; /* width of line number field */
! 92: int offst; /* number of page offset spaces */
! 93: int nodiag; /* do not report file open errors */
! 94: char schar; /* text column separation character */
! 95: int sflag; /* -s option for multiple columns */
! 96: int nohead; /* do not write head and trailer */
! 97: int pgwd; /* page width with multiple col output */
! 98: char *timefrmt; /* time conversion string */
! 99:
! 100: /*
! 101: * misc globals
! 102: */
! 103: FILE *err; /* error message file pointer */
! 104: int addone; /* page length is odd with double space */
! 105: int errcnt; /* error count on file processing */
! 106: char digs[] = "0123456789"; /* page number translation map */
! 107:
! 108: int
! 109: main(argc, argv)
! 110: int argc;
! 111: char *argv[];
! 112: {
! 113: int ret_val;
! 114:
! 115: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
! 116: (void)signal(SIGINT, terminate);
! 117: ret_val = setup(argc, argv);
! 118: if (!ret_val) {
! 119: /*
! 120: * select the output format based on options
! 121: */
! 122: if (merge)
! 123: ret_val = mulfile(argc, argv);
! 124: else if (clcnt == 1)
! 125: ret_val = onecol(argc, argv);
! 126: else if (across)
! 127: ret_val = horzcol(argc, argv);
! 128: else
! 129: ret_val = vertcol(argc, argv);
! 130: } else
! 131: usage();
! 132: flsh_errs();
! 133: if (errcnt || ret_val)
! 134: exit(1);
! 135: return(0);
! 136: }
! 137:
! 138: /*
! 139: * onecol: print files with only one column of output.
! 140: * Line length is unlimited.
! 141: */
! 142: int
! 143: onecol(argc, argv)
! 144: int argc;
! 145: char *argv[];
! 146: {
! 147: register int cnt = -1;
! 148: register int off;
! 149: register int lrgln;
! 150: register int linecnt;
! 151: register int num;
! 152: int lncnt;
! 153: int pagecnt;
! 154: int ips;
! 155: int ops;
! 156: int cps;
! 157: char *obuf;
! 158: char *lbuf;
! 159: char *nbuf;
! 160: char *hbuf;
! 161: char *ohbuf;
! 162: FILE *inf;
! 163: char *fname;
! 164: int mor;
! 165:
! 166: if (nmwd)
! 167: num = nmwd + 1;
! 168: else
! 169: num = 0;
! 170: off = num + offst;
! 171:
! 172: /*
! 173: * allocate line buffer
! 174: */
! 175: if ((obuf = malloc((unsigned)(LBUF + off)*sizeof(char))) == NULL) {
! 176: mfail();
! 177: return(1);
! 178: }
! 179: /*
! 180: * allocate header buffer
! 181: */
! 182: if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
! 183: mfail();
! 184: return(1);
! 185: }
! 186:
! 187: ohbuf = hbuf + offst;
! 188: nbuf = obuf + offst;
! 189: lbuf = nbuf + num;
! 190: if (num)
! 191: nbuf[--num] = nmchar;
! 192: if (offst) {
! 193: (void)memset(obuf, (int)' ', offst);
! 194: (void)memset(hbuf, (int)' ', offst);
! 195: }
! 196:
! 197: /*
! 198: * loop by file
! 199: */
! 200: while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
! 201: if (pgnm) {
! 202: /*
! 203: * skip to specified page
! 204: */
! 205: if (inskip(inf, pgnm, lines))
! 206: continue;
! 207: pagecnt = pgnm;
! 208: } else
! 209: pagecnt = 1;
! 210: lncnt = 0;
! 211:
! 212: /*
! 213: * loop by page
! 214: */
! 215: for(;;) {
! 216: linecnt = 0;
! 217: lrgln = 0;
! 218: ops = 0;
! 219: ips = 0;
! 220: cps = 0;
! 221:
! 222: /*
! 223: * loop by line
! 224: */
! 225: while (linecnt < lines) {
! 226: /*
! 227: * input next line
! 228: */
! 229: if ((cnt = inln(inf,lbuf,LBUF,&cps,0,&mor)) < 0)
! 230: break;
! 231: if (!linecnt && !nohead &&
! 232: prhead(hbuf, fname, pagecnt))
! 233: return(1);
! 234:
! 235: /*
! 236: * start of new line.
! 237: */
! 238: if (!lrgln) {
! 239: if (num)
! 240: addnum(nbuf, num, ++lncnt);
! 241: if (otln(obuf,cnt+off, &ips, &ops, mor))
! 242: return(1);
! 243: } else if (otln(lbuf, cnt, &ips, &ops, mor))
! 244: return(1);
! 245:
! 246: /*
! 247: * if line bigger than buffer, get more
! 248: */
! 249: if (mor) {
! 250: lrgln = 1;
! 251: continue;
! 252: }
! 253:
! 254: /*
! 255: * whole line rcvd. reset tab proc. state
! 256: */
! 257: ++linecnt;
! 258: lrgln = 0;
! 259: ops = 0;
! 260: ips = 0;
! 261: }
! 262:
! 263: /*
! 264: * fill to end of page
! 265: */
! 266: if (linecnt && prtail(lines-linecnt-lrgln, lrgln))
! 267: return(1);
! 268:
! 269: /*
! 270: * On EOF go to next file
! 271: */
! 272: if (cnt < 0)
! 273: break;
! 274: ++pagecnt;
! 275: }
! 276: if (inf != stdin)
! 277: (void)fclose(inf);
! 278: }
! 279: if (eoptind < argc)
! 280: return(1);
! 281: return(0);
! 282: }
! 283:
! 284: /*
! 285: * vertcol: print files with more than one column of output down a page
! 286: */
! 287: int
! 288: vertcol(argc, argv)
! 289: int argc;
! 290: char *argv[];
! 291: {
! 292: register char *ptbf;
! 293: register char **lstdat;
! 294: register int i;
! 295: register int j;
! 296: register int cnt = -1;
! 297: register int pln;
! 298: register int *indy;
! 299: int cvc;
! 300: int *lindy;
! 301: int lncnt;
! 302: int stp;
! 303: int pagecnt;
! 304: int col = colwd + 1;
! 305: int mxlen = pgwd + offst + 1;
! 306: int mclcnt = clcnt - 1;
! 307: struct vcol *vc;
! 308: int mvc;
! 309: int tvc;
! 310: int cw = nmwd + 1;
! 311: int fullcol;
! 312: char *buf;
! 313: char *hbuf;
! 314: char *ohbuf;
! 315: char *fname;
! 316: FILE *inf;
! 317: int ips = 0;
! 318: int cps = 0;
! 319: int ops = 0;
! 320: int mor = 0;
! 321:
! 322: /*
! 323: * allocate page buffer
! 324: */
! 325: if ((buf = malloc((unsigned)lines*mxlen*sizeof(char))) == NULL) {
! 326: mfail();
! 327: return(1);
! 328: }
! 329:
! 330: /*
! 331: * allocate page header
! 332: */
! 333: if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
! 334: mfail();
! 335: return(1);
! 336: }
! 337: ohbuf = hbuf + offst;
! 338: if (offst)
! 339: (void)memset(hbuf, (int)' ', offst);
! 340:
! 341: /*
! 342: * col pointers when no headers
! 343: */
! 344: mvc = lines * clcnt;
! 345: if ((vc =
! 346: (struct vcol *)malloc((unsigned)mvc*sizeof(struct vcol))) == NULL) {
! 347: mfail();
! 348: return(1);
! 349: }
! 350:
! 351: /*
! 352: * pointer into page where last data per line is located
! 353: */
! 354: if ((lstdat = (char **)malloc((unsigned)lines*sizeof(char *))) == NULL){
! 355: mfail();
! 356: return(1);
! 357: }
! 358:
! 359: /*
! 360: * fast index lookups to locate start of lines
! 361: */
! 362: if ((indy = (int *)malloc((unsigned)lines*sizeof(int))) == NULL) {
! 363: mfail();
! 364: return(1);
! 365: }
! 366: if ((lindy = (int *)malloc((unsigned)lines*sizeof(int))) == NULL) {
! 367: mfail();
! 368: return(1);
! 369: }
! 370:
! 371: if (nmwd)
! 372: fullcol = col + cw;
! 373: else
! 374: fullcol = col;
! 375:
! 376: /*
! 377: * initialize buffer lookup indexes and offset area
! 378: */
! 379: for (j = 0; j < lines; ++j) {
! 380: lindy[j] = j * mxlen;
! 381: indy[j] = lindy[j] + offst;
! 382: if (offst) {
! 383: ptbf = buf + lindy[j];
! 384: (void)memset(ptbf, (int)' ', offst);
! 385: ptbf += offst;
! 386: } else
! 387: ptbf = buf + indy[j];
! 388: lstdat[j] = ptbf;
! 389: }
! 390:
! 391: /*
! 392: * loop by file
! 393: */
! 394: while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
! 395: if (pgnm) {
! 396: /*
! 397: * skip to requested page
! 398: */
! 399: if (inskip(inf, pgnm, lines))
! 400: continue;
! 401: pagecnt = pgnm;
! 402: } else
! 403: pagecnt = 1;
! 404: lncnt = 0;
! 405:
! 406: /*
! 407: * loop by page
! 408: */
! 409: for(;;) {
! 410: /*
! 411: * loop by column
! 412: */
! 413: cvc = 0;
! 414: for (i = 0; i < clcnt; ++i) {
! 415: j = 0;
! 416: /*
! 417: * if last column, do not pad
! 418: */
! 419: if (i == mclcnt)
! 420: stp = 1;
! 421: else
! 422: stp = 0;
! 423: /*
! 424: * loop by line
! 425: */
! 426: for(;;) {
! 427: /*
! 428: * is this first column
! 429: */
! 430: if (!i) {
! 431: ptbf = buf + indy[j];
! 432: lstdat[j] = ptbf;
! 433: } else
! 434: ptbf = lstdat[j];
! 435: vc[cvc].pt = ptbf;
! 436:
! 437: /*
! 438: * add number
! 439: */
! 440: if (nmwd) {
! 441: addnum(ptbf, nmwd, ++lncnt);
! 442: ptbf += nmwd;
! 443: *ptbf++ = nmchar;
! 444: }
! 445:
! 446: /*
! 447: * input next line
! 448: */
! 449: cnt = inln(inf,ptbf,colwd,&cps,1,&mor);
! 450: vc[cvc++].cnt = cnt;
! 451: if (cnt < 0)
! 452: break;
! 453: ptbf += cnt;
! 454:
! 455: /*
! 456: * pad all but last column on page
! 457: */
! 458: if (!stp) {
! 459: /*
! 460: * pad to end of column
! 461: */
! 462: if (sflag)
! 463: *ptbf++ = schar;
! 464: else if ((pln = col-cnt) > 0) {
! 465: (void)memset(ptbf,
! 466: (int)' ',pln);
! 467: ptbf += pln;
! 468: }
! 469: }
! 470: /*
! 471: * remember last char in line
! 472: */
! 473: lstdat[j] = ptbf;
! 474: if (++j >= lines)
! 475: break;
! 476: }
! 477: if (cnt < 0)
! 478: break;
! 479: }
! 480:
! 481: /*
! 482: * when -t (no header) is specified the spec requires
! 483: * the min number of lines. The last page may not have
! 484: * balanced length columns. To fix this we must reorder
! 485: * the columns. This is a very slow technique so it is
! 486: * only used under limited conditions. Without -t, the
! 487: * balancing of text columns is unspecified. To NOT
! 488: * balance the last page, add the global variable
! 489: * nohead to the if statement below e.g.
! 490: *
! 491: * if ((cnt < 0) && nohead && cvc ......
! 492: */
! 493: --cvc;
! 494:
! 495: /*
! 496: * check to see if last page needs to be reordered
! 497: */
! 498: if ((cnt < 0) && cvc && ((mvc-cvc) >= clcnt)){
! 499: pln = cvc/clcnt;
! 500: if (cvc % clcnt)
! 501: ++pln;
! 502:
! 503: /*
! 504: * print header
! 505: */
! 506: if (!nohead && prhead(hbuf, fname, pagecnt))
! 507: return(1);
! 508: for (i = 0; i < pln; ++i) {
! 509: ips = 0;
! 510: ops = 0;
! 511: if (offst&& otln(buf,offst,&ips,&ops,1))
! 512: return(1);
! 513: tvc = i;
! 514:
! 515: for (j = 0; j < clcnt; ++j) {
! 516: /*
! 517: * determine column length
! 518: */
! 519: if (j == mclcnt) {
! 520: /*
! 521: * last column
! 522: */
! 523: cnt = vc[tvc].cnt;
! 524: if (nmwd)
! 525: cnt += cw;
! 526: } else if (sflag) {
! 527: /*
! 528: * single ch between
! 529: */
! 530: cnt = vc[tvc].cnt + 1;
! 531: if (nmwd)
! 532: cnt += cw;
! 533: } else
! 534: cnt = fullcol;
! 535: if (otln(vc[tvc].pt, cnt, &ips,
! 536: &ops, 1))
! 537: return(1);
! 538: tvc += pln;
! 539: if (tvc >= cvc)
! 540: break;
! 541: }
! 542: /*
! 543: * terminate line
! 544: */
! 545: if (otln(buf, 0, &ips, &ops, 0))
! 546: return(1);
! 547: }
! 548: /*
! 549: * pad to end of page
! 550: */
! 551: if (prtail((lines - pln), 0))
! 552: return(1);
! 553: /*
! 554: * done with output, go to next file
! 555: */
! 556: break;
! 557: }
! 558:
! 559: /*
! 560: * determine how many lines to output
! 561: */
! 562: if (i > 0)
! 563: pln = lines;
! 564: else
! 565: pln = j;
! 566:
! 567: /*
! 568: * print header
! 569: */
! 570: if (pln && !nohead && prhead(hbuf, fname, pagecnt))
! 571: return(1);
! 572:
! 573: /*
! 574: * output each line
! 575: */
! 576: for (i = 0; i < pln; ++i) {
! 577: ptbf = buf + lindy[i];
! 578: if ((j = lstdat[i] - ptbf) <= offst)
! 579: break;
! 580: if (otln(ptbf, j, &ips, &ops, 0))
! 581: return(1);
! 582: }
! 583:
! 584: /*
! 585: * pad to end of page
! 586: */
! 587: if (pln && prtail((lines - pln), 0))
! 588: return(1);
! 589:
! 590: /*
! 591: * if EOF go to next file
! 592: */
! 593: if (cnt < 0)
! 594: break;
! 595: ++pagecnt;
! 596: }
! 597: if (inf != stdin)
! 598: (void)fclose(inf);
! 599: }
! 600: if (eoptind < argc)
! 601: return(1);
! 602: return(0);
! 603: }
! 604:
! 605: /*
! 606: * horzcol: print files with more than one column of output across a page
! 607: */
! 608: int
! 609: horzcol(argc, argv)
! 610: int argc;
! 611: char *argv[];
! 612: {
! 613: register char *ptbf;
! 614: register int pln;
! 615: register int cnt = -1;
! 616: register char *lstdat;
! 617: register int col = colwd + 1;
! 618: register int j;
! 619: register int i;
! 620: int lncnt;
! 621: int pagecnt;
! 622: char *buf;
! 623: char *hbuf;
! 624: char *ohbuf;
! 625: char *fname;
! 626: FILE *inf;
! 627: int ips = 0;
! 628: int cps = 0;
! 629: int ops = 0;
! 630: int mor = 0;
! 631:
! 632: if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL) {
! 633: mfail();
! 634: return(1);
! 635: }
! 636:
! 637: /*
! 638: * page header
! 639: */
! 640: if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
! 641: mfail();
! 642: return(1);
! 643: }
! 644: ohbuf = hbuf + offst;
! 645: if (offst) {
! 646: (void)memset(buf, (int)' ', offst);
! 647: (void)memset(hbuf, (int)' ', offst);
! 648: }
! 649:
! 650: /*
! 651: * loop by file
! 652: */
! 653: while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
! 654: if (pgnm) {
! 655: if (inskip(inf, pgnm, lines))
! 656: continue;
! 657: pagecnt = pgnm;
! 658: } else
! 659: pagecnt = 1;
! 660: lncnt = 0;
! 661:
! 662: /*
! 663: * loop by page
! 664: */
! 665: for(;;) {
! 666: /*
! 667: * loop by line
! 668: */
! 669: for (i = 0; i < lines; ++i) {
! 670: ptbf = buf + offst;
! 671: lstdat = ptbf;
! 672: j = 0;
! 673: /*
! 674: * loop by col
! 675: */
! 676: for(;;) {
! 677: if (nmwd) {
! 678: /*
! 679: * add number to column
! 680: */
! 681: addnum(ptbf, nmwd, ++lncnt);
! 682: ptbf += nmwd;
! 683: *ptbf++ = nmchar;
! 684: }
! 685: /*
! 686: * input line
! 687: */
! 688: if ((cnt = inln(inf,ptbf,colwd,&cps,1,
! 689: &mor)) < 0)
! 690: break;
! 691: ptbf += cnt;
! 692: lstdat = ptbf;
! 693:
! 694: /*
! 695: * if last line skip padding
! 696: */
! 697: if (++j >= clcnt)
! 698: break;
! 699:
! 700: /*
! 701: * pad to end of column
! 702: */
! 703: if (sflag)
! 704: *ptbf++ = schar;
! 705: else if ((pln = col - cnt) > 0) {
! 706: (void)memset(ptbf,(int)' ',pln);
! 707: ptbf += pln;
! 708: }
! 709: }
! 710:
! 711: /*
! 712: * determine line length
! 713: */
! 714: if ((j = lstdat - buf) <= offst)
! 715: break;
! 716: if (!i && !nohead &&
! 717: prhead(hbuf, fname, pagecnt))
! 718: return(1);
! 719: /*
! 720: * output line
! 721: */
! 722: if (otln(buf, j, &ips, &ops, 0))
! 723: return(1);
! 724: }
! 725:
! 726: /*
! 727: * pad to end of page
! 728: */
! 729: if (i && prtail(lines-i, 0))
! 730: return(1);
! 731:
! 732: /*
! 733: * if EOF go to next file
! 734: */
! 735: if (cnt < 0)
! 736: break;
! 737: ++pagecnt;
! 738: }
! 739: if (inf != stdin)
! 740: (void)fclose(inf);
! 741: }
! 742: if (eoptind < argc)
! 743: return(1);
! 744: return(0);
! 745: }
! 746:
! 747: /*
! 748: * mulfile: print files with more than one column of output and
! 749: * more than one file concurrently
! 750: */
! 751: int
! 752: mulfile(argc, argv)
! 753: int argc;
! 754: char *argv[];
! 755: {
! 756: register char *ptbf;
! 757: register int j;
! 758: register int pln;
! 759: register int cnt;
! 760: register char *lstdat;
! 761: register int i;
! 762: FILE **fbuf;
! 763: int actf;
! 764: int lncnt;
! 765: int col;
! 766: int pagecnt;
! 767: int fproc;
! 768: char *buf;
! 769: char *hbuf;
! 770: char *ohbuf;
! 771: char *fname;
! 772: int ips = 0;
! 773: int cps = 0;
! 774: int ops = 0;
! 775: int mor = 0;
! 776:
! 777: /*
! 778: * array of FILE *, one for each operand
! 779: */
! 780: if ((fbuf = (FILE **)malloc((unsigned)clcnt*sizeof(FILE *))) == NULL) {
! 781: mfail();
! 782: return(1);
! 783: }
! 784:
! 785: /*
! 786: * page header
! 787: */
! 788: if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
! 789: mfail();
! 790: return(1);
! 791: }
! 792: ohbuf = hbuf + offst;
! 793:
! 794: /*
! 795: * do not know how many columns yet. The number of operands provide an
! 796: * upper bound on the number of columns. We use the number of files
! 797: * we can open successfully to set the number of columns. The operation
! 798: * of the merge operation (-m) in relation to unsuccesful file opens
! 799: * is unspecified by posix.
! 800: */
! 801: j = 0;
! 802: while (j < clcnt) {
! 803: if ((fbuf[j] = nxtfile(argc, argv, &fname, ohbuf, 1)) == NULL)
! 804: break;
! 805: if (pgnm && (inskip(fbuf[j], pgnm, lines)))
! 806: fbuf[j] = NULL;
! 807: ++j;
! 808: }
! 809:
! 810: /*
! 811: * if no files, exit
! 812: */
! 813: if (!j)
! 814: return(1);
! 815:
! 816: /*
! 817: * calculate page boundries based on open file count
! 818: */
! 819: clcnt = j;
! 820: if (nmwd) {
! 821: colwd = (pgwd - clcnt - nmwd)/clcnt;
! 822: pgwd = ((colwd + 1) * clcnt) - nmwd - 2;
! 823: } else {
! 824: colwd = (pgwd + 1 - clcnt)/clcnt;
! 825: pgwd = ((colwd + 1) * clcnt) - 1;
! 826: }
! 827: if (colwd < 1) {
! 828: (void)fprintf(err,
! 829: "pr: page width too small for %d columns\n", clcnt);
! 830: return(1);
! 831: }
! 832: actf = clcnt;
! 833: col = colwd + 1;
! 834:
! 835: /*
! 836: * line buffer
! 837: */
! 838: if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL) {
! 839: mfail();
! 840: return(1);
! 841: }
! 842: if (offst) {
! 843: (void)memset(buf, (int)' ', offst);
! 844: (void)memset(hbuf, (int)' ', offst);
! 845: }
! 846: if (pgnm)
! 847: pagecnt = pgnm;
! 848: else
! 849: pagecnt = 1;
! 850: lncnt = 0;
! 851:
! 852: /*
! 853: * continue to loop while any file still has data
! 854: */
! 855: while (actf > 0) {
! 856: /*
! 857: * loop by line
! 858: */
! 859: for (i = 0; i < lines; ++i) {
! 860: ptbf = buf + offst;
! 861: lstdat = ptbf;
! 862: if (nmwd) {
! 863: /*
! 864: * add line number to line
! 865: */
! 866: addnum(ptbf, nmwd, ++lncnt);
! 867: ptbf += nmwd;
! 868: *ptbf++ = nmchar;
! 869: }
! 870: j = 0;
! 871: fproc = 0;
! 872:
! 873: /*
! 874: * loop by column
! 875: */
! 876: for (j = 0; j < clcnt; ++j) {
! 877: if (fbuf[j] == NULL) {
! 878: /*
! 879: * empty column; EOF
! 880: */
! 881: cnt = 0;
! 882: } else if ((cnt = inln(fbuf[j], ptbf, colwd,
! 883: &cps, 1, &mor)) < 0) {
! 884: /*
! 885: * EOF hit; no data
! 886: */
! 887: if (fbuf[j] != stdin)
! 888: (void)fclose(fbuf[j]);
! 889: fbuf[j] = NULL;
! 890: --actf;
! 891: cnt = 0;
! 892: } else {
! 893: /*
! 894: * process file data
! 895: */
! 896: ptbf += cnt;
! 897: lstdat = ptbf;
! 898: fproc++;
! 899: }
! 900:
! 901: /*
! 902: * if last ACTIVE column, done with line
! 903: */
! 904: if (fproc >= actf)
! 905: break;
! 906:
! 907: /*
! 908: * pad to end of column
! 909: */
! 910: if (sflag) {
! 911: *ptbf++ = schar;
! 912: } else if ((pln = col - cnt) > 0) {
! 913: (void)memset(ptbf, (int)' ', pln);
! 914: ptbf += pln;
! 915: }
! 916: }
! 917:
! 918: /*
! 919: * calculate data in line
! 920: */
! 921: if ((j = lstdat - buf) <= offst)
! 922: break;
! 923:
! 924: if (!i && !nohead && prhead(hbuf, fname, pagecnt))
! 925: return(1);
! 926:
! 927: /*
! 928: * output line
! 929: */
! 930: if (otln(buf, j, &ips, &ops, 0))
! 931: return(1);
! 932:
! 933: /*
! 934: * if no more active files, done
! 935: */
! 936: if (actf <= 0) {
! 937: ++i;
! 938: break;
! 939: }
! 940: }
! 941:
! 942: /*
! 943: * pad to end of page
! 944: */
! 945: if (i && prtail(lines-i, 0))
! 946: return(1);
! 947: ++pagecnt;
! 948: }
! 949: if (eoptind < argc)
! 950: return(1);
! 951: return(0);
! 952: }
! 953:
! 954: /*
! 955: * inln(): input a line of data (unlimited length lines supported)
! 956: * Input is optionally expanded to spaces
! 957: *
! 958: * inf: file
! 959: * buf: buffer
! 960: * lim: buffer length
! 961: * cps: column positon 1st char in buffer (large line support)
! 962: * trnc: throw away data more than lim up to \n
! 963: * mor: set if more data in line (not truncated)
! 964: */
! 965: int
! 966: inln(inf, buf, lim, cps, trnc, mor)
! 967: FILE *inf;
! 968: char *buf;
! 969: register int lim;
! 970: int *cps;
! 971: int trnc;
! 972: int *mor;
! 973: {
! 974: register int col;
! 975: register int gap = ingap;
! 976: register int ch = EOF;
! 977: register char *ptbuf;
! 978: register int chk = (int)inchar;
! 979:
! 980: ptbuf = buf;
! 981:
! 982: if (gap) {
! 983: /*
! 984: * expanding input option
! 985: */
! 986: while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) {
! 987: /*
! 988: * is this the input "tab" char
! 989: */
! 990: if (ch == chk) {
! 991: /*
! 992: * expand to number of spaces
! 993: */
! 994: col = (ptbuf - buf) + *cps;
! 995: col = gap - (col % gap);
! 996:
! 997: /*
! 998: * if more than this line, push back
! 999: */
! 1000: if ((col > lim) && (ungetc(ch, inf) == EOF))
! 1001: return(1);
! 1002:
! 1003: /*
! 1004: * expand to spaces
! 1005: */
! 1006: while ((--col >= 0) && (--lim >= 0))
! 1007: *ptbuf++ = ' ';
! 1008: continue;
! 1009: }
! 1010: if (ch == '\n')
! 1011: break;
! 1012: *ptbuf++ = ch;
! 1013: }
! 1014: } else {
! 1015: /*
! 1016: * no expansion
! 1017: */
! 1018: while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) {
! 1019: if (ch == '\n')
! 1020: break;
! 1021: *ptbuf++ = ch;
! 1022: }
! 1023: }
! 1024: col = ptbuf - buf;
! 1025: if (ch == EOF) {
! 1026: *mor = 0;
! 1027: *cps = 0;
! 1028: if (!col)
! 1029: return(-1);
! 1030: return(col);
! 1031: }
! 1032: if (ch == '\n') {
! 1033: /*
! 1034: * entire line processed
! 1035: */
! 1036: *mor = 0;
! 1037: *cps = 0;
! 1038: return(col);
! 1039: }
! 1040:
! 1041: /*
! 1042: * line was larger than limit
! 1043: */
! 1044: if (trnc) {
! 1045: /*
! 1046: * throw away rest of line
! 1047: */
! 1048: while ((ch = getc(inf)) != EOF) {
! 1049: if (ch == '\n')
! 1050: break;
! 1051: }
! 1052: *cps = 0;
! 1053: *mor = 0;
! 1054: } else {
! 1055: /*
! 1056: * save column offset if not truncated
! 1057: */
! 1058: *cps += col;
! 1059: *mor = 1;
! 1060: }
! 1061:
! 1062: return(col);
! 1063: }
! 1064:
! 1065: /*
! 1066: * otln(): output a line of data. (Supports unlimited length lines)
! 1067: * output is optionally contracted to tabs
! 1068: *
! 1069: * buf: output buffer with data
! 1070: * cnt: number of chars of valid data in buf
! 1071: * svips: buffer input column position (for large lines)
! 1072: * svops: buffer output column position (for large lines)
! 1073: * mor: output line not complete in this buf; more data to come.
! 1074: * 1 is more, 0 is complete, -1 is no \n's
! 1075: */
! 1076: int
! 1077: otln(buf, cnt, svips, svops, mor)
! 1078: register char *buf;
! 1079: int cnt;
! 1080: int *svops;
! 1081: int *svips;
! 1082: int mor;
! 1083: {
! 1084: register int ops; /* last col output */
! 1085: register int ips; /* last col in buf examined */
! 1086: register int gap = ogap;
! 1087: register int tbps;
! 1088: register char *endbuf;
! 1089:
! 1090: if (ogap) {
! 1091: /*
! 1092: * contracting on output
! 1093: */
! 1094: endbuf = buf + cnt;
! 1095: ops = *svops;
! 1096: ips = *svips;
! 1097: while (buf < endbuf) {
! 1098: /*
! 1099: * count number of spaces and ochar in buffer
! 1100: */
! 1101: if (*buf == ' ') {
! 1102: ++ips;
! 1103: ++buf;
! 1104: continue;
! 1105: }
! 1106:
! 1107: /*
! 1108: * simulate ochar processing
! 1109: */
! 1110: if (*buf == ochar) {
! 1111: ips += gap - (ips % gap);
! 1112: ++buf;
! 1113: continue;
! 1114: }
! 1115:
! 1116: /*
! 1117: * got a non space char; contract out spaces
! 1118: */
! 1119: while (ops < ips) {
! 1120: /*
! 1121: * use as many ochar as will fit
! 1122: */
! 1123: if ((tbps = ops + gap - (ops % gap)) > ips)
! 1124: break;
! 1125: if (putchar(ochar) == EOF) {
! 1126: pfail();
! 1127: return(1);
! 1128: }
! 1129: ops = tbps;
! 1130: }
! 1131:
! 1132: while (ops < ips) {
! 1133: /*
! 1134: * finish off with spaces
! 1135: */
! 1136: if (putchar(' ') == EOF) {
! 1137: pfail();
! 1138: return(1);
! 1139: }
! 1140: ++ops;
! 1141: }
! 1142:
! 1143: /*
! 1144: * output non space char
! 1145: */
! 1146: if (putchar(*buf++) == EOF) {
! 1147: pfail();
! 1148: return(1);
! 1149: }
! 1150: ++ips;
! 1151: ++ops;
! 1152: }
! 1153:
! 1154: if (mor > 0) {
! 1155: /*
! 1156: * if incomplete line, save position counts
! 1157: */
! 1158: *svops = ops;
! 1159: *svips = ips;
! 1160: return(0);
! 1161: }
! 1162:
! 1163: if (mor < 0) {
! 1164: while (ops < ips) {
! 1165: /*
! 1166: * use as many ochar as will fit
! 1167: */
! 1168: if ((tbps = ops + gap - (ops % gap)) > ips)
! 1169: break;
! 1170: if (putchar(ochar) == EOF) {
! 1171: pfail();
! 1172: return(1);
! 1173: }
! 1174: ops = tbps;
! 1175: }
! 1176: while (ops < ips) {
! 1177: /*
! 1178: * finish off with spaces
! 1179: */
! 1180: if (putchar(' ') == EOF) {
! 1181: pfail();
! 1182: return(1);
! 1183: }
! 1184: ++ops;
! 1185: }
! 1186: return(0);
! 1187: }
! 1188: } else {
! 1189: /*
! 1190: * output is not contracted
! 1191: */
! 1192: if (cnt && (fwrite(buf, sizeof(char), cnt, stdout) <= 0)) {
! 1193: pfail();
! 1194: return(1);
! 1195: }
! 1196: if (mor != 0)
! 1197: return(0);
! 1198: }
! 1199:
! 1200: /*
! 1201: * process line end and double space as required
! 1202: */
! 1203: if ((putchar('\n') == EOF) || (dspace && (putchar('\n') == EOF))) {
! 1204: pfail();
! 1205: return(1);
! 1206: }
! 1207: return(0);
! 1208: }
! 1209:
! 1210: /*
! 1211: * inskip(): skip over pgcnt pages with lncnt lines per page
! 1212: * file is closed at EOF (if not stdin).
! 1213: *
! 1214: * inf FILE * to read from
! 1215: * pgcnt number of pages to skip
! 1216: * lncnt number of lines per page
! 1217: */
! 1218: int
! 1219: inskip(inf, pgcnt, lncnt)
! 1220: FILE *inf;
! 1221: register int pgcnt;
! 1222: register int lncnt;
! 1223: {
! 1224: register int c;
! 1225: register int cnt;
! 1226:
! 1227: while(--pgcnt > 0) {
! 1228: cnt = lncnt;
! 1229: while ((c = getc(inf)) != EOF) {
! 1230: if ((c == '\n') && (--cnt == 0))
! 1231: break;
! 1232: }
! 1233: if (c == EOF) {
! 1234: if (inf != stdin)
! 1235: (void)fclose(inf);
! 1236: return(1);
! 1237: }
! 1238: }
! 1239: return(0);
! 1240: }
! 1241:
! 1242: /*
! 1243: * nxtfile: returns a FILE * to next file in arg list and sets the
! 1244: * time field for this file (or current date).
! 1245: *
! 1246: * buf array to store proper date for the header.
! 1247: * dt if set skips the date processing (used with -m)
! 1248: */
! 1249: FILE *
! 1250: nxtfile(argc, argv, fname, buf, dt)
! 1251: int argc;
! 1252: char **argv;
! 1253: char **fname;
! 1254: char *buf;
! 1255: int dt;
! 1256: {
! 1257: FILE *inf = NULL;
! 1258: struct timeval tv;
! 1259: struct timezone tz;
! 1260: struct tm *timeptr = NULL;
! 1261: struct stat statbuf;
! 1262: time_t curtime;
! 1263: static int twice = -1;
! 1264:
! 1265: ++twice;
! 1266: if (eoptind >= argc) {
! 1267: /*
! 1268: * no file listed; default, use standard input
! 1269: */
! 1270: if (twice)
! 1271: return(NULL);
! 1272: clearerr(stdin);
! 1273: inf = stdin;
! 1274: if (header != NULL)
! 1275: *fname = header;
! 1276: else
! 1277: *fname = FNAME;
! 1278: if (nohead)
! 1279: return(inf);
! 1280: if (gettimeofday(&tv, &tz) < 0) {
! 1281: ++errcnt;
! 1282: (void)fprintf(err, "pr: cannot get time of day, %s\n",
! 1283: strerror(errno));
! 1284: eoptind = argc - 1;
! 1285: return(NULL);
! 1286: }
! 1287: curtime = tv.tv_sec;
! 1288: timeptr = localtime(&curtime);
! 1289: }
! 1290: for (; eoptind < argc; ++eoptind) {
! 1291: if (strcmp(argv[eoptind], "-") == 0) {
! 1292: /*
! 1293: * process a "-" for filename
! 1294: */
! 1295: clearerr(stdin);
! 1296: inf = stdin;
! 1297: if (header != NULL)
! 1298: *fname = header;
! 1299: else
! 1300: *fname = FNAME;
! 1301: ++eoptind;
! 1302: if (nohead || (dt && twice))
! 1303: return(inf);
! 1304: if (gettimeofday(&tv, &tz) < 0) {
! 1305: ++errcnt;
! 1306: (void)fprintf(err,
! 1307: "pr: cannot get time of day, %s\n",
! 1308: strerror(errno));
! 1309: return(NULL);
! 1310: }
! 1311: curtime = tv.tv_sec;
! 1312: timeptr = localtime(&curtime);
! 1313: } else {
! 1314: /*
! 1315: * normal file processing
! 1316: */
! 1317: if ((inf = fopen(argv[eoptind], "r")) == NULL) {
! 1318: ++errcnt;
! 1319: if (nodiag)
! 1320: continue;
! 1321: (void)fprintf(err, "pr: Cannot open %s, %s\n",
! 1322: argv[eoptind], strerror(errno));
! 1323: continue;
! 1324: }
! 1325: if (header != NULL)
! 1326: *fname = header;
! 1327: else if (dt)
! 1328: *fname = FNAME;
! 1329: else
! 1330: *fname = argv[eoptind];
! 1331: ++eoptind;
! 1332: if (nohead || (dt && twice))
! 1333: return(inf);
! 1334:
! 1335: if (dt) {
! 1336: if (gettimeofday(&tv, &tz) < 0) {
! 1337: ++errcnt;
! 1338: (void)fprintf(err,
! 1339: "pr: cannot get time of day, %s\n",
! 1340: strerror(errno));
! 1341: return(NULL);
! 1342: }
! 1343: curtime = tv.tv_sec;
! 1344: timeptr = localtime(&curtime);
! 1345: } else {
! 1346: if (fstat(fileno(inf), &statbuf) < 0) {
! 1347: ++errcnt;
! 1348: (void)fclose(inf);
! 1349: (void)fprintf(err,
! 1350: "pr: Cannot stat %s, %s\n",
! 1351: argv[eoptind], strerror(errno));
! 1352: return(NULL);
! 1353: }
! 1354: timeptr = localtime(&(statbuf.st_mtime));
! 1355: }
! 1356: }
! 1357: break;
! 1358: }
! 1359: if (inf == NULL)
! 1360: return(NULL);
! 1361:
! 1362: /*
! 1363: * set up time field used in header
! 1364: */
! 1365: if (strftime(buf, HDBUF, timefrmt, timeptr) <= 0) {
! 1366: ++errcnt;
! 1367: if (inf != stdin)
! 1368: (void)fclose(inf);
! 1369: (void)fputs("pr: time conversion failed\n", err);
! 1370: return(NULL);
! 1371: }
! 1372: return(inf);
! 1373: }
! 1374:
! 1375: /*
! 1376: * addnum(): adds the line number to the column
! 1377: * Truncates from the front or pads with spaces as required.
! 1378: * Numbers are right justified.
! 1379: *
! 1380: * buf buffer to store the number
! 1381: * wdth width of buffer to fill
! 1382: * line line number
! 1383: *
! 1384: * NOTE: numbers occupy part of the column. The posix
! 1385: * spec does not specify if -i processing should or should not
! 1386: * occur on number padding. The spec does say it occupies
! 1387: * part of the column. The usage of addnum currently treats
! 1388: * numbers as part of the column so spaces may be replaced.
! 1389: */
! 1390: void
! 1391: addnum(buf, wdth, line)
! 1392: register char *buf;
! 1393: register int wdth;
! 1394: register int line;
! 1395: {
! 1396: register char *pt = buf + wdth;
! 1397:
! 1398: do {
! 1399: *--pt = digs[line % 10];
! 1400: line /= 10;
! 1401: } while (line && (pt > buf));
! 1402:
! 1403: /*
! 1404: * pad with space as required
! 1405: */
! 1406: while (pt > buf)
! 1407: *--pt = ' ';
! 1408: }
! 1409:
! 1410: /*
! 1411: * prhead(): prints the top of page header
! 1412: *
! 1413: * buf buffer with time field (and offset)
! 1414: * cnt number of chars in buf
! 1415: * fname fname field for header
! 1416: * pagcnt page number
! 1417: */
! 1418: int
! 1419: prhead(buf, fname, pagcnt)
! 1420: char *buf;
! 1421: char *fname;
! 1422: int pagcnt;
! 1423: {
! 1424: int ips = 0;
! 1425: int ops = 0;
! 1426:
! 1427: if ((putchar('\n') == EOF) || (putchar('\n') == EOF)) {
! 1428: pfail();
! 1429: return(1);
! 1430: }
! 1431: /*
! 1432: * posix is not clear if the header is subject to line length
! 1433: * restrictions. The specification for header line format
! 1434: * in the spec clearly does not limit length. No pr currently
! 1435: * restricts header length. However if we need to truncate in
! 1436: * an reasonable way, adjust the length of the printf by
! 1437: * changing HDFMT to allow a length max as an arguement printf.
! 1438: * buf (which contains the offset spaces and time field could
! 1439: * also be trimmed
! 1440: *
! 1441: * note only the offset (if any) is processed for tab expansion
! 1442: */
! 1443: if (offst && otln(buf, offst, &ips, &ops, -1))
! 1444: return(1);
! 1445: (void)printf(HDFMT,buf+offst, fname, pagcnt);
! 1446: return(0);
! 1447: }
! 1448:
! 1449: /*
! 1450: * prtail(): pad page with empty lines (if required) and print page trailer
! 1451: * if requested
! 1452: *
! 1453: * cnt number of lines of padding needed
! 1454: * incomp was a '\n' missing from last line output
! 1455: */
! 1456: int
! 1457: prtail(cnt, incomp)
! 1458: register int cnt;
! 1459: int incomp;
! 1460: {
! 1461: if (nohead) {
! 1462: /*
! 1463: * only pad with no headers when incomplete last line
! 1464: */
! 1465: if (!incomp)
! 1466: return(0);
! 1467: if ((dspace && (putchar('\n') == EOF)) ||
! 1468: (putchar('\n') == EOF)) {
! 1469: pfail();
! 1470: return(1);
! 1471: }
! 1472: return(0);
! 1473: }
! 1474:
! 1475: /*
! 1476: * if double space output two \n
! 1477: */
! 1478: if (dspace)
! 1479: cnt *= 2;
! 1480:
! 1481: /*
! 1482: * if an odd number of lines per page, add an extra \n
! 1483: */
! 1484: if (addone)
! 1485: ++cnt;
! 1486:
! 1487: /*
! 1488: * pad page
! 1489: */
! 1490: if (formfeed) {
! 1491: if ((incomp && (putchar('\n') == EOF)) ||
! 1492: (putchar('\f') == EOF)) {
! 1493: pfail();
! 1494: return(1);
! 1495: }
! 1496: return(0);
! 1497: }
! 1498: cnt += TAILLEN;
! 1499: while (--cnt >= 0) {
! 1500: if (putchar('\n') == EOF) {
! 1501: pfail();
! 1502: return(1);
! 1503: }
! 1504: }
! 1505: return(0);
! 1506: }
! 1507:
! 1508: /*
! 1509: * terminate(): when a SIGINT is recvd
! 1510: */
! 1511: void
! 1512: terminate(which_sig)
! 1513: int which_sig;
! 1514: {
! 1515: flsh_errs();
! 1516: exit(1);
! 1517: }
! 1518:
! 1519:
! 1520: /*
! 1521: * flsh_errs(): output saved up diagnostic messages after all normal
! 1522: * processing has completed
! 1523: */
! 1524: void
! 1525: flsh_errs()
! 1526: {
! 1527: char buf[BUFSIZ];
! 1528:
! 1529: (void)fflush(stdout);
! 1530: (void)fflush(err);
! 1531: if (err == stderr)
! 1532: return;
! 1533: rewind(err);
! 1534: while (fgets(buf, BUFSIZ, err) != NULL)
! 1535: (void)fputs(buf, stderr);
! 1536: }
! 1537:
! 1538: void
! 1539: mfail()
! 1540: {
! 1541: (void)fputs("pr: memory allocation failed\n", err);
! 1542: }
! 1543:
! 1544: void
! 1545: pfail()
! 1546: {
! 1547: (void)fprintf(err, "pr: write failure, %s\n", strerror(errno));
! 1548: }
! 1549:
! 1550: void
! 1551: usage()
! 1552: {
! 1553: (void)fputs(
! 1554: "usage: pr [+page] [-col] [-adFmrt] [-e[ch][gap]] [-h header]\n",err);
! 1555: (void)fputs(
! 1556: " [-i[ch][gap]] [-l line] [-n[ch][width]] [-o offset]\n",err);
! 1557: (void)fputs(
! 1558: " [-s[ch]] [-w width] [-] [file ...]\n", err);
! 1559: }
! 1560:
! 1561: /*
! 1562: * setup: Validate command args, initialize and perform sanity
! 1563: * checks on options
! 1564: */
! 1565: int
! 1566: setup(argc, argv)
! 1567: register int argc;
! 1568: register char **argv;
! 1569: {
! 1570: register int c;
! 1571: int eflag = 0;
! 1572: int iflag = 0;
! 1573: int wflag = 0;
! 1574: int cflag = 0;
! 1575:
! 1576: if (isatty(fileno(stdout))) {
! 1577: /*
! 1578: * defer diagnostics until processing is done
! 1579: */
! 1580: if ((err = tmpfile()) == NULL) {
! 1581: (void)fputs("Cannot defer diagnostic messages\n",stderr);
! 1582: return(1);
! 1583: }
! 1584: } else
! 1585: err = stderr;
! 1586: while ((c = egetopt(argc, argv, "#adFmrte?h:i?l:n?o:s?w:")) != EOF) {
! 1587: switch (c) {
! 1588: case '+':
! 1589: if ((pgnm = atoi(eoptarg)) < 1) {
! 1590: (void)fputs("pr: +page number must be 1 or more\n",
! 1591: err);
! 1592: return(1);
! 1593: }
! 1594: break;
! 1595: case '-':
! 1596: if ((clcnt = atoi(eoptarg)) < 1) {
! 1597: (void)fputs("pr: -columns must be 1 or more\n",err);
! 1598: return(1);
! 1599: }
! 1600: if (clcnt > 1)
! 1601: ++cflag;
! 1602: break;
! 1603: case 'a':
! 1604: ++across;
! 1605: break;
! 1606: case 'd':
! 1607: ++dspace;
! 1608: break;
! 1609: case 'e':
! 1610: ++eflag;
! 1611: if ((eoptarg != NULL) && !isdigit(*eoptarg))
! 1612: inchar = *eoptarg++;
! 1613: else
! 1614: inchar = INCHAR;
! 1615: if ((eoptarg != NULL) && isdigit(*eoptarg)) {
! 1616: if ((ingap = atoi(eoptarg)) < 0) {
! 1617: (void)fputs(
! 1618: "pr: -e gap must be 0 or more\n", err);
! 1619: return(1);
! 1620: }
! 1621: if (ingap == 0)
! 1622: ingap = INGAP;
! 1623: } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
! 1624: (void)fprintf(err,
! 1625: "pr: invalid value for -e %s\n", eoptarg);
! 1626: return(1);
! 1627: } else
! 1628: ingap = INGAP;
! 1629: break;
! 1630: case 'F':
! 1631: ++formfeed;
! 1632: break;
! 1633: case 'h':
! 1634: header = eoptarg;
! 1635: break;
! 1636: case 'i':
! 1637: ++iflag;
! 1638: if ((eoptarg != NULL) && !isdigit(*eoptarg))
! 1639: ochar = *eoptarg++;
! 1640: else
! 1641: ochar = OCHAR;
! 1642: if ((eoptarg != NULL) && isdigit(*eoptarg)) {
! 1643: if ((ogap = atoi(eoptarg)) < 0) {
! 1644: (void)fputs(
! 1645: "pr: -i gap must be 0 or more\n", err);
! 1646: return(1);
! 1647: }
! 1648: if (ogap == 0)
! 1649: ogap = OGAP;
! 1650: } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
! 1651: (void)fprintf(err,
! 1652: "pr: invalid value for -i %s\n", eoptarg);
! 1653: return(1);
! 1654: } else
! 1655: ogap = OGAP;
! 1656: break;
! 1657: case 'l':
! 1658: if (!isdigit(*eoptarg) || ((lines=atoi(eoptarg)) < 1)) {
! 1659: (void)fputs(
! 1660: "pr: Number of lines must be 1 or more\n",err);
! 1661: return(1);
! 1662: }
! 1663: break;
! 1664: case 'm':
! 1665: ++merge;
! 1666: break;
! 1667: case 'n':
! 1668: if ((eoptarg != NULL) && !isdigit(*eoptarg))
! 1669: nmchar = *eoptarg++;
! 1670: else
! 1671: nmchar = NMCHAR;
! 1672: if ((eoptarg != NULL) && isdigit(*eoptarg)) {
! 1673: if ((nmwd = atoi(eoptarg)) < 1) {
! 1674: (void)fputs(
! 1675: "pr: -n width must be 1 or more\n",err);
! 1676: return(1);
! 1677: }
! 1678: } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
! 1679: (void)fprintf(err,
! 1680: "pr: invalid value for -n %s\n", eoptarg);
! 1681: return(1);
! 1682: } else
! 1683: nmwd = NMWD;
! 1684: break;
! 1685: case 'o':
! 1686: if (!isdigit(*eoptarg) || ((offst = atoi(eoptarg))< 1)){
! 1687: (void)fputs("pr: -o offset must be 1 or more\n",
! 1688: err);
! 1689: return(1);
! 1690: }
! 1691: break;
! 1692: case 'r':
! 1693: ++nodiag;
! 1694: break;
! 1695: case 's':
! 1696: ++sflag;
! 1697: if (eoptarg == NULL)
! 1698: schar = SCHAR;
! 1699: else
! 1700: schar = *eoptarg++;
! 1701: if (*eoptarg != '\0') {
! 1702: (void)fprintf(err,
! 1703: "pr: invalid value for -s %s\n", eoptarg);
! 1704: return(1);
! 1705: }
! 1706: break;
! 1707: case 't':
! 1708: ++nohead;
! 1709: break;
! 1710: case 'w':
! 1711: ++wflag;
! 1712: if (!isdigit(*eoptarg) || ((pgwd = atoi(eoptarg)) < 1)){
! 1713: (void)fputs(
! 1714: "pr: -w width must be 1 or more \n",err);
! 1715: return(1);
! 1716: }
! 1717: break;
! 1718: case '?':
! 1719: default:
! 1720: return(1);
! 1721: }
! 1722: }
! 1723:
! 1724: /*
! 1725: * default and sanity checks
! 1726: */
! 1727: if (!clcnt) {
! 1728: if (merge) {
! 1729: if ((clcnt = argc - eoptind) <= 1) {
! 1730: clcnt = CLCNT;
! 1731: merge = 0;
! 1732: }
! 1733: } else
! 1734: clcnt = CLCNT;
! 1735: }
! 1736: if (across) {
! 1737: if (clcnt == 1) {
! 1738: (void)fputs("pr: -a flag requires multiple columns\n",
! 1739: err);
! 1740: return(1);
! 1741: }
! 1742: if (merge) {
! 1743: (void)fputs("pr: -m cannot be used with -a\n", err);
! 1744: return(1);
! 1745: }
! 1746: }
! 1747: if (!wflag) {
! 1748: if (sflag)
! 1749: pgwd = SPGWD;
! 1750: else
! 1751: pgwd = PGWD;
! 1752: }
! 1753: if (cflag || merge) {
! 1754: if (!eflag) {
! 1755: inchar = INCHAR;
! 1756: ingap = INGAP;
! 1757: }
! 1758: if (!iflag) {
! 1759: ochar = OCHAR;
! 1760: ogap = OGAP;
! 1761: }
! 1762: }
! 1763: if (cflag) {
! 1764: if (merge) {
! 1765: (void)fputs(
! 1766: "pr: -m cannot be used with multiple columns\n", err);
! 1767: return(1);
! 1768: }
! 1769: if (nmwd) {
! 1770: colwd = (pgwd + 1 - (clcnt * (nmwd + 2)))/clcnt;
! 1771: pgwd = ((colwd + nmwd + 2) * clcnt) - 1;
! 1772: } else {
! 1773: colwd = (pgwd + 1 - clcnt)/clcnt;
! 1774: pgwd = ((colwd + 1) * clcnt) - 1;
! 1775: }
! 1776: if (colwd < 1) {
! 1777: (void)fprintf(err,
! 1778: "pr: page width is too small for %d columns\n",clcnt);
! 1779: return(1);
! 1780: }
! 1781: }
! 1782: if (!lines)
! 1783: lines = LINES;
! 1784:
! 1785: /*
! 1786: * make sure long enough for headers. if not disable
! 1787: */
! 1788: if (lines <= HEADLEN + TAILLEN)
! 1789: ++nohead;
! 1790: else if (!nohead)
! 1791: lines -= HEADLEN + TAILLEN;
! 1792:
! 1793: /*
! 1794: * adjust for double space on odd length pages
! 1795: */
! 1796: if (dspace) {
! 1797: if (lines == 1)
! 1798: dspace = 0;
! 1799: else {
! 1800: if (lines & 1)
! 1801: ++addone;
! 1802: lines /= 2;
! 1803: }
! 1804: }
! 1805:
! 1806: if ((timefrmt = getenv("LC_TIME")) == NULL)
! 1807: timefrmt = TIMEFMT;
! 1808: return(0);
! 1809: }