Subject: standards/19468: pr(1) does not support -f or -p options
To: None <gnats-bugs@gnats.netbsd.org>
From: None <ryany@pobox.com>
List: netbsd-bugs
Date: 12/19/2002 21:27:20
>Number:         19468
>Category:       standards
>Synopsis:       pr(1) does not support -f or -p options
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    standards-manager
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Dec 19 18:48:01 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Ryan Younce
>Release:        NetBSD 1.6K
>Organization:
>Environment:
System: NetBSD rdu25-023-020.nc.rr.com 1.6K NetBSD 1.6K (build) #0: Mon Dec 9 14:01:02 EST 2002 root@rdu168-187-047.nc.rr.com:/root/build i386
Architecture: i386
Machine: i386
>Description:
The 2001 version of the POSIX specification indicates two options, -f
and -p, for the pr(1) utility, one of which is new and one which was
pre-existing.

These are directly quoted from the specification:
-f  Use a form feed for new pages, instead of the default behavior that
    uses a sequence of <newline>s.  Pause before beginning the first page
    if the standard output is associated with a terminal.
-p  Pause before beginning each page if the standard output is
    directed to a terminal (pr shall write an <alert> to standard
    error and wait for a <carriage-return> to be read on /dev/tty).

I've updated the files pr.c, extern.h, and pr.1 to reflect this behavior.

(Note:  POSIX states -f is to pause at the beginning of the first page. 
This is rather vague as it could be debated that the first page indicates
the first page of output or the first page of each file.  The patch
assumes it means the first page of each file).

(Furthermore, -f does not state a required alert be generated to standard
error.  The patch does generate an alert to standard error whenever it
pauses, but the delay() function in pr.c is written to easily accomodate
either case by taking an integer parameter).

>How-To-Repeat:
Not applicable.

>Fix:

Index: extern.h
===================================================================
RCS file: /cvsroot/src/usr.bin/pr/extern.h,v
retrieving revision 1.2
diff -u -r1.2 extern.h
--- extern.h	1997/01/09 15:01:35	1.2
+++ extern.h	2002/12/20 02:37:40
@@ -44,6 +44,7 @@
 extern char *eoptarg;
 
 void	 addnum __P((char *, int, int));
+void	 delay __P((int));
 int	 egetopt __P((int, char * const *, const char *));
 void	 flsh_errs __P((void));
 int	 horzcol __P((int, char **));
Index: pr.1
===================================================================
RCS file: /cvsroot/src/usr.bin/pr/pr.1,v
retrieving revision 1.13
diff -u -r1.13 pr.1
--- pr.1	2002/02/08 01:36:31	1.13
+++ pr.1	2002/12/20 02:37:40
@@ -95,6 +95,7 @@
 .Bk -words
 .Op Fl w Ar width
 .Ek
+.Op Fl fp
 .Op -
 .Op Ar file ...
 .Sh DESCRIPTION
@@ -189,6 +190,14 @@
 sequence of
 .Em \*[Lt]newline\*[Gt]
 characters.
+.It Fl f
+Same as
+.Fl F ,
+except
+.Nm
+also pauses before beginning
+the first page if the standard output
+is associated with a terminal.
 .It Fl h Ar header
 Use the string
 .Ar header
@@ -267,6 +276,13 @@
 .Fl o
 option is not specified, the default is zero.
 The space taken is in addition to the output line width.
+.It Fl p
+If standard output refers to a terminal device, for the
+beginning of each page generate
+an alert on standard error and then pause until a
+.Em \*[Lt]carriage-return\*[Gt]
+is read from
+.Pa /dev/tty .
 .It Fl r
 Write no diagnostic reports on failure to open a file.
 .It Fl s Ar char
@@ -351,6 +367,6 @@
 .Sh STANDARDS
 The
 .Nm
-utility is
-.St -p1003.2
-compatible.
+utility is compliant with the
+.St -p1003.1-2001
+specification.
Index: pr.c
===================================================================
RCS file: /cvsroot/src/usr.bin/pr/pr.c,v
retrieving revision 1.10
diff -u -r1.10 pr.c
--- pr.c	2001/07/22 13:34:13	1.10
+++ pr.c	2002/12/20 02:37:41
@@ -101,6 +101,9 @@
 int	sflag;			/* -s option for multiple columns */
 int	nohead;			/* do not write head and trailer */
 int	pgwd;			/* page width with multiple col output */
+int	delayfile;		/* delay before each file (if terminal) */
+int	delaypage;		/* interpage delay (if terminal) */
+FILE	*tty;			/* terminal device for page delays */
 char	*timefrmt = TIMEFMT;	/* time conversion string */
 
 /*
@@ -217,6 +220,9 @@
 			pagecnt = 1;
 		lncnt = 0;
 
+		if (delayfile && !delaypage)
+			delay(1);
+
 		/*
 		 * loop by page
 		 */
