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

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