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