Hi!

After seeing the diff for cat -n earlier today, and just browsing Unix
stuff on my own, I noticed OpenBSD's pr(1) command has no -p option
despite pr.1 stating:
> The pr utility is compliant with the IEEE Std 1003.1-2008 ("POSIX.1") 
> specification.
https://man.openbsd.org/pr.1
This part of the man page was added in this diff:
https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/pr/pr.1.diff?r1=1.16&r2=1.17
https://github.com/openbsd/src/commit/7c5a075bb35c9874ed6ed8040f78870dae704a20
and was never correct.  -p has been a mandatory (it's neither XSI nor
optional) part of POSIX since 2001.
It's also not merely a SysVism or POSIXism, as -p exists in Unix 8th
and 10th editions:
http://man.cat-v.org/unix_8th/1/pr
http://man.cat-v.org/unix_10th/1/pr

In case the -p option is not desired, I have a small diff attached
(no-p.txt) that fixes the man page, and fixes a typo in pr.c
But I also have a bigger diff (pr-p.txt) adding -p to pr.
It's inspired by the FreeBSD and NetBSD diffs, but mostly the NetBSD one:
https://github.com/freebsd/freebsd/commit/cace3f9d081619c267182e7e1c926cafabc283e2
https://svnweb.freebsd.org/base?view=revision&revision=93481
https://github.com/NetBSD/src/commit/a19c45064f8d362783a3e36c2820544bc05d644a
http://cvsweb.netbsd.org/bsdweb.cgi/src/usr.bin/pr/pr.c

I did not touch -f or -F, though those can easily be changed later if desired.
I also did not touch -n and its numbering limit.
Implementation note: while POSIX says a "<carriage-return>", i.e.
'\r', should be waited for, FreeBSD, NetBSD, OpenSolaris, and Unix
10th edition wait for '\n' and I followed them rather than POSIX.  It
would be easy to make pr wait for either '\n' or '\r' though.

I don't know whether to add a new date or name to the
copyright/license text at the top.  A whole new flag was added, but
it's adapted from another implementation.
I mostly imitated pr's pre-existing non-style(9) style, except for
using proper style(9) inside the new prpause() function.

Thanks for reading!
Index: pr.1
===================================================================
RCS file: /cvs/src/usr.bin/pr/pr.1,v
retrieving revision 1.27
diff -u -p -r1.27 pr.1
--- pr.1        4 Jun 2014 07:57:27 -0000       1.27
+++ pr.1        11 Dec 2020 23:33:33 -0000
@@ -310,12 +310,6 @@ operand is
 .Xr more 1 ,
 .Xr ascii 7
 .Sh STANDARDS
-The
-.Nm
-utility is compliant with the
-.St -p1003.1-2008
-specification.
-.Pp
 The flag
 .Op Fl f
 is marked by
Index: pr.c
===================================================================
RCS file: /cvs/src/usr.bin/pr/pr.c,v
retrieving revision 1.43
diff -u -p -r1.43 pr.c
--- pr.c        22 Jan 2020 07:52:37 -0000      1.43
+++ pr.c        11 Dec 2020 23:33:33 -0000
@@ -64,7 +64,7 @@
  * pr: more boundary conditions than a four-legged porcupine
  *
  * the original version didn't support form-feeds, while many of the ad-hoc
- * pr implementations out there do.  Addding this and making it work reasonably
+ * pr implementations out there do.  Adding this and making it work reasonably
  * in all four output modes required quite a bit of hacking and a few minor
  * bugs were noted and fixed in the process.  Some implementations have this
  * as the as -f, some as -F so we accept either.
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.bin/pr/extern.h,v
retrieving revision 1.6
diff -u -p -r1.6 extern.h
--- extern.h    19 Jan 2015 15:30:52 -0000      1.6
+++ extern.h    12 Dec 2020 02:42:34 -0000
@@ -50,6 +50,7 @@ int    onecol(int, char **);
 int     otln(char *, int, int *, int *, int);
 void    pfail(void);
 int     prhead(char *, char *, int);
+void    prpause(int);
 int     prtail(int, int);
 int     setup(int, char **);
 void    terminate(int);
