xref: /freebsd/usr.bin/pr/pr.c (revision 06b959916f75676938f488ad04b4c00d5fbafad3)
19b50d902SRodney W. Grimes /*-
29b50d902SRodney W. Grimes  * Copyright (c) 1991 Keith Muller.
39b50d902SRodney W. Grimes  * Copyright (c) 1993
49b50d902SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
59b50d902SRodney W. Grimes  *
69b50d902SRodney W. Grimes  * This code is derived from software contributed to Berkeley by
79b50d902SRodney W. Grimes  * Keith Muller of the University of California, San Diego.
89b50d902SRodney W. Grimes  *
99b50d902SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
109b50d902SRodney W. Grimes  * modification, are permitted provided that the following conditions
119b50d902SRodney W. Grimes  * are met:
129b50d902SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
139b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
149b50d902SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
159b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
169b50d902SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
179b50d902SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
189b50d902SRodney W. Grimes  *    must display the following acknowledgement:
199b50d902SRodney W. Grimes  *	This product includes software developed by the University of
209b50d902SRodney W. Grimes  *	California, Berkeley and its contributors.
219b50d902SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
229b50d902SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
239b50d902SRodney W. Grimes  *    without specific prior written permission.
249b50d902SRodney W. Grimes  *
259b50d902SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
269b50d902SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
279b50d902SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
289b50d902SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
299b50d902SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
309b50d902SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
319b50d902SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
329b50d902SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
339b50d902SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
349b50d902SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
359b50d902SRodney W. Grimes  * SUCH DAMAGE.
36b5076d91SAndrey A. Chernov  *
37b5076d91SAndrey A. Chernov  * $FreeBSD$
389b50d902SRodney W. Grimes  */
399b50d902SRodney W. Grimes 
409b50d902SRodney W. Grimes #ifndef lint
419b50d902SRodney W. Grimes static char copyright[] =
429b50d902SRodney W. Grimes "@(#) Copyright (c) 1993\n\
439b50d902SRodney W. Grimes 	The Regents of the University of California.  All rights reserved.\n";
449b50d902SRodney W. Grimes #endif /* not lint */
459b50d902SRodney W. Grimes 
469b50d902SRodney W. Grimes #ifndef lint
479b50d902SRodney W. Grimes static char sccsid[] = "@(#)pr.c	8.2 (Berkeley) 4/16/94";
489b50d902SRodney W. Grimes #endif /* not lint */
499b50d902SRodney W. Grimes 
509b50d902SRodney W. Grimes #include <sys/types.h>
519b50d902SRodney W. Grimes #include <sys/time.h>
529b50d902SRodney W. Grimes #include <sys/stat.h>
539b50d902SRodney W. Grimes 
549b50d902SRodney W. Grimes #include <ctype.h>
559b50d902SRodney W. Grimes #include <errno.h>
5677b898c4SAndrey A. Chernov #include <langinfo.h>
57b5076d91SAndrey A. Chernov #include <locale.h>
589b50d902SRodney W. Grimes #include <signal.h>
599b50d902SRodney W. Grimes #include <stdio.h>
609b50d902SRodney W. Grimes #include <stdlib.h>
619b50d902SRodney W. Grimes #include <string.h>
629b50d902SRodney W. Grimes #include <unistd.h>
639b50d902SRodney W. Grimes 
649b50d902SRodney W. Grimes #include "pr.h"
659b50d902SRodney W. Grimes #include "extern.h"
669b50d902SRodney W. Grimes 
679b50d902SRodney W. Grimes /*
689b50d902SRodney W. Grimes  * pr:	a printing and pagination filter. If multiple input files
699b50d902SRodney W. Grimes  *	are specified, each is read, formatted, and written to standard
701a6e52d0SJeroen Ruigrok van der Werven  *	output. By default, input is separated into 66-line pages, each
719b50d902SRodney W. Grimes  *	with a header that includes the page number, date, time and the
729b50d902SRodney W. Grimes  *	files pathname.
739b50d902SRodney W. Grimes  *
749b50d902SRodney W. Grimes  *	Complies with posix P1003.2/D11
759b50d902SRodney W. Grimes  */
769b50d902SRodney W. Grimes 
779b50d902SRodney W. Grimes /*
789b50d902SRodney W. Grimes  * parameter variables
799b50d902SRodney W. Grimes  */
809b50d902SRodney W. Grimes int	pgnm;			/* starting page number */
819b50d902SRodney W. Grimes int	clcnt;			/* number of columns */
829b50d902SRodney W. Grimes int	colwd;			/* column data width - multiple columns */
839b50d902SRodney W. Grimes int	across;			/* mult col flag; write across page */
849b50d902SRodney W. Grimes int	dspace;			/* double space flag */
859b50d902SRodney W. Grimes char	inchar;			/* expand input char */
869b50d902SRodney W. Grimes int	ingap;			/* expand input gap */
87032b32adSJuli Mallett int	pausefst;		/* Pause before first page */
88032b32adSJuli Mallett int	pauseall;		/* Pause before each page */
899b50d902SRodney W. Grimes int	formfeed;		/* use formfeed as trailer */
909b50d902SRodney W. Grimes char	*header;		/* header name instead of file name */
919b50d902SRodney W. Grimes char	ochar;			/* contract output char */
929b50d902SRodney W. Grimes int	ogap;			/* contract output gap */
939b50d902SRodney W. Grimes int	lines;			/* number of lines per page */
949b50d902SRodney W. Grimes int	merge;			/* merge multiple files in output */
959b50d902SRodney W. Grimes char	nmchar;			/* line numbering append char */
969b50d902SRodney W. Grimes int	nmwd;			/* width of line number field */
979b50d902SRodney W. Grimes int	offst;			/* number of page offset spaces */
989b50d902SRodney W. Grimes int	nodiag;			/* do not report file open errors */
999b50d902SRodney W. Grimes char	schar;			/* text column separation character */
1009b50d902SRodney W. Grimes int	sflag;			/* -s option for multiple columns */
1019b50d902SRodney W. Grimes int	nohead;			/* do not write head and trailer */
1029b50d902SRodney W. Grimes int	pgwd;			/* page width with multiple col output */
1039b50d902SRodney W. Grimes char	*timefrmt;		/* time conversion string */
1049b50d902SRodney W. Grimes 
1059b50d902SRodney W. Grimes /*
1069b50d902SRodney W. Grimes  * misc globals
1079b50d902SRodney W. Grimes  */
1089b50d902SRodney W. Grimes FILE	*err;			/* error message file pointer */
1099b50d902SRodney W. Grimes int	addone;			/* page length is odd with double space */
1109b50d902SRodney W. Grimes int	errcnt;			/* error count on file processing */
1119b50d902SRodney W. Grimes char	digs[] = "0123456789";	/* page number translation map */
1129b50d902SRodney W. Grimes 
1139b50d902SRodney W. Grimes int
1149b50d902SRodney W. Grimes main(argc, argv)
1159b50d902SRodney W. Grimes         int argc;
1169b50d902SRodney W. Grimes         char *argv[];
1179b50d902SRodney W. Grimes {
1189b50d902SRodney W. Grimes 	int ret_val;
1199b50d902SRodney W. Grimes 
1209b50d902SRodney W. Grimes 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1219b50d902SRodney W. Grimes 		(void)signal(SIGINT, terminate);
1229b50d902SRodney W. Grimes 	ret_val = setup(argc, argv);
1239b50d902SRodney W. Grimes 	if (!ret_val) {
1249b50d902SRodney W. Grimes 		/*
1259b50d902SRodney W. Grimes 		 * select the output format based on options
1269b50d902SRodney W. Grimes 		 */
1279b50d902SRodney W. Grimes 		if (merge)
1289b50d902SRodney W. Grimes 			ret_val = mulfile(argc, argv);
1299b50d902SRodney W. Grimes 		else if (clcnt == 1)
1309b50d902SRodney W. Grimes 			ret_val = onecol(argc, argv);
1319b50d902SRodney W. Grimes 		else if (across)
1329b50d902SRodney W. Grimes 			ret_val = horzcol(argc, argv);
1339b50d902SRodney W. Grimes 		else
1349b50d902SRodney W. Grimes 			ret_val = vertcol(argc, argv);
1359b50d902SRodney W. Grimes 	} else
1369b50d902SRodney W. Grimes 		usage();
1379b50d902SRodney W. Grimes 	flsh_errs();
1389b50d902SRodney W. Grimes 	if (errcnt || ret_val)
1399b50d902SRodney W. Grimes 		exit(1);
1409b50d902SRodney W. Grimes 	return(0);
1419b50d902SRodney W. Grimes }
1429b50d902SRodney W. Grimes 
1439b50d902SRodney W. Grimes /*
144032b32adSJuli Mallett  * Check if we should pause and write an alert character and wait for a
145032b32adSJuli Mallett  * carriage return on /dev/tty.
146032b32adSJuli Mallett  */
147032b32adSJuli Mallett void
148032b32adSJuli Mallett ttypause(pagecnt)
149032b32adSJuli Mallett 	int pagecnt;
150032b32adSJuli Mallett {
151032b32adSJuli Mallett 	int pch;
152032b32adSJuli Mallett 	FILE *ttyfp;
153032b32adSJuli Mallett 
154032b32adSJuli Mallett 	if ((pauseall || (pausefst && pagecnt == 1)) &&
155032b32adSJuli Mallett 	    isatty(STDOUT_FILENO)) {
156032b32adSJuli Mallett 		if ((ttyfp = fopen("/dev/tty", "r")) != NULL) {
157032b32adSJuli Mallett 			(void)putc('\a', stderr);
158032b32adSJuli Mallett 			while ((pch = getc(ttyfp)) != '\n' && pch != EOF)
159032b32adSJuli Mallett 				;
160032b32adSJuli Mallett 			(void)fclose(ttyfp);
161032b32adSJuli Mallett 		}
162032b32adSJuli Mallett 	}
163032b32adSJuli Mallett }
164032b32adSJuli Mallett 
165032b32adSJuli Mallett /*
1669b50d902SRodney W. Grimes  * onecol:	print files with only one column of output.
1679b50d902SRodney W. Grimes  *		Line length is unlimited.
1689b50d902SRodney W. Grimes  */
1699b50d902SRodney W. Grimes int
1709b50d902SRodney W. Grimes onecol(argc, argv)
1719b50d902SRodney W. Grimes         int argc;
1729b50d902SRodney W. Grimes         char *argv[];
1739b50d902SRodney W. Grimes {
1749b50d902SRodney W. Grimes 	register int cnt = -1;
1759b50d902SRodney W. Grimes 	register int off;
1769b50d902SRodney W. Grimes 	register int lrgln;
1779b50d902SRodney W. Grimes 	register int linecnt;
1789b50d902SRodney W. Grimes 	register int num;
1799b50d902SRodney W. Grimes 	int lncnt;
1809b50d902SRodney W. Grimes 	int pagecnt;
1819b50d902SRodney W. Grimes 	int ips;
1829b50d902SRodney W. Grimes 	int ops;
1839b50d902SRodney W. Grimes 	int cps;
1849b50d902SRodney W. Grimes 	char *obuf;
1859b50d902SRodney W. Grimes 	char *lbuf;
1869b50d902SRodney W. Grimes 	char *nbuf;
1879b50d902SRodney W. Grimes 	char *hbuf;
1889b50d902SRodney W. Grimes 	char *ohbuf;
1899b50d902SRodney W. Grimes 	FILE *inf;
1909b50d902SRodney W. Grimes 	char *fname;
1919b50d902SRodney W. Grimes 	int mor;
1929b50d902SRodney W. Grimes 
1939b50d902SRodney W. Grimes 	if (nmwd)
1949b50d902SRodney W. Grimes 		num = nmwd + 1;
1959b50d902SRodney W. Grimes 	else
1969b50d902SRodney W. Grimes 		num = 0;
1979b50d902SRodney W. Grimes 	off = num + offst;
1989b50d902SRodney W. Grimes 
1999b50d902SRodney W. Grimes 	/*
2009b50d902SRodney W. Grimes 	 * allocate line buffer
2019b50d902SRodney W. Grimes 	 */
2029b50d902SRodney W. Grimes 	if ((obuf = malloc((unsigned)(LBUF + off)*sizeof(char))) == NULL) {
2039b50d902SRodney W. Grimes 		mfail();
2049b50d902SRodney W. Grimes 		return(1);
2059b50d902SRodney W. Grimes 	}
2069b50d902SRodney W. Grimes 	/*
2079b50d902SRodney W. Grimes 	 * allocate header buffer
2089b50d902SRodney W. Grimes 	 */
2099b50d902SRodney W. Grimes 	if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
2109b50d902SRodney W. Grimes 		mfail();
2119b50d902SRodney W. Grimes 		return(1);
2129b50d902SRodney W. Grimes 	}
2139b50d902SRodney W. Grimes 
2149b50d902SRodney W. Grimes 	ohbuf = hbuf + offst;
2159b50d902SRodney W. Grimes 	nbuf = obuf + offst;
2169b50d902SRodney W. Grimes 	lbuf = nbuf + num;
2179b50d902SRodney W. Grimes 	if (num)
2189b50d902SRodney W. Grimes 		nbuf[--num] = nmchar;
2199b50d902SRodney W. Grimes 	if (offst) {
2209b50d902SRodney W. Grimes 		(void)memset(obuf, (int)' ', offst);
2219b50d902SRodney W. Grimes 		(void)memset(hbuf, (int)' ', offst);
2229b50d902SRodney W. Grimes 	}
2239b50d902SRodney W. Grimes 
2249b50d902SRodney W. Grimes 	/*
2259b50d902SRodney W. Grimes 	 * loop by file
2269b50d902SRodney W. Grimes 	 */
2279b50d902SRodney W. Grimes 	while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
2289b50d902SRodney W. Grimes 		if (pgnm) {
2299b50d902SRodney W. Grimes 			/*
2309b50d902SRodney W. Grimes 			 * skip to specified page
2319b50d902SRodney W. Grimes 			 */
2329b50d902SRodney W. Grimes 			if (inskip(inf, pgnm, lines))
2339b50d902SRodney W. Grimes 				continue;
2349b50d902SRodney W. Grimes 			pagecnt = pgnm;
2359b50d902SRodney W. Grimes 		} else
2369b50d902SRodney W. Grimes 			pagecnt = 1;
2379b50d902SRodney W. Grimes 		lncnt = 0;
2389b50d902SRodney W. Grimes 
2399b50d902SRodney W. Grimes 		/*
2409b50d902SRodney W. Grimes 		 * loop by page
2419b50d902SRodney W. Grimes 		 */
2429b50d902SRodney W. Grimes 		for(;;) {
2439b50d902SRodney W. Grimes 			linecnt = 0;
2449b50d902SRodney W. Grimes 			lrgln = 0;
2459b50d902SRodney W. Grimes 			ops = 0;
2469b50d902SRodney W. Grimes 			ips = 0;
2479b50d902SRodney W. Grimes 			cps = 0;
2489b50d902SRodney W. Grimes 
249032b32adSJuli Mallett 			ttypause(pagecnt);
250032b32adSJuli Mallett 
2519b50d902SRodney W. Grimes 			/*
2529b50d902SRodney W. Grimes 			 * loop by line
2539b50d902SRodney W. Grimes 			 */
2549b50d902SRodney W. Grimes 			while (linecnt < lines) {
2559b50d902SRodney W. Grimes 				/*
2569b50d902SRodney W. Grimes 				 * input next line
2579b50d902SRodney W. Grimes 				 */
2589b50d902SRodney W. Grimes 				if ((cnt = inln(inf,lbuf,LBUF,&cps,0,&mor)) < 0)
2599b50d902SRodney W. Grimes 					break;
2609b50d902SRodney W. Grimes 				if (!linecnt && !nohead &&
2619b50d902SRodney W. Grimes 					prhead(hbuf, fname, pagecnt))
2629b50d902SRodney W. Grimes 					return(1);
2639b50d902SRodney W. Grimes 
2649b50d902SRodney W. Grimes 				/*
2659b50d902SRodney W. Grimes 				 * start of new line.
2669b50d902SRodney W. Grimes 				 */
2679b50d902SRodney W. Grimes 				if (!lrgln) {
2689b50d902SRodney W. Grimes 					if (num)
2699b50d902SRodney W. Grimes 						addnum(nbuf, num, ++lncnt);
2709b50d902SRodney W. Grimes 					if (otln(obuf,cnt+off, &ips, &ops, mor))
2719b50d902SRodney W. Grimes 						return(1);
2729b50d902SRodney W. Grimes 				} else if (otln(lbuf, cnt, &ips, &ops, mor))
2739b50d902SRodney W. Grimes 					return(1);
2749b50d902SRodney W. Grimes 
2759b50d902SRodney W. Grimes 				/*
2769b50d902SRodney W. Grimes 				 * if line bigger than buffer, get more
2779b50d902SRodney W. Grimes 				 */
2789b50d902SRodney W. Grimes 				if (mor) {
2799b50d902SRodney W. Grimes 					lrgln = 1;
2809b50d902SRodney W. Grimes 					continue;
2819b50d902SRodney W. Grimes 				}
2829b50d902SRodney W. Grimes 
2839b50d902SRodney W. Grimes 				/*
2849b50d902SRodney W. Grimes 				 * whole line rcvd. reset tab proc. state
2859b50d902SRodney W. Grimes 				 */
2869b50d902SRodney W. Grimes 				++linecnt;
2879b50d902SRodney W. Grimes 				lrgln = 0;
2889b50d902SRodney W. Grimes 				ops = 0;
2899b50d902SRodney W. Grimes 				ips = 0;
2909b50d902SRodney W. Grimes 			}
2919b50d902SRodney W. Grimes 
2929b50d902SRodney W. Grimes 			/*
2939b50d902SRodney W. Grimes 			 * fill to end of page
2949b50d902SRodney W. Grimes 			 */
2959b50d902SRodney W. Grimes 			if (linecnt && prtail(lines-linecnt-lrgln, lrgln))
2969b50d902SRodney W. Grimes 				return(1);
2979b50d902SRodney W. Grimes 
2989b50d902SRodney W. Grimes 			/*
2999b50d902SRodney W. Grimes 			 * On EOF go to next file
3009b50d902SRodney W. Grimes 			 */
3019b50d902SRodney W. Grimes 			if (cnt < 0)
3029b50d902SRodney W. Grimes 				break;
3039b50d902SRodney W. Grimes 			++pagecnt;
3049b50d902SRodney W. Grimes 		}
3059b50d902SRodney W. Grimes 		if (inf != stdin)
3069b50d902SRodney W. Grimes 			(void)fclose(inf);
3079b50d902SRodney W. Grimes 	}
3089b50d902SRodney W. Grimes 	if (eoptind < argc)
3099b50d902SRodney W. Grimes 		return(1);
3109b50d902SRodney W. Grimes 	return(0);
3119b50d902SRodney W. Grimes }
3129b50d902SRodney W. Grimes 
3139b50d902SRodney W. Grimes /*
3149b50d902SRodney W. Grimes  * vertcol:	print files with more than one column of output down a page
3159b50d902SRodney W. Grimes  */
3169b50d902SRodney W. Grimes int
3179b50d902SRodney W. Grimes vertcol(argc, argv)
3189b50d902SRodney W. Grimes         int argc;
3199b50d902SRodney W. Grimes         char *argv[];
3209b50d902SRodney W. Grimes {
3219b50d902SRodney W. Grimes 	register char *ptbf;
3229b50d902SRodney W. Grimes 	register char **lstdat;
3239b50d902SRodney W. Grimes 	register int i;
3249b50d902SRodney W. Grimes 	register int j;
3259b50d902SRodney W. Grimes 	register int cnt = -1;
3269b50d902SRodney W. Grimes 	register int pln;
3279b50d902SRodney W. Grimes 	register int *indy;
3289b50d902SRodney W. Grimes 	int cvc;
3299b50d902SRodney W. Grimes 	int *lindy;
3309b50d902SRodney W. Grimes 	int lncnt;
3319b50d902SRodney W. Grimes 	int stp;
3329b50d902SRodney W. Grimes 	int pagecnt;
3339b50d902SRodney W. Grimes 	int col = colwd + 1;
3349b50d902SRodney W. Grimes 	int mxlen = pgwd + offst + 1;
3359b50d902SRodney W. Grimes 	int mclcnt = clcnt - 1;
3369b50d902SRodney W. Grimes 	struct vcol *vc;
3379b50d902SRodney W. Grimes 	int mvc;
3389b50d902SRodney W. Grimes 	int tvc;
3399b50d902SRodney W. Grimes 	int cw = nmwd + 1;
3409b50d902SRodney W. Grimes 	int fullcol;
3419b50d902SRodney W. Grimes 	char *buf;
3429b50d902SRodney W. Grimes 	char *hbuf;
3439b50d902SRodney W. Grimes 	char *ohbuf;
3449b50d902SRodney W. Grimes 	char *fname;
3459b50d902SRodney W. Grimes 	FILE *inf;
3469b50d902SRodney W. Grimes 	int ips = 0;
3479b50d902SRodney W. Grimes 	int cps = 0;
3489b50d902SRodney W. Grimes 	int ops = 0;
3499b50d902SRodney W. Grimes 	int mor = 0;
3509b50d902SRodney W. Grimes 
3519b50d902SRodney W. Grimes 	/*
3529b50d902SRodney W. Grimes 	 * allocate page buffer
3539b50d902SRodney W. Grimes 	 */
3549b50d902SRodney W. Grimes 	if ((buf = malloc((unsigned)lines*mxlen*sizeof(char))) == NULL) {
3559b50d902SRodney W. Grimes 		mfail();
3569b50d902SRodney W. Grimes 		return(1);
3579b50d902SRodney W. Grimes 	}
3589b50d902SRodney W. Grimes 
3599b50d902SRodney W. Grimes 	/*
3609b50d902SRodney W. Grimes 	 * allocate page header
3619b50d902SRodney W. Grimes 	 */
3629b50d902SRodney W. Grimes 	if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
3639b50d902SRodney W. Grimes 		mfail();
3649b50d902SRodney W. Grimes 		return(1);
3659b50d902SRodney W. Grimes 	}
3669b50d902SRodney W. Grimes 	ohbuf = hbuf + offst;
3679b50d902SRodney W. Grimes 	if (offst)
3689b50d902SRodney W. Grimes 		(void)memset(hbuf, (int)' ', offst);
3699b50d902SRodney W. Grimes 
3709b50d902SRodney W. Grimes 	/*
3719b50d902SRodney W. Grimes 	 * col pointers when no headers
3729b50d902SRodney W. Grimes 	 */
3739b50d902SRodney W. Grimes 	mvc = lines * clcnt;
3749b50d902SRodney W. Grimes 	if ((vc =
3759b50d902SRodney W. Grimes 	    (struct vcol *)malloc((unsigned)mvc*sizeof(struct vcol))) == NULL) {
3769b50d902SRodney W. Grimes 		mfail();
3779b50d902SRodney W. Grimes 		return(1);
3789b50d902SRodney W. Grimes 	}
3799b50d902SRodney W. Grimes 
3809b50d902SRodney W. Grimes 	/*
3819b50d902SRodney W. Grimes 	 * pointer into page where last data per line is located
3829b50d902SRodney W. Grimes 	 */
3839b50d902SRodney W. Grimes 	if ((lstdat = (char **)malloc((unsigned)lines*sizeof(char *))) == NULL){
3849b50d902SRodney W. Grimes 		mfail();
3859b50d902SRodney W. Grimes 		return(1);
3869b50d902SRodney W. Grimes 	}
3879b50d902SRodney W. Grimes 
3889b50d902SRodney W. Grimes 	/*
3899b50d902SRodney W. Grimes 	 * fast index lookups to locate start of lines
3909b50d902SRodney W. Grimes 	 */
3919b50d902SRodney W. Grimes 	if ((indy = (int *)malloc((unsigned)lines*sizeof(int))) == NULL) {
3929b50d902SRodney W. Grimes 		mfail();
3939b50d902SRodney W. Grimes 		return(1);
3949b50d902SRodney W. Grimes 	}
3959b50d902SRodney W. Grimes 	if ((lindy = (int *)malloc((unsigned)lines*sizeof(int))) == NULL) {
3969b50d902SRodney W. Grimes 		mfail();
3979b50d902SRodney W. Grimes 		return(1);
3989b50d902SRodney W. Grimes 	}
3999b50d902SRodney W. Grimes 
4009b50d902SRodney W. Grimes 	if (nmwd)
4019b50d902SRodney W. Grimes 		fullcol = col + cw;
4029b50d902SRodney W. Grimes 	else
4039b50d902SRodney W. Grimes 		fullcol = col;
4049b50d902SRodney W. Grimes 
4059b50d902SRodney W. Grimes 	/*
4069b50d902SRodney W. Grimes 	 * initialize buffer lookup indexes and offset area
4079b50d902SRodney W. Grimes 	 */
4089b50d902SRodney W. Grimes 	for (j = 0; j < lines; ++j) {
4099b50d902SRodney W. Grimes 		lindy[j] = j * mxlen;
4109b50d902SRodney W. Grimes 		indy[j] = lindy[j] + offst;
4119b50d902SRodney W. Grimes 		if (offst) {
4129b50d902SRodney W. Grimes 			ptbf = buf + lindy[j];
4139b50d902SRodney W. Grimes 			(void)memset(ptbf, (int)' ', offst);
4149b50d902SRodney W. Grimes 			ptbf += offst;
4159b50d902SRodney W. Grimes 		} else
4169b50d902SRodney W. Grimes 			ptbf = buf + indy[j];
4179b50d902SRodney W. Grimes 		lstdat[j] = ptbf;
4189b50d902SRodney W. Grimes 	}
4199b50d902SRodney W. Grimes 
4209b50d902SRodney W. Grimes 	/*
4219b50d902SRodney W. Grimes 	 * loop by file
4229b50d902SRodney W. Grimes 	 */
4239b50d902SRodney W. Grimes 	while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
4249b50d902SRodney W. Grimes 		if (pgnm) {
4259b50d902SRodney W. Grimes 			/*
4269b50d902SRodney W. Grimes 			 * skip to requested page
4279b50d902SRodney W. Grimes 			 */
4289b50d902SRodney W. Grimes 			if (inskip(inf, pgnm, lines))
4299b50d902SRodney W. Grimes 				continue;
4309b50d902SRodney W. Grimes 			pagecnt = pgnm;
4319b50d902SRodney W. Grimes 		} else
4329b50d902SRodney W. Grimes 			pagecnt = 1;
4339b50d902SRodney W. Grimes 		lncnt = 0;
4349b50d902SRodney W. Grimes 
4359b50d902SRodney W. Grimes 		/*
4369b50d902SRodney W. Grimes 		 * loop by page
4379b50d902SRodney W. Grimes 		 */
4389b50d902SRodney W. Grimes 		for(;;) {
439032b32adSJuli Mallett 			ttypause(pagecnt);
440032b32adSJuli Mallett 
4419b50d902SRodney W. Grimes 			/*
4429b50d902SRodney W. Grimes 			 * loop by column
4439b50d902SRodney W. Grimes 			 */
4449b50d902SRodney W. Grimes 			cvc = 0;
4459b50d902SRodney W. Grimes 			for (i = 0; i < clcnt; ++i) {
4469b50d902SRodney W. Grimes 				j = 0;
4479b50d902SRodney W. Grimes 				/*
4489b50d902SRodney W. Grimes 				 * if last column, do not pad
4499b50d902SRodney W. Grimes 				 */
4509b50d902SRodney W. Grimes 				if (i == mclcnt)
4519b50d902SRodney W. Grimes 					stp = 1;
4529b50d902SRodney W. Grimes 				else
4539b50d902SRodney W. Grimes 					stp = 0;
4549b50d902SRodney W. Grimes 				/*
4559b50d902SRodney W. Grimes 				 * loop by line
4569b50d902SRodney W. Grimes 				 */
4579b50d902SRodney W. Grimes 				for(;;) {
4589b50d902SRodney W. Grimes 					/*
4599b50d902SRodney W. Grimes 					 * is this first column
4609b50d902SRodney W. Grimes 					 */
4619b50d902SRodney W. Grimes 					if (!i) {
4629b50d902SRodney W. Grimes 						ptbf = buf + indy[j];
4639b50d902SRodney W. Grimes 						lstdat[j] = ptbf;
4649b50d902SRodney W. Grimes 					} else
4659b50d902SRodney W. Grimes 						ptbf = lstdat[j];
4669b50d902SRodney W. Grimes 					vc[cvc].pt = ptbf;
4679b50d902SRodney W. Grimes 
4689b50d902SRodney W. Grimes 					/*
4699b50d902SRodney W. Grimes 					 * add number
4709b50d902SRodney W. Grimes 					 */
4719b50d902SRodney W. Grimes 					if (nmwd) {
4729b50d902SRodney W. Grimes 						addnum(ptbf, nmwd, ++lncnt);
4739b50d902SRodney W. Grimes 						ptbf += nmwd;
4749b50d902SRodney W. Grimes 						*ptbf++ = nmchar;
4759b50d902SRodney W. Grimes 					}
4769b50d902SRodney W. Grimes 
4779b50d902SRodney W. Grimes 					/*
4789b50d902SRodney W. Grimes 					 * input next line
4799b50d902SRodney W. Grimes 					 */
4809b50d902SRodney W. Grimes 					cnt = inln(inf,ptbf,colwd,&cps,1,&mor);
4819b50d902SRodney W. Grimes 					vc[cvc++].cnt = cnt;
4829b50d902SRodney W. Grimes 					if (cnt < 0)
4839b50d902SRodney W. Grimes 						break;
4849b50d902SRodney W. Grimes 					ptbf += cnt;
4859b50d902SRodney W. Grimes 
4869b50d902SRodney W. Grimes 					/*
4879b50d902SRodney W. Grimes 					 * pad all but last column on page
4889b50d902SRodney W. Grimes 					 */
4899b50d902SRodney W. Grimes 					if (!stp) {
4909b50d902SRodney W. Grimes 						/*
4919b50d902SRodney W. Grimes 						 * pad to end of column
4929b50d902SRodney W. Grimes 						 */
4939b50d902SRodney W. Grimes 						if (sflag)
4949b50d902SRodney W. Grimes 							*ptbf++ = schar;
4959b50d902SRodney W. Grimes 						else if ((pln = col-cnt) > 0) {
4969b50d902SRodney W. Grimes 							(void)memset(ptbf,
4979b50d902SRodney W. Grimes 								(int)' ',pln);
4989b50d902SRodney W. Grimes 							ptbf += pln;
4999b50d902SRodney W. Grimes 						}
5009b50d902SRodney W. Grimes 					}
5019b50d902SRodney W. Grimes 					/*
5029b50d902SRodney W. Grimes 					 * remember last char in line
5039b50d902SRodney W. Grimes 					 */
5049b50d902SRodney W. Grimes 					lstdat[j] = ptbf;
5059b50d902SRodney W. Grimes 					if (++j >= lines)
5069b50d902SRodney W. Grimes 						break;
5079b50d902SRodney W. Grimes 				}
5089b50d902SRodney W. Grimes 				if (cnt < 0)
5099b50d902SRodney W. Grimes 					break;
5109b50d902SRodney W. Grimes 			}
5119b50d902SRodney W. Grimes 
5129b50d902SRodney W. Grimes 			/*
5139b50d902SRodney W. Grimes 			 * when -t (no header) is specified the spec requires
5149b50d902SRodney W. Grimes 			 * the min number of lines. The last page may not have
5159b50d902SRodney W. Grimes 			 * balanced length columns. To fix this we must reorder
5169b50d902SRodney W. Grimes 			 * the columns. This is a very slow technique so it is
5179b50d902SRodney W. Grimes 			 * only used under limited conditions. Without -t, the
5189b50d902SRodney W. Grimes 			 * balancing of text columns is unspecified. To NOT
5199b50d902SRodney W. Grimes 			 * balance the last page, add the global variable
5209b50d902SRodney W. Grimes 			 * nohead to the if statement below e.g.
5219b50d902SRodney W. Grimes 			 *
5229b50d902SRodney W. Grimes 			 * if ((cnt < 0) && nohead && cvc ......
5239b50d902SRodney W. Grimes 			 */
5249b50d902SRodney W. Grimes 			--cvc;
5259b50d902SRodney W. Grimes 
5269b50d902SRodney W. Grimes 			/*
5279b50d902SRodney W. Grimes 			 * check to see if last page needs to be reordered
5289b50d902SRodney W. Grimes 			 */
5299b50d902SRodney W. Grimes 			if ((cnt < 0) && cvc && ((mvc-cvc) >= clcnt)){
5309b50d902SRodney W. Grimes 				pln = cvc/clcnt;
5319b50d902SRodney W. Grimes 				if (cvc % clcnt)
5329b50d902SRodney W. Grimes 					++pln;
5339b50d902SRodney W. Grimes 
5349b50d902SRodney W. Grimes 				/*
5359b50d902SRodney W. Grimes 				 * print header
5369b50d902SRodney W. Grimes 				 */
5379b50d902SRodney W. Grimes 				if (!nohead && prhead(hbuf, fname, pagecnt))
5389b50d902SRodney W. Grimes 					return(1);
5399b50d902SRodney W. Grimes 				for (i = 0; i < pln; ++i) {
5409b50d902SRodney W. Grimes 					ips = 0;
5419b50d902SRodney W. Grimes 					ops = 0;
5429b50d902SRodney W. Grimes 					if (offst&& otln(buf,offst,&ips,&ops,1))
5439b50d902SRodney W. Grimes 						return(1);
5449b50d902SRodney W. Grimes 					tvc = i;
5459b50d902SRodney W. Grimes 
5469b50d902SRodney W. Grimes 					for (j = 0; j < clcnt; ++j) {
5479b50d902SRodney W. Grimes 						/*
5489b50d902SRodney W. Grimes 						 * determine column length
5499b50d902SRodney W. Grimes 						 */
5509b50d902SRodney W. Grimes 						if (j == mclcnt) {
5519b50d902SRodney W. Grimes 							/*
5529b50d902SRodney W. Grimes 							 * last column
5539b50d902SRodney W. Grimes 							 */
5549b50d902SRodney W. Grimes 							cnt = vc[tvc].cnt;
5559b50d902SRodney W. Grimes 							if (nmwd)
5569b50d902SRodney W. Grimes 								cnt += cw;
5579b50d902SRodney W. Grimes 						} else if (sflag) {
5589b50d902SRodney W. Grimes 							/*
5599b50d902SRodney W. Grimes 							 * single ch between
5609b50d902SRodney W. Grimes 							 */
5619b50d902SRodney W. Grimes 							cnt = vc[tvc].cnt + 1;
5629b50d902SRodney W. Grimes 							if (nmwd)
5639b50d902SRodney W. Grimes 								cnt += cw;
5649b50d902SRodney W. Grimes 						} else
5659b50d902SRodney W. Grimes 							cnt = fullcol;
5669b50d902SRodney W. Grimes 						if (otln(vc[tvc].pt, cnt, &ips,
5679b50d902SRodney W. Grimes 								&ops, 1))
5689b50d902SRodney W. Grimes 							return(1);
5699b50d902SRodney W. Grimes 						tvc += pln;
5709b50d902SRodney W. Grimes 						if (tvc >= cvc)
5719b50d902SRodney W. Grimes 							break;
5729b50d902SRodney W. Grimes 					}
5739b50d902SRodney W. Grimes 					/*
5749b50d902SRodney W. Grimes 					 * terminate line
5759b50d902SRodney W. Grimes 					 */
5769b50d902SRodney W. Grimes 					if (otln(buf, 0, &ips, &ops, 0))
5779b50d902SRodney W. Grimes 						return(1);
5789b50d902SRodney W. Grimes 				}
5799b50d902SRodney W. Grimes 				/*
5809b50d902SRodney W. Grimes 				 * pad to end of page
5819b50d902SRodney W. Grimes 				 */
5829b50d902SRodney W. Grimes 				if (prtail((lines - pln), 0))
5839b50d902SRodney W. Grimes 					return(1);
5849b50d902SRodney W. Grimes 				/*
5859b50d902SRodney W. Grimes 				 * done with output, go to next file
5869b50d902SRodney W. Grimes 				 */
5879b50d902SRodney W. Grimes 				break;
5889b50d902SRodney W. Grimes 			}
5899b50d902SRodney W. Grimes 
5909b50d902SRodney W. Grimes 			/*
5919b50d902SRodney W. Grimes 			 * determine how many lines to output
5929b50d902SRodney W. Grimes 			 */
5939b50d902SRodney W. Grimes 			if (i > 0)
5949b50d902SRodney W. Grimes 				pln = lines;
5959b50d902SRodney W. Grimes 			else
5969b50d902SRodney W. Grimes 				pln = j;
5979b50d902SRodney W. Grimes 
5989b50d902SRodney W. Grimes 			/*
5999b50d902SRodney W. Grimes 			 * print header
6009b50d902SRodney W. Grimes 			 */
6019b50d902SRodney W. Grimes 			if (pln && !nohead && prhead(hbuf, fname, pagecnt))
6029b50d902SRodney W. Grimes 				return(1);
6039b50d902SRodney W. Grimes 
6049b50d902SRodney W. Grimes 			/*
6059b50d902SRodney W. Grimes 			 * output each line
6069b50d902SRodney W. Grimes 			 */
6079b50d902SRodney W. Grimes 			for (i = 0; i < pln; ++i) {
6089b50d902SRodney W. Grimes 				ptbf = buf + lindy[i];
6099b50d902SRodney W. Grimes 				if ((j = lstdat[i] - ptbf) <= offst)
6109b50d902SRodney W. Grimes 					break;
6119b50d902SRodney W. Grimes 				if (otln(ptbf, j, &ips, &ops, 0))
6129b50d902SRodney W. Grimes 					return(1);
6139b50d902SRodney W. Grimes 			}
6149b50d902SRodney W. Grimes 
6159b50d902SRodney W. Grimes 			/*
6169b50d902SRodney W. Grimes 			 * pad to end of page
6179b50d902SRodney W. Grimes 			 */
6189b50d902SRodney W. Grimes 			if (pln && prtail((lines - pln), 0))
6199b50d902SRodney W. Grimes 				return(1);
6209b50d902SRodney W. Grimes 
6219b50d902SRodney W. Grimes 			/*
6229b50d902SRodney W. Grimes 			 * if EOF go to next file
6239b50d902SRodney W. Grimes 			 */
6249b50d902SRodney W. Grimes 			if (cnt < 0)
6259b50d902SRodney W. Grimes 				break;
6269b50d902SRodney W. Grimes 			++pagecnt;
6279b50d902SRodney W. Grimes 		}
6289b50d902SRodney W. Grimes 		if (inf != stdin)
6299b50d902SRodney W. Grimes 			(void)fclose(inf);
6309b50d902SRodney W. Grimes 	}
6319b50d902SRodney W. Grimes 	if (eoptind < argc)
6329b50d902SRodney W. Grimes 		return(1);
6339b50d902SRodney W. Grimes 	return(0);
6349b50d902SRodney W. Grimes }
6359b50d902SRodney W. Grimes 
6369b50d902SRodney W. Grimes /*
6379b50d902SRodney W. Grimes  * horzcol:	print files with more than one column of output across a page
6389b50d902SRodney W. Grimes  */
6399b50d902SRodney W. Grimes int
6409b50d902SRodney W. Grimes horzcol(argc, argv)
6419b50d902SRodney W. Grimes         int argc;
6429b50d902SRodney W. Grimes         char *argv[];
6439b50d902SRodney W. Grimes {
6449b50d902SRodney W. Grimes 	register char *ptbf;
6459b50d902SRodney W. Grimes 	register int pln;
6469b50d902SRodney W. Grimes 	register int cnt = -1;
6479b50d902SRodney W. Grimes 	register char *lstdat;
6489b50d902SRodney W. Grimes 	register int col = colwd + 1;
6499b50d902SRodney W. Grimes 	register int j;
6509b50d902SRodney W. Grimes 	register int i;
6519b50d902SRodney W. Grimes 	int lncnt;
6529b50d902SRodney W. Grimes 	int pagecnt;
6539b50d902SRodney W. Grimes 	char *buf;
6549b50d902SRodney W. Grimes 	char *hbuf;
6559b50d902SRodney W. Grimes 	char *ohbuf;
6569b50d902SRodney W. Grimes 	char *fname;
6579b50d902SRodney W. Grimes 	FILE *inf;
6589b50d902SRodney W. Grimes 	int ips = 0;
6599b50d902SRodney W. Grimes 	int cps = 0;
6609b50d902SRodney W. Grimes 	int ops = 0;
6619b50d902SRodney W. Grimes 	int mor = 0;
6629b50d902SRodney W. Grimes 
6639b50d902SRodney W. Grimes 	if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL) {
6649b50d902SRodney W. Grimes 		mfail();
6659b50d902SRodney W. Grimes 		return(1);
6669b50d902SRodney W. Grimes 	}
6679b50d902SRodney W. Grimes 
6689b50d902SRodney W. Grimes 	/*
6699b50d902SRodney W. Grimes 	 * page header
6709b50d902SRodney W. Grimes 	 */
6719b50d902SRodney W. Grimes 	if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
6729b50d902SRodney W. Grimes 		mfail();
6739b50d902SRodney W. Grimes 		return(1);
6749b50d902SRodney W. Grimes 	}
6759b50d902SRodney W. Grimes 	ohbuf = hbuf + offst;
6769b50d902SRodney W. Grimes 	if (offst) {
6779b50d902SRodney W. Grimes 		(void)memset(buf, (int)' ', offst);
6789b50d902SRodney W. Grimes 		(void)memset(hbuf, (int)' ', offst);
6799b50d902SRodney W. Grimes 	}
6809b50d902SRodney W. Grimes 
6819b50d902SRodney W. Grimes 	/*
6829b50d902SRodney W. Grimes 	 * loop by file
6839b50d902SRodney W. Grimes 	 */
6849b50d902SRodney W. Grimes 	while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
6859b50d902SRodney W. Grimes 		if (pgnm) {
6869b50d902SRodney W. Grimes 			if (inskip(inf, pgnm, lines))
6879b50d902SRodney W. Grimes 				continue;
6889b50d902SRodney W. Grimes 			pagecnt = pgnm;
6899b50d902SRodney W. Grimes 		} else
6909b50d902SRodney W. Grimes 			pagecnt = 1;
6919b50d902SRodney W. Grimes 		lncnt = 0;
6929b50d902SRodney W. Grimes 
6939b50d902SRodney W. Grimes 		/*
6949b50d902SRodney W. Grimes 		 * loop by page
6959b50d902SRodney W. Grimes 		 */
6969b50d902SRodney W. Grimes 		for(;;) {
697032b32adSJuli Mallett 			ttypause(pagecnt);
698032b32adSJuli Mallett 
6999b50d902SRodney W. Grimes 			/*
7009b50d902SRodney W. Grimes 			 * loop by line
7019b50d902SRodney W. Grimes 			 */
7029b50d902SRodney W. Grimes 			for (i = 0; i < lines; ++i) {
7039b50d902SRodney W. Grimes 				ptbf = buf + offst;
7049b50d902SRodney W. Grimes 				lstdat = ptbf;
7059b50d902SRodney W. Grimes 				j = 0;
7069b50d902SRodney W. Grimes 				/*
7079b50d902SRodney W. Grimes 				 * loop by col
7089b50d902SRodney W. Grimes 				 */
7099b50d902SRodney W. Grimes 				for(;;) {
7109b50d902SRodney W. Grimes 					if (nmwd) {
7119b50d902SRodney W. Grimes 						/*
7129b50d902SRodney W. Grimes 						 * add number to column
7139b50d902SRodney W. Grimes 						 */
7149b50d902SRodney W. Grimes 						addnum(ptbf, nmwd, ++lncnt);
7159b50d902SRodney W. Grimes 						ptbf += nmwd;
7169b50d902SRodney W. Grimes 						*ptbf++ = nmchar;
7179b50d902SRodney W. Grimes 					}
7189b50d902SRodney W. Grimes 					/*
7199b50d902SRodney W. Grimes 					 * input line
7209b50d902SRodney W. Grimes 					 */
7219b50d902SRodney W. Grimes 					if ((cnt = inln(inf,ptbf,colwd,&cps,1,
7229b50d902SRodney W. Grimes 							&mor)) < 0)
7239b50d902SRodney W. Grimes 						break;
7249b50d902SRodney W. Grimes 					ptbf += cnt;
7259b50d902SRodney W. Grimes 					lstdat = ptbf;
7269b50d902SRodney W. Grimes 
7279b50d902SRodney W. Grimes 					/*
7289b50d902SRodney W. Grimes 					 * if last line skip padding
7299b50d902SRodney W. Grimes 					 */
7309b50d902SRodney W. Grimes 					if (++j >= clcnt)
7319b50d902SRodney W. Grimes 						break;
7329b50d902SRodney W. Grimes 
7339b50d902SRodney W. Grimes 					/*
7349b50d902SRodney W. Grimes 					 * pad to end of column
7359b50d902SRodney W. Grimes 					 */
7369b50d902SRodney W. Grimes 					if (sflag)
7379b50d902SRodney W. Grimes 						*ptbf++ = schar;
7389b50d902SRodney W. Grimes 					else if ((pln = col - cnt) > 0) {
7399b50d902SRodney W. Grimes 						(void)memset(ptbf,(int)' ',pln);
7409b50d902SRodney W. Grimes 						ptbf += pln;
7419b50d902SRodney W. Grimes 					}
7429b50d902SRodney W. Grimes 				}
7439b50d902SRodney W. Grimes 
7449b50d902SRodney W. Grimes 				/*
7459b50d902SRodney W. Grimes 				 * determine line length
7469b50d902SRodney W. Grimes 				 */
7479b50d902SRodney W. Grimes 				if ((j = lstdat - buf) <= offst)
7489b50d902SRodney W. Grimes 					break;
7499b50d902SRodney W. Grimes 				if (!i && !nohead &&
7509b50d902SRodney W. Grimes 					prhead(hbuf, fname, pagecnt))
7519b50d902SRodney W. Grimes 					return(1);
7529b50d902SRodney W. Grimes 				/*
7539b50d902SRodney W. Grimes 				 * output line
7549b50d902SRodney W. Grimes 				 */
7559b50d902SRodney W. Grimes 				if (otln(buf, j, &ips, &ops, 0))
7569b50d902SRodney W. Grimes 					return(1);
7579b50d902SRodney W. Grimes 			}
7589b50d902SRodney W. Grimes 
7599b50d902SRodney W. Grimes 			/*
7609b50d902SRodney W. Grimes 			 * pad to end of page
7619b50d902SRodney W. Grimes 			 */
7629b50d902SRodney W. Grimes 			if (i && prtail(lines-i, 0))
7639b50d902SRodney W. Grimes 				return(1);
7649b50d902SRodney W. Grimes 
7659b50d902SRodney W. Grimes 			/*
7669b50d902SRodney W. Grimes 			 * if EOF go to next file
7679b50d902SRodney W. Grimes 			 */
7689b50d902SRodney W. Grimes 			if (cnt < 0)
7699b50d902SRodney W. Grimes 				break;
7709b50d902SRodney W. Grimes 			++pagecnt;
7719b50d902SRodney W. Grimes 		}
7729b50d902SRodney W. Grimes 		if (inf != stdin)
7739b50d902SRodney W. Grimes 			(void)fclose(inf);
7749b50d902SRodney W. Grimes 	}
7759b50d902SRodney W. Grimes 	if (eoptind < argc)
7769b50d902SRodney W. Grimes 		return(1);
7779b50d902SRodney W. Grimes 	return(0);
7789b50d902SRodney W. Grimes }
7799b50d902SRodney W. Grimes 
7809b50d902SRodney W. Grimes /*
7819b50d902SRodney W. Grimes  * mulfile:	print files with more than one column of output and
7829b50d902SRodney W. Grimes  *		more than one file concurrently
7839b50d902SRodney W. Grimes  */
7849b50d902SRodney W. Grimes int
7859b50d902SRodney W. Grimes mulfile(argc, argv)
7869b50d902SRodney W. Grimes         int argc;
7879b50d902SRodney W. Grimes         char *argv[];
7889b50d902SRodney W. Grimes {
7899b50d902SRodney W. Grimes 	register char *ptbf;
7909b50d902SRodney W. Grimes 	register int j;
7919b50d902SRodney W. Grimes 	register int pln;
7929b50d902SRodney W. Grimes 	register int cnt;
7939b50d902SRodney W. Grimes 	register char *lstdat;
7949b50d902SRodney W. Grimes 	register int i;
7959b50d902SRodney W. Grimes 	FILE **fbuf;
7969b50d902SRodney W. Grimes 	int actf;
7979b50d902SRodney W. Grimes 	int lncnt;
7989b50d902SRodney W. Grimes 	int col;
7999b50d902SRodney W. Grimes 	int pagecnt;
8009b50d902SRodney W. Grimes 	int fproc;
8019b50d902SRodney W. Grimes 	char *buf;
8029b50d902SRodney W. Grimes 	char *hbuf;
8039b50d902SRodney W. Grimes 	char *ohbuf;
8049b50d902SRodney W. Grimes 	char *fname;
8059b50d902SRodney W. Grimes 	int ips = 0;
8069b50d902SRodney W. Grimes 	int cps = 0;
8079b50d902SRodney W. Grimes 	int ops = 0;
8089b50d902SRodney W. Grimes 	int mor = 0;
8099b50d902SRodney W. Grimes 
8109b50d902SRodney W. Grimes 	/*
8119b50d902SRodney W. Grimes 	 * array of FILE *, one for each operand
8129b50d902SRodney W. Grimes 	 */
8139b50d902SRodney W. Grimes 	if ((fbuf = (FILE **)malloc((unsigned)clcnt*sizeof(FILE *))) == NULL) {
8149b50d902SRodney W. Grimes 		mfail();
8159b50d902SRodney W. Grimes 		return(1);
8169b50d902SRodney W. Grimes 	}
8179b50d902SRodney W. Grimes 
8189b50d902SRodney W. Grimes 	/*
8199b50d902SRodney W. Grimes 	 * page header
8209b50d902SRodney W. Grimes 	 */
8219b50d902SRodney W. Grimes 	if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
8229b50d902SRodney W. Grimes 		mfail();
8239b50d902SRodney W. Grimes 		return(1);
8249b50d902SRodney W. Grimes 	}
8259b50d902SRodney W. Grimes 	ohbuf = hbuf + offst;
8269b50d902SRodney W. Grimes 
8279b50d902SRodney W. Grimes 	/*
8289b50d902SRodney W. Grimes 	 * do not know how many columns yet. The number of operands provide an
8299b50d902SRodney W. Grimes 	 * upper bound on the number of columns. We use the number of files
8309b50d902SRodney W. Grimes 	 * we can open successfully to set the number of columns. The operation
8319b50d902SRodney W. Grimes 	 * of the merge operation (-m) in relation to unsuccesful file opens
8329b50d902SRodney W. Grimes 	 * is unspecified by posix.
8339b50d902SRodney W. Grimes 	 */
8349b50d902SRodney W. Grimes 	j = 0;
8359b50d902SRodney W. Grimes 	while (j < clcnt) {
8369b50d902SRodney W. Grimes 		if ((fbuf[j] = nxtfile(argc, argv, &fname, ohbuf, 1)) == NULL)
8379b50d902SRodney W. Grimes 			break;
8389b50d902SRodney W. Grimes 		if (pgnm && (inskip(fbuf[j], pgnm, lines)))
8399b50d902SRodney W. Grimes 			fbuf[j] = NULL;
8409b50d902SRodney W. Grimes 		++j;
8419b50d902SRodney W. Grimes 	}
8429b50d902SRodney W. Grimes 
8439b50d902SRodney W. Grimes 	/*
8449b50d902SRodney W. Grimes 	 * if no files, exit
8459b50d902SRodney W. Grimes 	 */
8469b50d902SRodney W. Grimes 	if (!j)
8479b50d902SRodney W. Grimes 		return(1);
8489b50d902SRodney W. Grimes 
8499b50d902SRodney W. Grimes 	/*
8509b50d902SRodney W. Grimes 	 * calculate page boundries based on open file count
8519b50d902SRodney W. Grimes 	 */
8529b50d902SRodney W. Grimes 	clcnt = j;
8539b50d902SRodney W. Grimes 	if (nmwd) {
8549b50d902SRodney W. Grimes 		colwd = (pgwd - clcnt - nmwd)/clcnt;
8559b50d902SRodney W. Grimes 		pgwd = ((colwd + 1) * clcnt) - nmwd - 2;
8569b50d902SRodney W. Grimes 	} else {
8579b50d902SRodney W. Grimes 		colwd = (pgwd + 1 - clcnt)/clcnt;
8589b50d902SRodney W. Grimes 		pgwd = ((colwd + 1) * clcnt) - 1;
8599b50d902SRodney W. Grimes 	}
8609b50d902SRodney W. Grimes 	if (colwd < 1) {
8619b50d902SRodney W. Grimes 		(void)fprintf(err,
8629b50d902SRodney W. Grimes 		  "pr: page width too small for %d columns\n", clcnt);
8639b50d902SRodney W. Grimes 		return(1);
8649b50d902SRodney W. Grimes 	}
8659b50d902SRodney W. Grimes 	actf = clcnt;
8669b50d902SRodney W. Grimes 	col = colwd + 1;
8679b50d902SRodney W. Grimes 
8689b50d902SRodney W. Grimes 	/*
8699b50d902SRodney W. Grimes 	 * line buffer
8709b50d902SRodney W. Grimes 	 */
8719b50d902SRodney W. Grimes 	if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL) {
8729b50d902SRodney W. Grimes 		mfail();
8739b50d902SRodney W. Grimes 		return(1);
8749b50d902SRodney W. Grimes 	}
8759b50d902SRodney W. Grimes 	if (offst) {
8769b50d902SRodney W. Grimes 		(void)memset(buf, (int)' ', offst);
8779b50d902SRodney W. Grimes 		(void)memset(hbuf, (int)' ', offst);
8789b50d902SRodney W. Grimes 	}
8799b50d902SRodney W. Grimes 	if (pgnm)
8809b50d902SRodney W. Grimes 		pagecnt = pgnm;
8819b50d902SRodney W. Grimes 	else
8829b50d902SRodney W. Grimes 		pagecnt = 1;
8839b50d902SRodney W. Grimes 	lncnt = 0;
8849b50d902SRodney W. Grimes 
8859b50d902SRodney W. Grimes 	/*
8869b50d902SRodney W. Grimes 	 * continue to loop while any file still has data
8879b50d902SRodney W. Grimes 	 */
8889b50d902SRodney W. Grimes 	while (actf > 0) {
889032b32adSJuli Mallett 		ttypause(pagecnt);
890032b32adSJuli Mallett 
8919b50d902SRodney W. Grimes 		/*
8929b50d902SRodney W. Grimes 		 * loop by line
8939b50d902SRodney W. Grimes 		 */
8949b50d902SRodney W. Grimes 		for (i = 0; i < lines; ++i) {
8959b50d902SRodney W. Grimes 			ptbf = buf + offst;
8969b50d902SRodney W. Grimes 			lstdat = ptbf;
8979b50d902SRodney W. Grimes 			if (nmwd) {
8989b50d902SRodney W. Grimes 				/*
8999b50d902SRodney W. Grimes 				 * add line number to line
9009b50d902SRodney W. Grimes 				 */
9019b50d902SRodney W. Grimes 				addnum(ptbf, nmwd, ++lncnt);
9029b50d902SRodney W. Grimes 				ptbf += nmwd;
9039b50d902SRodney W. Grimes 				*ptbf++ = nmchar;
9049b50d902SRodney W. Grimes 			}
9059b50d902SRodney W. Grimes 			j = 0;
9069b50d902SRodney W. Grimes 			fproc = 0;
9079b50d902SRodney W. Grimes 
9089b50d902SRodney W. Grimes 			/*
9099b50d902SRodney W. Grimes 			 * loop by column
9109b50d902SRodney W. Grimes 			 */
9119b50d902SRodney W. Grimes 			for (j = 0; j < clcnt; ++j) {
9129b50d902SRodney W. Grimes 				if (fbuf[j] == NULL) {
9139b50d902SRodney W. Grimes 					/*
9149b50d902SRodney W. Grimes 					 * empty column; EOF
9159b50d902SRodney W. Grimes 					 */
9169b50d902SRodney W. Grimes 					cnt = 0;
9179b50d902SRodney W. Grimes 				} else if ((cnt = inln(fbuf[j], ptbf, colwd,
9189b50d902SRodney W. Grimes 							&cps, 1, &mor)) < 0) {
9199b50d902SRodney W. Grimes 					/*
9209b50d902SRodney W. Grimes 					 * EOF hit; no data
9219b50d902SRodney W. Grimes 					 */
9229b50d902SRodney W. Grimes 					if (fbuf[j] != stdin)
9239b50d902SRodney W. Grimes 						(void)fclose(fbuf[j]);
9249b50d902SRodney W. Grimes 					fbuf[j] = NULL;
9259b50d902SRodney W. Grimes 					--actf;
9269b50d902SRodney W. Grimes 					cnt = 0;
9279b50d902SRodney W. Grimes 				} else {
9289b50d902SRodney W. Grimes 					/*
9299b50d902SRodney W. Grimes 					 * process file data
9309b50d902SRodney W. Grimes 					 */
9319b50d902SRodney W. Grimes 					ptbf += cnt;
9329b50d902SRodney W. Grimes 					lstdat = ptbf;
9339b50d902SRodney W. Grimes 					fproc++;
9349b50d902SRodney W. Grimes 				}
9359b50d902SRodney W. Grimes 
9369b50d902SRodney W. Grimes 				/*
9379b50d902SRodney W. Grimes 				 * if last ACTIVE column, done with line
9389b50d902SRodney W. Grimes 				 */
9399b50d902SRodney W. Grimes 				if (fproc >= actf)
9409b50d902SRodney W. Grimes 					break;
9419b50d902SRodney W. Grimes 
9429b50d902SRodney W. Grimes 				/*
9439b50d902SRodney W. Grimes 				 * pad to end of column
9449b50d902SRodney W. Grimes 				 */
9459b50d902SRodney W. Grimes 				if (sflag) {
9469b50d902SRodney W. Grimes 					*ptbf++ = schar;
9479b50d902SRodney W. Grimes 				} else if ((pln = col - cnt) > 0) {
9489b50d902SRodney W. Grimes 					(void)memset(ptbf, (int)' ', pln);
9499b50d902SRodney W. Grimes 					ptbf += pln;
9509b50d902SRodney W. Grimes 				}
9519b50d902SRodney W. Grimes 			}
9529b50d902SRodney W. Grimes 
9539b50d902SRodney W. Grimes 			/*
9549b50d902SRodney W. Grimes 			 * calculate data in line
9559b50d902SRodney W. Grimes 			 */
9569b50d902SRodney W. Grimes 			if ((j = lstdat - buf) <= offst)
9579b50d902SRodney W. Grimes 				break;
9589b50d902SRodney W. Grimes 
9599b50d902SRodney W. Grimes 			if (!i && !nohead && prhead(hbuf, fname, pagecnt))
9609b50d902SRodney W. Grimes 				return(1);
9619b50d902SRodney W. Grimes 
9629b50d902SRodney W. Grimes 			/*
9639b50d902SRodney W. Grimes 			 * output line
9649b50d902SRodney W. Grimes 			 */
9659b50d902SRodney W. Grimes 			if (otln(buf, j, &ips, &ops, 0))
9669b50d902SRodney W. Grimes 				return(1);
9679b50d902SRodney W. Grimes 
9689b50d902SRodney W. Grimes 			/*
9699b50d902SRodney W. Grimes 			 * if no more active files, done
9709b50d902SRodney W. Grimes 			 */
9719b50d902SRodney W. Grimes 			if (actf <= 0) {
9729b50d902SRodney W. Grimes 				++i;
9739b50d902SRodney W. Grimes 				break;
9749b50d902SRodney W. Grimes 			}
9759b50d902SRodney W. Grimes 		}
9769b50d902SRodney W. Grimes 
9779b50d902SRodney W. Grimes 		/*
9789b50d902SRodney W. Grimes 		 * pad to end of page
9799b50d902SRodney W. Grimes 		 */
9809b50d902SRodney W. Grimes 		if (i && prtail(lines-i, 0))
9819b50d902SRodney W. Grimes 			return(1);
9829b50d902SRodney W. Grimes 		++pagecnt;
9839b50d902SRodney W. Grimes 	}
9849b50d902SRodney W. Grimes 	if (eoptind < argc)
9859b50d902SRodney W. Grimes 		return(1);
9869b50d902SRodney W. Grimes 	return(0);
9879b50d902SRodney W. Grimes }
9889b50d902SRodney W. Grimes 
9899b50d902SRodney W. Grimes /*
9909b50d902SRodney W. Grimes  * inln():	input a line of data (unlimited length lines supported)
9919b50d902SRodney W. Grimes  *		Input is optionally expanded to spaces
9929b50d902SRodney W. Grimes  *
9939b50d902SRodney W. Grimes  *	inf:	file
9949b50d902SRodney W. Grimes  *	buf:	buffer
9959b50d902SRodney W. Grimes  *	lim:	buffer length
9969b50d902SRodney W. Grimes  *	cps:	column positon 1st char in buffer (large line support)
9979b50d902SRodney W. Grimes  *	trnc:	throw away data more than lim up to \n
9989b50d902SRodney W. Grimes  *	mor:	set if more data in line (not truncated)
9999b50d902SRodney W. Grimes  */
10009b50d902SRodney W. Grimes int
10019b50d902SRodney W. Grimes inln(inf, buf, lim, cps, trnc, mor)
10029b50d902SRodney W. Grimes 	FILE *inf;
10039b50d902SRodney W. Grimes 	char *buf;
10049b50d902SRodney W. Grimes 	register int lim;
10059b50d902SRodney W. Grimes 	int *cps;
10069b50d902SRodney W. Grimes 	int trnc;
10079b50d902SRodney W. Grimes 	int *mor;
10089b50d902SRodney W. Grimes {
10099b50d902SRodney W. Grimes 	register int col;
10109b50d902SRodney W. Grimes 	register int gap = ingap;
10119b50d902SRodney W. Grimes 	register int ch = EOF;
10129b50d902SRodney W. Grimes 	register char *ptbuf;
10139b50d902SRodney W. Grimes 	register int chk = (int)inchar;
10149b50d902SRodney W. Grimes 
10159b50d902SRodney W. Grimes 	ptbuf = buf;
10169b50d902SRodney W. Grimes 
10179b50d902SRodney W. Grimes 	if (gap) {
10189b50d902SRodney W. Grimes 		/*
10199b50d902SRodney W. Grimes 		 * expanding input option
10209b50d902SRodney W. Grimes 		 */
10219b50d902SRodney W. Grimes 		while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) {
10229b50d902SRodney W. Grimes 			/*
10239b50d902SRodney W. Grimes 			 * is this the input "tab" char
10249b50d902SRodney W. Grimes 			 */
10259b50d902SRodney W. Grimes 			if (ch == chk) {
10269b50d902SRodney W. Grimes 				/*
10279b50d902SRodney W. Grimes 				 * expand to number of spaces
10289b50d902SRodney W. Grimes 				 */
10299b50d902SRodney W. Grimes 				col = (ptbuf - buf) + *cps;
10309b50d902SRodney W. Grimes 				col = gap - (col % gap);
10319b50d902SRodney W. Grimes 
10329b50d902SRodney W. Grimes 				/*
10339b50d902SRodney W. Grimes 				 * if more than this line, push back
10349b50d902SRodney W. Grimes 				 */
10359b50d902SRodney W. Grimes 				if ((col > lim) && (ungetc(ch, inf) == EOF))
10369b50d902SRodney W. Grimes 					return(1);
10379b50d902SRodney W. Grimes 
10389b50d902SRodney W. Grimes 				/*
10399b50d902SRodney W. Grimes 				 * expand to spaces
10409b50d902SRodney W. Grimes 				 */
10419b50d902SRodney W. Grimes 				while ((--col >= 0) && (--lim >= 0))
10429b50d902SRodney W. Grimes 					*ptbuf++ = ' ';
10439b50d902SRodney W. Grimes 				continue;
10449b50d902SRodney W. Grimes 			}
10459b50d902SRodney W. Grimes 			if (ch == '\n')
10469b50d902SRodney W. Grimes 				break;
10479b50d902SRodney W. Grimes 			*ptbuf++ = ch;
10489b50d902SRodney W. Grimes 		}
10499b50d902SRodney W. Grimes 	} else {
10509b50d902SRodney W. Grimes 		/*
10519b50d902SRodney W. Grimes 		 * no expansion
10529b50d902SRodney W. Grimes 		 */
10539b50d902SRodney W. Grimes 		while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) {
10549b50d902SRodney W. Grimes 			if (ch == '\n')
10559b50d902SRodney W. Grimes 				break;
10569b50d902SRodney W. Grimes 			*ptbuf++ = ch;
10579b50d902SRodney W. Grimes 		}
10589b50d902SRodney W. Grimes 	}
10599b50d902SRodney W. Grimes 	col = ptbuf - buf;
10609b50d902SRodney W. Grimes 	if (ch == EOF) {
10619b50d902SRodney W. Grimes 		*mor = 0;
10629b50d902SRodney W. Grimes 		*cps = 0;
10639b50d902SRodney W. Grimes 		if (!col)
10649b50d902SRodney W. Grimes 			return(-1);
10659b50d902SRodney W. Grimes 		return(col);
10669b50d902SRodney W. Grimes 	}
10679b50d902SRodney W. Grimes 	if (ch == '\n') {
10689b50d902SRodney W. Grimes 		/*
10699b50d902SRodney W. Grimes 		 * entire line processed
10709b50d902SRodney W. Grimes 		 */
10719b50d902SRodney W. Grimes 		*mor = 0;
10729b50d902SRodney W. Grimes 		*cps = 0;
10739b50d902SRodney W. Grimes 		return(col);
10749b50d902SRodney W. Grimes 	}
10759b50d902SRodney W. Grimes 
10769b50d902SRodney W. Grimes 	/*
10779b50d902SRodney W. Grimes 	 * line was larger than limit
10789b50d902SRodney W. Grimes 	 */
10799b50d902SRodney W. Grimes 	if (trnc) {
10809b50d902SRodney W. Grimes 		/*
10819b50d902SRodney W. Grimes 		 * throw away rest of line
10829b50d902SRodney W. Grimes 		 */
10839b50d902SRodney W. Grimes 		while ((ch = getc(inf)) != EOF) {
10849b50d902SRodney W. Grimes 			if (ch == '\n')
10859b50d902SRodney W. Grimes 				break;
10869b50d902SRodney W. Grimes 		}
10879b50d902SRodney W. Grimes 		*cps = 0;
10889b50d902SRodney W. Grimes 		*mor = 0;
10899b50d902SRodney W. Grimes 	} else {
10909b50d902SRodney W. Grimes 		/*
10919b50d902SRodney W. Grimes 		 * save column offset if not truncated
10929b50d902SRodney W. Grimes 		 */
10939b50d902SRodney W. Grimes 		*cps += col;
10949b50d902SRodney W. Grimes 		*mor = 1;
10959b50d902SRodney W. Grimes 	}
10969b50d902SRodney W. Grimes 
10979b50d902SRodney W. Grimes 	return(col);
10989b50d902SRodney W. Grimes }
10999b50d902SRodney W. Grimes 
11009b50d902SRodney W. Grimes /*
11019b50d902SRodney W. Grimes  * otln():	output a line of data. (Supports unlimited length lines)
11029b50d902SRodney W. Grimes  *		output is optionally contracted to tabs
11039b50d902SRodney W. Grimes  *
11049b50d902SRodney W. Grimes  *	buf:	output buffer with data
11059b50d902SRodney W. Grimes  *	cnt:	number of chars of valid data in buf
11069b50d902SRodney W. Grimes  *	svips:	buffer input column position (for large lines)
11079b50d902SRodney W. Grimes  *	svops:	buffer output column position (for large lines)
11089b50d902SRodney W. Grimes  *	mor:	output line not complete in this buf; more data to come.
11099b50d902SRodney W. Grimes  *		1 is more, 0 is complete, -1 is no \n's
11109b50d902SRodney W. Grimes  */
11119b50d902SRodney W. Grimes int
11129b50d902SRodney W. Grimes otln(buf, cnt, svips, svops, mor)
11139b50d902SRodney W. Grimes 	register char *buf;
11149b50d902SRodney W. Grimes 	int cnt;
11159b50d902SRodney W. Grimes 	int *svops;
11169b50d902SRodney W. Grimes 	int *svips;
11179b50d902SRodney W. Grimes 	int mor;
11189b50d902SRodney W. Grimes {
11199b50d902SRodney W. Grimes 	register int ops;		/* last col output */
11209b50d902SRodney W. Grimes 	register int ips;		/* last col in buf examined */
11219b50d902SRodney W. Grimes 	register int gap = ogap;
11229b50d902SRodney W. Grimes 	register int tbps;
11239b50d902SRodney W. Grimes 	register char *endbuf;
11249b50d902SRodney W. Grimes 
11259b50d902SRodney W. Grimes 	if (ogap) {
11269b50d902SRodney W. Grimes 		/*
11279b50d902SRodney W. Grimes 		 * contracting on output
11289b50d902SRodney W. Grimes 		 */
11299b50d902SRodney W. Grimes 		endbuf = buf + cnt;
11309b50d902SRodney W. Grimes 		ops = *svops;
11319b50d902SRodney W. Grimes 		ips = *svips;
11329b50d902SRodney W. Grimes 		while (buf < endbuf) {
11339b50d902SRodney W. Grimes 			/*
11349b50d902SRodney W. Grimes 			 * count number of spaces and ochar in buffer
11359b50d902SRodney W. Grimes 			 */
11369b50d902SRodney W. Grimes 			if (*buf == ' ') {
11379b50d902SRodney W. Grimes 				++ips;
11389b50d902SRodney W. Grimes 				++buf;
11399b50d902SRodney W. Grimes 				continue;
11409b50d902SRodney W. Grimes 			}
11419b50d902SRodney W. Grimes 
11429b50d902SRodney W. Grimes 			/*
11439b50d902SRodney W. Grimes 			 * simulate ochar processing
11449b50d902SRodney W. Grimes 			 */
11459b50d902SRodney W. Grimes 			if (*buf == ochar) {
11469b50d902SRodney W. Grimes 				ips += gap - (ips % gap);
11479b50d902SRodney W. Grimes 				++buf;
11489b50d902SRodney W. Grimes 				continue;
11499b50d902SRodney W. Grimes 			}
11509b50d902SRodney W. Grimes 
11519b50d902SRodney W. Grimes 			/*
11529b50d902SRodney W. Grimes 			 * got a non space char; contract out spaces
11539b50d902SRodney W. Grimes 			 */
115406b95991STim J. Robbins 			while (ips - ops > 1) {
11559b50d902SRodney W. Grimes 				/*
11569b50d902SRodney W. Grimes 				 * use as many ochar as will fit
11579b50d902SRodney W. Grimes 				 */
11589b50d902SRodney W. Grimes 				if ((tbps = ops + gap - (ops % gap)) > ips)
11599b50d902SRodney W. Grimes 					break;
11609b50d902SRodney W. Grimes 				if (putchar(ochar) == EOF) {
11619b50d902SRodney W. Grimes 					pfail();
11629b50d902SRodney W. Grimes 					return(1);
11639b50d902SRodney W. Grimes 				}
11649b50d902SRodney W. Grimes 				ops = tbps;
11659b50d902SRodney W. Grimes 			}
11669b50d902SRodney W. Grimes 
11679b50d902SRodney W. Grimes 			while (ops < ips) {
11689b50d902SRodney W. Grimes 				/*
11699b50d902SRodney W. Grimes 				 * finish off with spaces
11709b50d902SRodney W. Grimes 				 */
11719b50d902SRodney W. Grimes 				if (putchar(' ') == EOF) {
11729b50d902SRodney W. Grimes 					pfail();
11739b50d902SRodney W. Grimes 					return(1);
11749b50d902SRodney W. Grimes 				}
11759b50d902SRodney W. Grimes 				++ops;
11769b50d902SRodney W. Grimes 			}
11779b50d902SRodney W. Grimes 
11789b50d902SRodney W. Grimes 			/*
11799b50d902SRodney W. Grimes 			 * output non space char
11809b50d902SRodney W. Grimes 			 */
11819b50d902SRodney W. Grimes 			if (putchar(*buf++) == EOF) {
11829b50d902SRodney W. Grimes 				pfail();
11839b50d902SRodney W. Grimes 				return(1);
11849b50d902SRodney W. Grimes 			}
11859b50d902SRodney W. Grimes 			++ips;
11869b50d902SRodney W. Grimes 			++ops;
11879b50d902SRodney W. Grimes 		}
11889b50d902SRodney W. Grimes 
11899b50d902SRodney W. Grimes 		if (mor > 0) {
11909b50d902SRodney W. Grimes 			/*
11919b50d902SRodney W. Grimes 			 * if incomplete line, save position counts
11929b50d902SRodney W. Grimes 			 */
11939b50d902SRodney W. Grimes 			*svops = ops;
11949b50d902SRodney W. Grimes 			*svips = ips;
11959b50d902SRodney W. Grimes 			return(0);
11969b50d902SRodney W. Grimes 		}
11979b50d902SRodney W. Grimes 
11989b50d902SRodney W. Grimes 		if (mor < 0) {
119906b95991STim J. Robbins 			while (ips - ops > 1) {
12009b50d902SRodney W. Grimes 				/*
12019b50d902SRodney W. Grimes 				 * use as many ochar as will fit
12029b50d902SRodney W. Grimes 				 */
12039b50d902SRodney W. Grimes 				if ((tbps = ops + gap - (ops % gap)) > ips)
12049b50d902SRodney W. Grimes 					break;
12059b50d902SRodney W. Grimes 				if (putchar(ochar) == EOF) {
12069b50d902SRodney W. Grimes 					pfail();
12079b50d902SRodney W. Grimes 					return(1);
12089b50d902SRodney W. Grimes 				}
12099b50d902SRodney W. Grimes 				ops = tbps;
12109b50d902SRodney W. Grimes 			}
12119b50d902SRodney W. Grimes 			while (ops < ips) {
12129b50d902SRodney W. Grimes 				/*
12139b50d902SRodney W. Grimes 				 * finish off with spaces
12149b50d902SRodney W. Grimes 				 */
12159b50d902SRodney W. Grimes 				if (putchar(' ') == EOF) {
12169b50d902SRodney W. Grimes 					pfail();
12179b50d902SRodney W. Grimes 					return(1);
12189b50d902SRodney W. Grimes 				}
12199b50d902SRodney W. Grimes 				++ops;
12209b50d902SRodney W. Grimes 			}
12219b50d902SRodney W. Grimes 			return(0);
12229b50d902SRodney W. Grimes 		}
12239b50d902SRodney W. Grimes 	} else {
12249b50d902SRodney W. Grimes 		/*
12259b50d902SRodney W. Grimes 		 * output is not contracted
12269b50d902SRodney W. Grimes 		 */
12279b50d902SRodney W. Grimes 		if (cnt && (fwrite(buf, sizeof(char), cnt, stdout) <= 0)) {
12289b50d902SRodney W. Grimes 			pfail();
12299b50d902SRodney W. Grimes 			return(1);
12309b50d902SRodney W. Grimes 		}
12319b50d902SRodney W. Grimes 		if (mor != 0)
12329b50d902SRodney W. Grimes 			return(0);
12339b50d902SRodney W. Grimes 	}
12349b50d902SRodney W. Grimes 
12359b50d902SRodney W. Grimes 	/*
12369b50d902SRodney W. Grimes 	 * process line end and double space as required
12379b50d902SRodney W. Grimes 	 */
12389b50d902SRodney W. Grimes 	if ((putchar('\n') == EOF) || (dspace && (putchar('\n') == EOF))) {
12399b50d902SRodney W. Grimes 		pfail();
12409b50d902SRodney W. Grimes 		return(1);
12419b50d902SRodney W. Grimes 	}
12429b50d902SRodney W. Grimes 	return(0);
12439b50d902SRodney W. Grimes }
12449b50d902SRodney W. Grimes 
12459b50d902SRodney W. Grimes /*
12469b50d902SRodney W. Grimes  * inskip():	skip over pgcnt pages with lncnt lines per page
12479b50d902SRodney W. Grimes  *		file is closed at EOF (if not stdin).
12489b50d902SRodney W. Grimes  *
12499b50d902SRodney W. Grimes  *	inf	FILE * to read from
12509b50d902SRodney W. Grimes  *	pgcnt	number of pages to skip
12519b50d902SRodney W. Grimes  *	lncnt	number of lines per page
12529b50d902SRodney W. Grimes  */
12539b50d902SRodney W. Grimes int
12549b50d902SRodney W. Grimes inskip(inf, pgcnt, lncnt)
12559b50d902SRodney W. Grimes 	FILE *inf;
12569b50d902SRodney W. Grimes 	register int pgcnt;
12579b50d902SRodney W. Grimes 	register int lncnt;
12589b50d902SRodney W. Grimes {
12599b50d902SRodney W. Grimes 	register int c;
12609b50d902SRodney W. Grimes 	register int cnt;
12619b50d902SRodney W. Grimes 
12629b50d902SRodney W. Grimes 	while(--pgcnt > 0) {
12639b50d902SRodney W. Grimes 		cnt = lncnt;
12649b50d902SRodney W. Grimes 		while ((c = getc(inf)) != EOF) {
12659b50d902SRodney W. Grimes 			if ((c == '\n') && (--cnt == 0))
12669b50d902SRodney W. Grimes 				break;
12679b50d902SRodney W. Grimes 		}
12689b50d902SRodney W. Grimes 		if (c == EOF) {
12699b50d902SRodney W. Grimes 			if (inf != stdin)
12709b50d902SRodney W. Grimes 				(void)fclose(inf);
12719b50d902SRodney W. Grimes 			return(1);
12729b50d902SRodney W. Grimes 		}
12739b50d902SRodney W. Grimes 	}
12749b50d902SRodney W. Grimes 	return(0);
12759b50d902SRodney W. Grimes }
12769b50d902SRodney W. Grimes 
12779b50d902SRodney W. Grimes /*
12789b50d902SRodney W. Grimes  * nxtfile:	returns a FILE * to next file in arg list and sets the
12799b50d902SRodney W. Grimes  *		time field for this file (or current date).
12809b50d902SRodney W. Grimes  *
12819b50d902SRodney W. Grimes  *	buf	array to store proper date for the header.
12829b50d902SRodney W. Grimes  *	dt	if set skips the date processing (used with -m)
12839b50d902SRodney W. Grimes  */
12849b50d902SRodney W. Grimes FILE *
12859b50d902SRodney W. Grimes nxtfile(argc, argv, fname, buf, dt)
12869b50d902SRodney W. Grimes 	int argc;
12879b50d902SRodney W. Grimes 	char **argv;
12889b50d902SRodney W. Grimes 	char **fname;
12899b50d902SRodney W. Grimes 	char *buf;
12909b50d902SRodney W. Grimes 	int dt;
12919b50d902SRodney W. Grimes {
12929b50d902SRodney W. Grimes 	FILE *inf = NULL;
12939b50d902SRodney W. Grimes 	struct timeval tv;
1294375557fcSBruce Evans 	time_t tv_sec;
12959b50d902SRodney W. Grimes 	struct timezone tz;
12969b50d902SRodney W. Grimes 	struct tm *timeptr = NULL;
12979b50d902SRodney W. Grimes 	struct stat statbuf;
12989b50d902SRodney W. Grimes 	static int twice = -1;
12999b50d902SRodney W. Grimes 
13009b50d902SRodney W. Grimes 	++twice;
13019b50d902SRodney W. Grimes 	if (eoptind >= argc) {
13029b50d902SRodney W. Grimes 		/*
13039b50d902SRodney W. Grimes 		 * no file listed; default, use standard input
13049b50d902SRodney W. Grimes 		 */
13059b50d902SRodney W. Grimes 		if (twice)
13069b50d902SRodney W. Grimes 			return(NULL);
13079b50d902SRodney W. Grimes 		clearerr(stdin);
13089b50d902SRodney W. Grimes 		inf = stdin;
13099b50d902SRodney W. Grimes 		if (header != NULL)
13109b50d902SRodney W. Grimes 			*fname = header;
13119b50d902SRodney W. Grimes 		else
13129b50d902SRodney W. Grimes 			*fname = FNAME;
13139b50d902SRodney W. Grimes 		if (nohead)
13149b50d902SRodney W. Grimes 			return(inf);
13159b50d902SRodney W. Grimes 		if (gettimeofday(&tv, &tz) < 0) {
13169b50d902SRodney W. Grimes 			++errcnt;
13179b50d902SRodney W. Grimes 			(void)fprintf(err, "pr: cannot get time of day, %s\n",
13189b50d902SRodney W. Grimes 				strerror(errno));
13199b50d902SRodney W. Grimes 			eoptind = argc - 1;
13209b50d902SRodney W. Grimes 			return(NULL);
13219b50d902SRodney W. Grimes 		}
1322375557fcSBruce Evans 		tv_sec = tv.tv_sec;
1323375557fcSBruce Evans 		timeptr = localtime(&tv_sec);
13249b50d902SRodney W. Grimes 	}
13259b50d902SRodney W. Grimes 	for (; eoptind < argc; ++eoptind) {
13269b50d902SRodney W. Grimes 		if (strcmp(argv[eoptind], "-") == 0) {
13279b50d902SRodney W. Grimes 			/*
13289b50d902SRodney W. Grimes 			 * process a "-" for filename
13299b50d902SRodney W. Grimes 			 */
13309b50d902SRodney W. Grimes 			clearerr(stdin);
13319b50d902SRodney W. Grimes 			inf = stdin;
13329b50d902SRodney W. Grimes 			if (header != NULL)
13339b50d902SRodney W. Grimes 				*fname = header;
13349b50d902SRodney W. Grimes 			else
13359b50d902SRodney W. Grimes 				*fname = FNAME;
13369b50d902SRodney W. Grimes 			++eoptind;
13379b50d902SRodney W. Grimes 			if (nohead || (dt && twice))
13389b50d902SRodney W. Grimes 				return(inf);
13399b50d902SRodney W. Grimes 			if (gettimeofday(&tv, &tz) < 0) {
13409b50d902SRodney W. Grimes 				++errcnt;
13419b50d902SRodney W. Grimes 				(void)fprintf(err,
13429b50d902SRodney W. Grimes 					"pr: cannot get time of day, %s\n",
13439b50d902SRodney W. Grimes 					strerror(errno));
13449b50d902SRodney W. Grimes 				return(NULL);
13459b50d902SRodney W. Grimes 			}
1346375557fcSBruce Evans 			tv_sec = tv.tv_sec;
1347375557fcSBruce Evans 			timeptr = localtime(&tv_sec);
13489b50d902SRodney W. Grimes 		} else {
13499b50d902SRodney W. Grimes 			/*
13509b50d902SRodney W. Grimes 			 * normal file processing
13519b50d902SRodney W. Grimes 			 */
13529b50d902SRodney W. Grimes 			if ((inf = fopen(argv[eoptind], "r")) == NULL) {
13539b50d902SRodney W. Grimes 				++errcnt;
13549b50d902SRodney W. Grimes 				if (nodiag)
13559b50d902SRodney W. Grimes 					continue;
13569b50d902SRodney W. Grimes 				(void)fprintf(err, "pr: Cannot open %s, %s\n",
13579b50d902SRodney W. Grimes 					argv[eoptind], strerror(errno));
13589b50d902SRodney W. Grimes 				continue;
13599b50d902SRodney W. Grimes 			}
13609b50d902SRodney W. Grimes 			if (header != NULL)
13619b50d902SRodney W. Grimes 				*fname = header;
13629b50d902SRodney W. Grimes 			else if (dt)
13639b50d902SRodney W. Grimes 				*fname = FNAME;
13649b50d902SRodney W. Grimes 			else
13659b50d902SRodney W. Grimes 				*fname = argv[eoptind];
13669b50d902SRodney W. Grimes 			++eoptind;
13679b50d902SRodney W. Grimes 			if (nohead || (dt && twice))
13689b50d902SRodney W. Grimes 				return(inf);
13699b50d902SRodney W. Grimes 
13709b50d902SRodney W. Grimes 			if (dt) {
13719b50d902SRodney W. Grimes 				if (gettimeofday(&tv, &tz) < 0) {
13729b50d902SRodney W. Grimes 					++errcnt;
13739b50d902SRodney W. Grimes 					(void)fprintf(err,
13749b50d902SRodney W. Grimes 					     "pr: cannot get time of day, %s\n",
13759b50d902SRodney W. Grimes 					     strerror(errno));
13769b50d902SRodney W. Grimes 					return(NULL);
13779b50d902SRodney W. Grimes 				}
1378375557fcSBruce Evans 				tv_sec = tv.tv_sec;
1379375557fcSBruce Evans 				timeptr = localtime(&tv_sec);
13809b50d902SRodney W. Grimes 			} else {
13819b50d902SRodney W. Grimes 				if (fstat(fileno(inf), &statbuf) < 0) {
13829b50d902SRodney W. Grimes 					++errcnt;
13839b50d902SRodney W. Grimes 					(void)fclose(inf);
13849b50d902SRodney W. Grimes 					(void)fprintf(err,
13859b50d902SRodney W. Grimes 						"pr: Cannot stat %s, %s\n",
13869b50d902SRodney W. Grimes 						argv[eoptind], strerror(errno));
13879b50d902SRodney W. Grimes 					return(NULL);
13889b50d902SRodney W. Grimes 				}
13899b50d902SRodney W. Grimes 				timeptr = localtime(&(statbuf.st_mtime));
13909b50d902SRodney W. Grimes 			}
13919b50d902SRodney W. Grimes 		}
13929b50d902SRodney W. Grimes 		break;
13939b50d902SRodney W. Grimes 	}
13949b50d902SRodney W. Grimes 	if (inf == NULL)
13959b50d902SRodney W. Grimes 		return(NULL);
13969b50d902SRodney W. Grimes 
13979b50d902SRodney W. Grimes 	/*
13989b50d902SRodney W. Grimes 	 * set up time field used in header
13999b50d902SRodney W. Grimes 	 */
14009b50d902SRodney W. Grimes 	if (strftime(buf, HDBUF, timefrmt, timeptr) <= 0) {
14019b50d902SRodney W. Grimes 		++errcnt;
14029b50d902SRodney W. Grimes 		if (inf != stdin)
14039b50d902SRodney W. Grimes 			(void)fclose(inf);
14049b50d902SRodney W. Grimes 		(void)fputs("pr: time conversion failed\n", err);
14059b50d902SRodney W. Grimes 		return(NULL);
14069b50d902SRodney W. Grimes 	}
14079b50d902SRodney W. Grimes 	return(inf);
14089b50d902SRodney W. Grimes }
14099b50d902SRodney W. Grimes 
14109b50d902SRodney W. Grimes /*
14119b50d902SRodney W. Grimes  * addnum():	adds the line number to the column
14129b50d902SRodney W. Grimes  *		Truncates from the front or pads with spaces as required.
14139b50d902SRodney W. Grimes  *		Numbers are right justified.
14149b50d902SRodney W. Grimes  *
14159b50d902SRodney W. Grimes  *	buf	buffer to store the number
14169b50d902SRodney W. Grimes  *	wdth	width of buffer to fill
14179b50d902SRodney W. Grimes  *	line	line number
14189b50d902SRodney W. Grimes  *
14199b50d902SRodney W. Grimes  *		NOTE: numbers occupy part of the column. The posix
14209b50d902SRodney W. Grimes  *		spec does not specify if -i processing should or should not
14219b50d902SRodney W. Grimes  *		occur on number padding. The spec does say it occupies
14229b50d902SRodney W. Grimes  *		part of the column. The usage of addnum	currently treats
14239b50d902SRodney W. Grimes  *		numbers as part of the column so spaces may be replaced.
14249b50d902SRodney W. Grimes  */
14259b50d902SRodney W. Grimes void
14269b50d902SRodney W. Grimes addnum(buf, wdth, line)
14279b50d902SRodney W. Grimes 	register char *buf;
14289b50d902SRodney W. Grimes 	register int wdth;
14299b50d902SRodney W. Grimes 	register int line;
14309b50d902SRodney W. Grimes {
14319b50d902SRodney W. Grimes 	register char *pt = buf + wdth;
14329b50d902SRodney W. Grimes 
14339b50d902SRodney W. Grimes 	do {
14349b50d902SRodney W. Grimes 		*--pt = digs[line % 10];
14359b50d902SRodney W. Grimes 		line /= 10;
14369b50d902SRodney W. Grimes 	} while (line && (pt > buf));
14379b50d902SRodney W. Grimes 
14389b50d902SRodney W. Grimes 	/*
14399b50d902SRodney W. Grimes 	 * pad with space as required
14409b50d902SRodney W. Grimes 	 */
14419b50d902SRodney W. Grimes 	while (pt > buf)
14429b50d902SRodney W. Grimes 		*--pt = ' ';
14439b50d902SRodney W. Grimes }
14449b50d902SRodney W. Grimes 
14459b50d902SRodney W. Grimes /*
14469b50d902SRodney W. Grimes  * prhead():	prints the top of page header
14479b50d902SRodney W. Grimes  *
14489b50d902SRodney W. Grimes  *	buf	buffer with time field (and offset)
14499b50d902SRodney W. Grimes  *	cnt	number of chars in buf
14509b50d902SRodney W. Grimes  *	fname	fname field for header
14519b50d902SRodney W. Grimes  *	pagcnt	page number
14529b50d902SRodney W. Grimes  */
14539b50d902SRodney W. Grimes int
14549b50d902SRodney W. Grimes prhead(buf, fname, pagcnt)
14559b50d902SRodney W. Grimes 	char *buf;
14569b50d902SRodney W. Grimes 	char *fname;
14579b50d902SRodney W. Grimes 	int pagcnt;
14589b50d902SRodney W. Grimes {
14599b50d902SRodney W. Grimes 	int ips = 0;
14609b50d902SRodney W. Grimes 	int ops = 0;
14619b50d902SRodney W. Grimes 
14629b50d902SRodney W. Grimes 	if ((putchar('\n') == EOF) || (putchar('\n') == EOF)) {
14639b50d902SRodney W. Grimes 		pfail();
14649b50d902SRodney W. Grimes 		return(1);
14659b50d902SRodney W. Grimes 	}
14669b50d902SRodney W. Grimes 	/*
14679b50d902SRodney W. Grimes 	 * posix is not clear if the header is subject to line length
14689b50d902SRodney W. Grimes 	 * restrictions. The specification for header line format
14699b50d902SRodney W. Grimes 	 * in the spec clearly does not limit length. No pr currently
14709b50d902SRodney W. Grimes 	 * restricts header length. However if we need to truncate in
14719b50d902SRodney W. Grimes 	 * an reasonable way, adjust the length of the printf by
14729b50d902SRodney W. Grimes 	 * changing HDFMT to allow a length max as an arguement printf.
14739b50d902SRodney W. Grimes 	 * buf (which contains the offset spaces and time field could
14749b50d902SRodney W. Grimes 	 * also be trimmed
14759b50d902SRodney W. Grimes 	 *
14769b50d902SRodney W. Grimes 	 * note only the offset (if any) is processed for tab expansion
14779b50d902SRodney W. Grimes 	 */
14789b50d902SRodney W. Grimes 	if (offst && otln(buf, offst, &ips, &ops, -1))
14799b50d902SRodney W. Grimes 		return(1);
14809b50d902SRodney W. Grimes 	(void)printf(HDFMT,buf+offst, fname, pagcnt);
14819b50d902SRodney W. Grimes 	return(0);
14829b50d902SRodney W. Grimes }
14839b50d902SRodney W. Grimes 
14849b50d902SRodney W. Grimes /*
14859b50d902SRodney W. Grimes  * prtail():	pad page with empty lines (if required) and print page trailer
14869b50d902SRodney W. Grimes  *		if requested
14879b50d902SRodney W. Grimes  *
14889b50d902SRodney W. Grimes  *	cnt	number of lines of padding needed
14899b50d902SRodney W. Grimes  *	incomp	was a '\n' missing from last line output
14909b50d902SRodney W. Grimes  */
14919b50d902SRodney W. Grimes int
14929b50d902SRodney W. Grimes prtail(cnt, incomp)
14939b50d902SRodney W. Grimes 	register int cnt;
14949b50d902SRodney W. Grimes 	int incomp;
14959b50d902SRodney W. Grimes {
14969b50d902SRodney W. Grimes 	if (nohead) {
14979b50d902SRodney W. Grimes 		/*
14989b50d902SRodney W. Grimes 		 * only pad with no headers when incomplete last line
14999b50d902SRodney W. Grimes 		 */
1500ebcf24fbSMarc G. Fournier 		if (incomp &&
1501ebcf24fbSMarc G. Fournier 		    ((dspace && (putchar('\n') == EOF)) ||
1502ebcf24fbSMarc G. Fournier 		     (putchar('\n') == EOF))) {
15039b50d902SRodney W. Grimes 			pfail();
15049b50d902SRodney W. Grimes 			return(1);
15059b50d902SRodney W. Grimes 		}
1506ebcf24fbSMarc G. Fournier 		/*
1507ebcf24fbSMarc G. Fournier 		 * but honor the formfeed request
1508ebcf24fbSMarc G. Fournier 		 */
1509ebcf24fbSMarc G. Fournier 		if (formfeed) {
1510ebcf24fbSMarc G. Fournier 			if (putchar('\f') == EOF) {
1511ebcf24fbSMarc G. Fournier 				pfail();
1512ebcf24fbSMarc G. Fournier 				return(1);
1513ebcf24fbSMarc G. Fournier 			}
1514ebcf24fbSMarc G. Fournier 		}
15159b50d902SRodney W. Grimes 		return(0);
15169b50d902SRodney W. Grimes 	}
15179b50d902SRodney W. Grimes 	/*
15189b50d902SRodney W. Grimes 	 * if double space output two \n
15199b50d902SRodney W. Grimes 	 */
15209b50d902SRodney W. Grimes 	if (dspace)
15219b50d902SRodney W. Grimes 		cnt *= 2;
15229b50d902SRodney W. Grimes 
15239b50d902SRodney W. Grimes 	/*
15249b50d902SRodney W. Grimes 	 * if an odd number of lines per page, add an extra \n
15259b50d902SRodney W. Grimes 	 */
15269b50d902SRodney W. Grimes 	if (addone)
15279b50d902SRodney W. Grimes 		++cnt;
15289b50d902SRodney W. Grimes 
15299b50d902SRodney W. Grimes 	/*
15309b50d902SRodney W. Grimes 	 * pad page
15319b50d902SRodney W. Grimes 	 */
15329b50d902SRodney W. Grimes 	if (formfeed) {
15339b50d902SRodney W. Grimes 		if ((incomp && (putchar('\n') == EOF)) ||
15349b50d902SRodney W. Grimes 		    (putchar('\f') == EOF)) {
15359b50d902SRodney W. Grimes 			pfail();
15369b50d902SRodney W. Grimes 			return(1);
15379b50d902SRodney W. Grimes 		}
15389b50d902SRodney W. Grimes 		return(0);
15399b50d902SRodney W. Grimes 	}
15409b50d902SRodney W. Grimes 	cnt += TAILLEN;
15419b50d902SRodney W. Grimes 	while (--cnt >= 0) {
15429b50d902SRodney W. Grimes 		if (putchar('\n') == EOF) {
15439b50d902SRodney W. Grimes 			pfail();
15449b50d902SRodney W. Grimes 			return(1);
15459b50d902SRodney W. Grimes 		}
15469b50d902SRodney W. Grimes 	}
15479b50d902SRodney W. Grimes 	return(0);
15489b50d902SRodney W. Grimes }
15499b50d902SRodney W. Grimes 
15509b50d902SRodney W. Grimes /*
15519b50d902SRodney W. Grimes  * terminate():	when a SIGINT is recvd
15529b50d902SRodney W. Grimes  */
15539b50d902SRodney W. Grimes void
15549b50d902SRodney W. Grimes terminate(which_sig)
15559b50d902SRodney W. Grimes 	int which_sig;
15569b50d902SRodney W. Grimes {
15579b50d902SRodney W. Grimes 	flsh_errs();
15589b50d902SRodney W. Grimes 	exit(1);
15599b50d902SRodney W. Grimes }
15609b50d902SRodney W. Grimes 
15619b50d902SRodney W. Grimes 
15629b50d902SRodney W. Grimes /*
15639b50d902SRodney W. Grimes  * flsh_errs():	output saved up diagnostic messages after all normal
15649b50d902SRodney W. Grimes  *		processing has completed
15659b50d902SRodney W. Grimes  */
15669b50d902SRodney W. Grimes void
15679b50d902SRodney W. Grimes flsh_errs()
15689b50d902SRodney W. Grimes {
15699b50d902SRodney W. Grimes 	char buf[BUFSIZ];
15709b50d902SRodney W. Grimes 
15719b50d902SRodney W. Grimes 	(void)fflush(stdout);
15729b50d902SRodney W. Grimes 	(void)fflush(err);
15739b50d902SRodney W. Grimes 	if (err == stderr)
15749b50d902SRodney W. Grimes 		return;
15759b50d902SRodney W. Grimes 	rewind(err);
15769b50d902SRodney W. Grimes 	while (fgets(buf, BUFSIZ, err) != NULL)
15779b50d902SRodney W. Grimes 		(void)fputs(buf, stderr);
15789b50d902SRodney W. Grimes }
15799b50d902SRodney W. Grimes 
15809b50d902SRodney W. Grimes void
15819b50d902SRodney W. Grimes mfail()
15829b50d902SRodney W. Grimes {
15839b50d902SRodney W. Grimes 	(void)fputs("pr: memory allocation failed\n", err);
15849b50d902SRodney W. Grimes }
15859b50d902SRodney W. Grimes 
15869b50d902SRodney W. Grimes void
15879b50d902SRodney W. Grimes pfail()
15889b50d902SRodney W. Grimes {
15899b50d902SRodney W. Grimes 	(void)fprintf(err, "pr: write failure, %s\n", strerror(errno));
15909b50d902SRodney W. Grimes }
15919b50d902SRodney W. Grimes 
15929b50d902SRodney W. Grimes void
15939b50d902SRodney W. Grimes usage()
15949b50d902SRodney W. Grimes {
15959b50d902SRodney W. Grimes 	(void)fputs(
1596032b32adSJuli Mallett 	 "usage: pr [+page] [-col] [-adFfmprt] [-e[ch][gap]] [-h header]\n",
1597032b32adSJuli Mallett 	 err);
15989b50d902SRodney W. Grimes 	(void)fputs(
15999b50d902SRodney W. Grimes 	 "          [-i[ch][gap]] [-l line] [-n[ch][width]] [-o offset]\n",err);
16009b50d902SRodney W. Grimes 	(void)fputs(
16014bf9895eSAndrey A. Chernov 	 "          [-L locale] [-s[ch]] [-w width] [-] [file ...]\n", err);
16029b50d902SRodney W. Grimes }
16039b50d902SRodney W. Grimes 
16049b50d902SRodney W. Grimes /*
16059b50d902SRodney W. Grimes  * setup:	Validate command args, initialize and perform sanity
16069b50d902SRodney W. Grimes  *		checks on options
16079b50d902SRodney W. Grimes  */
16089b50d902SRodney W. Grimes int
16099b50d902SRodney W. Grimes setup(argc, argv)
16109b50d902SRodney W. Grimes 	register int argc;
16119b50d902SRodney W. Grimes 	register char **argv;
16129b50d902SRodney W. Grimes {
16139b50d902SRodney W. Grimes 	register int c;
161477b898c4SAndrey A. Chernov 	int d_first;
16159b50d902SRodney W. Grimes 	int eflag = 0;
16169b50d902SRodney W. Grimes 	int iflag = 0;
16179b50d902SRodney W. Grimes 	int wflag = 0;
16189b50d902SRodney W. Grimes 	int cflag = 0;
16194bf9895eSAndrey A. Chernov 	char *Lflag = NULL;
16209b50d902SRodney W. Grimes 
16219b50d902SRodney W. Grimes 	if (isatty(fileno(stdout))) {
16229b50d902SRodney W. Grimes 		/*
16239b50d902SRodney W. Grimes 		 * defer diagnostics until processing is done
16249b50d902SRodney W. Grimes 		 */
16259b50d902SRodney W. Grimes 		if ((err = tmpfile()) == NULL) {
162696c066ccSChris D. Faulhaber 		       err = stderr;
16279b50d902SRodney W. Grimes 		       (void)fputs("Cannot defer diagnostic messages\n",stderr);
16289b50d902SRodney W. Grimes 		       return(1);
16299b50d902SRodney W. Grimes 		}
16309b50d902SRodney W. Grimes 	} else
16319b50d902SRodney W. Grimes 		err = stderr;
1632032b32adSJuli Mallett 	while ((c = egetopt(argc, argv, "#adFfmrte?h:i?L:l:n?o:ps?w:")) != -1) {
16339b50d902SRodney W. Grimes 		switch (c) {
16349b50d902SRodney W. Grimes 		case '+':
16359b50d902SRodney W. Grimes 			if ((pgnm = atoi(eoptarg)) < 1) {
16369b50d902SRodney W. Grimes 			    (void)fputs("pr: +page number must be 1 or more\n",
16379b50d902SRodney W. Grimes 				err);
16389b50d902SRodney W. Grimes 			    return(1);
16399b50d902SRodney W. Grimes 			}
16409b50d902SRodney W. Grimes 			break;
16419b50d902SRodney W. Grimes 		case '-':
16429b50d902SRodney W. Grimes 			if ((clcnt = atoi(eoptarg)) < 1) {
16439b50d902SRodney W. Grimes 			    (void)fputs("pr: -columns must be 1 or more\n",err);
16449b50d902SRodney W. Grimes 			    return(1);
16459b50d902SRodney W. Grimes 			}
16469b50d902SRodney W. Grimes 			if (clcnt > 1)
16479b50d902SRodney W. Grimes 				++cflag;
16489b50d902SRodney W. Grimes 			break;
16499b50d902SRodney W. Grimes 		case 'a':
16509b50d902SRodney W. Grimes 			++across;
16519b50d902SRodney W. Grimes 			break;
16529b50d902SRodney W. Grimes 		case 'd':
16539b50d902SRodney W. Grimes 			++dspace;
16549b50d902SRodney W. Grimes 			break;
16559b50d902SRodney W. Grimes 		case 'e':
16569b50d902SRodney W. Grimes 			++eflag;
1657b5076d91SAndrey A. Chernov 			if ((eoptarg != NULL) && !isdigit((unsigned char)*eoptarg))
16589b50d902SRodney W. Grimes 				inchar = *eoptarg++;
16599b50d902SRodney W. Grimes 			else
16609b50d902SRodney W. Grimes 				inchar = INCHAR;
1661b5076d91SAndrey A. Chernov 			if ((eoptarg != NULL) && isdigit((unsigned char)*eoptarg)) {
16629b50d902SRodney W. Grimes 				if ((ingap = atoi(eoptarg)) < 0) {
16639b50d902SRodney W. Grimes 					(void)fputs(
16649b50d902SRodney W. Grimes 					"pr: -e gap must be 0 or more\n", err);
16659b50d902SRodney W. Grimes 					return(1);
16669b50d902SRodney W. Grimes 				}
16679b50d902SRodney W. Grimes 				if (ingap == 0)
16689b50d902SRodney W. Grimes 					ingap = INGAP;
16699b50d902SRodney W. Grimes 			} else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
16709b50d902SRodney W. Grimes 				(void)fprintf(err,
16719b50d902SRodney W. Grimes 				      "pr: invalid value for -e %s\n", eoptarg);
16729b50d902SRodney W. Grimes 				return(1);
16739b50d902SRodney W. Grimes 			} else
16749b50d902SRodney W. Grimes 				ingap = INGAP;
16759b50d902SRodney W. Grimes 			break;
1676032b32adSJuli Mallett 		case 'f':
1677032b32adSJuli Mallett 			++pausefst;
1678032b32adSJuli Mallett 			/*FALLTHROUGH*/
16799b50d902SRodney W. Grimes 		case 'F':
16809b50d902SRodney W. Grimes 			++formfeed;
16819b50d902SRodney W. Grimes 			break;
16829b50d902SRodney W. Grimes 		case 'h':
16839b50d902SRodney W. Grimes 			header = eoptarg;
16849b50d902SRodney W. Grimes 			break;
16859b50d902SRodney W. Grimes 		case 'i':
16869b50d902SRodney W. Grimes 			++iflag;
1687b5076d91SAndrey A. Chernov 			if ((eoptarg != NULL) && !isdigit((unsigned char)*eoptarg))
16889b50d902SRodney W. Grimes 				ochar = *eoptarg++;
16899b50d902SRodney W. Grimes 			else
16909b50d902SRodney W. Grimes 				ochar = OCHAR;
1691b5076d91SAndrey A. Chernov 			if ((eoptarg != NULL) && isdigit((unsigned char)*eoptarg)) {
16929b50d902SRodney W. Grimes 				if ((ogap = atoi(eoptarg)) < 0) {
16939b50d902SRodney W. Grimes 					(void)fputs(
16949b50d902SRodney W. Grimes 					"pr: -i gap must be 0 or more\n", err);
16959b50d902SRodney W. Grimes 					return(1);
16969b50d902SRodney W. Grimes 				}
16979b50d902SRodney W. Grimes 				if (ogap == 0)
16989b50d902SRodney W. Grimes 					ogap = OGAP;
16999b50d902SRodney W. Grimes 			} else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
17009b50d902SRodney W. Grimes 				(void)fprintf(err,
17019b50d902SRodney W. Grimes 				      "pr: invalid value for -i %s\n", eoptarg);
17029b50d902SRodney W. Grimes 				return(1);
17039b50d902SRodney W. Grimes 			} else
17049b50d902SRodney W. Grimes 				ogap = OGAP;
17059b50d902SRodney W. Grimes 			break;
1706b5076d91SAndrey A. Chernov 		case 'L':
17074bf9895eSAndrey A. Chernov 			Lflag = eoptarg;
1708b5076d91SAndrey A. Chernov 			break;
17099b50d902SRodney W. Grimes 		case 'l':
1710b5076d91SAndrey A. Chernov 			if (!isdigit((unsigned char)*eoptarg) || ((lines=atoi(eoptarg)) < 1)) {
17119b50d902SRodney W. Grimes 				(void)fputs(
17129b50d902SRodney W. Grimes 				 "pr: Number of lines must be 1 or more\n",err);
17139b50d902SRodney W. Grimes 				return(1);
17149b50d902SRodney W. Grimes 			}
17159b50d902SRodney W. Grimes 			break;
17169b50d902SRodney W. Grimes 		case 'm':
17179b50d902SRodney W. Grimes 			++merge;
17189b50d902SRodney W. Grimes 			break;
17199b50d902SRodney W. Grimes 		case 'n':
1720b5076d91SAndrey A. Chernov 			if ((eoptarg != NULL) && !isdigit((unsigned char)*eoptarg))
17219b50d902SRodney W. Grimes 				nmchar = *eoptarg++;
17229b50d902SRodney W. Grimes 			else
17239b50d902SRodney W. Grimes 				nmchar = NMCHAR;
1724b5076d91SAndrey A. Chernov 			if ((eoptarg != NULL) && isdigit((unsigned char)*eoptarg)) {
17259b50d902SRodney W. Grimes 				if ((nmwd = atoi(eoptarg)) < 1) {
17269b50d902SRodney W. Grimes 					(void)fputs(
17279b50d902SRodney W. Grimes 					"pr: -n width must be 1 or more\n",err);
17289b50d902SRodney W. Grimes 					return(1);
17299b50d902SRodney W. Grimes 				}
17309b50d902SRodney W. Grimes 			} else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
17319b50d902SRodney W. Grimes 				(void)fprintf(err,
17329b50d902SRodney W. Grimes 				      "pr: invalid value for -n %s\n", eoptarg);
17339b50d902SRodney W. Grimes 				return(1);
17349b50d902SRodney W. Grimes 			} else
17359b50d902SRodney W. Grimes 				nmwd = NMWD;
17369b50d902SRodney W. Grimes 			break;
17379b50d902SRodney W. Grimes 		case 'o':
1738b5076d91SAndrey A. Chernov 			if (!isdigit((unsigned char)*eoptarg) || ((offst = atoi(eoptarg))< 1)){
17399b50d902SRodney W. Grimes 				(void)fputs("pr: -o offset must be 1 or more\n",
17409b50d902SRodney W. Grimes 					err);
17419b50d902SRodney W. Grimes 				return(1);
17429b50d902SRodney W. Grimes 			}
17439b50d902SRodney W. Grimes 			break;
1744032b32adSJuli Mallett 		case 'p':
1745032b32adSJuli Mallett 			++pauseall;
1746032b32adSJuli Mallett 			break;
17479b50d902SRodney W. Grimes 		case 'r':
17489b50d902SRodney W. Grimes 			++nodiag;
17499b50d902SRodney W. Grimes 			break;
17509b50d902SRodney W. Grimes 		case 's':
17519b50d902SRodney W. Grimes 			++sflag;
17529b50d902SRodney W. Grimes 			if (eoptarg == NULL)
17539b50d902SRodney W. Grimes 				schar = SCHAR;
1754d68e2acdSKris Kennaway 			else {
17559b50d902SRodney W. Grimes 				schar = *eoptarg++;
17569b50d902SRodney W. Grimes 				if (*eoptarg != '\0') {
17579b50d902SRodney W. Grimes 					(void)fprintf(err,
1758d68e2acdSKris Kennaway 					    "pr: invalid value for -s %s\n",
1759d68e2acdSKris Kennaway 					    eoptarg);
17609b50d902SRodney W. Grimes 					return(1);
17619b50d902SRodney W. Grimes 				}
1762d68e2acdSKris Kennaway 			}
17639b50d902SRodney W. Grimes 			break;
17649b50d902SRodney W. Grimes 		case 't':
17659b50d902SRodney W. Grimes 			++nohead;
17669b50d902SRodney W. Grimes 			break;
17679b50d902SRodney W. Grimes 		case 'w':
17689b50d902SRodney W. Grimes 			++wflag;
1769b5076d91SAndrey A. Chernov 			if (!isdigit((unsigned char)*eoptarg) || ((pgwd = atoi(eoptarg)) < 1)){
17709b50d902SRodney W. Grimes 				(void)fputs(
17719b50d902SRodney W. Grimes 				   "pr: -w width must be 1 or more \n",err);
17729b50d902SRodney W. Grimes 				return(1);
17739b50d902SRodney W. Grimes 			}
17749b50d902SRodney W. Grimes 			break;
17759b50d902SRodney W. Grimes 		case '?':
17769b50d902SRodney W. Grimes 		default:
17779b50d902SRodney W. Grimes 			return(1);
17789b50d902SRodney W. Grimes 		}
17799b50d902SRodney W. Grimes 	}
17809b50d902SRodney W. Grimes 
17819b50d902SRodney W. Grimes 	/*
17829b50d902SRodney W. Grimes 	 * default and sanity checks
17839b50d902SRodney W. Grimes 	 */
17849b50d902SRodney W. Grimes 	if (!clcnt) {
17859b50d902SRodney W. Grimes 		if (merge) {
17869b50d902SRodney W. Grimes 			if ((clcnt = argc - eoptind) <= 1) {
17879b50d902SRodney W. Grimes 				clcnt = CLCNT;
17889b50d902SRodney W. Grimes 				merge = 0;
17899b50d902SRodney W. Grimes 			}
17909b50d902SRodney W. Grimes 		} else
17919b50d902SRodney W. Grimes 			clcnt = CLCNT;
17929b50d902SRodney W. Grimes 	}
17939b50d902SRodney W. Grimes 	if (across) {
17949b50d902SRodney W. Grimes 		if (clcnt == 1) {
17959b50d902SRodney W. Grimes 			(void)fputs("pr: -a flag requires multiple columns\n",
17969b50d902SRodney W. Grimes 				err);
17979b50d902SRodney W. Grimes 			return(1);
17989b50d902SRodney W. Grimes 		}
17999b50d902SRodney W. Grimes 		if (merge) {
18009b50d902SRodney W. Grimes 			(void)fputs("pr: -m cannot be used with -a\n", err);
18019b50d902SRodney W. Grimes 			return(1);
18029b50d902SRodney W. Grimes 		}
18039b50d902SRodney W. Grimes 	}
18049b50d902SRodney W. Grimes 	if (!wflag) {
18059b50d902SRodney W. Grimes 		if (sflag)
18069b50d902SRodney W. Grimes 			pgwd = SPGWD;
18079b50d902SRodney W. Grimes 		else
18089b50d902SRodney W. Grimes 			pgwd = PGWD;
18099b50d902SRodney W. Grimes 	}
18109b50d902SRodney W. Grimes 	if (cflag || merge) {
18119b50d902SRodney W. Grimes 		if (!eflag) {
18129b50d902SRodney W. Grimes 			inchar = INCHAR;
18139b50d902SRodney W. Grimes 			ingap = INGAP;
18149b50d902SRodney W. Grimes 		}
18159b50d902SRodney W. Grimes 		if (!iflag) {
18169b50d902SRodney W. Grimes 			ochar = OCHAR;
18179b50d902SRodney W. Grimes 			ogap = OGAP;
18189b50d902SRodney W. Grimes 		}
18199b50d902SRodney W. Grimes 	}
18209b50d902SRodney W. Grimes 	if (cflag) {
18219b50d902SRodney W. Grimes 		if (merge) {
18229b50d902SRodney W. Grimes 			(void)fputs(
18239b50d902SRodney W. Grimes 			  "pr: -m cannot be used with multiple columns\n", err);
18249b50d902SRodney W. Grimes 			return(1);
18259b50d902SRodney W. Grimes 		}
18269b50d902SRodney W. Grimes 		if (nmwd) {
18279b50d902SRodney W. Grimes 			colwd = (pgwd + 1 - (clcnt * (nmwd + 2)))/clcnt;
18289b50d902SRodney W. Grimes 			pgwd = ((colwd + nmwd + 2) * clcnt) - 1;
18299b50d902SRodney W. Grimes 		} else {
18309b50d902SRodney W. Grimes 			colwd = (pgwd + 1 - clcnt)/clcnt;
18319b50d902SRodney W. Grimes 			pgwd = ((colwd + 1) * clcnt) - 1;
18329b50d902SRodney W. Grimes 		}
18339b50d902SRodney W. Grimes 		if (colwd < 1) {
18349b50d902SRodney W. Grimes 			(void)fprintf(err,
18359b50d902SRodney W. Grimes 			  "pr: page width is too small for %d columns\n",clcnt);
18369b50d902SRodney W. Grimes 			return(1);
18379b50d902SRodney W. Grimes 		}
18389b50d902SRodney W. Grimes 	}
18399b50d902SRodney W. Grimes 	if (!lines)
18409b50d902SRodney W. Grimes 		lines = LINES;
18419b50d902SRodney W. Grimes 
18429b50d902SRodney W. Grimes 	/*
18439b50d902SRodney W. Grimes 	 * make sure long enough for headers. if not disable
18449b50d902SRodney W. Grimes 	 */
18459b50d902SRodney W. Grimes 	if (lines <= HEADLEN + TAILLEN)
18469b50d902SRodney W. Grimes 		++nohead;
18479b50d902SRodney W. Grimes 	else if (!nohead)
18489b50d902SRodney W. Grimes 		lines -= HEADLEN + TAILLEN;
18499b50d902SRodney W. Grimes 
18509b50d902SRodney W. Grimes 	/*
18519b50d902SRodney W. Grimes 	 * adjust for double space on odd length pages
18529b50d902SRodney W. Grimes 	 */
18539b50d902SRodney W. Grimes 	if (dspace) {
18549b50d902SRodney W. Grimes 		if (lines == 1)
18559b50d902SRodney W. Grimes 			dspace = 0;
18569b50d902SRodney W. Grimes 		else {
18579b50d902SRodney W. Grimes 			if (lines & 1)
18589b50d902SRodney W. Grimes 				++addone;
18599b50d902SRodney W. Grimes 			lines /= 2;
18609b50d902SRodney W. Grimes 		}
18619b50d902SRodney W. Grimes 	}
18629b50d902SRodney W. Grimes 
18634bf9895eSAndrey A. Chernov 	(void) setlocale(LC_TIME, (Lflag != NULL) ? Lflag : "");
1864b5076d91SAndrey A. Chernov 
186577b898c4SAndrey A. Chernov 	d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
186677b898c4SAndrey A. Chernov 	timefrmt = d_first ? TIMEFMTD : TIMEFMTM;
186777b898c4SAndrey A. Chernov 
18689b50d902SRodney W. Grimes 	return(0);
18699b50d902SRodney W. Grimes }
1870