[BACK]Return to pr.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / pr

Annotation of src/usr.bin/pr/pr.c, Revision 1.5

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