Index: pr.1
===================================================================
RCS file: /cvs/src/usr.bin/pr/pr.1,v
retrieving revision 1.27
diff -u -p -r1.27 pr.1
--- pr.1        4 Jun 2014 07:57:27 -0000       1.27
+++ pr.1        12 Dec 2020 02:42:34 -0000
@@ -33,7 +33,7 @@
 .\"
 .\"     from: @(#)pr.1 8.1 (Berkeley) 6/6/93
 .\"
-.Dd $Mdocdate: June 4 2014 $
+.Dd $Mdocdate: December 11 2020 $
 .Dt PR 1
 .Os
 .Sh NAME
@@ -43,7 +43,7 @@
 .Nm pr
 .Op Cm + Ns Ar page
 .Op Fl Ar column
-.Op Fl adFfmrt
+.Op Fl adFfmprt
 .Op Fl e Ns Oo Ar char Oc Ns Op Ar gap
 .Op Fl h Ar header
 .Op Fl i Ns Oo Ar char Oc Ns Op Ar gap
@@ -256,6 +256,9 @@ If the
 .Fl o
 option is not specified, the default is zero.
 The space taken is in addition to the output line width.
+.It Fl p
+Pause before beginning each page if the standard output is a terminal, ring 
the bell, and wait for a newline on
+.Pa /dev/tty
 .It Fl r
 Write no diagnostic reports on failure to open a file.
 .It Fl s Ns Op Ar char
Index: pr.c
===================================================================
RCS file: /cvs/src/usr.bin/pr/pr.c,v
retrieving revision 1.43
diff -u -p -r1.43 pr.c
--- pr.c        22 Jan 2020 07:52:37 -0000      1.43
+++ pr.c        12 Dec 2020 02:42:34 -0000
@@ -64,7 +64,7 @@
  * pr: more boundary conditions than a four-legged porcupine
  *
  * the original version didn't support form-feeds, while many of the ad-hoc
- * pr implementations out there do.  Addding this and making it work reasonably
+ * pr implementations out there do.  Adding this and making it work reasonably
  * in all four output modes required quite a bit of hacking and a few minor
  * bugs were noted and fixed in the process.  Some implementations have this
  * as the as -f, some as -F so we accept either.
@@ -123,16 +123,19 @@ int       nodiag;         /* do not report file open 
 char   schar;          /* text column separation character */
 int    sflag;          /* -s option for multiple columns */
 int    nohead;         /* do not write head and trailer */
+int    pgpause;        /* pause before each page */
 int    pgwd;           /* page width with multiple col output */
 
 /*
  * misc globals
  */
 volatile sig_atomic_t  ferr;   /* error message delayed */
+int    ttyout; /* output is a tty */
 int    addone = 0;     /* page length is odd with double space */
 int    errcnt = 0;     /* error count on file processing */
 int    beheaded = 0;   /* header / trailer link */
 char   digs[] = "0123456789";  /* page number translation map */
+FILE   *ttyinf;        /* input terminal for page pauses */
 
 int
 main(int argc, char *argv[])
