16ea7f916SThomas Cort /* $NetBSD: pr.c,v 1.24 2012/08/01 02:27:48 ginsbach Exp $ */
26ea7f916SThomas Cort
36ea7f916SThomas Cort /*-
46ea7f916SThomas Cort * Copyright (c) 1991 Keith Muller.
56ea7f916SThomas Cort * Copyright (c) 1993
66ea7f916SThomas Cort * The Regents of the University of California. All rights reserved.
76ea7f916SThomas Cort * Copyright (c) 2012
86ea7f916SThomas Cort * The NetBSD Foundation, Inc.
96ea7f916SThomas Cort *
106ea7f916SThomas Cort * This code is derived from software contributed to Berkeley by
116ea7f916SThomas Cort * Keith Muller of the University of California, San Diego.
126ea7f916SThomas Cort *
136ea7f916SThomas Cort * Redistribution and use in source and binary forms, with or without
146ea7f916SThomas Cort * modification, are permitted provided that the following conditions
156ea7f916SThomas Cort * are met:
166ea7f916SThomas Cort * 1. Redistributions of source code must retain the above copyright
176ea7f916SThomas Cort * notice, this list of conditions and the following disclaimer.
186ea7f916SThomas Cort * 2. Redistributions in binary form must reproduce the above copyright
196ea7f916SThomas Cort * notice, this list of conditions and the following disclaimer in the
206ea7f916SThomas Cort * documentation and/or other materials provided with the distribution.
216ea7f916SThomas Cort * 3. Neither the name of the University nor the names of its contributors
226ea7f916SThomas Cort * may be used to endorse or promote products derived from this software
236ea7f916SThomas Cort * without specific prior written permission.
246ea7f916SThomas Cort *
256ea7f916SThomas Cort * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
266ea7f916SThomas Cort * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
276ea7f916SThomas Cort * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
286ea7f916SThomas Cort * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
296ea7f916SThomas Cort * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
306ea7f916SThomas Cort * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
316ea7f916SThomas Cort * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
326ea7f916SThomas Cort * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
336ea7f916SThomas Cort * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
346ea7f916SThomas Cort * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
356ea7f916SThomas Cort * SUCH DAMAGE.
366ea7f916SThomas Cort */
376ea7f916SThomas Cort
386ea7f916SThomas Cort #include <sys/cdefs.h>
396ea7f916SThomas Cort #ifndef lint
406ea7f916SThomas Cort __COPYRIGHT("@(#) Copyright (c) 1993\
416ea7f916SThomas Cort The Regents of the University of California. All rights reserved.");
426ea7f916SThomas Cort #endif /* not lint */
436ea7f916SThomas Cort
446ea7f916SThomas Cort #ifndef lint
456ea7f916SThomas Cort #if 0
466ea7f916SThomas Cort from: static char sccsid[] = "@(#)pr.c 8.1 (Berkeley) 6/6/93";
476ea7f916SThomas Cort #else
486ea7f916SThomas Cort __RCSID("$NetBSD: pr.c,v 1.24 2012/08/01 02:27:48 ginsbach Exp $");
496ea7f916SThomas Cort #endif
506ea7f916SThomas Cort #endif /* not lint */
516ea7f916SThomas Cort
526ea7f916SThomas Cort #include <sys/types.h>
536ea7f916SThomas Cort #include <sys/time.h>
546ea7f916SThomas Cort #include <sys/stat.h>
556ea7f916SThomas Cort
566ea7f916SThomas Cort #include <ctype.h>
576ea7f916SThomas Cort #include <errno.h>
586ea7f916SThomas Cort #include <signal.h>
596ea7f916SThomas Cort #include <stdio.h>
606ea7f916SThomas Cort #include <stdlib.h>
616ea7f916SThomas Cort #include <string.h>
626ea7f916SThomas Cort #include <time.h>
636ea7f916SThomas Cort #include <unistd.h>
646ea7f916SThomas Cort #include <util.h>
656ea7f916SThomas Cort
666ea7f916SThomas Cort #include "pr.h"
676ea7f916SThomas Cort #include "extern.h"
686ea7f916SThomas Cort
696ea7f916SThomas Cort /*
706ea7f916SThomas Cort * pr: a printing and pagination filter. If multiple input files
716ea7f916SThomas Cort * are specified, each is read, formatted, and written to standard
726ea7f916SThomas Cort * output. By default, input is separated into 66-line pages, each
736ea7f916SThomas Cort * with a header that includes the page number, date, time and the
746ea7f916SThomas Cort * files pathname.
756ea7f916SThomas Cort *
766ea7f916SThomas Cort * Complies with posix P1003.2/D11
776ea7f916SThomas Cort */
786ea7f916SThomas Cort
796ea7f916SThomas Cort /*
806ea7f916SThomas Cort * parameter variables
816ea7f916SThomas Cort */
826ea7f916SThomas Cort static int pgnm; /* starting page number */
836ea7f916SThomas Cort static int clcnt; /* number of columns */
846ea7f916SThomas Cort static int colwd; /* column data width - multiple columns */
856ea7f916SThomas Cort static int across; /* mult col flag; write across page */
866ea7f916SThomas Cort static int dspace; /* double space flag */
876ea7f916SThomas Cort static char inchar; /* expand input char */
886ea7f916SThomas Cort static int ingap; /* expand input gap */
896ea7f916SThomas Cort static int formfeed; /* use formfeed as trailer */
906ea7f916SThomas Cort static char *header; /* header name instead of file name */
916ea7f916SThomas Cort static char ochar; /* contract output char */
926ea7f916SThomas Cort static int ogap; /* contract output gap */
936ea7f916SThomas Cort static int lines; /* number of lines per page */
946ea7f916SThomas Cort static int merge; /* merge multiple files in output */
956ea7f916SThomas Cort static char nmchar; /* line numbering append char */
966ea7f916SThomas Cort static int nmwd; /* width of line number field */
976ea7f916SThomas Cort static int offst; /* number of page offset spaces */
986ea7f916SThomas Cort static int nodiag; /* do not report file open errors */
996ea7f916SThomas Cort static char schar; /* text column separation character */
1006ea7f916SThomas Cort static int sflag; /* -s option for multiple columns */
1016ea7f916SThomas Cort static int ttyout; /* output is a tty */
1026ea7f916SThomas Cort static int nohead; /* do not write head and trailer */
1036ea7f916SThomas Cort static int pgpause; /* pause before each page */
1046ea7f916SThomas Cort static int pgwd; /* page width with multiple col output */
1056ea7f916SThomas Cort static const char *timefrmt = TIMEFMT; /* time conversion string */
1066ea7f916SThomas Cort static FILE *ttyinf; /* input terminal for page pauses */
1076ea7f916SThomas Cort
1086ea7f916SThomas Cort /*
1096ea7f916SThomas Cort * misc globals
1106ea7f916SThomas Cort */
1116ea7f916SThomas Cort static FILE *errf; /* error message file pointer */
1126ea7f916SThomas Cort static int addone; /* page length is odd with double space */
1136ea7f916SThomas Cort static int errcnt; /* error count on file processing */
1146ea7f916SThomas Cort static const char digs[] = "0123456789"; /* page number translation map */
1156ea7f916SThomas Cort
1166ea7f916SThomas Cort static void addnum(char *, int, int);
1176ea7f916SThomas Cort static void flsh_errs(void);
1186ea7f916SThomas Cort static int horzcol(int, char **);
1196ea7f916SThomas Cort static int inln(FILE *, char *, int, int *, int, int *);
1206ea7f916SThomas Cort static int inskip(FILE *, int, int);
1216ea7f916SThomas Cort static void mfail(void);
1226ea7f916SThomas Cort static int mulfile(int, char **);
1236ea7f916SThomas Cort static FILE *nxtfile(int, char **, const char **, char *, int);
1246ea7f916SThomas Cort static int onecol(int, char **);
1256ea7f916SThomas Cort static int otln(char *, int, int *, int *, int);
1266ea7f916SThomas Cort static void pfail(void);
1276ea7f916SThomas Cort static int prhead(char *, const char *, int);
1286ea7f916SThomas Cort static void prpause(int);
1296ea7f916SThomas Cort static int prtail(int, int);
1306ea7f916SThomas Cort static int setup(int, char **);
1316ea7f916SThomas Cort __dead static void terminate(int);
1326ea7f916SThomas Cort static void usage(void);
1336ea7f916SThomas Cort static int vertcol(int, char **);
1346ea7f916SThomas Cort
1356ea7f916SThomas Cort int
main(int argc,char * argv[])1366ea7f916SThomas Cort main(int argc, char *argv[])
1376ea7f916SThomas Cort {
1386ea7f916SThomas Cort int ret_val;
1396ea7f916SThomas Cort
1406ea7f916SThomas Cort if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1416ea7f916SThomas Cort (void)signal(SIGINT, terminate);
1426ea7f916SThomas Cort ret_val = setup(argc, argv);
1436ea7f916SThomas Cort if (!ret_val) {
1446ea7f916SThomas Cort /*
1456ea7f916SThomas Cort * select the output format based on options
1466ea7f916SThomas Cort */
1476ea7f916SThomas Cort if (merge)
1486ea7f916SThomas Cort ret_val = mulfile(argc, argv);
1496ea7f916SThomas Cort else if (clcnt == 1)
1506ea7f916SThomas Cort ret_val = onecol(argc, argv);
1516ea7f916SThomas Cort else if (across)
1526ea7f916SThomas Cort ret_val = horzcol(argc, argv);
1536ea7f916SThomas Cort else
1546ea7f916SThomas Cort ret_val = vertcol(argc, argv);
1556ea7f916SThomas Cort } else
1566ea7f916SThomas Cort usage();
1576ea7f916SThomas Cort flsh_errs();
1586ea7f916SThomas Cort if (errcnt || ret_val)
1596ea7f916SThomas Cort exit(1);
1606ea7f916SThomas Cort return(0);
1616ea7f916SThomas Cort }
1626ea7f916SThomas Cort
1636ea7f916SThomas Cort /*
1646ea7f916SThomas Cort * onecol: print files with only one column of output.
1656ea7f916SThomas Cort * Line length is unlimited.
1666ea7f916SThomas Cort */
1676ea7f916SThomas Cort static int
onecol(int argc,char * argv[])1686ea7f916SThomas Cort onecol(int argc, char *argv[])
1696ea7f916SThomas Cort {
1706ea7f916SThomas Cort int cnt = -1;
1716ea7f916SThomas Cort int off;
1726ea7f916SThomas Cort int lrgln;
1736ea7f916SThomas Cort int linecnt;
1746ea7f916SThomas Cort int num;
1756ea7f916SThomas Cort int lncnt;
1766ea7f916SThomas Cort int pagecnt;
1776ea7f916SThomas Cort int ips;
1786ea7f916SThomas Cort int ops;
1796ea7f916SThomas Cort int cps;
1806ea7f916SThomas Cort char *obuf = NULL;
1816ea7f916SThomas Cort char *lbuf;
1826ea7f916SThomas Cort char *nbuf;
1836ea7f916SThomas Cort char *hbuf = NULL;
1846ea7f916SThomas Cort char *ohbuf;
1856ea7f916SThomas Cort FILE *inf = NULL;
1866ea7f916SThomas Cort const char *fname;
1876ea7f916SThomas Cort int mor;
1886ea7f916SThomas Cort int error = 1;
1896ea7f916SThomas Cort
190*e1cdaee1SLionel Sambuc #if defined(__minix)
191*e1cdaee1SLionel Sambuc /* LSC: -Werror=maybe-uninitialized, when compiling with -O3 */
192*e1cdaee1SLionel Sambuc mor = 0;
193*e1cdaee1SLionel Sambuc #endif /* defined(__minix) */
1946ea7f916SThomas Cort if (nmwd)
1956ea7f916SThomas Cort num = nmwd + 1;
1966ea7f916SThomas Cort else
1976ea7f916SThomas Cort num = 0;
1986ea7f916SThomas Cort off = num + offst;
1996ea7f916SThomas Cort
2006ea7f916SThomas Cort /*
2016ea7f916SThomas Cort * allocate line buffer
2026ea7f916SThomas Cort */
2036ea7f916SThomas Cort if ((obuf = malloc((unsigned)(LBUF + off)*sizeof(char))) == NULL)
2046ea7f916SThomas Cort goto oomem;
2056ea7f916SThomas Cort /*
2066ea7f916SThomas Cort * allocate header buffer
2076ea7f916SThomas Cort */
2086ea7f916SThomas Cort if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL)
2096ea7f916SThomas Cort goto oomem;
2106ea7f916SThomas Cort
2116ea7f916SThomas Cort ohbuf = hbuf + offst;
2126ea7f916SThomas Cort nbuf = obuf + offst;
2136ea7f916SThomas Cort lbuf = nbuf + num;
2146ea7f916SThomas Cort if (num)
2156ea7f916SThomas Cort nbuf[--num] = nmchar;
2166ea7f916SThomas Cort if (offst) {
2176ea7f916SThomas Cort (void)memset(obuf, (int)' ', offst);
2186ea7f916SThomas Cort (void)memset(hbuf, (int)' ', offst);
2196ea7f916SThomas Cort }
2206ea7f916SThomas Cort
2216ea7f916SThomas Cort /*
2226ea7f916SThomas Cort * loop by file
2236ea7f916SThomas Cort */
2246ea7f916SThomas Cort while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
2256ea7f916SThomas Cort if (pgnm) {
2266ea7f916SThomas Cort /*
2276ea7f916SThomas Cort * skip to specified page
2286ea7f916SThomas Cort */
2296ea7f916SThomas Cort if (inskip(inf, pgnm, lines))
2306ea7f916SThomas Cort continue;
2316ea7f916SThomas Cort pagecnt = pgnm;
2326ea7f916SThomas Cort } else
2336ea7f916SThomas Cort pagecnt = 1;
2346ea7f916SThomas Cort lncnt = 0;
2356ea7f916SThomas Cort
2366ea7f916SThomas Cort /*
2376ea7f916SThomas Cort * loop by page
2386ea7f916SThomas Cort */
2396ea7f916SThomas Cort for(;;) {
2406ea7f916SThomas Cort linecnt = 0;
2416ea7f916SThomas Cort lrgln = 0;
2426ea7f916SThomas Cort ops = 0;
2436ea7f916SThomas Cort ips = 0;
2446ea7f916SThomas Cort cps = 0;
2456ea7f916SThomas Cort
2466ea7f916SThomas Cort /*
2476ea7f916SThomas Cort * loop by line
2486ea7f916SThomas Cort */
2496ea7f916SThomas Cort while (linecnt < lines) {
2506ea7f916SThomas Cort /*
2516ea7f916SThomas Cort * input next line
2526ea7f916SThomas Cort */
2536ea7f916SThomas Cort if ((cnt = inln(inf,lbuf,LBUF,&cps,0,&mor)) < 0)
2546ea7f916SThomas Cort break;
2556ea7f916SThomas Cort if (!linecnt) {
2566ea7f916SThomas Cort if (pgpause)
2576ea7f916SThomas Cort prpause(pagecnt);
2586ea7f916SThomas Cort
2596ea7f916SThomas Cort if (!nohead &&
2606ea7f916SThomas Cort prhead(hbuf, fname, pagecnt))
2616ea7f916SThomas Cort goto out;
2626ea7f916SThomas Cort }
2636ea7f916SThomas Cort
2646ea7f916SThomas Cort /*
2656ea7f916SThomas Cort * start of new line.
2666ea7f916SThomas Cort */
2676ea7f916SThomas Cort if (!lrgln) {
2686ea7f916SThomas Cort if (num)
2696ea7f916SThomas Cort addnum(nbuf, num, ++lncnt);
2706ea7f916SThomas Cort if (otln(obuf,cnt+off, &ips, &ops, mor))
2716ea7f916SThomas Cort goto out;
2726ea7f916SThomas Cort } else if (otln(lbuf, cnt, &ips, &ops, mor))
2736ea7f916SThomas Cort goto out;
2746ea7f916SThomas Cort
2756ea7f916SThomas Cort /*
2766ea7f916SThomas Cort * if line bigger than buffer, get more
2776ea7f916SThomas Cort */
2786ea7f916SThomas Cort if (mor) {
2796ea7f916SThomas Cort lrgln = 1;
2806ea7f916SThomas Cort continue;
2816ea7f916SThomas Cort }
2826ea7f916SThomas Cort
2836ea7f916SThomas Cort /*
2846ea7f916SThomas Cort * whole line rcvd. reset tab proc. state
2856ea7f916SThomas Cort */
2866ea7f916SThomas Cort ++linecnt;
2876ea7f916SThomas Cort lrgln = 0;
2886ea7f916SThomas Cort ops = 0;
2896ea7f916SThomas Cort ips = 0;
2906ea7f916SThomas Cort }
2916ea7f916SThomas Cort
2926ea7f916SThomas Cort /*
2936ea7f916SThomas Cort * fill to end of page
2946ea7f916SThomas Cort */
2956ea7f916SThomas Cort if (linecnt && prtail(lines-linecnt-lrgln, lrgln))
2966ea7f916SThomas Cort goto out;
2976ea7f916SThomas Cort
2986ea7f916SThomas Cort /*
2996ea7f916SThomas Cort * On EOF go to next file
3006ea7f916SThomas Cort */
3016ea7f916SThomas Cort if (cnt < 0)
3026ea7f916SThomas Cort break;
3036ea7f916SThomas Cort ++pagecnt;
3046ea7f916SThomas Cort }
3056ea7f916SThomas Cort if (inf != stdin)
3066ea7f916SThomas Cort (void)fclose(inf);
3076ea7f916SThomas Cort }
3086ea7f916SThomas Cort if (eoptind < argc)
3096ea7f916SThomas Cort goto out;
3106ea7f916SThomas Cort error = 0;
3116ea7f916SThomas Cort goto out;
3126ea7f916SThomas Cort oomem:
3136ea7f916SThomas Cort mfail();
3146ea7f916SThomas Cort out:
3156ea7f916SThomas Cort free(obuf);
3166ea7f916SThomas Cort free(hbuf);
3176ea7f916SThomas Cort if (inf != NULL && inf != stdin)
3186ea7f916SThomas Cort (void)fclose(inf);
3196ea7f916SThomas Cort return error;
3206ea7f916SThomas Cort }
3216ea7f916SThomas Cort
3226ea7f916SThomas Cort /*
3236ea7f916SThomas Cort * vertcol: print files with more than one column of output down a page
3246ea7f916SThomas Cort */
3256ea7f916SThomas Cort static int
vertcol(int argc,char * argv[])3266ea7f916SThomas Cort vertcol(int argc, char *argv[])
3276ea7f916SThomas Cort {
3286ea7f916SThomas Cort char *ptbf;
3296ea7f916SThomas Cort char **lstdat = NULL;
3306ea7f916SThomas Cort int i;
3316ea7f916SThomas Cort int j;
3326ea7f916SThomas Cort int cnt = -1;
3336ea7f916SThomas Cort int pln;
3346ea7f916SThomas Cort int *indy = NULL;
3356ea7f916SThomas Cort int cvc;
3366ea7f916SThomas Cort int *lindy = NULL;
3376ea7f916SThomas Cort int lncnt;
3386ea7f916SThomas Cort int stp;
3396ea7f916SThomas Cort int pagecnt;
3406ea7f916SThomas Cort int col = colwd + 1;
3416ea7f916SThomas Cort int mxlen = pgwd + offst + 1;
3426ea7f916SThomas Cort int mclcnt = clcnt - 1;
3436ea7f916SThomas Cort struct vcol *vc = NULL;
3446ea7f916SThomas Cort int mvc;
3456ea7f916SThomas Cort int tvc;
3466ea7f916SThomas Cort int cw = nmwd + 1;
3476ea7f916SThomas Cort int fullcol;
3486ea7f916SThomas Cort char *buf = NULL;
3496ea7f916SThomas Cort char *hbuf = NULL;
3506ea7f916SThomas Cort char *ohbuf;
3516ea7f916SThomas Cort const char *fname;
3526ea7f916SThomas Cort FILE *inf = NULL;
3536ea7f916SThomas Cort int ips = 0;
3546ea7f916SThomas Cort int cps = 0;
3556ea7f916SThomas Cort int ops = 0;
3566ea7f916SThomas Cort int mor = 0;
3576ea7f916SThomas Cort int error = 1;
3586ea7f916SThomas Cort
3596ea7f916SThomas Cort /*
3606ea7f916SThomas Cort * allocate page buffer
3616ea7f916SThomas Cort */
3626ea7f916SThomas Cort if ((buf = malloc((unsigned)lines*mxlen*sizeof(char))) == NULL)
3636ea7f916SThomas Cort goto oomem;
3646ea7f916SThomas Cort
3656ea7f916SThomas Cort /*
3666ea7f916SThomas Cort * allocate page header
3676ea7f916SThomas Cort */
3686ea7f916SThomas Cort if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL)
3696ea7f916SThomas Cort goto oomem;
3706ea7f916SThomas Cort ohbuf = hbuf + offst;
3716ea7f916SThomas Cort if (offst)
3726ea7f916SThomas Cort (void)memset(hbuf, (int)' ', offst);
3736ea7f916SThomas Cort
3746ea7f916SThomas Cort /*
3756ea7f916SThomas Cort * col pointers when no headers
3766ea7f916SThomas Cort */
3776ea7f916SThomas Cort mvc = lines * clcnt;
3786ea7f916SThomas Cort if ((vc = malloc((unsigned)mvc*sizeof(struct vcol))) == NULL)
3796ea7f916SThomas Cort goto oomem;
3806ea7f916SThomas Cort
3816ea7f916SThomas Cort /*
3826ea7f916SThomas Cort * pointer into page where last data per line is located
3836ea7f916SThomas Cort */
3846ea7f916SThomas Cort if ((lstdat = malloc((unsigned)lines*sizeof(char *))) == NULL)
3856ea7f916SThomas Cort goto oomem;
3866ea7f916SThomas Cort
3876ea7f916SThomas Cort /*
3886ea7f916SThomas Cort * fast index lookups to locate start of lines
3896ea7f916SThomas Cort */
3906ea7f916SThomas Cort if ((indy = malloc((unsigned)lines*sizeof(int))) == NULL)
3916ea7f916SThomas Cort goto oomem;
3926ea7f916SThomas Cort if ((lindy = malloc((unsigned)lines*sizeof(int))) == NULL)
3936ea7f916SThomas Cort goto oomem;
3946ea7f916SThomas Cort
3956ea7f916SThomas Cort if (nmwd)
3966ea7f916SThomas Cort fullcol = col + cw;
3976ea7f916SThomas Cort else
3986ea7f916SThomas Cort fullcol = col;
3996ea7f916SThomas Cort
4006ea7f916SThomas Cort /*
4016ea7f916SThomas Cort * initialize buffer lookup indexes and offset area
4026ea7f916SThomas Cort */
4036ea7f916SThomas Cort for (j = 0; j < lines; ++j) {
4046ea7f916SThomas Cort lindy[j] = j * mxlen;
4056ea7f916SThomas Cort indy[j] = lindy[j] + offst;
4066ea7f916SThomas Cort if (offst) {
4076ea7f916SThomas Cort ptbf = buf + lindy[j];
4086ea7f916SThomas Cort (void)memset(ptbf, (int)' ', offst);
4096ea7f916SThomas Cort ptbf += offst;
4106ea7f916SThomas Cort } else
4116ea7f916SThomas Cort ptbf = buf + indy[j];
4126ea7f916SThomas Cort lstdat[j] = ptbf;
4136ea7f916SThomas Cort }
4146ea7f916SThomas Cort
4156ea7f916SThomas Cort /*
4166ea7f916SThomas Cort * loop by file
4176ea7f916SThomas Cort */
4186ea7f916SThomas Cort while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
4196ea7f916SThomas Cort if (pgnm) {
4206ea7f916SThomas Cort /*
4216ea7f916SThomas Cort * skip to requested page
4226ea7f916SThomas Cort */
4236ea7f916SThomas Cort if (inskip(inf, pgnm, lines))
4246ea7f916SThomas Cort continue;
4256ea7f916SThomas Cort pagecnt = pgnm;
4266ea7f916SThomas Cort } else
4276ea7f916SThomas Cort pagecnt = 1;
4286ea7f916SThomas Cort lncnt = 0;
4296ea7f916SThomas Cort
4306ea7f916SThomas Cort /*
4316ea7f916SThomas Cort * loop by page
4326ea7f916SThomas Cort */
4336ea7f916SThomas Cort for(;;) {
4346ea7f916SThomas Cort /*
4356ea7f916SThomas Cort * loop by column
4366ea7f916SThomas Cort */
4376ea7f916SThomas Cort cvc = 0;
4386ea7f916SThomas Cort for (i = 0; i < clcnt; ++i) {
4396ea7f916SThomas Cort j = 0;
4406ea7f916SThomas Cort /*
4416ea7f916SThomas Cort * if last column, do not pad
4426ea7f916SThomas Cort */
4436ea7f916SThomas Cort if (i == mclcnt)
4446ea7f916SThomas Cort stp = 1;
4456ea7f916SThomas Cort else
4466ea7f916SThomas Cort stp = 0;
4476ea7f916SThomas Cort /*
4486ea7f916SThomas Cort * loop by line
4496ea7f916SThomas Cort */
4506ea7f916SThomas Cort for(;;) {
4516ea7f916SThomas Cort /*
4526ea7f916SThomas Cort * is this first column
4536ea7f916SThomas Cort */
4546ea7f916SThomas Cort if (!i) {
4556ea7f916SThomas Cort ptbf = buf + indy[j];
4566ea7f916SThomas Cort lstdat[j] = ptbf;
4576ea7f916SThomas Cort } else
4586ea7f916SThomas Cort ptbf = lstdat[j];
4596ea7f916SThomas Cort vc[cvc].pt = ptbf;
4606ea7f916SThomas Cort
4616ea7f916SThomas Cort /*
4626ea7f916SThomas Cort * add number
4636ea7f916SThomas Cort */
4646ea7f916SThomas Cort if (nmwd) {
4656ea7f916SThomas Cort addnum(ptbf, nmwd, ++lncnt);
4666ea7f916SThomas Cort ptbf += nmwd;
4676ea7f916SThomas Cort *ptbf++ = nmchar;
4686ea7f916SThomas Cort }
4696ea7f916SThomas Cort
4706ea7f916SThomas Cort /*
4716ea7f916SThomas Cort * input next line
4726ea7f916SThomas Cort */
4736ea7f916SThomas Cort cnt = inln(inf,ptbf,colwd,&cps,1,&mor);
4746ea7f916SThomas Cort vc[cvc++].cnt = cnt;
4756ea7f916SThomas Cort if (cnt < 0)
4766ea7f916SThomas Cort break;
4776ea7f916SThomas Cort ptbf += cnt;
4786ea7f916SThomas Cort
4796ea7f916SThomas Cort /*
4806ea7f916SThomas Cort * pad all but last column on page
4816ea7f916SThomas Cort */
4826ea7f916SThomas Cort if (!stp) {
4836ea7f916SThomas Cort /*
4846ea7f916SThomas Cort * pad to end of column
4856ea7f916SThomas Cort */
4866ea7f916SThomas Cort if (sflag)
4876ea7f916SThomas Cort *ptbf++ = schar;
4886ea7f916SThomas Cort else if ((pln = col-cnt) > 0) {
4896ea7f916SThomas Cort (void)memset(ptbf,
4906ea7f916SThomas Cort (int)' ',pln);
4916ea7f916SThomas Cort ptbf += pln;
4926ea7f916SThomas Cort }
4936ea7f916SThomas Cort }
4946ea7f916SThomas Cort /*
4956ea7f916SThomas Cort * remember last char in line
4966ea7f916SThomas Cort */
4976ea7f916SThomas Cort lstdat[j] = ptbf;
4986ea7f916SThomas Cort if (++j >= lines)
4996ea7f916SThomas Cort break;
5006ea7f916SThomas Cort }
5016ea7f916SThomas Cort if (cnt < 0)
5026ea7f916SThomas Cort break;
5036ea7f916SThomas Cort }
5046ea7f916SThomas Cort
5056ea7f916SThomas Cort /*
5066ea7f916SThomas Cort * when -t (no header) is specified the spec requires
5076ea7f916SThomas Cort * the min number of lines. The last page may not have
5086ea7f916SThomas Cort * balanced length columns. To fix this we must reorder
5096ea7f916SThomas Cort * the columns. This is a very slow technique so it is
5106ea7f916SThomas Cort * only used under limited conditions. Without -t, the
5116ea7f916SThomas Cort * balancing of text columns is unspecified. To NOT
5126ea7f916SThomas Cort * balance the last page, add the global variable
5136ea7f916SThomas Cort * nohead to the if statement below e.g.
5146ea7f916SThomas Cort *
5156ea7f916SThomas Cort * if ((cnt < 0) && nohead && cvc ......
5166ea7f916SThomas Cort */
5176ea7f916SThomas Cort --cvc;
5186ea7f916SThomas Cort
5196ea7f916SThomas Cort /*
5206ea7f916SThomas Cort * check to see if last page needs to be reordered
5216ea7f916SThomas Cort */
5226ea7f916SThomas Cort if ((cnt < 0) && cvc && ((mvc-cvc) >= clcnt)){
5236ea7f916SThomas Cort pln = cvc/clcnt;
5246ea7f916SThomas Cort if (cvc % clcnt)
5256ea7f916SThomas Cort ++pln;
5266ea7f916SThomas Cort
5276ea7f916SThomas Cort if (pgpause)
5286ea7f916SThomas Cort prpause(pagecnt);
5296ea7f916SThomas Cort
5306ea7f916SThomas Cort /*
5316ea7f916SThomas Cort * print header
5326ea7f916SThomas Cort */
5336ea7f916SThomas Cort if (!nohead && prhead(hbuf, fname, pagecnt))
5346ea7f916SThomas Cort goto out;
5356ea7f916SThomas Cort for (i = 0; i < pln; ++i) {
5366ea7f916SThomas Cort ips = 0;
5376ea7f916SThomas Cort ops = 0;
5386ea7f916SThomas Cort if (offst&& otln(buf,offst,&ips,&ops,1)) {
5396ea7f916SThomas Cort error = 1;
5406ea7f916SThomas Cort goto out;
5416ea7f916SThomas Cort }
5426ea7f916SThomas Cort tvc = i;
5436ea7f916SThomas Cort
5446ea7f916SThomas Cort for (j = 0; j < clcnt; ++j) {
5456ea7f916SThomas Cort /*
5466ea7f916SThomas Cort * determine column length
5476ea7f916SThomas Cort */
5486ea7f916SThomas Cort if (j == mclcnt) {
5496ea7f916SThomas Cort /*
5506ea7f916SThomas Cort * last column
5516ea7f916SThomas Cort */
5526ea7f916SThomas Cort cnt = vc[tvc].cnt;
5536ea7f916SThomas Cort if (nmwd)
5546ea7f916SThomas Cort cnt += cw;
5556ea7f916SThomas Cort } else if (sflag) {
5566ea7f916SThomas Cort /*
5576ea7f916SThomas Cort * single ch between
5586ea7f916SThomas Cort */
5596ea7f916SThomas Cort cnt = vc[tvc].cnt + 1;
5606ea7f916SThomas Cort if (nmwd)
5616ea7f916SThomas Cort cnt += cw;
5626ea7f916SThomas Cort } else
5636ea7f916SThomas Cort cnt = fullcol;
5646ea7f916SThomas Cort if (otln(vc[tvc].pt, cnt, &ips,
5656ea7f916SThomas Cort &ops, 1))
5666ea7f916SThomas Cort goto out;
5676ea7f916SThomas Cort tvc += pln;
5686ea7f916SThomas Cort if (tvc >= cvc)
5696ea7f916SThomas Cort break;
5706ea7f916SThomas Cort }
5716ea7f916SThomas Cort /*
5726ea7f916SThomas Cort * terminate line
5736ea7f916SThomas Cort */
5746ea7f916SThomas Cort if (otln(buf, 0, &ips, &ops, 0))
5756ea7f916SThomas Cort goto out;
5766ea7f916SThomas Cort }
5776ea7f916SThomas Cort /*
5786ea7f916SThomas Cort * pad to end of page
5796ea7f916SThomas Cort */
5806ea7f916SThomas Cort if (prtail((lines - pln), 0))
5816ea7f916SThomas Cort goto out;
5826ea7f916SThomas Cort /*
5836ea7f916SThomas Cort * done with output, go to next file
5846ea7f916SThomas Cort */
5856ea7f916SThomas Cort break;
5866ea7f916SThomas Cort }
5876ea7f916SThomas Cort
5886ea7f916SThomas Cort /*
5896ea7f916SThomas Cort * determine how many lines to output
5906ea7f916SThomas Cort */
5916ea7f916SThomas Cort if (i > 0)
5926ea7f916SThomas Cort pln = lines;
5936ea7f916SThomas Cort else
5946ea7f916SThomas Cort pln = j;
5956ea7f916SThomas Cort
5966ea7f916SThomas Cort /*
5976ea7f916SThomas Cort * print header
5986ea7f916SThomas Cort */
5996ea7f916SThomas Cort if (pln) {
6006ea7f916SThomas Cort if (pgpause)
6016ea7f916SThomas Cort prpause(pagecnt);
6026ea7f916SThomas Cort
6036ea7f916SThomas Cort if (!nohead && prhead(hbuf, fname, pagecnt))
6046ea7f916SThomas Cort goto out;
6056ea7f916SThomas Cort }
6066ea7f916SThomas Cort
6076ea7f916SThomas Cort /*
6086ea7f916SThomas Cort * output each line
6096ea7f916SThomas Cort */
6106ea7f916SThomas Cort for (i = 0; i < pln; ++i) {
6116ea7f916SThomas Cort ptbf = buf + lindy[i];
6126ea7f916SThomas Cort if ((j = lstdat[i] - ptbf) <= offst)
6136ea7f916SThomas Cort break;
6146ea7f916SThomas Cort if (otln(ptbf, j, &ips, &ops, 0))
6156ea7f916SThomas Cort goto out;
6166ea7f916SThomas Cort }
6176ea7f916SThomas Cort
6186ea7f916SThomas Cort /*
6196ea7f916SThomas Cort * pad to end of page
6206ea7f916SThomas Cort */
6216ea7f916SThomas Cort if (pln && prtail((lines - pln), 0))
6226ea7f916SThomas Cort goto out;
6236ea7f916SThomas Cort
6246ea7f916SThomas Cort /*
6256ea7f916SThomas Cort * if EOF go to next file
6266ea7f916SThomas Cort */
6276ea7f916SThomas Cort if (cnt < 0)
6286ea7f916SThomas Cort break;
6296ea7f916SThomas Cort ++pagecnt;
6306ea7f916SThomas Cort }
6316ea7f916SThomas Cort if (inf != stdin)
6326ea7f916SThomas Cort (void)fclose(inf);
6336ea7f916SThomas Cort }
6346ea7f916SThomas Cort if (eoptind < argc)
6356ea7f916SThomas Cort goto out;
6366ea7f916SThomas Cort error = 0;
6376ea7f916SThomas Cort goto out;
6386ea7f916SThomas Cort oomem:
6396ea7f916SThomas Cort mfail();
6406ea7f916SThomas Cort out:
6416ea7f916SThomas Cort free(buf);
6426ea7f916SThomas Cort free(hbuf);
6436ea7f916SThomas Cort free(vc);
6446ea7f916SThomas Cort free(lstdat);
6456ea7f916SThomas Cort free(lindy);
6466ea7f916SThomas Cort if (inf != NULL && inf != stdin)
6476ea7f916SThomas Cort (void)fclose(inf);
6486ea7f916SThomas Cort return error;
6496ea7f916SThomas Cort }
6506ea7f916SThomas Cort
6516ea7f916SThomas Cort /*
6526ea7f916SThomas Cort * horzcol: print files with more than one column of output across a page
6536ea7f916SThomas Cort */
6546ea7f916SThomas Cort static int
horzcol(int argc,char * argv[])6556ea7f916SThomas Cort horzcol(int argc, char *argv[])
6566ea7f916SThomas Cort {
6576ea7f916SThomas Cort char *ptbf;
6586ea7f916SThomas Cort int pln;
6596ea7f916SThomas Cort int cnt = -1;
6606ea7f916SThomas Cort char *lstdat;
6616ea7f916SThomas Cort int col = colwd + 1;
6626ea7f916SThomas Cort int j;
6636ea7f916SThomas Cort int i;
6646ea7f916SThomas Cort int lncnt;
6656ea7f916SThomas Cort int pagecnt;
6666ea7f916SThomas Cort char *buf = NULL;
6676ea7f916SThomas Cort char *hbuf = NULL;
6686ea7f916SThomas Cort char *ohbuf;
6696ea7f916SThomas Cort const char *fname;
6706ea7f916SThomas Cort FILE *inf = NULL;
6716ea7f916SThomas Cort int ips = 0;
6726ea7f916SThomas Cort int cps = 0;
6736ea7f916SThomas Cort int ops = 0;
6746ea7f916SThomas Cort int mor = 0;
6756ea7f916SThomas Cort int error = 1;
6766ea7f916SThomas Cort
6776ea7f916SThomas Cort if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL)
6786ea7f916SThomas Cort goto oomem;
6796ea7f916SThomas Cort
6806ea7f916SThomas Cort /*
6816ea7f916SThomas Cort * page header
6826ea7f916SThomas Cort */
6836ea7f916SThomas Cort if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL)
6846ea7f916SThomas Cort goto oomem;
6856ea7f916SThomas Cort ohbuf = hbuf + offst;
6866ea7f916SThomas Cort if (offst) {
6876ea7f916SThomas Cort (void)memset(buf, (int)' ', offst);
6886ea7f916SThomas Cort (void)memset(hbuf, (int)' ', offst);
6896ea7f916SThomas Cort }
6906ea7f916SThomas Cort
6916ea7f916SThomas Cort /*
6926ea7f916SThomas Cort * loop by file
6936ea7f916SThomas Cort */
6946ea7f916SThomas Cort while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
6956ea7f916SThomas Cort if (pgnm) {
6966ea7f916SThomas Cort if (inskip(inf, pgnm, lines))
6976ea7f916SThomas Cort continue;
6986ea7f916SThomas Cort pagecnt = pgnm;
6996ea7f916SThomas Cort } else
7006ea7f916SThomas Cort pagecnt = 1;
7016ea7f916SThomas Cort lncnt = 0;
7026ea7f916SThomas Cort
7036ea7f916SThomas Cort /*
7046ea7f916SThomas Cort * loop by page
7056ea7f916SThomas Cort */
7066ea7f916SThomas Cort for(;;) {
7076ea7f916SThomas Cort /*
7086ea7f916SThomas Cort * loop by line
7096ea7f916SThomas Cort */
7106ea7f916SThomas Cort for (i = 0; i < lines; ++i) {
7116ea7f916SThomas Cort ptbf = buf + offst;
7126ea7f916SThomas Cort lstdat = ptbf;
7136ea7f916SThomas Cort j = 0;
7146ea7f916SThomas Cort /*
7156ea7f916SThomas Cort * loop by col
7166ea7f916SThomas Cort */
7176ea7f916SThomas Cort for(;;) {
7186ea7f916SThomas Cort if (nmwd) {
7196ea7f916SThomas Cort /*
7206ea7f916SThomas Cort * add number to column
7216ea7f916SThomas Cort */
7226ea7f916SThomas Cort addnum(ptbf, nmwd, ++lncnt);
7236ea7f916SThomas Cort ptbf += nmwd;
7246ea7f916SThomas Cort *ptbf++ = nmchar;
7256ea7f916SThomas Cort }
7266ea7f916SThomas Cort /*
7276ea7f916SThomas Cort * input line
7286ea7f916SThomas Cort */
7296ea7f916SThomas Cort if ((cnt = inln(inf,ptbf,colwd,&cps,1,
7306ea7f916SThomas Cort &mor)) < 0)
7316ea7f916SThomas Cort break;
7326ea7f916SThomas Cort ptbf += cnt;
7336ea7f916SThomas Cort lstdat = ptbf;
7346ea7f916SThomas Cort
7356ea7f916SThomas Cort /*
7366ea7f916SThomas Cort * if last line skip padding
7376ea7f916SThomas Cort */
7386ea7f916SThomas Cort if (++j >= clcnt)
7396ea7f916SThomas Cort break;
7406ea7f916SThomas Cort
7416ea7f916SThomas Cort /*
7426ea7f916SThomas Cort * pad to end of column
7436ea7f916SThomas Cort */
7446ea7f916SThomas Cort if (sflag)
7456ea7f916SThomas Cort *ptbf++ = schar;
7466ea7f916SThomas Cort else if ((pln = col - cnt) > 0) {
7476ea7f916SThomas Cort (void)memset(ptbf,(int)' ',pln);
7486ea7f916SThomas Cort ptbf += pln;
7496ea7f916SThomas Cort }
7506ea7f916SThomas Cort }
7516ea7f916SThomas Cort
7526ea7f916SThomas Cort /*
7536ea7f916SThomas Cort * determine line length
7546ea7f916SThomas Cort */
7556ea7f916SThomas Cort if ((j = lstdat - buf) <= offst)
7566ea7f916SThomas Cort break;
7576ea7f916SThomas Cort if (!i) {
7586ea7f916SThomas Cort if (pgpause)
7596ea7f916SThomas Cort prpause(pagecnt);
7606ea7f916SThomas Cort
7616ea7f916SThomas Cort if (!nohead &&
7626ea7f916SThomas Cort prhead(hbuf, fname, pagecnt))
7636ea7f916SThomas Cort goto out;
7646ea7f916SThomas Cort }
7656ea7f916SThomas Cort /*
7666ea7f916SThomas Cort * output line
7676ea7f916SThomas Cort */
7686ea7f916SThomas Cort if (otln(buf, j, &ips, &ops, 0))
7696ea7f916SThomas Cort goto out;
7706ea7f916SThomas Cort }
7716ea7f916SThomas Cort
7726ea7f916SThomas Cort /*
7736ea7f916SThomas Cort * pad to end of page
7746ea7f916SThomas Cort */
7756ea7f916SThomas Cort if (i && prtail(lines-i, 0))
7766ea7f916SThomas Cort goto out;
7776ea7f916SThomas Cort
7786ea7f916SThomas Cort /*
7796ea7f916SThomas Cort * if EOF go to next file
7806ea7f916SThomas Cort */
7816ea7f916SThomas Cort if (cnt < 0)
7826ea7f916SThomas Cort break;
7836ea7f916SThomas Cort ++pagecnt;
7846ea7f916SThomas Cort }
7856ea7f916SThomas Cort if (inf != stdin)
7866ea7f916SThomas Cort (void)fclose(inf);
7876ea7f916SThomas Cort }
7886ea7f916SThomas Cort if (eoptind < argc)
7896ea7f916SThomas Cort goto out;
7906ea7f916SThomas Cort error = 0;
7916ea7f916SThomas Cort goto out;
7926ea7f916SThomas Cort oomem:
7936ea7f916SThomas Cort mfail();
7946ea7f916SThomas Cort out:
7956ea7f916SThomas Cort free(buf);
7966ea7f916SThomas Cort free(hbuf);
7976ea7f916SThomas Cort if (inf != NULL && inf != stdin)
7986ea7f916SThomas Cort (void)fclose(inf);
7996ea7f916SThomas Cort return error;
8006ea7f916SThomas Cort }
8016ea7f916SThomas Cort
8026ea7f916SThomas Cort /*
8036ea7f916SThomas Cort * mulfile: print files with more than one column of output and
8046ea7f916SThomas Cort * more than one file concurrently
8056ea7f916SThomas Cort */
8066ea7f916SThomas Cort static int
mulfile(int argc,char * argv[])8076ea7f916SThomas Cort mulfile(int argc, char *argv[])
8086ea7f916SThomas Cort {
8096ea7f916SThomas Cort char *ptbf;
8106ea7f916SThomas Cort int j;
8116ea7f916SThomas Cort int pln;
8126ea7f916SThomas Cort int cnt;
8136ea7f916SThomas Cort char *lstdat;
8146ea7f916SThomas Cort int i;
8156ea7f916SThomas Cort FILE **fbuf = NULL;
8166ea7f916SThomas Cort int actf;
8176ea7f916SThomas Cort int lncnt;
8186ea7f916SThomas Cort int col;
8196ea7f916SThomas Cort int pagecnt;
8206ea7f916SThomas Cort int fproc;
8216ea7f916SThomas Cort char *buf = NULL;
8226ea7f916SThomas Cort char *hbuf = NULL;
8236ea7f916SThomas Cort char *ohbuf;
8246ea7f916SThomas Cort const char *fname;
8256ea7f916SThomas Cort int ips = 0;
8266ea7f916SThomas Cort int cps = 0;
8276ea7f916SThomas Cort int ops = 0;
8286ea7f916SThomas Cort int mor = 0;
8296ea7f916SThomas Cort int error = 1;
8306ea7f916SThomas Cort
8316ea7f916SThomas Cort /*
8326ea7f916SThomas Cort * array of FILE *, one for each operand
8336ea7f916SThomas Cort */
8346ea7f916SThomas Cort if ((fbuf = calloc(clcnt, sizeof(FILE *))) == NULL)
8356ea7f916SThomas Cort goto oomem;
8366ea7f916SThomas Cort
8376ea7f916SThomas Cort /*
8386ea7f916SThomas Cort * page header
8396ea7f916SThomas Cort */
8406ea7f916SThomas Cort if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL)
8416ea7f916SThomas Cort goto oomem;
8426ea7f916SThomas Cort ohbuf = hbuf + offst;
8436ea7f916SThomas Cort
8446ea7f916SThomas Cort /*
8456ea7f916SThomas Cort * do not know how many columns yet. The number of operands provide an
8466ea7f916SThomas Cort * upper bound on the number of columns. We use the number of files
8476ea7f916SThomas Cort * we can open successfully to set the number of columns. The operation
8486ea7f916SThomas Cort * of the merge operation (-m) in relation to unsuccesful file opens
8496ea7f916SThomas Cort * is unspecified by posix.
8506ea7f916SThomas Cort */
8516ea7f916SThomas Cort j = 0;
8526ea7f916SThomas Cort while (j < clcnt) {
8536ea7f916SThomas Cort if ((fbuf[j] = nxtfile(argc, argv, &fname, ohbuf, 1)) == NULL)
8546ea7f916SThomas Cort break;
8556ea7f916SThomas Cort if (pgnm && (inskip(fbuf[j], pgnm, lines)))
8566ea7f916SThomas Cort fbuf[j] = NULL;
8576ea7f916SThomas Cort ++j;
8586ea7f916SThomas Cort }
8596ea7f916SThomas Cort
8606ea7f916SThomas Cort /*
8616ea7f916SThomas Cort * if no files, exit
8626ea7f916SThomas Cort */
8636ea7f916SThomas Cort if (!j)
8646ea7f916SThomas Cort goto out;
8656ea7f916SThomas Cort
8666ea7f916SThomas Cort /*
8676ea7f916SThomas Cort * calculate page boundries based on open file count
8686ea7f916SThomas Cort */
8696ea7f916SThomas Cort clcnt = j;
8706ea7f916SThomas Cort if (nmwd) {
8716ea7f916SThomas Cort colwd = (pgwd - clcnt - nmwd)/clcnt;
8726ea7f916SThomas Cort pgwd = ((colwd + 1) * clcnt) - nmwd - 2;
8736ea7f916SThomas Cort } else {
8746ea7f916SThomas Cort colwd = (pgwd + 1 - clcnt)/clcnt;
8756ea7f916SThomas Cort pgwd = ((colwd + 1) * clcnt) - 1;
8766ea7f916SThomas Cort }
8776ea7f916SThomas Cort if (colwd < 1) {
8786ea7f916SThomas Cort (void)fprintf(errf,
8796ea7f916SThomas Cort "pr: page width too small for %d columns\n", clcnt);
8806ea7f916SThomas Cort goto out;
8816ea7f916SThomas Cort }
8826ea7f916SThomas Cort actf = clcnt;
8836ea7f916SThomas Cort col = colwd + 1;
8846ea7f916SThomas Cort
8856ea7f916SThomas Cort /*
8866ea7f916SThomas Cort * line buffer
8876ea7f916SThomas Cort */
8886ea7f916SThomas Cort if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL)
8896ea7f916SThomas Cort goto out;
8906ea7f916SThomas Cort if (offst) {
8916ea7f916SThomas Cort (void)memset(buf, (int)' ', offst);
8926ea7f916SThomas Cort (void)memset(hbuf, (int)' ', offst);
8936ea7f916SThomas Cort }
8946ea7f916SThomas Cort if (pgnm)
8956ea7f916SThomas Cort pagecnt = pgnm;
8966ea7f916SThomas Cort else
8976ea7f916SThomas Cort pagecnt = 1;
8986ea7f916SThomas Cort lncnt = 0;
8996ea7f916SThomas Cort
9006ea7f916SThomas Cort /*
9016ea7f916SThomas Cort * continue to loop while any file still has data
9026ea7f916SThomas Cort */
9036ea7f916SThomas Cort while (actf > 0) {
9046ea7f916SThomas Cort /*
9056ea7f916SThomas Cort * loop by line
9066ea7f916SThomas Cort */
9076ea7f916SThomas Cort for (i = 0; i < lines; ++i) {
9086ea7f916SThomas Cort ptbf = buf + offst;
9096ea7f916SThomas Cort lstdat = ptbf;
9106ea7f916SThomas Cort if (nmwd) {
9116ea7f916SThomas Cort /*
9126ea7f916SThomas Cort * add line number to line
9136ea7f916SThomas Cort */
9146ea7f916SThomas Cort addnum(ptbf, nmwd, ++lncnt);
9156ea7f916SThomas Cort ptbf += nmwd;
9166ea7f916SThomas Cort *ptbf++ = nmchar;
9176ea7f916SThomas Cort }
9186ea7f916SThomas Cort j = 0;
9196ea7f916SThomas Cort fproc = 0;
9206ea7f916SThomas Cort
9216ea7f916SThomas Cort /*
9226ea7f916SThomas Cort * loop by column
9236ea7f916SThomas Cort */
9246ea7f916SThomas Cort for (j = 0; j < clcnt; ++j) {
9256ea7f916SThomas Cort if (fbuf[j] == NULL) {
9266ea7f916SThomas Cort /*
9276ea7f916SThomas Cort * empty column; EOF
9286ea7f916SThomas Cort */
9296ea7f916SThomas Cort cnt = 0;
9306ea7f916SThomas Cort } else if ((cnt = inln(fbuf[j], ptbf, colwd,
9316ea7f916SThomas Cort &cps, 1, &mor)) < 0) {
9326ea7f916SThomas Cort /*
9336ea7f916SThomas Cort * EOF hit; no data
9346ea7f916SThomas Cort */
9356ea7f916SThomas Cort if (fbuf[j] != stdin)
9366ea7f916SThomas Cort (void)fclose(fbuf[j]);
9376ea7f916SThomas Cort fbuf[j] = NULL;
9386ea7f916SThomas Cort --actf;
9396ea7f916SThomas Cort cnt = 0;
9406ea7f916SThomas Cort } else {
9416ea7f916SThomas Cort /*
9426ea7f916SThomas Cort * process file data
9436ea7f916SThomas Cort */
9446ea7f916SThomas Cort ptbf += cnt;
9456ea7f916SThomas Cort lstdat = ptbf;
9466ea7f916SThomas Cort fproc++;
9476ea7f916SThomas Cort }
9486ea7f916SThomas Cort
9496ea7f916SThomas Cort /*
9506ea7f916SThomas Cort * if last ACTIVE column, done with line
9516ea7f916SThomas Cort */
9526ea7f916SThomas Cort if (fproc >= actf)
9536ea7f916SThomas Cort break;
9546ea7f916SThomas Cort
9556ea7f916SThomas Cort /*
9566ea7f916SThomas Cort * pad to end of column
9576ea7f916SThomas Cort */
9586ea7f916SThomas Cort if (sflag) {
9596ea7f916SThomas Cort *ptbf++ = schar;
9606ea7f916SThomas Cort } else if ((pln = col - cnt) > 0) {
9616ea7f916SThomas Cort (void)memset(ptbf, (int)' ', pln);
9626ea7f916SThomas Cort ptbf += pln;
9636ea7f916SThomas Cort }
9646ea7f916SThomas Cort }
9656ea7f916SThomas Cort
9666ea7f916SThomas Cort /*
9676ea7f916SThomas Cort * calculate data in line
9686ea7f916SThomas Cort */
9696ea7f916SThomas Cort if ((j = lstdat - buf) <= offst)
9706ea7f916SThomas Cort break;
9716ea7f916SThomas Cort
9726ea7f916SThomas Cort if (!i) {
9736ea7f916SThomas Cort if (pgpause)
9746ea7f916SThomas Cort prpause(pagecnt);
9756ea7f916SThomas Cort
9766ea7f916SThomas Cort if (!nohead && prhead(hbuf, fname, pagecnt))
9776ea7f916SThomas Cort goto out;
9786ea7f916SThomas Cort }
9796ea7f916SThomas Cort
9806ea7f916SThomas Cort /*
9816ea7f916SThomas Cort * output line
9826ea7f916SThomas Cort */
9836ea7f916SThomas Cort if (otln(buf, j, &ips, &ops, 0))
9846ea7f916SThomas Cort goto out;
9856ea7f916SThomas Cort
9866ea7f916SThomas Cort /*
9876ea7f916SThomas Cort * if no more active files, done
9886ea7f916SThomas Cort */
9896ea7f916SThomas Cort if (actf <= 0) {
9906ea7f916SThomas Cort ++i;
9916ea7f916SThomas Cort break;
9926ea7f916SThomas Cort }
9936ea7f916SThomas Cort }
9946ea7f916SThomas Cort
9956ea7f916SThomas Cort /*
9966ea7f916SThomas Cort * pad to end of page
9976ea7f916SThomas Cort */
9986ea7f916SThomas Cort if (i && prtail(lines-i, 0))
9996ea7f916SThomas Cort goto out;
10006ea7f916SThomas Cort ++pagecnt;
10016ea7f916SThomas Cort }
10026ea7f916SThomas Cort if (eoptind < argc)
10036ea7f916SThomas Cort goto out;
10046ea7f916SThomas Cort error = 0;
10056ea7f916SThomas Cort goto out;
10066ea7f916SThomas Cort oomem:
10076ea7f916SThomas Cort mfail();
10086ea7f916SThomas Cort out:
10096ea7f916SThomas Cort if (fbuf) {
10106ea7f916SThomas Cort for (j = 0; j < clcnt; j++)
10116ea7f916SThomas Cort if (fbuf[j] && fbuf[j] != stdin)
10126ea7f916SThomas Cort (void)fclose(fbuf[j]);
10136ea7f916SThomas Cort free(fbuf);
10146ea7f916SThomas Cort }
10156ea7f916SThomas Cort free(hbuf);
10166ea7f916SThomas Cort free(buf);
10176ea7f916SThomas Cort return error;
10186ea7f916SThomas Cort }
10196ea7f916SThomas Cort
10206ea7f916SThomas Cort /*
10216ea7f916SThomas Cort * inln(): input a line of data (unlimited length lines supported)
10226ea7f916SThomas Cort * Input is optionally expanded to spaces
10236ea7f916SThomas Cort *
10246ea7f916SThomas Cort * inf: file
10256ea7f916SThomas Cort * buf: buffer
10266ea7f916SThomas Cort * lim: buffer length
10276ea7f916SThomas Cort * cps: column positon 1st char in buffer (large line support)
10286ea7f916SThomas Cort * trnc: throw away data more than lim up to \n
10296ea7f916SThomas Cort * mor: set if more data in line (not truncated)
10306ea7f916SThomas Cort */
10316ea7f916SThomas Cort static int
inln(FILE * inf,char * buf,int lim,int * cps,int trnc,int * mor)10326ea7f916SThomas Cort inln(FILE *inf, char *buf, int lim, int *cps, int trnc, int *mor)
10336ea7f916SThomas Cort {
10346ea7f916SThomas Cort int col;
10356ea7f916SThomas Cort int gap = ingap;
10366ea7f916SThomas Cort int ch = EOF;
10376ea7f916SThomas Cort char *ptbuf;
10386ea7f916SThomas Cort int chk = (int)inchar;
10396ea7f916SThomas Cort
10406ea7f916SThomas Cort ptbuf = buf;
10416ea7f916SThomas Cort
10426ea7f916SThomas Cort if (gap) {
10436ea7f916SThomas Cort /*
10446ea7f916SThomas Cort * expanding input option
10456ea7f916SThomas Cort */
10466ea7f916SThomas Cort while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) {
10476ea7f916SThomas Cort /*
10486ea7f916SThomas Cort * is this the input "tab" char
10496ea7f916SThomas Cort */
10506ea7f916SThomas Cort if (ch == chk) {
10516ea7f916SThomas Cort /*
10526ea7f916SThomas Cort * expand to number of spaces
10536ea7f916SThomas Cort */
10546ea7f916SThomas Cort col = (ptbuf - buf) + *cps;
10556ea7f916SThomas Cort col = gap - (col % gap);
10566ea7f916SThomas Cort
10576ea7f916SThomas Cort /*
10586ea7f916SThomas Cort * if more than this line, push back
10596ea7f916SThomas Cort */
10606ea7f916SThomas Cort if ((col > lim) && (ungetc(ch, inf) == EOF))
10616ea7f916SThomas Cort return(1);
10626ea7f916SThomas Cort
10636ea7f916SThomas Cort /*
10646ea7f916SThomas Cort * expand to spaces
10656ea7f916SThomas Cort */
10666ea7f916SThomas Cort while ((--col >= 0) && (--lim >= 0))
10676ea7f916SThomas Cort *ptbuf++ = ' ';
10686ea7f916SThomas Cort continue;
10696ea7f916SThomas Cort }
10706ea7f916SThomas Cort if (ch == '\n')
10716ea7f916SThomas Cort break;
10726ea7f916SThomas Cort *ptbuf++ = ch;
10736ea7f916SThomas Cort }
10746ea7f916SThomas Cort } else {
10756ea7f916SThomas Cort /*
10766ea7f916SThomas Cort * no expansion
10776ea7f916SThomas Cort */
10786ea7f916SThomas Cort while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) {
10796ea7f916SThomas Cort if (ch == '\n')
10806ea7f916SThomas Cort break;
10816ea7f916SThomas Cort *ptbuf++ = ch;
10826ea7f916SThomas Cort }
10836ea7f916SThomas Cort }
10846ea7f916SThomas Cort col = ptbuf - buf;
10856ea7f916SThomas Cort if (ch == EOF) {
10866ea7f916SThomas Cort *mor = 0;
10876ea7f916SThomas Cort *cps = 0;
10886ea7f916SThomas Cort if (!col)
10896ea7f916SThomas Cort return(-1);
10906ea7f916SThomas Cort return(col);
10916ea7f916SThomas Cort }
10926ea7f916SThomas Cort if (ch == '\n') {
10936ea7f916SThomas Cort /*
10946ea7f916SThomas Cort * entire line processed
10956ea7f916SThomas Cort */
10966ea7f916SThomas Cort *mor = 0;
10976ea7f916SThomas Cort *cps = 0;
10986ea7f916SThomas Cort return(col);
10996ea7f916SThomas Cort }
11006ea7f916SThomas Cort
11016ea7f916SThomas Cort /*
11026ea7f916SThomas Cort * line was larger than limit
11036ea7f916SThomas Cort */
11046ea7f916SThomas Cort if (trnc) {
11056ea7f916SThomas Cort /*
11066ea7f916SThomas Cort * throw away rest of line
11076ea7f916SThomas Cort */
11086ea7f916SThomas Cort while ((ch = getc(inf)) != EOF) {
11096ea7f916SThomas Cort if (ch == '\n')
11106ea7f916SThomas Cort break;
11116ea7f916SThomas Cort }
11126ea7f916SThomas Cort *cps = 0;
11136ea7f916SThomas Cort *mor = 0;
11146ea7f916SThomas Cort } else {
11156ea7f916SThomas Cort /*
11166ea7f916SThomas Cort * save column offset if not truncated
11176ea7f916SThomas Cort */
11186ea7f916SThomas Cort *cps += col;
11196ea7f916SThomas Cort *mor = 1;
11206ea7f916SThomas Cort }
11216ea7f916SThomas Cort
11226ea7f916SThomas Cort return(col);
11236ea7f916SThomas Cort }
11246ea7f916SThomas Cort
11256ea7f916SThomas Cort /*
11266ea7f916SThomas Cort * otln(): output a line of data. (Supports unlimited length lines)
11276ea7f916SThomas Cort * output is optionally contracted to tabs
11286ea7f916SThomas Cort *
11296ea7f916SThomas Cort * buf: output buffer with data
11306ea7f916SThomas Cort * cnt: number of chars of valid data in buf
11316ea7f916SThomas Cort * svips: buffer input column position (for large lines)
11326ea7f916SThomas Cort * svops: buffer output column position (for large lines)
11336ea7f916SThomas Cort * mor: output line not complete in this buf; more data to come.
11346ea7f916SThomas Cort * 1 is more, 0 is complete, -1 is no \n's
11356ea7f916SThomas Cort */
11366ea7f916SThomas Cort static int
otln(char * buf,int cnt,int * svips,int * svops,int mor)11376ea7f916SThomas Cort otln(char *buf, int cnt, int *svips, int *svops, int mor)
11386ea7f916SThomas Cort {
11396ea7f916SThomas Cort int ops; /* last col output */
11406ea7f916SThomas Cort int ips; /* last col in buf examined */
11416ea7f916SThomas Cort int gap = ogap;
11426ea7f916SThomas Cort int tbps;
11436ea7f916SThomas Cort char *endbuf;
11446ea7f916SThomas Cort
11456ea7f916SThomas Cort if (ogap) {
11466ea7f916SThomas Cort /*
11476ea7f916SThomas Cort * contracting on output
11486ea7f916SThomas Cort */
11496ea7f916SThomas Cort endbuf = buf + cnt;
11506ea7f916SThomas Cort ops = *svops;
11516ea7f916SThomas Cort ips = *svips;
11526ea7f916SThomas Cort while (buf < endbuf) {
11536ea7f916SThomas Cort /*
11546ea7f916SThomas Cort * count number of spaces and ochar in buffer
11556ea7f916SThomas Cort */
11566ea7f916SThomas Cort if (*buf == ' ') {
11576ea7f916SThomas Cort ++ips;
11586ea7f916SThomas Cort ++buf;
11596ea7f916SThomas Cort continue;
11606ea7f916SThomas Cort }
11616ea7f916SThomas Cort
11626ea7f916SThomas Cort /*
11636ea7f916SThomas Cort * simulate ochar processing
11646ea7f916SThomas Cort */
11656ea7f916SThomas Cort if (*buf == ochar) {
11666ea7f916SThomas Cort ips += gap - (ips % gap);
11676ea7f916SThomas Cort ++buf;
11686ea7f916SThomas Cort continue;
11696ea7f916SThomas Cort }
11706ea7f916SThomas Cort
11716ea7f916SThomas Cort /*
11726ea7f916SThomas Cort * got a non space char; contract out spaces
11736ea7f916SThomas Cort */
11746ea7f916SThomas Cort while (ips - ops > 1) {
11756ea7f916SThomas Cort /*
11766ea7f916SThomas Cort * use as many ochar as will fit
11776ea7f916SThomas Cort */
11786ea7f916SThomas Cort if ((tbps = ops + gap - (ops % gap)) > ips)
11796ea7f916SThomas Cort break;
11806ea7f916SThomas Cort if (putchar(ochar) == EOF) {
11816ea7f916SThomas Cort pfail();
11826ea7f916SThomas Cort return(1);
11836ea7f916SThomas Cort }
11846ea7f916SThomas Cort ops = tbps;
11856ea7f916SThomas Cort }
11866ea7f916SThomas Cort
11876ea7f916SThomas Cort while (ops < ips) {
11886ea7f916SThomas Cort /*
11896ea7f916SThomas Cort * finish off with spaces
11906ea7f916SThomas Cort */
11916ea7f916SThomas Cort if (putchar(' ') == EOF) {
11926ea7f916SThomas Cort pfail();
11936ea7f916SThomas Cort return(1);
11946ea7f916SThomas Cort }
11956ea7f916SThomas Cort ++ops;
11966ea7f916SThomas Cort }
11976ea7f916SThomas Cort
11986ea7f916SThomas Cort /*
11996ea7f916SThomas Cort * output non space char
12006ea7f916SThomas Cort */
12016ea7f916SThomas Cort if (putchar(*buf++) == EOF) {
12026ea7f916SThomas Cort pfail();
12036ea7f916SThomas Cort return(1);
12046ea7f916SThomas Cort }
12056ea7f916SThomas Cort ++ips;
12066ea7f916SThomas Cort ++ops;
12076ea7f916SThomas Cort }
12086ea7f916SThomas Cort
12096ea7f916SThomas Cort if (mor > 0) {
12106ea7f916SThomas Cort /*
12116ea7f916SThomas Cort * if incomplete line, save position counts
12126ea7f916SThomas Cort */
12136ea7f916SThomas Cort *svops = ops;
12146ea7f916SThomas Cort *svips = ips;
12156ea7f916SThomas Cort return(0);
12166ea7f916SThomas Cort }
12176ea7f916SThomas Cort
12186ea7f916SThomas Cort if (mor < 0) {
12196ea7f916SThomas Cort while (ips - ops > 1) {
12206ea7f916SThomas Cort /*
12216ea7f916SThomas Cort * use as many ochar as will fit
12226ea7f916SThomas Cort */
12236ea7f916SThomas Cort if ((tbps = ops + gap - (ops % gap)) > ips)
12246ea7f916SThomas Cort break;
12256ea7f916SThomas Cort if (putchar(ochar) == EOF) {
12266ea7f916SThomas Cort pfail();
12276ea7f916SThomas Cort return(1);
12286ea7f916SThomas Cort }
12296ea7f916SThomas Cort ops = tbps;
12306ea7f916SThomas Cort }
12316ea7f916SThomas Cort while (ops < ips) {
12326ea7f916SThomas Cort /*
12336ea7f916SThomas Cort * finish off with spaces
12346ea7f916SThomas Cort */
12356ea7f916SThomas Cort if (putchar(' ') == EOF) {
12366ea7f916SThomas Cort pfail();
12376ea7f916SThomas Cort return(1);
12386ea7f916SThomas Cort }
12396ea7f916SThomas Cort ++ops;
12406ea7f916SThomas Cort }
12416ea7f916SThomas Cort return(0);
12426ea7f916SThomas Cort }
12436ea7f916SThomas Cort } else {
12446ea7f916SThomas Cort /*
12456ea7f916SThomas Cort * output is not contracted
12466ea7f916SThomas Cort */
12476ea7f916SThomas Cort if (cnt && (fwrite(buf, sizeof(char), cnt, stdout) <= 0)) {
12486ea7f916SThomas Cort pfail();
12496ea7f916SThomas Cort return(1);
12506ea7f916SThomas Cort }
12516ea7f916SThomas Cort if (mor != 0)
12526ea7f916SThomas Cort return(0);
12536ea7f916SThomas Cort }
12546ea7f916SThomas Cort
12556ea7f916SThomas Cort /*
12566ea7f916SThomas Cort * process line end and double space as required
12576ea7f916SThomas Cort */
12586ea7f916SThomas Cort if ((putchar('\n') == EOF) || (dspace && (putchar('\n') == EOF))) {
12596ea7f916SThomas Cort pfail();
12606ea7f916SThomas Cort return(1);
12616ea7f916SThomas Cort }
12626ea7f916SThomas Cort return(0);
12636ea7f916SThomas Cort }
12646ea7f916SThomas Cort
12656ea7f916SThomas Cort /*
12666ea7f916SThomas Cort * inskip(): skip over pgcnt pages with lncnt lines per page
12676ea7f916SThomas Cort * file is closed at EOF (if not stdin).
12686ea7f916SThomas Cort *
12696ea7f916SThomas Cort * inf FILE * to read from
12706ea7f916SThomas Cort * pgcnt number of pages to skip
12716ea7f916SThomas Cort * lncnt number of lines per page
12726ea7f916SThomas Cort */
12736ea7f916SThomas Cort static int
inskip(FILE * inf,int pgcnt,int lncnt)12746ea7f916SThomas Cort inskip(FILE *inf, int pgcnt, int lncnt)
12756ea7f916SThomas Cort {
12766ea7f916SThomas Cort int c;
12776ea7f916SThomas Cort int cnt;
12786ea7f916SThomas Cort
12796ea7f916SThomas Cort while(--pgcnt > 0) {
12806ea7f916SThomas Cort cnt = lncnt;
12816ea7f916SThomas Cort while ((c = getc(inf)) != EOF) {
12826ea7f916SThomas Cort if ((c == '\n') && (--cnt == 0))
12836ea7f916SThomas Cort break;
12846ea7f916SThomas Cort }
12856ea7f916SThomas Cort if (c == EOF) {
12866ea7f916SThomas Cort if (inf != stdin)
12876ea7f916SThomas Cort (void)fclose(inf);
12886ea7f916SThomas Cort return(1);
12896ea7f916SThomas Cort }
12906ea7f916SThomas Cort }
12916ea7f916SThomas Cort return(0);
12926ea7f916SThomas Cort }
12936ea7f916SThomas Cort
12946ea7f916SThomas Cort /*
12956ea7f916SThomas Cort * nxtfile: returns a FILE * to next file in arg list and sets the
12966ea7f916SThomas Cort * time field for this file (or current date).
12976ea7f916SThomas Cort *
12986ea7f916SThomas Cort * buf array to store proper date for the header.
12996ea7f916SThomas Cort * dt if set skips the date processing (used with -m)
13006ea7f916SThomas Cort */
13016ea7f916SThomas Cort static FILE *
nxtfile(int argc,char ** argv,const char ** fname,char * buf,int dt)13026ea7f916SThomas Cort nxtfile(int argc, char **argv, const char **fname, char *buf, int dt)
13036ea7f916SThomas Cort {
13046ea7f916SThomas Cort FILE *inf = NULL;
13056ea7f916SThomas Cort struct timeval tv;
13066ea7f916SThomas Cort struct timezone tz;
13076ea7f916SThomas Cort struct tm *timeptr = NULL;
13086ea7f916SThomas Cort struct stat statbuf;
13096ea7f916SThomas Cort time_t curtime;
13106ea7f916SThomas Cort static int twice = -1;
13116ea7f916SThomas Cort
13126ea7f916SThomas Cort ++twice;
13136ea7f916SThomas Cort if (eoptind >= argc) {
13146ea7f916SThomas Cort /*
13156ea7f916SThomas Cort * no file listed; default, use standard input
13166ea7f916SThomas Cort */
13176ea7f916SThomas Cort if (twice)
13186ea7f916SThomas Cort return(NULL);
13196ea7f916SThomas Cort clearerr(stdin);
13206ea7f916SThomas Cort inf = stdin;
13216ea7f916SThomas Cort if (header != NULL)
13226ea7f916SThomas Cort *fname = header;
13236ea7f916SThomas Cort else
13246ea7f916SThomas Cort *fname = FNAME;
13256ea7f916SThomas Cort if (nohead)
13266ea7f916SThomas Cort return(inf);
13276ea7f916SThomas Cort if (gettimeofday(&tv, &tz) < 0) {
13286ea7f916SThomas Cort ++errcnt;
13296ea7f916SThomas Cort (void)fprintf(errf, "pr: cannot get time of day, %s\n",
13306ea7f916SThomas Cort strerror(errno));
13316ea7f916SThomas Cort eoptind = argc - 1;
13326ea7f916SThomas Cort return(NULL);
13336ea7f916SThomas Cort }
13346ea7f916SThomas Cort curtime = tv.tv_sec;
13356ea7f916SThomas Cort timeptr = localtime(&curtime);
13366ea7f916SThomas Cort }
13376ea7f916SThomas Cort for (; eoptind < argc; ++eoptind) {
13386ea7f916SThomas Cort if (strcmp(argv[eoptind], "-") == 0) {
13396ea7f916SThomas Cort /*
13406ea7f916SThomas Cort * process a "-" for filename
13416ea7f916SThomas Cort */
13426ea7f916SThomas Cort clearerr(stdin);
13436ea7f916SThomas Cort inf = stdin;
13446ea7f916SThomas Cort if (header != NULL)
13456ea7f916SThomas Cort *fname = header;
13466ea7f916SThomas Cort else
13476ea7f916SThomas Cort *fname = FNAME;
13486ea7f916SThomas Cort ++eoptind;
13496ea7f916SThomas Cort if (nohead || (dt && twice))
13506ea7f916SThomas Cort return(inf);
13516ea7f916SThomas Cort if (gettimeofday(&tv, &tz) < 0) {
13526ea7f916SThomas Cort ++errcnt;
13536ea7f916SThomas Cort (void)fprintf(errf,
13546ea7f916SThomas Cort "pr: cannot get time of day, %s\n",
13556ea7f916SThomas Cort strerror(errno));
13566ea7f916SThomas Cort return(NULL);
13576ea7f916SThomas Cort }
13586ea7f916SThomas Cort curtime = tv.tv_sec;
13596ea7f916SThomas Cort timeptr = localtime(&curtime);
13606ea7f916SThomas Cort } else {
13616ea7f916SThomas Cort /*
13626ea7f916SThomas Cort * normal file processing
13636ea7f916SThomas Cort */
13646ea7f916SThomas Cort if ((inf = fopen(argv[eoptind], "r")) == NULL) {
13656ea7f916SThomas Cort ++errcnt;
13666ea7f916SThomas Cort if (nodiag)
13676ea7f916SThomas Cort continue;
13686ea7f916SThomas Cort (void)fprintf(errf, "pr: Cannot open %s, %s\n",
13696ea7f916SThomas Cort argv[eoptind], strerror(errno));
13706ea7f916SThomas Cort continue;
13716ea7f916SThomas Cort }
13726ea7f916SThomas Cort if (header != NULL)
13736ea7f916SThomas Cort *fname = header;
13746ea7f916SThomas Cort else if (dt)
13756ea7f916SThomas Cort *fname = FNAME;
13766ea7f916SThomas Cort else
13776ea7f916SThomas Cort *fname = argv[eoptind];
13786ea7f916SThomas Cort ++eoptind;
13796ea7f916SThomas Cort if (nohead || (dt && twice))
13806ea7f916SThomas Cort return(inf);
13816ea7f916SThomas Cort
13826ea7f916SThomas Cort if (dt) {
13836ea7f916SThomas Cort if (gettimeofday(&tv, &tz) < 0) {
13846ea7f916SThomas Cort ++errcnt;
13856ea7f916SThomas Cort (void)fprintf(errf,
13866ea7f916SThomas Cort "pr: cannot get time of day, %s\n",
13876ea7f916SThomas Cort strerror(errno));
13886ea7f916SThomas Cort return(NULL);
13896ea7f916SThomas Cort }
13906ea7f916SThomas Cort curtime = tv.tv_sec;
13916ea7f916SThomas Cort timeptr = localtime(&curtime);
13926ea7f916SThomas Cort } else {
13936ea7f916SThomas Cort if (fstat(fileno(inf), &statbuf) < 0) {
13946ea7f916SThomas Cort ++errcnt;
13956ea7f916SThomas Cort (void)fclose(inf);
13966ea7f916SThomas Cort (void)fprintf(errf,
13976ea7f916SThomas Cort "pr: Cannot stat %s, %s\n",
13986ea7f916SThomas Cort argv[eoptind], strerror(errno));
13996ea7f916SThomas Cort return(NULL);
14006ea7f916SThomas Cort }
14016ea7f916SThomas Cort timeptr = localtime(&(statbuf.st_mtime));
14026ea7f916SThomas Cort }
14036ea7f916SThomas Cort }
14046ea7f916SThomas Cort break;
14056ea7f916SThomas Cort }
14066ea7f916SThomas Cort if (inf == NULL)
14076ea7f916SThomas Cort return(NULL);
14086ea7f916SThomas Cort
14096ea7f916SThomas Cort /*
14106ea7f916SThomas Cort * set up time field used in header
14116ea7f916SThomas Cort */
14126ea7f916SThomas Cort if (strftime(buf, HDBUF, timefrmt, timeptr) <= 0) {
14136ea7f916SThomas Cort ++errcnt;
14146ea7f916SThomas Cort if (inf != stdin)
14156ea7f916SThomas Cort (void)fclose(inf);
14166ea7f916SThomas Cort (void)fputs("pr: time conversion failed\n", errf);
14176ea7f916SThomas Cort return(NULL);
14186ea7f916SThomas Cort }
14196ea7f916SThomas Cort return(inf);
14206ea7f916SThomas Cort }
14216ea7f916SThomas Cort
14226ea7f916SThomas Cort /*
14236ea7f916SThomas Cort * addnum(): adds the line number to the column
14246ea7f916SThomas Cort * Truncates from the front or pads with spaces as required.
14256ea7f916SThomas Cort * Numbers are right justified.
14266ea7f916SThomas Cort *
14276ea7f916SThomas Cort * buf buffer to store the number
14286ea7f916SThomas Cort * wdth width of buffer to fill
14296ea7f916SThomas Cort * line line number
14306ea7f916SThomas Cort *
14316ea7f916SThomas Cort * NOTE: numbers occupy part of the column. The posix
14326ea7f916SThomas Cort * spec does not specify if -i processing should or should not
14336ea7f916SThomas Cort * occur on number padding. The spec does say it occupies
14346ea7f916SThomas Cort * part of the column. The usage of addnum currently treats
14356ea7f916SThomas Cort * numbers as part of the column so spaces may be replaced.
14366ea7f916SThomas Cort */
14376ea7f916SThomas Cort void
addnum(char * buf,int wdth,int line)14386ea7f916SThomas Cort addnum(char *buf, int wdth, int line)
14396ea7f916SThomas Cort {
14406ea7f916SThomas Cort char *pt = buf + wdth;
14416ea7f916SThomas Cort
14426ea7f916SThomas Cort do {
14436ea7f916SThomas Cort *--pt = digs[line % 10];
14446ea7f916SThomas Cort line /= 10;
14456ea7f916SThomas Cort } while (line && (pt > buf));
14466ea7f916SThomas Cort
14476ea7f916SThomas Cort /*
14486ea7f916SThomas Cort * pad with space as required
14496ea7f916SThomas Cort */
14506ea7f916SThomas Cort while (pt > buf)
14516ea7f916SThomas Cort *--pt = ' ';
14526ea7f916SThomas Cort }
14536ea7f916SThomas Cort
14546ea7f916SThomas Cort /*
14556ea7f916SThomas Cort * prpause(): pause before printing each page
14566ea7f916SThomas Cort *
14576ea7f916SThomas Cort * pagcnt page number
14586ea7f916SThomas Cort */
14596ea7f916SThomas Cort static void
prpause(int pagcnt)14606ea7f916SThomas Cort prpause(int pagcnt)
14616ea7f916SThomas Cort {
14626ea7f916SThomas Cort
14636ea7f916SThomas Cort if (ttyout) {
14646ea7f916SThomas Cort int c;
14656ea7f916SThomas Cort
14666ea7f916SThomas Cort (void)putc('\a', stderr);
14676ea7f916SThomas Cort (void)fflush(stderr);
14686ea7f916SThomas Cort
14696ea7f916SThomas Cort while ((c = getc(ttyinf)) != '\n' && c != EOF)
14706ea7f916SThomas Cort ;
14716ea7f916SThomas Cort
14726ea7f916SThomas Cort /*
14736ea7f916SThomas Cort * pause ONLY before first page of first file
14746ea7f916SThomas Cort */
14756ea7f916SThomas Cort if (pgpause == FIRSTPAGE && pagcnt == 1)
14766ea7f916SThomas Cort pgpause = NO_PAUSE;
14776ea7f916SThomas Cort }
14786ea7f916SThomas Cort }
14796ea7f916SThomas Cort
14806ea7f916SThomas Cort /*
14816ea7f916SThomas Cort * prhead(): prints the top of page header
14826ea7f916SThomas Cort *
14836ea7f916SThomas Cort * buf buffer with time field (and offset)
14846ea7f916SThomas Cort * cnt number of chars in buf
14856ea7f916SThomas Cort * fname fname field for header
14866ea7f916SThomas Cort * pagcnt page number
14876ea7f916SThomas Cort */
14886ea7f916SThomas Cort static int
prhead(char * buf,const char * fname,int pagcnt)14896ea7f916SThomas Cort prhead(char *buf, const char *fname, int pagcnt)
14906ea7f916SThomas Cort {
14916ea7f916SThomas Cort int ips = 0;
14926ea7f916SThomas Cort int ops = 0;
14936ea7f916SThomas Cort
14946ea7f916SThomas Cort if ((putchar('\n') == EOF) || (putchar('\n') == EOF)) {
14956ea7f916SThomas Cort pfail();
14966ea7f916SThomas Cort return(1);
14976ea7f916SThomas Cort }
14986ea7f916SThomas Cort /*
14996ea7f916SThomas Cort * posix is not clear if the header is subject to line length
15006ea7f916SThomas Cort * restrictions. The specification for header line format
15016ea7f916SThomas Cort * in the spec clearly does not limit length. No pr currently
15026ea7f916SThomas Cort * restricts header length. However if we need to truncate in
15036ea7f916SThomas Cort * an reasonable way, adjust the length of the printf by
15046ea7f916SThomas Cort * changing HDFMT to allow a length max as an argument printf.
15056ea7f916SThomas Cort * buf (which contains the offset spaces and time field could
15066ea7f916SThomas Cort * also be trimmed
15076ea7f916SThomas Cort *
15086ea7f916SThomas Cort * note only the offset (if any) is processed for tab expansion
15096ea7f916SThomas Cort */
15106ea7f916SThomas Cort if (offst && otln(buf, offst, &ips, &ops, -1))
15116ea7f916SThomas Cort return(1);
15126ea7f916SThomas Cort (void)printf(HDFMT,buf+offst, fname, pagcnt);
15136ea7f916SThomas Cort return(0);
15146ea7f916SThomas Cort }
15156ea7f916SThomas Cort
15166ea7f916SThomas Cort /*
15176ea7f916SThomas Cort * prtail(): pad page with empty lines (if required) and print page trailer
15186ea7f916SThomas Cort * if requested
15196ea7f916SThomas Cort *
15206ea7f916SThomas Cort * cnt number of lines of padding needed
15216ea7f916SThomas Cort * incomp was a '\n' missing from last line output
15226ea7f916SThomas Cort */
15236ea7f916SThomas Cort static int
prtail(int cnt,int incomp)15246ea7f916SThomas Cort prtail(int cnt, int incomp)
15256ea7f916SThomas Cort {
15266ea7f916SThomas Cort if (nohead) {
15276ea7f916SThomas Cort /*
15286ea7f916SThomas Cort * only pad with no headers when incomplete last line
15296ea7f916SThomas Cort */
15306ea7f916SThomas Cort if (!incomp)
15316ea7f916SThomas Cort return(0);
15326ea7f916SThomas Cort if ((dspace && (putchar('\n') == EOF)) ||
15336ea7f916SThomas Cort (putchar('\n') == EOF)) {
15346ea7f916SThomas Cort pfail();
15356ea7f916SThomas Cort return(1);
15366ea7f916SThomas Cort }
15376ea7f916SThomas Cort return(0);
15386ea7f916SThomas Cort }
15396ea7f916SThomas Cort
15406ea7f916SThomas Cort /*
15416ea7f916SThomas Cort * if double space output two \n
15426ea7f916SThomas Cort */
15436ea7f916SThomas Cort if (dspace)
15446ea7f916SThomas Cort cnt *= 2;
15456ea7f916SThomas Cort
15466ea7f916SThomas Cort /*
15476ea7f916SThomas Cort * if an odd number of lines per page, add an extra \n
15486ea7f916SThomas Cort */
15496ea7f916SThomas Cort if (addone)
15506ea7f916SThomas Cort ++cnt;
15516ea7f916SThomas Cort
15526ea7f916SThomas Cort /*
15536ea7f916SThomas Cort * pad page
15546ea7f916SThomas Cort */
15556ea7f916SThomas Cort if (formfeed) {
15566ea7f916SThomas Cort if ((incomp && (putchar('\n') == EOF)) ||
15576ea7f916SThomas Cort (putchar('\f') == EOF)) {
15586ea7f916SThomas Cort pfail();
15596ea7f916SThomas Cort return(1);
15606ea7f916SThomas Cort }
15616ea7f916SThomas Cort return(0);
15626ea7f916SThomas Cort }
15636ea7f916SThomas Cort cnt += TAILLEN;
15646ea7f916SThomas Cort while (--cnt >= 0) {
15656ea7f916SThomas Cort if (putchar('\n') == EOF) {
15666ea7f916SThomas Cort pfail();
15676ea7f916SThomas Cort return(1);
15686ea7f916SThomas Cort }
15696ea7f916SThomas Cort }
15706ea7f916SThomas Cort return(0);
15716ea7f916SThomas Cort }
15726ea7f916SThomas Cort
15736ea7f916SThomas Cort /*
15746ea7f916SThomas Cort * terminate(): when a SIGINT is recvd
15756ea7f916SThomas Cort */
15766ea7f916SThomas Cort static void
terminate(int which_sig)15776ea7f916SThomas Cort terminate(int which_sig)
15786ea7f916SThomas Cort {
15796ea7f916SThomas Cort flsh_errs();
15806ea7f916SThomas Cort (void)raise_default_signal(which_sig);
15816ea7f916SThomas Cort exit(1);
15826ea7f916SThomas Cort }
15836ea7f916SThomas Cort
15846ea7f916SThomas Cort
15856ea7f916SThomas Cort /*
15866ea7f916SThomas Cort * flsh_errs(): output saved up diagnostic messages after all normal
15876ea7f916SThomas Cort * processing has completed
15886ea7f916SThomas Cort */
15896ea7f916SThomas Cort static void
flsh_errs(void)15906ea7f916SThomas Cort flsh_errs(void)
15916ea7f916SThomas Cort {
15926ea7f916SThomas Cort char buf[BUFSIZ];
15936ea7f916SThomas Cort
15946ea7f916SThomas Cort (void)fflush(stdout);
15956ea7f916SThomas Cort (void)fflush(errf);
15966ea7f916SThomas Cort if (errf == stderr)
15976ea7f916SThomas Cort return;
15986ea7f916SThomas Cort rewind(errf);
15996ea7f916SThomas Cort while (fgets(buf, BUFSIZ, errf) != NULL)
16006ea7f916SThomas Cort (void)fputs(buf, stderr);
16016ea7f916SThomas Cort }
16026ea7f916SThomas Cort
16036ea7f916SThomas Cort static void
mfail(void)16046ea7f916SThomas Cort mfail(void)
16056ea7f916SThomas Cort {
16066ea7f916SThomas Cort (void)fputs("pr: memory allocation failed\n", errf);
16076ea7f916SThomas Cort }
16086ea7f916SThomas Cort
16096ea7f916SThomas Cort static void
pfail(void)16106ea7f916SThomas Cort pfail(void)
16116ea7f916SThomas Cort {
16126ea7f916SThomas Cort (void)fprintf(errf, "pr: write failure, %s\n", strerror(errno));
16136ea7f916SThomas Cort }
16146ea7f916SThomas Cort
16156ea7f916SThomas Cort static void
usage(void)16166ea7f916SThomas Cort usage(void)
16176ea7f916SThomas Cort {
16186ea7f916SThomas Cort (void)fputs(
16196ea7f916SThomas Cort "usage: pr [+page] [-col] [-adFfmprt] [-e[ch][gap]] [-h header]\n",
16206ea7f916SThomas Cort errf);
16216ea7f916SThomas Cort (void)fputs(
16226ea7f916SThomas Cort " [-i[ch][gap]] [-l line] [-n[ch][width]] [-o offset]\n",
16236ea7f916SThomas Cort errf);
16246ea7f916SThomas Cort (void)fputs(
16256ea7f916SThomas Cort " [-s[ch]] [-T timefmt] [-w width] [-] [file ...]\n",
16266ea7f916SThomas Cort errf);
16276ea7f916SThomas Cort }
16286ea7f916SThomas Cort
16296ea7f916SThomas Cort /*
16306ea7f916SThomas Cort * setup: Validate command args, initialize and perform sanity
16316ea7f916SThomas Cort * checks on options
16326ea7f916SThomas Cort */
16336ea7f916SThomas Cort static int
setup(int argc,char ** argv)16346ea7f916SThomas Cort setup(int argc, char **argv)
16356ea7f916SThomas Cort {
16366ea7f916SThomas Cort int c;
16376ea7f916SThomas Cort int eflag = 0;
16386ea7f916SThomas Cort int iflag = 0;
16396ea7f916SThomas Cort int wflag = 0;
16406ea7f916SThomas Cort int cflag = 0;
16416ea7f916SThomas Cort
16426ea7f916SThomas Cort ttyinf = stdin;
16436ea7f916SThomas Cort
16446ea7f916SThomas Cort if (isatty(fileno(stdout))) {
16456ea7f916SThomas Cort /*
16466ea7f916SThomas Cort * defer diagnostics until processing is done
16476ea7f916SThomas Cort */
16486ea7f916SThomas Cort if ((errf = tmpfile()) == NULL) {
16496ea7f916SThomas Cort (void)fputs("Cannot defer diagnostic messages\n",stderr);
16506ea7f916SThomas Cort return(1);
16516ea7f916SThomas Cort }
16526ea7f916SThomas Cort ttyout = 1;
16536ea7f916SThomas Cort } else
16546ea7f916SThomas Cort errf = stderr;
16556ea7f916SThomas Cort while ((c = egetopt(argc, argv, "#adFfmrte?h:i?l:n?o:ps?T:w:")) != -1) {
16566ea7f916SThomas Cort switch (c) {
16576ea7f916SThomas Cort case '+':
16586ea7f916SThomas Cort if ((pgnm = atoi(eoptarg)) < 1) {
16596ea7f916SThomas Cort (void)fputs("pr: +page number must be 1 or more\n",
16606ea7f916SThomas Cort errf);
16616ea7f916SThomas Cort return(1);
16626ea7f916SThomas Cort }
16636ea7f916SThomas Cort break;
16646ea7f916SThomas Cort case '-':
16656ea7f916SThomas Cort if ((clcnt = atoi(eoptarg)) < 1) {
16666ea7f916SThomas Cort (void)fputs("pr: -columns must be 1 or more\n",errf);
16676ea7f916SThomas Cort return(1);
16686ea7f916SThomas Cort }
16696ea7f916SThomas Cort if (clcnt > 1)
16706ea7f916SThomas Cort ++cflag;
16716ea7f916SThomas Cort break;
16726ea7f916SThomas Cort case 'a':
16736ea7f916SThomas Cort ++across;
16746ea7f916SThomas Cort break;
16756ea7f916SThomas Cort case 'd':
16766ea7f916SThomas Cort ++dspace;
16776ea7f916SThomas Cort break;
16786ea7f916SThomas Cort case 'e':
16796ea7f916SThomas Cort ++eflag;
16806ea7f916SThomas Cort if ((eoptarg != NULL) &&
16816ea7f916SThomas Cort !isdigit((unsigned char)*eoptarg))
16826ea7f916SThomas Cort inchar = *eoptarg++;
16836ea7f916SThomas Cort else
16846ea7f916SThomas Cort inchar = INCHAR;
16856ea7f916SThomas Cort if ((eoptarg != NULL) &&
16866ea7f916SThomas Cort isdigit((unsigned char)*eoptarg)) {
16876ea7f916SThomas Cort if ((ingap = atoi(eoptarg)) < 0) {
16886ea7f916SThomas Cort (void)fputs(
16896ea7f916SThomas Cort "pr: -e gap must be 0 or more\n", errf);
16906ea7f916SThomas Cort return(1);
16916ea7f916SThomas Cort }
16926ea7f916SThomas Cort if (ingap == 0)
16936ea7f916SThomas Cort ingap = INGAP;
16946ea7f916SThomas Cort } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
16956ea7f916SThomas Cort (void)fprintf(errf,
16966ea7f916SThomas Cort "pr: invalid value for -e %s\n", eoptarg);
16976ea7f916SThomas Cort return(1);
16986ea7f916SThomas Cort } else
16996ea7f916SThomas Cort ingap = INGAP;
17006ea7f916SThomas Cort break;
17016ea7f916SThomas Cort case 'f':
17026ea7f916SThomas Cort pgpause |= FIRSTPAGE;
17036ea7f916SThomas Cort /*FALLTHROUGH*/
17046ea7f916SThomas Cort case 'F':
17056ea7f916SThomas Cort ++formfeed;
17066ea7f916SThomas Cort break;
17076ea7f916SThomas Cort case 'h':
17086ea7f916SThomas Cort header = eoptarg;
17096ea7f916SThomas Cort break;
17106ea7f916SThomas Cort case 'i':
17116ea7f916SThomas Cort ++iflag;
17126ea7f916SThomas Cort if ((eoptarg != NULL) &&
17136ea7f916SThomas Cort !isdigit((unsigned char)*eoptarg))
17146ea7f916SThomas Cort ochar = *eoptarg++;
17156ea7f916SThomas Cort else
17166ea7f916SThomas Cort ochar = OCHAR;
17176ea7f916SThomas Cort if ((eoptarg != NULL) &&
17186ea7f916SThomas Cort isdigit((unsigned char)*eoptarg)) {
17196ea7f916SThomas Cort if ((ogap = atoi(eoptarg)) < 0) {
17206ea7f916SThomas Cort (void)fputs(
17216ea7f916SThomas Cort "pr: -i gap must be 0 or more\n", errf);
17226ea7f916SThomas Cort return(1);
17236ea7f916SThomas Cort }
17246ea7f916SThomas Cort if (ogap == 0)
17256ea7f916SThomas Cort ogap = OGAP;
17266ea7f916SThomas Cort } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
17276ea7f916SThomas Cort (void)fprintf(errf,
17286ea7f916SThomas Cort "pr: invalid value for -i %s\n", eoptarg);
17296ea7f916SThomas Cort return(1);
17306ea7f916SThomas Cort } else
17316ea7f916SThomas Cort ogap = OGAP;
17326ea7f916SThomas Cort break;
17336ea7f916SThomas Cort case 'l':
17346ea7f916SThomas Cort if (!isdigit((unsigned char)*eoptarg) ||
17356ea7f916SThomas Cort ((lines=atoi(eoptarg)) < 1)) {
17366ea7f916SThomas Cort (void)fputs(
17376ea7f916SThomas Cort "pr: Number of lines must be 1 or more\n",errf);
17386ea7f916SThomas Cort return(1);
17396ea7f916SThomas Cort }
17406ea7f916SThomas Cort break;
17416ea7f916SThomas Cort case 'm':
17426ea7f916SThomas Cort ++merge;
17436ea7f916SThomas Cort break;
17446ea7f916SThomas Cort case 'n':
17456ea7f916SThomas Cort if ((eoptarg != NULL) &&
17466ea7f916SThomas Cort !isdigit((unsigned char)*eoptarg))
17476ea7f916SThomas Cort nmchar = *eoptarg++;
17486ea7f916SThomas Cort else
17496ea7f916SThomas Cort nmchar = NMCHAR;
17506ea7f916SThomas Cort if ((eoptarg != NULL) &&
17516ea7f916SThomas Cort isdigit((unsigned char)*eoptarg)) {
17526ea7f916SThomas Cort if ((nmwd = atoi(eoptarg)) < 1) {
17536ea7f916SThomas Cort (void)fputs(
17546ea7f916SThomas Cort "pr: -n width must be 1 or more\n",errf);
17556ea7f916SThomas Cort return(1);
17566ea7f916SThomas Cort }
17576ea7f916SThomas Cort } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
17586ea7f916SThomas Cort (void)fprintf(errf,
17596ea7f916SThomas Cort "pr: invalid value for -n %s\n", eoptarg);
17606ea7f916SThomas Cort return(1);
17616ea7f916SThomas Cort } else
17626ea7f916SThomas Cort nmwd = NMWD;
17636ea7f916SThomas Cort break;
17646ea7f916SThomas Cort case 'o':
17656ea7f916SThomas Cort if (!isdigit((unsigned char)*eoptarg) ||
17666ea7f916SThomas Cort ((offst = atoi(eoptarg))< 1)){
17676ea7f916SThomas Cort (void)fputs("pr: -o offset must be 1 or more\n",
17686ea7f916SThomas Cort errf);
17696ea7f916SThomas Cort return(1);
17706ea7f916SThomas Cort }
17716ea7f916SThomas Cort break;
17726ea7f916SThomas Cort case 'p':
17736ea7f916SThomas Cort pgpause |= EACHPAGE;
17746ea7f916SThomas Cort break;
17756ea7f916SThomas Cort case 'r':
17766ea7f916SThomas Cort ++nodiag;
17776ea7f916SThomas Cort break;
17786ea7f916SThomas Cort case 's':
17796ea7f916SThomas Cort ++sflag;
17806ea7f916SThomas Cort if (eoptarg == NULL)
17816ea7f916SThomas Cort schar = SCHAR;
17826ea7f916SThomas Cort else
17836ea7f916SThomas Cort schar = *eoptarg++;
17846ea7f916SThomas Cort if (eoptarg && *eoptarg != '\0') {
17856ea7f916SThomas Cort (void)fprintf(errf,
17866ea7f916SThomas Cort "pr: invalid value for -s %s\n", eoptarg);
17876ea7f916SThomas Cort return(1);
17886ea7f916SThomas Cort }
17896ea7f916SThomas Cort break;
17906ea7f916SThomas Cort case 'T':
17916ea7f916SThomas Cort timefrmt = eoptarg;
17926ea7f916SThomas Cort break;
17936ea7f916SThomas Cort case 't':
17946ea7f916SThomas Cort ++nohead;
17956ea7f916SThomas Cort break;
17966ea7f916SThomas Cort case 'w':
17976ea7f916SThomas Cort ++wflag;
17986ea7f916SThomas Cort if (!isdigit((unsigned char)*eoptarg) ||
17996ea7f916SThomas Cort ((pgwd = atoi(eoptarg)) < 1)){
18006ea7f916SThomas Cort (void)fputs(
18016ea7f916SThomas Cort "pr: -w width must be 1 or more \n",errf);
18026ea7f916SThomas Cort return(1);
18036ea7f916SThomas Cort }
18046ea7f916SThomas Cort break;
18056ea7f916SThomas Cort case '?':
18066ea7f916SThomas Cort default:
18076ea7f916SThomas Cort return(1);
18086ea7f916SThomas Cort }
18096ea7f916SThomas Cort }
18106ea7f916SThomas Cort
18116ea7f916SThomas Cort /*
18126ea7f916SThomas Cort * default and sanity checks
18136ea7f916SThomas Cort */
18146ea7f916SThomas Cort if (!clcnt) {
18156ea7f916SThomas Cort if (merge) {
18166ea7f916SThomas Cort if ((clcnt = argc - eoptind) <= 1) {
18176ea7f916SThomas Cort clcnt = CLCNT;
18186ea7f916SThomas Cort merge = 0;
18196ea7f916SThomas Cort }
18206ea7f916SThomas Cort } else
18216ea7f916SThomas Cort clcnt = CLCNT;
18226ea7f916SThomas Cort }
18236ea7f916SThomas Cort if (across) {
18246ea7f916SThomas Cort if (clcnt == 1) {
18256ea7f916SThomas Cort (void)fputs("pr: -a flag requires multiple columns\n",
18266ea7f916SThomas Cort errf);
18276ea7f916SThomas Cort return(1);
18286ea7f916SThomas Cort }
18296ea7f916SThomas Cort if (merge) {
18306ea7f916SThomas Cort (void)fputs("pr: -m cannot be used with -a\n", errf);
18316ea7f916SThomas Cort return(1);
18326ea7f916SThomas Cort }
18336ea7f916SThomas Cort }
18346ea7f916SThomas Cort if (!wflag) {
18356ea7f916SThomas Cort if (sflag)
18366ea7f916SThomas Cort pgwd = SPGWD;
18376ea7f916SThomas Cort else
18386ea7f916SThomas Cort pgwd = PGWD;
18396ea7f916SThomas Cort }
18406ea7f916SThomas Cort if (cflag || merge) {
18416ea7f916SThomas Cort if (!eflag) {
18426ea7f916SThomas Cort inchar = INCHAR;
18436ea7f916SThomas Cort ingap = INGAP;
18446ea7f916SThomas Cort }
18456ea7f916SThomas Cort if (!iflag) {
18466ea7f916SThomas Cort ochar = OCHAR;
18476ea7f916SThomas Cort ogap = OGAP;
18486ea7f916SThomas Cort }
18496ea7f916SThomas Cort }
18506ea7f916SThomas Cort if (cflag) {
18516ea7f916SThomas Cort if (merge) {
18526ea7f916SThomas Cort (void)fputs(
18536ea7f916SThomas Cort "pr: -m cannot be used with multiple columns\n", errf);
18546ea7f916SThomas Cort return(1);
18556ea7f916SThomas Cort }
18566ea7f916SThomas Cort if (nmwd) {
18576ea7f916SThomas Cort colwd = (pgwd + 1 - (clcnt * (nmwd + 2)))/clcnt;
18586ea7f916SThomas Cort pgwd = ((colwd + nmwd + 2) * clcnt) - 1;
18596ea7f916SThomas Cort } else {
18606ea7f916SThomas Cort colwd = (pgwd + 1 - clcnt)/clcnt;
18616ea7f916SThomas Cort pgwd = ((colwd + 1) * clcnt) - 1;
18626ea7f916SThomas Cort }
18636ea7f916SThomas Cort if (colwd < 1) {
18646ea7f916SThomas Cort (void)fprintf(errf,
18656ea7f916SThomas Cort "pr: page width is too small for %d columns\n",clcnt);
18666ea7f916SThomas Cort return(1);
18676ea7f916SThomas Cort }
18686ea7f916SThomas Cort }
18696ea7f916SThomas Cort if (!lines)
18706ea7f916SThomas Cort lines = LINES;
18716ea7f916SThomas Cort
18726ea7f916SThomas Cort /*
18736ea7f916SThomas Cort * make sure long enough for headers. if not disable
18746ea7f916SThomas Cort */
18756ea7f916SThomas Cort if (lines <= HEADLEN + TAILLEN)
18766ea7f916SThomas Cort ++nohead;
18776ea7f916SThomas Cort else if (!nohead)
18786ea7f916SThomas Cort lines -= HEADLEN + TAILLEN;
18796ea7f916SThomas Cort
18806ea7f916SThomas Cort /*
18816ea7f916SThomas Cort * adjust for double space on odd length pages
18826ea7f916SThomas Cort */
18836ea7f916SThomas Cort if (dspace) {
18846ea7f916SThomas Cort if (lines == 1)
18856ea7f916SThomas Cort dspace = 0;
18866ea7f916SThomas Cort else {
18876ea7f916SThomas Cort if (lines & 1)
18886ea7f916SThomas Cort ++addone;
18896ea7f916SThomas Cort lines /= 2;
18906ea7f916SThomas Cort }
18916ea7f916SThomas Cort }
18926ea7f916SThomas Cort
18936ea7f916SThomas Cort /*
18946ea7f916SThomas Cort * open /dev/tty if we are to pause before each page
18956ea7f916SThomas Cort * but only if stdout is a terminal and stdin is not a terminal
18966ea7f916SThomas Cort */
18976ea7f916SThomas Cort if (ttyout && pgpause && !isatty(fileno(stdin))) {
18986ea7f916SThomas Cort if ((ttyinf = fopen("/dev/tty", "r")) == NULL) {
18996ea7f916SThomas Cort (void)fprintf(errf, "pr: cannot open terminal\n");
19006ea7f916SThomas Cort return(1);
19016ea7f916SThomas Cort }
19026ea7f916SThomas Cort }
19036ea7f916SThomas Cort
19046ea7f916SThomas Cort return(0);
19056ea7f916SThomas Cort }
1906