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