@@ -258,8 +261,13 @@ onecol(int argc, char *argv[])
                    rc = inln(inf,lbuf,LBUF,&cnt,&cps,0,&mor);
                    if (cnt >= 0) {
                        if (!lrgln)
-                           if (!linecnt && prhead(hbuf, fname, ++pagecnt))
-                                goto out;
+                           if (!linecnt) {
+                               if (pgpause)
+                                   prpause(pagecnt+1);
+
+                               if (prhead(hbuf, fname, ++pagecnt))
+                                   goto out;
+                           }
 
                        /*
                         * start new line or continue a long one
@@ -541,6 +549,8 @@ vertcol(int argc, char *argv[])
                 * print header iff we got anything on the first read
                 */
                if (vc[0].cnt >= 0) {
+                   if (pgpause)
+                       prpause(pagecnt+1);
                    if (prhead(hbuf, fname, ++pagecnt))
                        goto out;
 
@@ -751,8 +761,13 @@ horzcol(int argc, char *argv[])
                         */
                        rc = inln(inf,ptbf,colwd,&cnt,&cps,1, &mor);
                        if (cnt >= 0) {
-                           if (!i && !j && prhead(hbuf, fname, ++pagecnt))
-                               goto out;
+                           if (!i && !j) {
+                               if (pgpause)
+                                   prpause(pagecnt+1);
+
+                               if (prhead(hbuf, fname, ++pagecnt))
+                                   goto out;
+                           }
 
                            ptbf += cnt;
                            lstdat = ptbf;
@@ -1075,8 +1090,13 @@ mulfile(int argc, char *argv[])
                 * if there was anything to do, print it
                 */
                if (fproc != 0) {
-                   if (!i && prhead(hbuf, fname, ++pagecnt))
-                       goto out;
+                   if (!i) {
+                       if (pgpause)
+                           prpause(pagecnt+1);
+
+                       if (prhead(hbuf, fname, ++pagecnt))
+                           goto out;
+                   }
 
                    /*
                     * output line
@@ -1619,6 +1639,32 @@ prhead(char *buf, char *fname, int pagcn
 }
 
 /*
+ * prpause():  pause before printing each page
+ *
+ *     pagcnt  page number
+ */
+void
+prpause(int pagcnt)
+{
+       if (ttyout) {
+               int c;
+
+               putc('\a', stderr);
+               fflush(stderr);
+
+               while ((c = getc(ttyinf)) != '\n' && c != EOF)
+                       ;
+
+               /*
+                * Pause ONLY before first page of first file.
+                * This would be used in order to pause ONLY before first page 
of first file to support an XSI-style -f option, but is currently a no-op.
+                */
+               if (pgpause == FIRSTPAGE && pagcnt == 1)
+                       pgpause = NO_PAUSE;
+       }
+}
+
+/*
  * prtail():    pad page with empty lines (if required) and print page trailer
  *        if requested
  *
@@ -1741,7 +1787,7 @@ void
 usage(void)
 {
     ferrout(
-     "usage: pr [+page] [-column] [-adFfmrt] [-e[char][gap]] [-h header]\n");
+     "usage: pr [+page] [-column] [-adFfmprt] [-e[char][gap]] [-h header]\n");
     ferrout(
      "\t[-i[char][gap]] [-l lines] [-n[char][width]] [-o offset] 
[-s[char]]\n");
     ferrout(
@@ -1762,10 +1808,14 @@ setup(int argc, char *argv[])
     int cflag = 0;
     const char *errstr;
 
-    if (isatty(fileno(stdout)))
+    ttyinf = stdin;
+
+    if (isatty(fileno(stdout))) {
        ferr = 1;
+       ttyout = 1;
+    }
 
-    while ((c = egetopt(argc, argv, "#adfFmrte?h:i?l:n?o:s?w:")) != -1) {
+    while ((c = egetopt(argc, argv, "#adfFmprte?h:i?l:n?o:s?w:")) != -1) {
        switch (c) {
        case '+':
            pgnm = strtonum(eoptarg, 1, INT_MAX, &errstr);
@@ -1871,6 +1921,9 @@ setup(int argc, char *argv[])
                return(1);
            }
            break;
+       case 'p':
+           pgpause |= EACHPAGE;
+           break;
        case 'r':
            nodiag = 1;
            break;
@@ -1982,6 +2035,17 @@ setup(int argc, char *argv[])
            if (lines & 1)
                ++addone;
            lines /= 2;
+       }
+    }
+
+    /*
+     * Open /dev/tty if we are to pause before each page,
+     * but only if stdout is a terminal and stdin is not a terminal.
+     */
+    if (ttyout && pgpause && !isatty(fileno(stdin))) {
+       if ((ttyinf = fopen("/dev/tty", "r")) == NULL) {
+           ferrout("pr: cannot open terminal\n");
+           return (1);
        }
     }
 
Index: pr.h
===================================================================
RCS file: /cvs/src/usr.bin/pr/pr.h,v
retrieving revision 1.5
diff -u -p -r1.5 pr.h
--- pr.h        19 Jan 2015 15:30:52 -0000      1.5
+++ pr.h        12 Dec 2020 02:42:34 -0000
@@ -70,6 +70,14 @@
 #define NORMAL         0
 
 /*
+ * Which pages to pause before (for -p option, and for a potential XSI-style 
-f option)
+ */
+#define NO_PAUSE       0
+#define FIRSTPAGE      1
+#define ENSUINGPAGES   2
+#define EACHPAGE       (FIRSTPAGE | ENSUINGPAGES)
+
+/*
  * structure for vertical columns. Used to balance cols on last page
  */
 struct vcol {

Reply via email to