pr.c revision 72091
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1991 Keith Muller. 31590Srgrimes * Copyright (c) 1993 41590Srgrimes * The Regents of the University of California. All rights reserved. 51590Srgrimes * 61590Srgrimes * This code is derived from software contributed to Berkeley by 71590Srgrimes * Keith Muller of the University of California, San Diego. 81590Srgrimes * 91590Srgrimes * Redistribution and use in source and binary forms, with or without 101590Srgrimes * modification, are permitted provided that the following conditions 111590Srgrimes * are met: 121590Srgrimes * 1. Redistributions of source code must retain the above copyright 131590Srgrimes * notice, this list of conditions and the following disclaimer. 141590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151590Srgrimes * notice, this list of conditions and the following disclaimer in the 161590Srgrimes * documentation and/or other materials provided with the distribution. 171590Srgrimes * 3. All advertising materials mentioning features or use of this software 181590Srgrimes * must display the following acknowledgement: 191590Srgrimes * This product includes software developed by the University of 201590Srgrimes * California, Berkeley and its contributors. 211590Srgrimes * 4. Neither the name of the University nor the names of its contributors 221590Srgrimes * may be used to endorse or promote products derived from this software 231590Srgrimes * without specific prior written permission. 241590Srgrimes * 251590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351590Srgrimes * SUCH DAMAGE. 3653948Sache * 3753948Sache * $FreeBSD: head/usr.bin/pr/pr.c 72091 2001-02-06 11:21:58Z asmodai $ 381590Srgrimes */ 391590Srgrimes 401590Srgrimes#ifndef lint 411590Srgrimesstatic char copyright[] = 421590Srgrimes"@(#) Copyright (c) 1993\n\ 431590Srgrimes The Regents of the University of California. All rights reserved.\n"; 441590Srgrimes#endif /* not lint */ 451590Srgrimes 461590Srgrimes#ifndef lint 471590Srgrimesstatic char sccsid[] = "@(#)pr.c 8.2 (Berkeley) 4/16/94"; 481590Srgrimes#endif /* not lint */ 491590Srgrimes 501590Srgrimes#include <sys/types.h> 511590Srgrimes#include <sys/time.h> 521590Srgrimes#include <sys/stat.h> 531590Srgrimes 541590Srgrimes#include <ctype.h> 551590Srgrimes#include <errno.h> 5653948Sache#include <locale.h> 571590Srgrimes#include <signal.h> 581590Srgrimes#include <stdio.h> 591590Srgrimes#include <stdlib.h> 601590Srgrimes#include <string.h> 611590Srgrimes#include <unistd.h> 621590Srgrimes 631590Srgrimes#include "pr.h" 641590Srgrimes#include "extern.h" 651590Srgrimes 661590Srgrimes/* 671590Srgrimes * pr: a printing and pagination filter. If multiple input files 681590Srgrimes * are specified, each is read, formatted, and written to standard 6972091Sasmodai * output. By default, input is separated into 66-line pages, each 701590Srgrimes * with a header that includes the page number, date, time and the 711590Srgrimes * files pathname. 721590Srgrimes * 731590Srgrimes * Complies with posix P1003.2/D11 741590Srgrimes */ 751590Srgrimes 761590Srgrimes/* 771590Srgrimes * parameter variables 781590Srgrimes */ 791590Srgrimesint pgnm; /* starting page number */ 801590Srgrimesint clcnt; /* number of columns */ 811590Srgrimesint colwd; /* column data width - multiple columns */ 821590Srgrimesint across; /* mult col flag; write across page */ 831590Srgrimesint dspace; /* double space flag */ 841590Srgrimeschar inchar; /* expand input char */ 851590Srgrimesint ingap; /* expand input gap */ 861590Srgrimesint formfeed; /* use formfeed as trailer */ 871590Srgrimeschar *header; /* header name instead of file name */ 881590Srgrimeschar ochar; /* contract output char */ 891590Srgrimesint ogap; /* contract output gap */ 901590Srgrimesint lines; /* number of lines per page */ 911590Srgrimesint merge; /* merge multiple files in output */ 921590Srgrimeschar nmchar; /* line numbering append char */ 931590Srgrimesint nmwd; /* width of line number field */ 941590Srgrimesint offst; /* number of page offset spaces */ 951590Srgrimesint nodiag; /* do not report file open errors */ 961590Srgrimeschar schar; /* text column separation character */ 971590Srgrimesint sflag; /* -s option for multiple columns */ 981590Srgrimesint nohead; /* do not write head and trailer */ 991590Srgrimesint pgwd; /* page width with multiple col output */ 1001590Srgrimeschar *timefrmt; /* time conversion string */ 1011590Srgrimes 1021590Srgrimes/* 1031590Srgrimes * misc globals 1041590Srgrimes */ 1051590SrgrimesFILE *err; /* error message file pointer */ 1061590Srgrimesint addone; /* page length is odd with double space */ 1071590Srgrimesint errcnt; /* error count on file processing */ 1081590Srgrimeschar digs[] = "0123456789"; /* page number translation map */ 1091590Srgrimes 1101590Srgrimesint 1111590Srgrimesmain(argc, argv) 1121590Srgrimes int argc; 1131590Srgrimes char *argv[]; 1141590Srgrimes{ 1151590Srgrimes int ret_val; 1161590Srgrimes 1171590Srgrimes if (signal(SIGINT, SIG_IGN) != SIG_IGN) 1181590Srgrimes (void)signal(SIGINT, terminate); 1191590Srgrimes ret_val = setup(argc, argv); 1201590Srgrimes if (!ret_val) { 1211590Srgrimes /* 1221590Srgrimes * select the output format based on options 1231590Srgrimes */ 1241590Srgrimes if (merge) 1251590Srgrimes ret_val = mulfile(argc, argv); 1261590Srgrimes else if (clcnt == 1) 1271590Srgrimes ret_val = onecol(argc, argv); 1281590Srgrimes else if (across) 1291590Srgrimes ret_val = horzcol(argc, argv); 1301590Srgrimes else 1311590Srgrimes ret_val = vertcol(argc, argv); 1321590Srgrimes } else 1331590Srgrimes usage(); 1341590Srgrimes flsh_errs(); 1351590Srgrimes if (errcnt || ret_val) 1361590Srgrimes exit(1); 1371590Srgrimes return(0); 1381590Srgrimes} 1391590Srgrimes 1401590Srgrimes/* 1411590Srgrimes * onecol: print files with only one column of output. 1421590Srgrimes * Line length is unlimited. 1431590Srgrimes */ 1441590Srgrimesint 1451590Srgrimesonecol(argc, argv) 1461590Srgrimes int argc; 1471590Srgrimes char *argv[]; 1481590Srgrimes{ 1491590Srgrimes register int cnt = -1; 1501590Srgrimes register int off; 1511590Srgrimes register int lrgln; 1521590Srgrimes register int linecnt; 1531590Srgrimes register int num; 1541590Srgrimes int lncnt; 1551590Srgrimes int pagecnt; 1561590Srgrimes int ips; 1571590Srgrimes int ops; 1581590Srgrimes int cps; 1591590Srgrimes char *obuf; 1601590Srgrimes char *lbuf; 1611590Srgrimes char *nbuf; 1621590Srgrimes char *hbuf; 1631590Srgrimes char *ohbuf; 1641590Srgrimes FILE *inf; 1651590Srgrimes char *fname; 1661590Srgrimes int mor; 1671590Srgrimes 1681590Srgrimes if (nmwd) 1691590Srgrimes num = nmwd + 1; 1701590Srgrimes else 1711590Srgrimes num = 0; 1721590Srgrimes off = num + offst; 1731590Srgrimes 1741590Srgrimes /* 1751590Srgrimes * allocate line buffer 1761590Srgrimes */ 1771590Srgrimes if ((obuf = malloc((unsigned)(LBUF + off)*sizeof(char))) == NULL) { 1781590Srgrimes mfail(); 1791590Srgrimes return(1); 1801590Srgrimes } 1811590Srgrimes /* 1821590Srgrimes * allocate header buffer 1831590Srgrimes */ 1841590Srgrimes if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) { 1851590Srgrimes mfail(); 1861590Srgrimes return(1); 1871590Srgrimes } 1881590Srgrimes 1891590Srgrimes ohbuf = hbuf + offst; 1901590Srgrimes nbuf = obuf + offst; 1911590Srgrimes lbuf = nbuf + num; 1921590Srgrimes if (num) 1931590Srgrimes nbuf[--num] = nmchar; 1941590Srgrimes if (offst) { 1951590Srgrimes (void)memset(obuf, (int)' ', offst); 1961590Srgrimes (void)memset(hbuf, (int)' ', offst); 1971590Srgrimes } 1981590Srgrimes 1991590Srgrimes /* 2001590Srgrimes * loop by file 2011590Srgrimes */ 2021590Srgrimes while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) { 2031590Srgrimes if (pgnm) { 2041590Srgrimes /* 2051590Srgrimes * skip to specified page 2061590Srgrimes */ 2071590Srgrimes if (inskip(inf, pgnm, lines)) 2081590Srgrimes continue; 2091590Srgrimes pagecnt = pgnm; 2101590Srgrimes } else 2111590Srgrimes pagecnt = 1; 2121590Srgrimes lncnt = 0; 2131590Srgrimes 2141590Srgrimes /* 2151590Srgrimes * loop by page 2161590Srgrimes */ 2171590Srgrimes for(;;) { 2181590Srgrimes linecnt = 0; 2191590Srgrimes lrgln = 0; 2201590Srgrimes ops = 0; 2211590Srgrimes ips = 0; 2221590Srgrimes cps = 0; 2231590Srgrimes 2241590Srgrimes /* 2251590Srgrimes * loop by line 2261590Srgrimes */ 2271590Srgrimes while (linecnt < lines) { 2281590Srgrimes /* 2291590Srgrimes * input next line 2301590Srgrimes */ 2311590Srgrimes if ((cnt = inln(inf,lbuf,LBUF,&cps,0,&mor)) < 0) 2321590Srgrimes break; 2331590Srgrimes if (!linecnt && !nohead && 2341590Srgrimes prhead(hbuf, fname, pagecnt)) 2351590Srgrimes return(1); 2361590Srgrimes 2371590Srgrimes /* 2381590Srgrimes * start of new line. 2391590Srgrimes */ 2401590Srgrimes if (!lrgln) { 2411590Srgrimes if (num) 2421590Srgrimes addnum(nbuf, num, ++lncnt); 2431590Srgrimes if (otln(obuf,cnt+off, &ips, &ops, mor)) 2441590Srgrimes return(1); 2451590Srgrimes } else if (otln(lbuf, cnt, &ips, &ops, mor)) 2461590Srgrimes return(1); 2471590Srgrimes 2481590Srgrimes /* 2491590Srgrimes * if line bigger than buffer, get more 2501590Srgrimes */ 2511590Srgrimes if (mor) { 2521590Srgrimes lrgln = 1; 2531590Srgrimes continue; 2541590Srgrimes } 2551590Srgrimes 2561590Srgrimes /* 2571590Srgrimes * whole line rcvd. reset tab proc. state 2581590Srgrimes */ 2591590Srgrimes ++linecnt; 2601590Srgrimes lrgln = 0; 2611590Srgrimes ops = 0; 2621590Srgrimes ips = 0; 2631590Srgrimes } 2641590Srgrimes 2651590Srgrimes /* 2661590Srgrimes * fill to end of page 2671590Srgrimes */ 2681590Srgrimes if (linecnt && prtail(lines-linecnt-lrgln, lrgln)) 2691590Srgrimes return(1); 2701590Srgrimes 2711590Srgrimes /* 2721590Srgrimes * On EOF go to next file 2731590Srgrimes */ 2741590Srgrimes if (cnt < 0) 2751590Srgrimes break; 2761590Srgrimes ++pagecnt; 2771590Srgrimes } 2781590Srgrimes if (inf != stdin) 2791590Srgrimes (void)fclose(inf); 2801590Srgrimes } 2811590Srgrimes if (eoptind < argc) 2821590Srgrimes return(1); 2831590Srgrimes return(0); 2841590Srgrimes} 2851590Srgrimes 2861590Srgrimes/* 2871590Srgrimes * vertcol: print files with more than one column of output down a page 2881590Srgrimes */ 2891590Srgrimesint 2901590Srgrimesvertcol(argc, argv) 2911590Srgrimes int argc; 2921590Srgrimes char *argv[]; 2931590Srgrimes{ 2941590Srgrimes register char *ptbf; 2951590Srgrimes register char **lstdat; 2961590Srgrimes register int i; 2971590Srgrimes register int j; 2981590Srgrimes register int cnt = -1; 2991590Srgrimes register int pln; 3001590Srgrimes register int *indy; 3011590Srgrimes int cvc; 3021590Srgrimes int *lindy; 3031590Srgrimes int lncnt; 3041590Srgrimes int stp; 3051590Srgrimes int pagecnt; 3061590Srgrimes int col = colwd + 1; 3071590Srgrimes int mxlen = pgwd + offst + 1; 3081590Srgrimes int mclcnt = clcnt - 1; 3091590Srgrimes struct vcol *vc; 3101590Srgrimes int mvc; 3111590Srgrimes int tvc; 3121590Srgrimes int cw = nmwd + 1; 3131590Srgrimes int fullcol; 3141590Srgrimes char *buf; 3151590Srgrimes char *hbuf; 3161590Srgrimes char *ohbuf; 3171590Srgrimes char *fname; 3181590Srgrimes FILE *inf; 3191590Srgrimes int ips = 0; 3201590Srgrimes int cps = 0; 3211590Srgrimes int ops = 0; 3221590Srgrimes int mor = 0; 3231590Srgrimes 3241590Srgrimes /* 3251590Srgrimes * allocate page buffer 3261590Srgrimes */ 3271590Srgrimes if ((buf = malloc((unsigned)lines*mxlen*sizeof(char))) == NULL) { 3281590Srgrimes mfail(); 3291590Srgrimes return(1); 3301590Srgrimes } 3311590Srgrimes 3321590Srgrimes /* 3331590Srgrimes * allocate page header 3341590Srgrimes */ 3351590Srgrimes if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) { 3361590Srgrimes mfail(); 3371590Srgrimes return(1); 3381590Srgrimes } 3391590Srgrimes ohbuf = hbuf + offst; 3401590Srgrimes if (offst) 3411590Srgrimes (void)memset(hbuf, (int)' ', offst); 3421590Srgrimes 3431590Srgrimes /* 3441590Srgrimes * col pointers when no headers 3451590Srgrimes */ 3461590Srgrimes mvc = lines * clcnt; 3471590Srgrimes if ((vc = 3481590Srgrimes (struct vcol *)malloc((unsigned)mvc*sizeof(struct vcol))) == NULL) { 3491590Srgrimes mfail(); 3501590Srgrimes return(1); 3511590Srgrimes } 3521590Srgrimes 3531590Srgrimes /* 3541590Srgrimes * pointer into page where last data per line is located 3551590Srgrimes */ 3561590Srgrimes if ((lstdat = (char **)malloc((unsigned)lines*sizeof(char *))) == NULL){ 3571590Srgrimes mfail(); 3581590Srgrimes return(1); 3591590Srgrimes } 3601590Srgrimes 3611590Srgrimes /* 3621590Srgrimes * fast index lookups to locate start of lines 3631590Srgrimes */ 3641590Srgrimes if ((indy = (int *)malloc((unsigned)lines*sizeof(int))) == NULL) { 3651590Srgrimes mfail(); 3661590Srgrimes return(1); 3671590Srgrimes } 3681590Srgrimes if ((lindy = (int *)malloc((unsigned)lines*sizeof(int))) == NULL) { 3691590Srgrimes mfail(); 3701590Srgrimes return(1); 3711590Srgrimes } 3721590Srgrimes 3731590Srgrimes if (nmwd) 3741590Srgrimes fullcol = col + cw; 3751590Srgrimes else 3761590Srgrimes fullcol = col; 3771590Srgrimes 3781590Srgrimes /* 3791590Srgrimes * initialize buffer lookup indexes and offset area 3801590Srgrimes */ 3811590Srgrimes for (j = 0; j < lines; ++j) { 3821590Srgrimes lindy[j] = j * mxlen; 3831590Srgrimes indy[j] = lindy[j] + offst; 3841590Srgrimes if (offst) { 3851590Srgrimes ptbf = buf + lindy[j]; 3861590Srgrimes (void)memset(ptbf, (int)' ', offst); 3871590Srgrimes ptbf += offst; 3881590Srgrimes } else 3891590Srgrimes ptbf = buf + indy[j]; 3901590Srgrimes lstdat[j] = ptbf; 3911590Srgrimes } 3921590Srgrimes 3931590Srgrimes /* 3941590Srgrimes * loop by file 3951590Srgrimes */ 3961590Srgrimes while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) { 3971590Srgrimes if (pgnm) { 3981590Srgrimes /* 3991590Srgrimes * skip to requested page 4001590Srgrimes */ 4011590Srgrimes if (inskip(inf, pgnm, lines)) 4021590Srgrimes continue; 4031590Srgrimes pagecnt = pgnm; 4041590Srgrimes } else 4051590Srgrimes pagecnt = 1; 4061590Srgrimes lncnt = 0; 4071590Srgrimes 4081590Srgrimes /* 4091590Srgrimes * loop by page 4101590Srgrimes */ 4111590Srgrimes for(;;) { 4121590Srgrimes /* 4131590Srgrimes * loop by column 4141590Srgrimes */ 4151590Srgrimes cvc = 0; 4161590Srgrimes for (i = 0; i < clcnt; ++i) { 4171590Srgrimes j = 0; 4181590Srgrimes /* 4191590Srgrimes * if last column, do not pad 4201590Srgrimes */ 4211590Srgrimes if (i == mclcnt) 4221590Srgrimes stp = 1; 4231590Srgrimes else 4241590Srgrimes stp = 0; 4251590Srgrimes /* 4261590Srgrimes * loop by line 4271590Srgrimes */ 4281590Srgrimes for(;;) { 4291590Srgrimes /* 4301590Srgrimes * is this first column 4311590Srgrimes */ 4321590Srgrimes if (!i) { 4331590Srgrimes ptbf = buf + indy[j]; 4341590Srgrimes lstdat[j] = ptbf; 4358874Srgrimes } else 4361590Srgrimes ptbf = lstdat[j]; 4371590Srgrimes vc[cvc].pt = ptbf; 4381590Srgrimes 4391590Srgrimes /* 4401590Srgrimes * add number 4411590Srgrimes */ 4421590Srgrimes if (nmwd) { 4431590Srgrimes addnum(ptbf, nmwd, ++lncnt); 4441590Srgrimes ptbf += nmwd; 4451590Srgrimes *ptbf++ = nmchar; 4461590Srgrimes } 4471590Srgrimes 4481590Srgrimes /* 4491590Srgrimes * input next line 4501590Srgrimes */ 4511590Srgrimes cnt = inln(inf,ptbf,colwd,&cps,1,&mor); 4521590Srgrimes vc[cvc++].cnt = cnt; 4531590Srgrimes if (cnt < 0) 4541590Srgrimes break; 4551590Srgrimes ptbf += cnt; 4561590Srgrimes 4571590Srgrimes /* 4581590Srgrimes * pad all but last column on page 4591590Srgrimes */ 4601590Srgrimes if (!stp) { 4611590Srgrimes /* 4621590Srgrimes * pad to end of column 4631590Srgrimes */ 4641590Srgrimes if (sflag) 4651590Srgrimes *ptbf++ = schar; 4661590Srgrimes else if ((pln = col-cnt) > 0) { 4671590Srgrimes (void)memset(ptbf, 4681590Srgrimes (int)' ',pln); 4691590Srgrimes ptbf += pln; 4701590Srgrimes } 4711590Srgrimes } 4721590Srgrimes /* 4731590Srgrimes * remember last char in line 4741590Srgrimes */ 4751590Srgrimes lstdat[j] = ptbf; 4761590Srgrimes if (++j >= lines) 4771590Srgrimes break; 4781590Srgrimes } 4791590Srgrimes if (cnt < 0) 4801590Srgrimes break; 4811590Srgrimes } 4821590Srgrimes 4831590Srgrimes /* 4841590Srgrimes * when -t (no header) is specified the spec requires 4851590Srgrimes * the min number of lines. The last page may not have 4861590Srgrimes * balanced length columns. To fix this we must reorder 4871590Srgrimes * the columns. This is a very slow technique so it is 4881590Srgrimes * only used under limited conditions. Without -t, the 4891590Srgrimes * balancing of text columns is unspecified. To NOT 4901590Srgrimes * balance the last page, add the global variable 4911590Srgrimes * nohead to the if statement below e.g. 4921590Srgrimes * 4931590Srgrimes * if ((cnt < 0) && nohead && cvc ...... 4941590Srgrimes */ 4951590Srgrimes --cvc; 4961590Srgrimes 4971590Srgrimes /* 4981590Srgrimes * check to see if last page needs to be reordered 4991590Srgrimes */ 5001590Srgrimes if ((cnt < 0) && cvc && ((mvc-cvc) >= clcnt)){ 5011590Srgrimes pln = cvc/clcnt; 5021590Srgrimes if (cvc % clcnt) 5031590Srgrimes ++pln; 5041590Srgrimes 5051590Srgrimes /* 5061590Srgrimes * print header 5071590Srgrimes */ 5081590Srgrimes if (!nohead && prhead(hbuf, fname, pagecnt)) 5091590Srgrimes return(1); 5101590Srgrimes for (i = 0; i < pln; ++i) { 5111590Srgrimes ips = 0; 5121590Srgrimes ops = 0; 5131590Srgrimes if (offst&& otln(buf,offst,&ips,&ops,1)) 5141590Srgrimes return(1); 5151590Srgrimes tvc = i; 5161590Srgrimes 5171590Srgrimes for (j = 0; j < clcnt; ++j) { 5181590Srgrimes /* 5191590Srgrimes * determine column length 5201590Srgrimes */ 5211590Srgrimes if (j == mclcnt) { 5221590Srgrimes /* 5231590Srgrimes * last column 5241590Srgrimes */ 5251590Srgrimes cnt = vc[tvc].cnt; 5261590Srgrimes if (nmwd) 5271590Srgrimes cnt += cw; 5281590Srgrimes } else if (sflag) { 5291590Srgrimes /* 5301590Srgrimes * single ch between 5311590Srgrimes */ 5321590Srgrimes cnt = vc[tvc].cnt + 1; 5331590Srgrimes if (nmwd) 5341590Srgrimes cnt += cw; 5351590Srgrimes } else 5361590Srgrimes cnt = fullcol; 5371590Srgrimes if (otln(vc[tvc].pt, cnt, &ips, 5381590Srgrimes &ops, 1)) 5391590Srgrimes return(1); 5401590Srgrimes tvc += pln; 5411590Srgrimes if (tvc >= cvc) 5421590Srgrimes break; 5431590Srgrimes } 5441590Srgrimes /* 5451590Srgrimes * terminate line 5461590Srgrimes */ 5471590Srgrimes if (otln(buf, 0, &ips, &ops, 0)) 5481590Srgrimes return(1); 5491590Srgrimes } 5501590Srgrimes /* 5511590Srgrimes * pad to end of page 5521590Srgrimes */ 5531590Srgrimes if (prtail((lines - pln), 0)) 5541590Srgrimes return(1); 5551590Srgrimes /* 5561590Srgrimes * done with output, go to next file 5571590Srgrimes */ 5581590Srgrimes break; 5591590Srgrimes } 5601590Srgrimes 5611590Srgrimes /* 5621590Srgrimes * determine how many lines to output 5631590Srgrimes */ 5641590Srgrimes if (i > 0) 5651590Srgrimes pln = lines; 5661590Srgrimes else 5671590Srgrimes pln = j; 5681590Srgrimes 5691590Srgrimes /* 5701590Srgrimes * print header 5711590Srgrimes */ 5721590Srgrimes if (pln && !nohead && prhead(hbuf, fname, pagecnt)) 5731590Srgrimes return(1); 5741590Srgrimes 5751590Srgrimes /* 5761590Srgrimes * output each line 5771590Srgrimes */ 5781590Srgrimes for (i = 0; i < pln; ++i) { 5791590Srgrimes ptbf = buf + lindy[i]; 5801590Srgrimes if ((j = lstdat[i] - ptbf) <= offst) 5811590Srgrimes break; 5821590Srgrimes if (otln(ptbf, j, &ips, &ops, 0)) 5831590Srgrimes return(1); 5841590Srgrimes } 5851590Srgrimes 5861590Srgrimes /* 5871590Srgrimes * pad to end of page 5881590Srgrimes */ 5891590Srgrimes if (pln && prtail((lines - pln), 0)) 5901590Srgrimes return(1); 5911590Srgrimes 5921590Srgrimes /* 5931590Srgrimes * if EOF go to next file 5941590Srgrimes */ 5951590Srgrimes if (cnt < 0) 5961590Srgrimes break; 5971590Srgrimes ++pagecnt; 5981590Srgrimes } 5991590Srgrimes if (inf != stdin) 6001590Srgrimes (void)fclose(inf); 6011590Srgrimes } 6021590Srgrimes if (eoptind < argc) 6031590Srgrimes return(1); 6041590Srgrimes return(0); 6051590Srgrimes} 6061590Srgrimes 6071590Srgrimes/* 6081590Srgrimes * horzcol: print files with more than one column of output across a page 6091590Srgrimes */ 6101590Srgrimesint 6111590Srgrimeshorzcol(argc, argv) 6121590Srgrimes int argc; 6131590Srgrimes char *argv[]; 6141590Srgrimes{ 6151590Srgrimes register char *ptbf; 6161590Srgrimes register int pln; 6171590Srgrimes register int cnt = -1; 6181590Srgrimes register char *lstdat; 6191590Srgrimes register int col = colwd + 1; 6201590Srgrimes register int j; 6211590Srgrimes register int i; 6221590Srgrimes int lncnt; 6231590Srgrimes int pagecnt; 6241590Srgrimes char *buf; 6251590Srgrimes char *hbuf; 6261590Srgrimes char *ohbuf; 6271590Srgrimes char *fname; 6281590Srgrimes FILE *inf; 6291590Srgrimes int ips = 0; 6301590Srgrimes int cps = 0; 6311590Srgrimes int ops = 0; 6321590Srgrimes int mor = 0; 6331590Srgrimes 6341590Srgrimes if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL) { 6351590Srgrimes mfail(); 6361590Srgrimes return(1); 6371590Srgrimes } 6381590Srgrimes 6391590Srgrimes /* 6401590Srgrimes * page header 6411590Srgrimes */ 6421590Srgrimes if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) { 6431590Srgrimes mfail(); 6441590Srgrimes return(1); 6451590Srgrimes } 6461590Srgrimes ohbuf = hbuf + offst; 6471590Srgrimes if (offst) { 6481590Srgrimes (void)memset(buf, (int)' ', offst); 6491590Srgrimes (void)memset(hbuf, (int)' ', offst); 6501590Srgrimes } 6511590Srgrimes 6521590Srgrimes /* 6531590Srgrimes * loop by file 6541590Srgrimes */ 6551590Srgrimes while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) { 6561590Srgrimes if (pgnm) { 6571590Srgrimes if (inskip(inf, pgnm, lines)) 6581590Srgrimes continue; 6591590Srgrimes pagecnt = pgnm; 6601590Srgrimes } else 6611590Srgrimes pagecnt = 1; 6621590Srgrimes lncnt = 0; 6631590Srgrimes 6641590Srgrimes /* 6651590Srgrimes * loop by page 6661590Srgrimes */ 6671590Srgrimes for(;;) { 6681590Srgrimes /* 6691590Srgrimes * loop by line 6701590Srgrimes */ 6711590Srgrimes for (i = 0; i < lines; ++i) { 6721590Srgrimes ptbf = buf + offst; 6731590Srgrimes lstdat = ptbf; 6741590Srgrimes j = 0; 6751590Srgrimes /* 6761590Srgrimes * loop by col 6771590Srgrimes */ 6781590Srgrimes for(;;) { 6791590Srgrimes if (nmwd) { 6801590Srgrimes /* 6811590Srgrimes * add number to column 6821590Srgrimes */ 6831590Srgrimes addnum(ptbf, nmwd, ++lncnt); 6841590Srgrimes ptbf += nmwd; 6851590Srgrimes *ptbf++ = nmchar; 6861590Srgrimes } 6871590Srgrimes /* 6881590Srgrimes * input line 6891590Srgrimes */ 6901590Srgrimes if ((cnt = inln(inf,ptbf,colwd,&cps,1, 6911590Srgrimes &mor)) < 0) 6921590Srgrimes break; 6931590Srgrimes ptbf += cnt; 6941590Srgrimes lstdat = ptbf; 6951590Srgrimes 6961590Srgrimes /* 6971590Srgrimes * if last line skip padding 6981590Srgrimes */ 6991590Srgrimes if (++j >= clcnt) 7001590Srgrimes break; 7011590Srgrimes 7021590Srgrimes /* 7031590Srgrimes * pad to end of column 7041590Srgrimes */ 7051590Srgrimes if (sflag) 7061590Srgrimes *ptbf++ = schar; 7071590Srgrimes else if ((pln = col - cnt) > 0) { 7081590Srgrimes (void)memset(ptbf,(int)' ',pln); 7091590Srgrimes ptbf += pln; 7101590Srgrimes } 7111590Srgrimes } 7121590Srgrimes 7131590Srgrimes /* 7141590Srgrimes * determine line length 7151590Srgrimes */ 7161590Srgrimes if ((j = lstdat - buf) <= offst) 7171590Srgrimes break; 7181590Srgrimes if (!i && !nohead && 7191590Srgrimes prhead(hbuf, fname, pagecnt)) 7201590Srgrimes return(1); 7211590Srgrimes /* 7221590Srgrimes * output line 7231590Srgrimes */ 7241590Srgrimes if (otln(buf, j, &ips, &ops, 0)) 7251590Srgrimes return(1); 7261590Srgrimes } 7271590Srgrimes 7281590Srgrimes /* 7291590Srgrimes * pad to end of page 7301590Srgrimes */ 7311590Srgrimes if (i && prtail(lines-i, 0)) 7321590Srgrimes return(1); 7331590Srgrimes 7341590Srgrimes /* 7351590Srgrimes * if EOF go to next file 7361590Srgrimes */ 7371590Srgrimes if (cnt < 0) 7381590Srgrimes break; 7391590Srgrimes ++pagecnt; 7401590Srgrimes } 7411590Srgrimes if (inf != stdin) 7421590Srgrimes (void)fclose(inf); 7431590Srgrimes } 7441590Srgrimes if (eoptind < argc) 7451590Srgrimes return(1); 7461590Srgrimes return(0); 7471590Srgrimes} 7481590Srgrimes 7491590Srgrimes/* 7501590Srgrimes * mulfile: print files with more than one column of output and 7511590Srgrimes * more than one file concurrently 7521590Srgrimes */ 7531590Srgrimesint 7541590Srgrimesmulfile(argc, argv) 7551590Srgrimes int argc; 7561590Srgrimes char *argv[]; 7571590Srgrimes{ 7581590Srgrimes register char *ptbf; 7591590Srgrimes register int j; 7601590Srgrimes register int pln; 7611590Srgrimes register int cnt; 7621590Srgrimes register char *lstdat; 7631590Srgrimes register int i; 7641590Srgrimes FILE **fbuf; 7651590Srgrimes int actf; 7661590Srgrimes int lncnt; 7671590Srgrimes int col; 7681590Srgrimes int pagecnt; 7691590Srgrimes int fproc; 7701590Srgrimes char *buf; 7711590Srgrimes char *hbuf; 7721590Srgrimes char *ohbuf; 7731590Srgrimes char *fname; 7741590Srgrimes int ips = 0; 7751590Srgrimes int cps = 0; 7761590Srgrimes int ops = 0; 7771590Srgrimes int mor = 0; 7781590Srgrimes 7791590Srgrimes /* 7801590Srgrimes * array of FILE *, one for each operand 7811590Srgrimes */ 7821590Srgrimes if ((fbuf = (FILE **)malloc((unsigned)clcnt*sizeof(FILE *))) == NULL) { 7831590Srgrimes mfail(); 7841590Srgrimes return(1); 7851590Srgrimes } 7861590Srgrimes 7871590Srgrimes /* 7881590Srgrimes * page header 7891590Srgrimes */ 7901590Srgrimes if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) { 7911590Srgrimes mfail(); 7921590Srgrimes return(1); 7931590Srgrimes } 7941590Srgrimes ohbuf = hbuf + offst; 7951590Srgrimes 7961590Srgrimes /* 7971590Srgrimes * do not know how many columns yet. The number of operands provide an 7981590Srgrimes * upper bound on the number of columns. We use the number of files 7991590Srgrimes * we can open successfully to set the number of columns. The operation 8001590Srgrimes * of the merge operation (-m) in relation to unsuccesful file opens 8011590Srgrimes * is unspecified by posix. 8021590Srgrimes */ 8031590Srgrimes j = 0; 8041590Srgrimes while (j < clcnt) { 8051590Srgrimes if ((fbuf[j] = nxtfile(argc, argv, &fname, ohbuf, 1)) == NULL) 8061590Srgrimes break; 8071590Srgrimes if (pgnm && (inskip(fbuf[j], pgnm, lines))) 8081590Srgrimes fbuf[j] = NULL; 8091590Srgrimes ++j; 8101590Srgrimes } 8111590Srgrimes 8121590Srgrimes /* 8131590Srgrimes * if no files, exit 8141590Srgrimes */ 8151590Srgrimes if (!j) 8161590Srgrimes return(1); 8171590Srgrimes 8181590Srgrimes /* 8191590Srgrimes * calculate page boundries based on open file count 8201590Srgrimes */ 8211590Srgrimes clcnt = j; 8221590Srgrimes if (nmwd) { 8231590Srgrimes colwd = (pgwd - clcnt - nmwd)/clcnt; 8241590Srgrimes pgwd = ((colwd + 1) * clcnt) - nmwd - 2; 8251590Srgrimes } else { 8261590Srgrimes colwd = (pgwd + 1 - clcnt)/clcnt; 8271590Srgrimes pgwd = ((colwd + 1) * clcnt) - 1; 8281590Srgrimes } 8291590Srgrimes if (colwd < 1) { 8301590Srgrimes (void)fprintf(err, 8311590Srgrimes "pr: page width too small for %d columns\n", clcnt); 8321590Srgrimes return(1); 8331590Srgrimes } 8341590Srgrimes actf = clcnt; 8351590Srgrimes col = colwd + 1; 8361590Srgrimes 8371590Srgrimes /* 8381590Srgrimes * line buffer 8391590Srgrimes */ 8401590Srgrimes if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL) { 8411590Srgrimes mfail(); 8421590Srgrimes return(1); 8431590Srgrimes } 8441590Srgrimes if (offst) { 8451590Srgrimes (void)memset(buf, (int)' ', offst); 8461590Srgrimes (void)memset(hbuf, (int)' ', offst); 8471590Srgrimes } 8481590Srgrimes if (pgnm) 8491590Srgrimes pagecnt = pgnm; 8501590Srgrimes else 8511590Srgrimes pagecnt = 1; 8521590Srgrimes lncnt = 0; 8531590Srgrimes 8541590Srgrimes /* 8551590Srgrimes * continue to loop while any file still has data 8561590Srgrimes */ 8571590Srgrimes while (actf > 0) { 8581590Srgrimes /* 8591590Srgrimes * loop by line 8601590Srgrimes */ 8611590Srgrimes for (i = 0; i < lines; ++i) { 8621590Srgrimes ptbf = buf + offst; 8631590Srgrimes lstdat = ptbf; 8641590Srgrimes if (nmwd) { 8651590Srgrimes /* 8661590Srgrimes * add line number to line 8671590Srgrimes */ 8681590Srgrimes addnum(ptbf, nmwd, ++lncnt); 8691590Srgrimes ptbf += nmwd; 8701590Srgrimes *ptbf++ = nmchar; 8711590Srgrimes } 8721590Srgrimes j = 0; 8731590Srgrimes fproc = 0; 8741590Srgrimes 8751590Srgrimes /* 8761590Srgrimes * loop by column 8771590Srgrimes */ 8781590Srgrimes for (j = 0; j < clcnt; ++j) { 8791590Srgrimes if (fbuf[j] == NULL) { 8801590Srgrimes /* 8811590Srgrimes * empty column; EOF 8821590Srgrimes */ 8831590Srgrimes cnt = 0; 8841590Srgrimes } else if ((cnt = inln(fbuf[j], ptbf, colwd, 8851590Srgrimes &cps, 1, &mor)) < 0) { 8861590Srgrimes /* 8871590Srgrimes * EOF hit; no data 8881590Srgrimes */ 8891590Srgrimes if (fbuf[j] != stdin) 8901590Srgrimes (void)fclose(fbuf[j]); 8911590Srgrimes fbuf[j] = NULL; 8921590Srgrimes --actf; 8931590Srgrimes cnt = 0; 8941590Srgrimes } else { 8951590Srgrimes /* 8961590Srgrimes * process file data 8971590Srgrimes */ 8981590Srgrimes ptbf += cnt; 8991590Srgrimes lstdat = ptbf; 9001590Srgrimes fproc++; 9011590Srgrimes } 9021590Srgrimes 9031590Srgrimes /* 9041590Srgrimes * if last ACTIVE column, done with line 9051590Srgrimes */ 9061590Srgrimes if (fproc >= actf) 9071590Srgrimes break; 9081590Srgrimes 9091590Srgrimes /* 9101590Srgrimes * pad to end of column 9111590Srgrimes */ 9121590Srgrimes if (sflag) { 9131590Srgrimes *ptbf++ = schar; 9141590Srgrimes } else if ((pln = col - cnt) > 0) { 9151590Srgrimes (void)memset(ptbf, (int)' ', pln); 9161590Srgrimes ptbf += pln; 9171590Srgrimes } 9181590Srgrimes } 9191590Srgrimes 9201590Srgrimes /* 9211590Srgrimes * calculate data in line 9221590Srgrimes */ 9231590Srgrimes if ((j = lstdat - buf) <= offst) 9241590Srgrimes break; 9251590Srgrimes 9261590Srgrimes if (!i && !nohead && prhead(hbuf, fname, pagecnt)) 9271590Srgrimes return(1); 9281590Srgrimes 9291590Srgrimes /* 9301590Srgrimes * output line 9311590Srgrimes */ 9321590Srgrimes if (otln(buf, j, &ips, &ops, 0)) 9331590Srgrimes return(1); 9341590Srgrimes 9351590Srgrimes /* 9361590Srgrimes * if no more active files, done 9371590Srgrimes */ 9381590Srgrimes if (actf <= 0) { 9391590Srgrimes ++i; 9401590Srgrimes break; 9411590Srgrimes } 9421590Srgrimes } 9431590Srgrimes 9441590Srgrimes /* 9451590Srgrimes * pad to end of page 9461590Srgrimes */ 9471590Srgrimes if (i && prtail(lines-i, 0)) 9481590Srgrimes return(1); 9491590Srgrimes ++pagecnt; 9501590Srgrimes } 9511590Srgrimes if (eoptind < argc) 9521590Srgrimes return(1); 9531590Srgrimes return(0); 9541590Srgrimes} 9551590Srgrimes 9561590Srgrimes/* 9571590Srgrimes * inln(): input a line of data (unlimited length lines supported) 9581590Srgrimes * Input is optionally expanded to spaces 9591590Srgrimes * 9601590Srgrimes * inf: file 9611590Srgrimes * buf: buffer 9621590Srgrimes * lim: buffer length 9631590Srgrimes * cps: column positon 1st char in buffer (large line support) 9648874Srgrimes * trnc: throw away data more than lim up to \n 9651590Srgrimes * mor: set if more data in line (not truncated) 9661590Srgrimes */ 9671590Srgrimesint 9681590Srgrimesinln(inf, buf, lim, cps, trnc, mor) 9691590Srgrimes FILE *inf; 9701590Srgrimes char *buf; 9711590Srgrimes register int lim; 9721590Srgrimes int *cps; 9731590Srgrimes int trnc; 9741590Srgrimes int *mor; 9751590Srgrimes{ 9761590Srgrimes register int col; 9771590Srgrimes register int gap = ingap; 9781590Srgrimes register int ch = EOF; 9791590Srgrimes register char *ptbuf; 9801590Srgrimes register int chk = (int)inchar; 9811590Srgrimes 9821590Srgrimes ptbuf = buf; 9831590Srgrimes 9841590Srgrimes if (gap) { 9851590Srgrimes /* 9861590Srgrimes * expanding input option 9871590Srgrimes */ 9881590Srgrimes while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) { 9891590Srgrimes /* 9901590Srgrimes * is this the input "tab" char 9911590Srgrimes */ 9921590Srgrimes if (ch == chk) { 9931590Srgrimes /* 9941590Srgrimes * expand to number of spaces 9951590Srgrimes */ 9961590Srgrimes col = (ptbuf - buf) + *cps; 9971590Srgrimes col = gap - (col % gap); 9981590Srgrimes 9991590Srgrimes /* 10001590Srgrimes * if more than this line, push back 10011590Srgrimes */ 10021590Srgrimes if ((col > lim) && (ungetc(ch, inf) == EOF)) 10031590Srgrimes return(1); 10041590Srgrimes 10051590Srgrimes /* 10061590Srgrimes * expand to spaces 10071590Srgrimes */ 10081590Srgrimes while ((--col >= 0) && (--lim >= 0)) 10091590Srgrimes *ptbuf++ = ' '; 10101590Srgrimes continue; 10111590Srgrimes } 10121590Srgrimes if (ch == '\n') 10131590Srgrimes break; 10141590Srgrimes *ptbuf++ = ch; 10151590Srgrimes } 10161590Srgrimes } else { 10171590Srgrimes /* 10181590Srgrimes * no expansion 10191590Srgrimes */ 10201590Srgrimes while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) { 10211590Srgrimes if (ch == '\n') 10221590Srgrimes break; 10231590Srgrimes *ptbuf++ = ch; 10241590Srgrimes } 10251590Srgrimes } 10261590Srgrimes col = ptbuf - buf; 10271590Srgrimes if (ch == EOF) { 10281590Srgrimes *mor = 0; 10291590Srgrimes *cps = 0; 10301590Srgrimes if (!col) 10311590Srgrimes return(-1); 10321590Srgrimes return(col); 10331590Srgrimes } 10341590Srgrimes if (ch == '\n') { 10351590Srgrimes /* 10361590Srgrimes * entire line processed 10371590Srgrimes */ 10381590Srgrimes *mor = 0; 10391590Srgrimes *cps = 0; 10401590Srgrimes return(col); 10411590Srgrimes } 10421590Srgrimes 10431590Srgrimes /* 10441590Srgrimes * line was larger than limit 10451590Srgrimes */ 10461590Srgrimes if (trnc) { 10471590Srgrimes /* 10481590Srgrimes * throw away rest of line 10491590Srgrimes */ 10501590Srgrimes while ((ch = getc(inf)) != EOF) { 10511590Srgrimes if (ch == '\n') 10521590Srgrimes break; 10531590Srgrimes } 10541590Srgrimes *cps = 0; 10551590Srgrimes *mor = 0; 10561590Srgrimes } else { 10571590Srgrimes /* 10581590Srgrimes * save column offset if not truncated 10591590Srgrimes */ 10601590Srgrimes *cps += col; 10611590Srgrimes *mor = 1; 10621590Srgrimes } 10631590Srgrimes 10641590Srgrimes return(col); 10651590Srgrimes} 10661590Srgrimes 10671590Srgrimes/* 10681590Srgrimes * otln(): output a line of data. (Supports unlimited length lines) 10691590Srgrimes * output is optionally contracted to tabs 10701590Srgrimes * 10711590Srgrimes * buf: output buffer with data 10721590Srgrimes * cnt: number of chars of valid data in buf 10731590Srgrimes * svips: buffer input column position (for large lines) 10741590Srgrimes * svops: buffer output column position (for large lines) 10758874Srgrimes * mor: output line not complete in this buf; more data to come. 10761590Srgrimes * 1 is more, 0 is complete, -1 is no \n's 10771590Srgrimes */ 10781590Srgrimesint 10791590Srgrimesotln(buf, cnt, svips, svops, mor) 10801590Srgrimes register char *buf; 10811590Srgrimes int cnt; 10821590Srgrimes int *svops; 10831590Srgrimes int *svips; 10841590Srgrimes int mor; 10851590Srgrimes{ 10861590Srgrimes register int ops; /* last col output */ 10871590Srgrimes register int ips; /* last col in buf examined */ 10881590Srgrimes register int gap = ogap; 10891590Srgrimes register int tbps; 10901590Srgrimes register char *endbuf; 10911590Srgrimes 10921590Srgrimes if (ogap) { 10931590Srgrimes /* 10941590Srgrimes * contracting on output 10951590Srgrimes */ 10961590Srgrimes endbuf = buf + cnt; 10971590Srgrimes ops = *svops; 10981590Srgrimes ips = *svips; 10991590Srgrimes while (buf < endbuf) { 11001590Srgrimes /* 11011590Srgrimes * count number of spaces and ochar in buffer 11021590Srgrimes */ 11031590Srgrimes if (*buf == ' ') { 11041590Srgrimes ++ips; 11051590Srgrimes ++buf; 11061590Srgrimes continue; 11071590Srgrimes } 11081590Srgrimes 11091590Srgrimes /* 11101590Srgrimes * simulate ochar processing 11111590Srgrimes */ 11121590Srgrimes if (*buf == ochar) { 11131590Srgrimes ips += gap - (ips % gap); 11141590Srgrimes ++buf; 11151590Srgrimes continue; 11161590Srgrimes } 11171590Srgrimes 11181590Srgrimes /* 11191590Srgrimes * got a non space char; contract out spaces 11201590Srgrimes */ 11211590Srgrimes while (ops < ips) { 11221590Srgrimes /* 11231590Srgrimes * use as many ochar as will fit 11241590Srgrimes */ 11251590Srgrimes if ((tbps = ops + gap - (ops % gap)) > ips) 11261590Srgrimes break; 11271590Srgrimes if (putchar(ochar) == EOF) { 11281590Srgrimes pfail(); 11291590Srgrimes return(1); 11301590Srgrimes } 11311590Srgrimes ops = tbps; 11321590Srgrimes } 11331590Srgrimes 11341590Srgrimes while (ops < ips) { 11351590Srgrimes /* 11361590Srgrimes * finish off with spaces 11371590Srgrimes */ 11381590Srgrimes if (putchar(' ') == EOF) { 11391590Srgrimes pfail(); 11401590Srgrimes return(1); 11411590Srgrimes } 11421590Srgrimes ++ops; 11431590Srgrimes } 11441590Srgrimes 11451590Srgrimes /* 11461590Srgrimes * output non space char 11471590Srgrimes */ 11481590Srgrimes if (putchar(*buf++) == EOF) { 11491590Srgrimes pfail(); 11501590Srgrimes return(1); 11511590Srgrimes } 11521590Srgrimes ++ips; 11531590Srgrimes ++ops; 11541590Srgrimes } 11551590Srgrimes 11561590Srgrimes if (mor > 0) { 11571590Srgrimes /* 11581590Srgrimes * if incomplete line, save position counts 11591590Srgrimes */ 11601590Srgrimes *svops = ops; 11611590Srgrimes *svips = ips; 11621590Srgrimes return(0); 11631590Srgrimes } 11641590Srgrimes 11651590Srgrimes if (mor < 0) { 11661590Srgrimes while (ops < ips) { 11671590Srgrimes /* 11681590Srgrimes * use as many ochar as will fit 11691590Srgrimes */ 11701590Srgrimes if ((tbps = ops + gap - (ops % gap)) > ips) 11711590Srgrimes break; 11721590Srgrimes if (putchar(ochar) == EOF) { 11731590Srgrimes pfail(); 11741590Srgrimes return(1); 11751590Srgrimes } 11761590Srgrimes ops = tbps; 11771590Srgrimes } 11781590Srgrimes while (ops < ips) { 11791590Srgrimes /* 11801590Srgrimes * finish off with spaces 11811590Srgrimes */ 11821590Srgrimes if (putchar(' ') == EOF) { 11831590Srgrimes pfail(); 11841590Srgrimes return(1); 11851590Srgrimes } 11861590Srgrimes ++ops; 11871590Srgrimes } 11881590Srgrimes return(0); 11891590Srgrimes } 11901590Srgrimes } else { 11911590Srgrimes /* 11921590Srgrimes * output is not contracted 11931590Srgrimes */ 11941590Srgrimes if (cnt && (fwrite(buf, sizeof(char), cnt, stdout) <= 0)) { 11951590Srgrimes pfail(); 11961590Srgrimes return(1); 11971590Srgrimes } 11981590Srgrimes if (mor != 0) 11991590Srgrimes return(0); 12001590Srgrimes } 12011590Srgrimes 12021590Srgrimes /* 12031590Srgrimes * process line end and double space as required 12041590Srgrimes */ 12051590Srgrimes if ((putchar('\n') == EOF) || (dspace && (putchar('\n') == EOF))) { 12061590Srgrimes pfail(); 12071590Srgrimes return(1); 12081590Srgrimes } 12091590Srgrimes return(0); 12101590Srgrimes} 12111590Srgrimes 12121590Srgrimes/* 12131590Srgrimes * inskip(): skip over pgcnt pages with lncnt lines per page 12141590Srgrimes * file is closed at EOF (if not stdin). 12151590Srgrimes * 12161590Srgrimes * inf FILE * to read from 12171590Srgrimes * pgcnt number of pages to skip 12181590Srgrimes * lncnt number of lines per page 12191590Srgrimes */ 12201590Srgrimesint 12211590Srgrimesinskip(inf, pgcnt, lncnt) 12221590Srgrimes FILE *inf; 12231590Srgrimes register int pgcnt; 12241590Srgrimes register int lncnt; 12251590Srgrimes{ 12261590Srgrimes register int c; 12271590Srgrimes register int cnt; 12281590Srgrimes 12291590Srgrimes while(--pgcnt > 0) { 12301590Srgrimes cnt = lncnt; 12311590Srgrimes while ((c = getc(inf)) != EOF) { 12321590Srgrimes if ((c == '\n') && (--cnt == 0)) 12331590Srgrimes break; 12341590Srgrimes } 12351590Srgrimes if (c == EOF) { 12361590Srgrimes if (inf != stdin) 12371590Srgrimes (void)fclose(inf); 12381590Srgrimes return(1); 12391590Srgrimes } 12401590Srgrimes } 12411590Srgrimes return(0); 12421590Srgrimes} 12431590Srgrimes 12441590Srgrimes/* 12451590Srgrimes * nxtfile: returns a FILE * to next file in arg list and sets the 12461590Srgrimes * time field for this file (or current date). 12471590Srgrimes * 12481590Srgrimes * buf array to store proper date for the header. 12491590Srgrimes * dt if set skips the date processing (used with -m) 12501590Srgrimes */ 12511590SrgrimesFILE * 12521590Srgrimesnxtfile(argc, argv, fname, buf, dt) 12531590Srgrimes int argc; 12541590Srgrimes char **argv; 12551590Srgrimes char **fname; 12561590Srgrimes char *buf; 12571590Srgrimes int dt; 12581590Srgrimes{ 12591590Srgrimes FILE *inf = NULL; 12601590Srgrimes struct timeval tv; 126137262Sbde time_t tv_sec; 12621590Srgrimes struct timezone tz; 12631590Srgrimes struct tm *timeptr = NULL; 12641590Srgrimes struct stat statbuf; 12651590Srgrimes static int twice = -1; 12661590Srgrimes 12671590Srgrimes ++twice; 12681590Srgrimes if (eoptind >= argc) { 12691590Srgrimes /* 12701590Srgrimes * no file listed; default, use standard input 12711590Srgrimes */ 12721590Srgrimes if (twice) 12731590Srgrimes return(NULL); 12741590Srgrimes clearerr(stdin); 12751590Srgrimes inf = stdin; 12761590Srgrimes if (header != NULL) 12771590Srgrimes *fname = header; 12781590Srgrimes else 12791590Srgrimes *fname = FNAME; 12801590Srgrimes if (nohead) 12811590Srgrimes return(inf); 12821590Srgrimes if (gettimeofday(&tv, &tz) < 0) { 12831590Srgrimes ++errcnt; 12841590Srgrimes (void)fprintf(err, "pr: cannot get time of day, %s\n", 12851590Srgrimes strerror(errno)); 12861590Srgrimes eoptind = argc - 1; 12871590Srgrimes return(NULL); 12881590Srgrimes } 128937262Sbde tv_sec = tv.tv_sec; 129037262Sbde timeptr = localtime(&tv_sec); 12911590Srgrimes } 12921590Srgrimes for (; eoptind < argc; ++eoptind) { 12931590Srgrimes if (strcmp(argv[eoptind], "-") == 0) { 12941590Srgrimes /* 12951590Srgrimes * process a "-" for filename 12961590Srgrimes */ 12971590Srgrimes clearerr(stdin); 12981590Srgrimes inf = stdin; 12991590Srgrimes if (header != NULL) 13001590Srgrimes *fname = header; 13011590Srgrimes else 13021590Srgrimes *fname = FNAME; 13031590Srgrimes ++eoptind; 13041590Srgrimes if (nohead || (dt && twice)) 13051590Srgrimes return(inf); 13061590Srgrimes if (gettimeofday(&tv, &tz) < 0) { 13071590Srgrimes ++errcnt; 13081590Srgrimes (void)fprintf(err, 13091590Srgrimes "pr: cannot get time of day, %s\n", 13101590Srgrimes strerror(errno)); 13111590Srgrimes return(NULL); 13121590Srgrimes } 131337262Sbde tv_sec = tv.tv_sec; 131437262Sbde timeptr = localtime(&tv_sec); 13151590Srgrimes } else { 13161590Srgrimes /* 13171590Srgrimes * normal file processing 13181590Srgrimes */ 13191590Srgrimes if ((inf = fopen(argv[eoptind], "r")) == NULL) { 13201590Srgrimes ++errcnt; 13211590Srgrimes if (nodiag) 13221590Srgrimes continue; 13231590Srgrimes (void)fprintf(err, "pr: Cannot open %s, %s\n", 13241590Srgrimes argv[eoptind], strerror(errno)); 13251590Srgrimes continue; 13261590Srgrimes } 13271590Srgrimes if (header != NULL) 13281590Srgrimes *fname = header; 13291590Srgrimes else if (dt) 13301590Srgrimes *fname = FNAME; 13311590Srgrimes else 13321590Srgrimes *fname = argv[eoptind]; 13331590Srgrimes ++eoptind; 13341590Srgrimes if (nohead || (dt && twice)) 13351590Srgrimes return(inf); 13361590Srgrimes 13371590Srgrimes if (dt) { 13381590Srgrimes if (gettimeofday(&tv, &tz) < 0) { 13391590Srgrimes ++errcnt; 13401590Srgrimes (void)fprintf(err, 13411590Srgrimes "pr: cannot get time of day, %s\n", 13421590Srgrimes strerror(errno)); 13431590Srgrimes return(NULL); 13441590Srgrimes } 134537262Sbde tv_sec = tv.tv_sec; 134637262Sbde timeptr = localtime(&tv_sec); 13471590Srgrimes } else { 13481590Srgrimes if (fstat(fileno(inf), &statbuf) < 0) { 13491590Srgrimes ++errcnt; 13501590Srgrimes (void)fclose(inf); 13518874Srgrimes (void)fprintf(err, 13521590Srgrimes "pr: Cannot stat %s, %s\n", 13531590Srgrimes argv[eoptind], strerror(errno)); 13541590Srgrimes return(NULL); 13551590Srgrimes } 13561590Srgrimes timeptr = localtime(&(statbuf.st_mtime)); 13571590Srgrimes } 13581590Srgrimes } 13591590Srgrimes break; 13601590Srgrimes } 13611590Srgrimes if (inf == NULL) 13621590Srgrimes return(NULL); 13631590Srgrimes 13641590Srgrimes /* 13651590Srgrimes * set up time field used in header 13661590Srgrimes */ 13671590Srgrimes if (strftime(buf, HDBUF, timefrmt, timeptr) <= 0) { 13681590Srgrimes ++errcnt; 13691590Srgrimes if (inf != stdin) 13701590Srgrimes (void)fclose(inf); 13711590Srgrimes (void)fputs("pr: time conversion failed\n", err); 13721590Srgrimes return(NULL); 13731590Srgrimes } 13741590Srgrimes return(inf); 13751590Srgrimes} 13761590Srgrimes 13771590Srgrimes/* 13781590Srgrimes * addnum(): adds the line number to the column 13791590Srgrimes * Truncates from the front or pads with spaces as required. 13801590Srgrimes * Numbers are right justified. 13811590Srgrimes * 13821590Srgrimes * buf buffer to store the number 13831590Srgrimes * wdth width of buffer to fill 13841590Srgrimes * line line number 13851590Srgrimes * 13861590Srgrimes * NOTE: numbers occupy part of the column. The posix 13871590Srgrimes * spec does not specify if -i processing should or should not 13881590Srgrimes * occur on number padding. The spec does say it occupies 13891590Srgrimes * part of the column. The usage of addnum currently treats 13901590Srgrimes * numbers as part of the column so spaces may be replaced. 13911590Srgrimes */ 13921590Srgrimesvoid 13931590Srgrimesaddnum(buf, wdth, line) 13941590Srgrimes register char *buf; 13951590Srgrimes register int wdth; 13961590Srgrimes register int line; 13971590Srgrimes{ 13981590Srgrimes register char *pt = buf + wdth; 13991590Srgrimes 14001590Srgrimes do { 14011590Srgrimes *--pt = digs[line % 10]; 14021590Srgrimes line /= 10; 14031590Srgrimes } while (line && (pt > buf)); 14041590Srgrimes 14051590Srgrimes /* 14061590Srgrimes * pad with space as required 14071590Srgrimes */ 14081590Srgrimes while (pt > buf) 14091590Srgrimes *--pt = ' '; 14101590Srgrimes} 14111590Srgrimes 14121590Srgrimes/* 14131590Srgrimes * prhead(): prints the top of page header 14141590Srgrimes * 14151590Srgrimes * buf buffer with time field (and offset) 14161590Srgrimes * cnt number of chars in buf 14171590Srgrimes * fname fname field for header 14181590Srgrimes * pagcnt page number 14191590Srgrimes */ 14201590Srgrimesint 14211590Srgrimesprhead(buf, fname, pagcnt) 14221590Srgrimes char *buf; 14231590Srgrimes char *fname; 14241590Srgrimes int pagcnt; 14251590Srgrimes{ 14261590Srgrimes int ips = 0; 14271590Srgrimes int ops = 0; 14281590Srgrimes 14291590Srgrimes if ((putchar('\n') == EOF) || (putchar('\n') == EOF)) { 14301590Srgrimes pfail(); 14311590Srgrimes return(1); 14321590Srgrimes } 14331590Srgrimes /* 14341590Srgrimes * posix is not clear if the header is subject to line length 14351590Srgrimes * restrictions. The specification for header line format 14361590Srgrimes * in the spec clearly does not limit length. No pr currently 14371590Srgrimes * restricts header length. However if we need to truncate in 14381590Srgrimes * an reasonable way, adjust the length of the printf by 14391590Srgrimes * changing HDFMT to allow a length max as an arguement printf. 14401590Srgrimes * buf (which contains the offset spaces and time field could 14411590Srgrimes * also be trimmed 14421590Srgrimes * 14431590Srgrimes * note only the offset (if any) is processed for tab expansion 14441590Srgrimes */ 14451590Srgrimes if (offst && otln(buf, offst, &ips, &ops, -1)) 14461590Srgrimes return(1); 14471590Srgrimes (void)printf(HDFMT,buf+offst, fname, pagcnt); 14481590Srgrimes return(0); 14491590Srgrimes} 14501590Srgrimes 14511590Srgrimes/* 14521590Srgrimes * prtail(): pad page with empty lines (if required) and print page trailer 14531590Srgrimes * if requested 14541590Srgrimes * 14551590Srgrimes * cnt number of lines of padding needed 14561590Srgrimes * incomp was a '\n' missing from last line output 14571590Srgrimes */ 14581590Srgrimesint 14591590Srgrimesprtail(cnt, incomp) 14601590Srgrimes register int cnt; 14611590Srgrimes int incomp; 14621590Srgrimes{ 14631590Srgrimes if (nohead) { 14641590Srgrimes /* 14651590Srgrimes * only pad with no headers when incomplete last line 14661590Srgrimes */ 146719092Sscrappy if (incomp && 146819092Sscrappy ((dspace && (putchar('\n') == EOF)) || 146919092Sscrappy (putchar('\n') == EOF))) { 14701590Srgrimes pfail(); 14711590Srgrimes return(1); 14721590Srgrimes } 147319092Sscrappy /* 147419092Sscrappy * but honor the formfeed request 147519092Sscrappy */ 147619092Sscrappy if (formfeed) { 147719092Sscrappy if (putchar('\f') == EOF) { 147819092Sscrappy pfail(); 147919092Sscrappy return(1); 148019092Sscrappy } 148119092Sscrappy } 14821590Srgrimes return(0); 14831590Srgrimes } 14841590Srgrimes /* 14851590Srgrimes * if double space output two \n 14861590Srgrimes */ 14871590Srgrimes if (dspace) 14881590Srgrimes cnt *= 2; 14891590Srgrimes 14901590Srgrimes /* 14911590Srgrimes * if an odd number of lines per page, add an extra \n 14921590Srgrimes */ 14931590Srgrimes if (addone) 14941590Srgrimes ++cnt; 14951590Srgrimes 14961590Srgrimes /* 14971590Srgrimes * pad page 14981590Srgrimes */ 14991590Srgrimes if (formfeed) { 15008874Srgrimes if ((incomp && (putchar('\n') == EOF)) || 15011590Srgrimes (putchar('\f') == EOF)) { 15021590Srgrimes pfail(); 15031590Srgrimes return(1); 15041590Srgrimes } 15051590Srgrimes return(0); 15068874Srgrimes } 15071590Srgrimes cnt += TAILLEN; 15081590Srgrimes while (--cnt >= 0) { 15091590Srgrimes if (putchar('\n') == EOF) { 15101590Srgrimes pfail(); 15111590Srgrimes return(1); 15121590Srgrimes } 15131590Srgrimes } 15141590Srgrimes return(0); 15151590Srgrimes} 15161590Srgrimes 15171590Srgrimes/* 15181590Srgrimes * terminate(): when a SIGINT is recvd 15191590Srgrimes */ 15201590Srgrimesvoid 15211590Srgrimesterminate(which_sig) 15221590Srgrimes int which_sig; 15231590Srgrimes{ 15241590Srgrimes flsh_errs(); 15251590Srgrimes exit(1); 15261590Srgrimes} 15271590Srgrimes 15281590Srgrimes 15291590Srgrimes/* 15301590Srgrimes * flsh_errs(): output saved up diagnostic messages after all normal 15311590Srgrimes * processing has completed 15321590Srgrimes */ 15331590Srgrimesvoid 15341590Srgrimesflsh_errs() 15351590Srgrimes{ 15361590Srgrimes char buf[BUFSIZ]; 15371590Srgrimes 15381590Srgrimes (void)fflush(stdout); 15391590Srgrimes (void)fflush(err); 15401590Srgrimes if (err == stderr) 15411590Srgrimes return; 15421590Srgrimes rewind(err); 15431590Srgrimes while (fgets(buf, BUFSIZ, err) != NULL) 15441590Srgrimes (void)fputs(buf, stderr); 15451590Srgrimes} 15461590Srgrimes 15471590Srgrimesvoid 15481590Srgrimesmfail() 15491590Srgrimes{ 15501590Srgrimes (void)fputs("pr: memory allocation failed\n", err); 15511590Srgrimes} 15521590Srgrimes 15531590Srgrimesvoid 15541590Srgrimespfail() 15551590Srgrimes{ 15561590Srgrimes (void)fprintf(err, "pr: write failure, %s\n", strerror(errno)); 15571590Srgrimes} 15581590Srgrimes 15591590Srgrimesvoid 15601590Srgrimesusage() 15611590Srgrimes{ 15621590Srgrimes (void)fputs( 156353955Sache "usage: pr [+page] [-col] [-adFmrt] [-e[ch][gap]] [-h header]\n",err); 15641590Srgrimes (void)fputs( 15651590Srgrimes " [-i[ch][gap]] [-l line] [-n[ch][width]] [-o offset]\n",err); 15661590Srgrimes (void)fputs( 156753955Sache " [-L locale] [-s[ch]] [-w width] [-] [file ...]\n", err); 15681590Srgrimes} 15691590Srgrimes 15701590Srgrimes/* 15718874Srgrimes * setup: Validate command args, initialize and perform sanity 15721590Srgrimes * checks on options 15731590Srgrimes */ 15741590Srgrimesint 15751590Srgrimessetup(argc, argv) 15761590Srgrimes register int argc; 15771590Srgrimes register char **argv; 15781590Srgrimes{ 15791590Srgrimes register int c; 15801590Srgrimes int eflag = 0; 15811590Srgrimes int iflag = 0; 15821590Srgrimes int wflag = 0; 15831590Srgrimes int cflag = 0; 158453955Sache char *Lflag = NULL; 15851590Srgrimes 15861590Srgrimes if (isatty(fileno(stdout))) { 15871590Srgrimes /* 15881590Srgrimes * defer diagnostics until processing is done 15891590Srgrimes */ 15901590Srgrimes if ((err = tmpfile()) == NULL) { 15911590Srgrimes (void)fputs("Cannot defer diagnostic messages\n",stderr); 15921590Srgrimes return(1); 15931590Srgrimes } 15941590Srgrimes } else 15951590Srgrimes err = stderr; 159653955Sache while ((c = egetopt(argc, argv, "#adFmrte?h:i?L:l:n?o:s?w:")) != -1) { 15971590Srgrimes switch (c) { 15981590Srgrimes case '+': 15991590Srgrimes if ((pgnm = atoi(eoptarg)) < 1) { 16001590Srgrimes (void)fputs("pr: +page number must be 1 or more\n", 16011590Srgrimes err); 16021590Srgrimes return(1); 16031590Srgrimes } 16041590Srgrimes break; 16051590Srgrimes case '-': 16061590Srgrimes if ((clcnt = atoi(eoptarg)) < 1) { 16071590Srgrimes (void)fputs("pr: -columns must be 1 or more\n",err); 16081590Srgrimes return(1); 16091590Srgrimes } 16101590Srgrimes if (clcnt > 1) 16111590Srgrimes ++cflag; 16121590Srgrimes break; 16131590Srgrimes case 'a': 16141590Srgrimes ++across; 16151590Srgrimes break; 16161590Srgrimes case 'd': 16171590Srgrimes ++dspace; 16181590Srgrimes break; 16191590Srgrimes case 'e': 16201590Srgrimes ++eflag; 162153948Sache if ((eoptarg != NULL) && !isdigit((unsigned char)*eoptarg)) 16221590Srgrimes inchar = *eoptarg++; 16231590Srgrimes else 16241590Srgrimes inchar = INCHAR; 162553948Sache if ((eoptarg != NULL) && isdigit((unsigned char)*eoptarg)) { 16261590Srgrimes if ((ingap = atoi(eoptarg)) < 0) { 16271590Srgrimes (void)fputs( 16281590Srgrimes "pr: -e gap must be 0 or more\n", err); 16291590Srgrimes return(1); 16301590Srgrimes } 16311590Srgrimes if (ingap == 0) 16321590Srgrimes ingap = INGAP; 16331590Srgrimes } else if ((eoptarg != NULL) && (*eoptarg != '\0')) { 16341590Srgrimes (void)fprintf(err, 16351590Srgrimes "pr: invalid value for -e %s\n", eoptarg); 16361590Srgrimes return(1); 16371590Srgrimes } else 16381590Srgrimes ingap = INGAP; 16391590Srgrimes break; 16401590Srgrimes case 'F': 16411590Srgrimes ++formfeed; 16421590Srgrimes break; 16431590Srgrimes case 'h': 16441590Srgrimes header = eoptarg; 16451590Srgrimes break; 16461590Srgrimes case 'i': 16471590Srgrimes ++iflag; 164853948Sache if ((eoptarg != NULL) && !isdigit((unsigned char)*eoptarg)) 16491590Srgrimes ochar = *eoptarg++; 16501590Srgrimes else 16511590Srgrimes ochar = OCHAR; 165253948Sache if ((eoptarg != NULL) && isdigit((unsigned char)*eoptarg)) { 16531590Srgrimes if ((ogap = atoi(eoptarg)) < 0) { 16541590Srgrimes (void)fputs( 16551590Srgrimes "pr: -i gap must be 0 or more\n", err); 16561590Srgrimes return(1); 16571590Srgrimes } 16581590Srgrimes if (ogap == 0) 16591590Srgrimes ogap = OGAP; 16601590Srgrimes } else if ((eoptarg != NULL) && (*eoptarg != '\0')) { 16611590Srgrimes (void)fprintf(err, 16621590Srgrimes "pr: invalid value for -i %s\n", eoptarg); 16631590Srgrimes return(1); 16641590Srgrimes } else 16651590Srgrimes ogap = OGAP; 16661590Srgrimes break; 166753948Sache case 'L': 166853955Sache Lflag = eoptarg; 166953948Sache break; 16701590Srgrimes case 'l': 167153948Sache if (!isdigit((unsigned char)*eoptarg) || ((lines=atoi(eoptarg)) < 1)) { 16721590Srgrimes (void)fputs( 16731590Srgrimes "pr: Number of lines must be 1 or more\n",err); 16741590Srgrimes return(1); 16751590Srgrimes } 16761590Srgrimes break; 16771590Srgrimes case 'm': 16781590Srgrimes ++merge; 16791590Srgrimes break; 16801590Srgrimes case 'n': 168153948Sache if ((eoptarg != NULL) && !isdigit((unsigned char)*eoptarg)) 16821590Srgrimes nmchar = *eoptarg++; 16831590Srgrimes else 16841590Srgrimes nmchar = NMCHAR; 168553948Sache if ((eoptarg != NULL) && isdigit((unsigned char)*eoptarg)) { 16861590Srgrimes if ((nmwd = atoi(eoptarg)) < 1) { 16871590Srgrimes (void)fputs( 16881590Srgrimes "pr: -n width must be 1 or more\n",err); 16891590Srgrimes return(1); 16901590Srgrimes } 16911590Srgrimes } else if ((eoptarg != NULL) && (*eoptarg != '\0')) { 16921590Srgrimes (void)fprintf(err, 16931590Srgrimes "pr: invalid value for -n %s\n", eoptarg); 16941590Srgrimes return(1); 16951590Srgrimes } else 16961590Srgrimes nmwd = NMWD; 16971590Srgrimes break; 16981590Srgrimes case 'o': 169953948Sache if (!isdigit((unsigned char)*eoptarg) || ((offst = atoi(eoptarg))< 1)){ 17001590Srgrimes (void)fputs("pr: -o offset must be 1 or more\n", 17011590Srgrimes err); 17021590Srgrimes return(1); 17031590Srgrimes } 17041590Srgrimes break; 17051590Srgrimes case 'r': 17061590Srgrimes ++nodiag; 17071590Srgrimes break; 17081590Srgrimes case 's': 17091590Srgrimes ++sflag; 17101590Srgrimes if (eoptarg == NULL) 17111590Srgrimes schar = SCHAR; 171254114Skris else { 17131590Srgrimes schar = *eoptarg++; 171454114Skris if (*eoptarg != '\0') { 171554114Skris (void)fprintf(err, 171654114Skris "pr: invalid value for -s %s\n", 171754114Skris eoptarg); 171854114Skris return(1); 171954114Skris } 17201590Srgrimes } 17211590Srgrimes break; 17221590Srgrimes case 't': 17231590Srgrimes ++nohead; 17241590Srgrimes break; 17251590Srgrimes case 'w': 17261590Srgrimes ++wflag; 172753948Sache if (!isdigit((unsigned char)*eoptarg) || ((pgwd = atoi(eoptarg)) < 1)){ 17281590Srgrimes (void)fputs( 17291590Srgrimes "pr: -w width must be 1 or more \n",err); 17301590Srgrimes return(1); 17311590Srgrimes } 17321590Srgrimes break; 17331590Srgrimes case '?': 17341590Srgrimes default: 17351590Srgrimes return(1); 17361590Srgrimes } 17371590Srgrimes } 17381590Srgrimes 17391590Srgrimes /* 17401590Srgrimes * default and sanity checks 17411590Srgrimes */ 17421590Srgrimes if (!clcnt) { 17431590Srgrimes if (merge) { 17441590Srgrimes if ((clcnt = argc - eoptind) <= 1) { 17451590Srgrimes clcnt = CLCNT; 17461590Srgrimes merge = 0; 17471590Srgrimes } 17481590Srgrimes } else 17491590Srgrimes clcnt = CLCNT; 17501590Srgrimes } 17511590Srgrimes if (across) { 17521590Srgrimes if (clcnt == 1) { 17531590Srgrimes (void)fputs("pr: -a flag requires multiple columns\n", 17541590Srgrimes err); 17551590Srgrimes return(1); 17561590Srgrimes } 17571590Srgrimes if (merge) { 17581590Srgrimes (void)fputs("pr: -m cannot be used with -a\n", err); 17591590Srgrimes return(1); 17601590Srgrimes } 17611590Srgrimes } 17621590Srgrimes if (!wflag) { 17631590Srgrimes if (sflag) 17641590Srgrimes pgwd = SPGWD; 17651590Srgrimes else 17661590Srgrimes pgwd = PGWD; 17671590Srgrimes } 17681590Srgrimes if (cflag || merge) { 17691590Srgrimes if (!eflag) { 17701590Srgrimes inchar = INCHAR; 17711590Srgrimes ingap = INGAP; 17721590Srgrimes } 17731590Srgrimes if (!iflag) { 17741590Srgrimes ochar = OCHAR; 17751590Srgrimes ogap = OGAP; 17761590Srgrimes } 17771590Srgrimes } 17781590Srgrimes if (cflag) { 17791590Srgrimes if (merge) { 17801590Srgrimes (void)fputs( 17811590Srgrimes "pr: -m cannot be used with multiple columns\n", err); 17821590Srgrimes return(1); 17831590Srgrimes } 17841590Srgrimes if (nmwd) { 17851590Srgrimes colwd = (pgwd + 1 - (clcnt * (nmwd + 2)))/clcnt; 17861590Srgrimes pgwd = ((colwd + nmwd + 2) * clcnt) - 1; 17871590Srgrimes } else { 17881590Srgrimes colwd = (pgwd + 1 - clcnt)/clcnt; 17891590Srgrimes pgwd = ((colwd + 1) * clcnt) - 1; 17901590Srgrimes } 17911590Srgrimes if (colwd < 1) { 17921590Srgrimes (void)fprintf(err, 17931590Srgrimes "pr: page width is too small for %d columns\n",clcnt); 17941590Srgrimes return(1); 17951590Srgrimes } 17961590Srgrimes } 17971590Srgrimes if (!lines) 17981590Srgrimes lines = LINES; 17991590Srgrimes 18001590Srgrimes /* 18011590Srgrimes * make sure long enough for headers. if not disable 18021590Srgrimes */ 18031590Srgrimes if (lines <= HEADLEN + TAILLEN) 18048874Srgrimes ++nohead; 18051590Srgrimes else if (!nohead) 18061590Srgrimes lines -= HEADLEN + TAILLEN; 18071590Srgrimes 18081590Srgrimes /* 18091590Srgrimes * adjust for double space on odd length pages 18101590Srgrimes */ 18111590Srgrimes if (dspace) { 18121590Srgrimes if (lines == 1) 18131590Srgrimes dspace = 0; 18141590Srgrimes else { 18151590Srgrimes if (lines & 1) 18161590Srgrimes ++addone; 18171590Srgrimes lines /= 2; 18181590Srgrimes } 18191590Srgrimes } 18201590Srgrimes 182111763Sache timefrmt = TIMEFMT; 182253955Sache (void) setlocale(LC_TIME, (Lflag != NULL) ? Lflag : ""); 182353948Sache 18241590Srgrimes return(0); 18251590Srgrimes} 1826