@@ -227,6 +233,9 @@
 			ips = 0;
 			cps = 0;
 
+			if (delaypage)
+				delay(1);
+
 			/*
 			 * loop by line
 			 */
@@ -411,10 +420,16 @@
 			pagecnt = 1;
 		lncnt = 0;
 
+		if (delayfile && !delaypage)
+			delay(1);
+
 		/*
 		 * loop by page
 		 */
 		for(;;) {
+			if (delaypage)
+				delay(1);
+
 			/*
 			 * loop by column
 			 */
@@ -438,7 +453,7 @@
 					if (!i) {
 						ptbf = buf + indy[j];
 						lstdat[j] = ptbf;
-					} else 
+					} else
 						ptbf = lstdat[j];
 					vc[cvc].pt = ptbf;
 
@@ -667,10 +682,16 @@
 			pagecnt = 1;
 		lncnt = 0;
 
+		if (delayfile && !delaypage)
+			delay(1);
+
 		/*
 		 * loop by page
 		 */
 		for(;;) {
+			if (delaypage)
+				delay(1);
+
 			/*
 			 * loop by line
 			 */
@@ -857,6 +878,9 @@
 		pagecnt = 1;
 	lncnt = 0;
 
+	if (delayfile && !delaypage)
+		delay(1);
+
 	/*
 	 * continue to loop while any file still has data
 	 */
@@ -929,8 +953,12 @@
 			if ((j = lstdat - buf) <= offst)
 				break;
 
-			if (!i && !nohead && prhead(hbuf, fname, pagecnt))
-				return(1);
+			if (!i && !nohead) {
+				if (delaypage)
+					delay(1);
+				if (prhead(hbuf, fname, pagecnt))
+					return(1);
+			}
 
 			/*
 			 * output line
@@ -960,6 +988,27 @@
 }
 
 /*
+ * delay():	delay page until carriage-return is entered on terminal
+ *
+ *	alert:	sound bell on standard error before pausing
+ */
+void
+delay(int alert)
+{
+	int ch;
+
+	if (tty) {
+		if (alert) {
+			fputc('\a', stderr);
+			fflush(stderr);
+		}
+		do {
+			ch = fgetc(tty);
+		} while (ch != EOF && ch != '\n');
+	}
+}
+
+/*
  * inln():	input a line of data (unlimited length lines supported)
  *		Input is optionally expanded to spaces
  *
@@ -967,7 +1016,7 @@
  *	buf:	buffer
  *	lim:	buffer length
  *	cps:	column positon 1st char in buffer (large line support)
- *	trnc:	throw away data more than lim up to \n 
+ *	trnc:	throw away data more than lim up to \n
  *	mor:	set if more data in line (not truncated)
  */
 int
@@ -1516,7 +1565,7 @@
 			return(1);
 		}
 		return(0);
-	} 
+	}
 	cnt += TAILLEN;
 	while (--cnt >= 0) {
 		if (putchar('\n') == EOF) {
@@ -1577,7 +1626,7 @@
 	(void)fputs(
 	 "          [-i[ch][gap]] [-l line] [-n[ch][width]] [-o offset]\n",err);
 	(void)fputs(
-	 "          [-s[ch]] [-w width] [-] [file ...]\n", err);
+	 "          [-s[ch]] [-w width] [-fp] [-] [file ...]\n", err);
 }
 
 /*
@@ -1605,7 +1654,7 @@
 		}
 	} else
 		err = stderr;
-	while ((c = egetopt(argc, argv, "#adFmrte?h:i?l:n?o:s?T:w:")) != -1) {
+	while ((c = egetopt(argc, argv, "#adfFmrte?h:i?l:n?po:s?T:w:")) != -1) {
 		switch (c) {
 		case '+':
 			if ((pgnm = atoi(eoptarg)) < 1) {
@@ -1654,6 +1703,10 @@
 		case 'F':
 			++formfeed;
 			break;
+		case 'f':
+			++formfeed;
+			++delayfile;
+			break;
 		case 'h':
 			header = eoptarg;
 			break;
@@ -1719,6 +1772,9 @@
 				return(1);
 			}
 			break;
+		case 'p':
+			++delaypage;
+			break;
 		case 'r':
 			++nodiag;
 			break;
@@ -1834,6 +1890,16 @@
 			if (lines & 1)
 				++addone;
 			lines /= 2;
+		}
+	}
+
+	/*
+	 * open /dev/tty if we are to delay pages (only if stdout is a terminal)
+	 */
+	if ((delayfile || delaypage) && isatty(fileno(stdout))) {
+		if ((tty = fopen("/dev/tty", "r")) == NULL) {
+			(void)fprintf(err, "pr: cannot open terminal\n");
+			return(1);
 		}
 	}
 
>Release-Note:
>Audit-Trail:
>Unformatted:
 Using current source dated 19 Dec 2002.