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