[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.12

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