Importing usr.bin/pr

Replaces commands/pr. No Minix-specific changes needed.

Change-Id: I3c4c03b38fc8c654e7c54c3a8af0e07a0dfc9f67
This commit is contained in:
Thomas Cort 2013-10-24 12:39:25 -04:00
parent f0f2dcddaa
commit 6ea7f916db
13 changed files with 2614 additions and 568 deletions

View file

@ -18,7 +18,7 @@ SUBDIR= add_route arp ash at backup btrace \
mesg mined mkfifo \
mount mt netconf \
nonamed od paste patch \
ping postinstall poweroff pr prep printroot \
ping postinstall poweroff prep printroot \
profile progressbar pr_routes ps pwdauth \
ramdisk rarpd rawspeed rcp readclock \
reboot remsync rget rlogin \

View file

@ -1,4 +0,0 @@
PROG= pr
MAN=
.include <bsd.prog.mk>

View file

@ -1,504 +0,0 @@
/* pr - print files Author: Michiel Huisjes */
/* Pr - print files
*
* Author: Michiel Huisjes.
* Modified: Jacob P. Bunschoten. (30 nov 87)
* When "columns" is not given and numbering is on:
* line numbers are correlated with input lines.
* (try pr [-1] -n file )
* tabs are accounted for.
* When numbering is turned on, width know this.
* automatic line-folding. -f to get the original program.
* backspaces are accounted for. -b to disable this.
* multi-column mode changed.
* header can be given and used.
* format changed may occur between printing of several files:
* pr -l30 file1 -w75 file2
*
* Modified: Rick Thomas. (Sept 12, 1988)
* added "-M" option to cover functionality of old "-n" option,
* and made "-n" option behavior compatible with system V.
*
* Usage: pr [+page] [-columns] [-h header] [-wwidth] [-llength] [-ntm] [files]
* -t : Do not print the 5 line header and trailer at the page.
* -n : Turn on line numbering.
* -M : Use "Minix" style line numbering -- Each page begins at
* a line number that is an even multiple of the page length.
* Like the listings in Appendix E of the book.
* +page : Start printing at page n.
* -columns : Print files in n-columns.
* -l length: Take the length of the page to be n instead of 66
* -h header: Take next argument as page header.
* -w width : Take the width of the page to be n instead of default 79
* -f : do not fold lines.
*
* Modified: Lars Fredriksen (Jan 19, 1990)
* fixed the program so that
* pr -n *.c
* would work. The clobal variable 'width' was decremented
* by NUM_WIDTH, for each file, resulting in width finally
* being so small that nothing was printed. Used the local
* variable 'w' for the width adjustment (in print())
*
* Modified: Kenneth J. Hendrickson (10 April 1991)
* date in header should be last modification date for files,
* and the current time for stdin.
*
* Modified: Kees J. Bot (5 October 1992)
* Use localtime(3) to get the date, it knows TZ.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#define DEF_LENGTH 66
#define DEF_WIDTH 79
#define NUM_WIDTH 8
#define TAB_WIDTH 8 /* fixed tab_width */
/* Used to compute next (fixed) tabstop */
#define TO_TAB(x) (( (x) + TAB_WIDTH ) & ~07 )
typedef char BOOL;
#define FALSE 0
#define TRUE 1
/* EAT: eat rest of input line */
#define EAT(fp) while((c=getc(fp))!='\n' && c!=EOF)
/* L_BUF: calculate address of pointer to char (string) used in format */
#define L_BUF(i,j) * (char **) (line_buf + (i + j*length)*sizeof(char *))
char *header;
BOOL no_header;
BOOL number = FALSE;
BOOL minix_number = FALSE;
BOOL ext_header_set = FALSE; /* external header given */
BOOL back_space = TRUE; /* back space correction in line width */
BOOL dont_fold = FALSE; /* original. If the line does not fit eat it. */
short columns;
short cwidth;
short start_page = 1;
short width = DEF_WIDTH;
short length = DEF_LENGTH;
short linenr;
char *line_buf; /* used in format for multi-column output */
char output[1024];
int main(int argc, char **argv);
static char *myalloc(size_t size);
char skip_page(int lines, int width, FILE * filep);
void format(FILE * filep);
void print_page(int pagenr, int maxcol);
void print(FILE * filep);
void out_header(int page);
void print_time(time_t t);
int main(argc, argv)
int argc;
char *argv[];
{
FILE *file;
char *ptr;
int index = 1; /* index is one ahead of argc */
int line, col;
setbuf(stdout, output);
do {
if (argc == index) /* No arguments (left) */
goto pr_files;
ptr = argv[index++];
if (*ptr == '+') {
start_page = atoi(++ptr);
continue;
}
if (*ptr != '-') { /* no flags */
index--;
goto pr_files;
}
if (*++ptr >= '0' && *ptr <= '9') {
columns = atoi(ptr);
if (columns <= 0) columns = 1;
continue; /* Fetch next flag */
}
while (*ptr) switch (*ptr++) {
case 't': no_header = TRUE; break;
case 'n':
number = TRUE;
minix_number = FALSE;
break;
case 'M':
number = TRUE;
minix_number = TRUE;
break;
case 'h':
header = argv[index++];
ext_header_set = TRUE;
break;
case 'w':
if ((width = atoi(ptr)) <= 0) width = DEF_WIDTH;
*ptr = '\0';
break;
case 'l':
if ((length = atoi(ptr)) <= 0) length = DEF_LENGTH;
*ptr = '\0';
break;
case 'b': /* back_space correction off */
back_space = FALSE;
break;
case 'f': /* do not fold lines */
dont_fold = TRUE;
break;
default:
fprintf(stderr, "Usage: %s [+page] [-columns] [-h header] [-w<width>] [-l<length>] [-nMt] [files]\n", argv[0]);
exit(1);
}
continue; /* Scan for next flags */
/* ============== flags are read. Print the file(s) ========= */
pr_files:
if (!no_header) length -= 10;
if (columns) {
cwidth = width / columns + 1;
if (columns > width) {
fprintf(stderr, "Too many columns for page width.\n");
exit(1);
}
/* Allocate piece of mem to hold some pointers */
line_buf = myalloc(length * columns * sizeof(char *));
}
for (line = 0; line < length; line++)
for (col = 0; col < columns; col++)
L_BUF(line, col) = NULL;
if (length <= 0) {
fprintf(stderr, "Minimal length should be %d\n", no_header ?
1 : 11);
exit(1);
}
while (index <= argc) { /* print all files, including stdin */
if (index < argc && (*argv[index] == '-' || *argv[index] == '+'))
break; /* Format change */
if (argc == index) { /* no file specified, so stdin */
if (!ext_header_set) header = "";
file = stdin;
} else {
if ((file = fopen(argv[index], "r")) == (FILE *) 0) {
fprintf(stderr, "Cannot open %s\n", argv[index++]);
continue;
}
if (!ext_header_set) header = argv[index];
}
if (columns)
format(file);
else
print(file);
fclose(file);
if (++index >= argc)
break; /* all files (including stdin) done */
}
if (index >= argc) break;
/* When control comes here. format changes are to be done.
* reinitialize some variables */
if (!no_header) length += 10;
start_page = 1;
ext_header_set = FALSE;
if (columns) free(line_buf);
} while (index <= argc); /* "pr -l60" should work too */
(void) fflush(stdout);
return(0);
}
char skip_page(lines, width, filep)
int lines, width;
FILE *filep;
{
short c;
int char_cnt;
int w;
do {
w = width;
if (number) /* first lines are shorter */
if (!columns || /* called from print(file) */
!(lines % columns)) /* called from format(file) */
w -= NUM_WIDTH;
char_cnt = 0;
while ((c = getc(filep)) != '\n' && c != EOF && char_cnt < w) {
/* Calculate if this line is longer than "width (w)"
* characters */
if (c == '\b' && back_space) {
if (--char_cnt < 0) char_cnt = 0;
} else if (c == '\t')
char_cnt = TO_TAB(char_cnt);
else
char_cnt++;
}
if (dont_fold && c != '\n' && c != EOF) EAT(filep);
lines--;
if (c == '\n') linenr++;
} while (lines > 0 && c != EOF);
return c; /* last char read */
}
void format(filep)
FILE *filep;
{
char buf[512];
short c = '\0';
short index, lines, i;
short page_number = 0;
short maxcol = columns;
short wdth;
short line, col;
do {
/* Check printing of page */
page_number++;
if (page_number < start_page && c != EOF) {
c = (char) skip_page(columns * length, cwidth, filep);
continue;
}
if (c == EOF) return;
lines = columns * length;
for (line = 0; line < length; line++)
for (col = 0; col < columns; col++) {
if (L_BUF(line, col) != NULL)
free(L_BUF(line, col));
L_BUF(line, col) = (char *) NULL;
}
line = 0;
col = 0;
do {
index = 0;
wdth = cwidth - 1;
if (number && !col) /* need room for numbers */
wdth -= NUM_WIDTH;
/* Intermidiate colums are shortened by 1 char */
/* Last column not */
if (col + 1 == columns) wdth++;
for (i = 0; i < wdth - 1; i++) {
c = getc(filep);
if (c == '\n' || c == EOF) break;
if (c == '\b' && back_space) {
buf[index++] = '\b';
if (--i < 0) { /* just in case ... */
i = 0;
index = 0;
}
} else if (c == '\t') {
int cnt, max;
max = TO_TAB(i);
for (cnt = i; cnt < max; cnt++)
buf[index++] = ' ';
i = max - 1;
} else
buf[index++] = (char) c;
}
buf[index++] = '\0';
/* Collected enough chars (or eoln, or EOF) */
/* First char is EOF */
if (i == 0 && lines == columns * length && c == EOF) return;
/* Alloc mem to hold this (sub) string */
L_BUF(line, col) = myalloc(index * sizeof(char));
strcpy(L_BUF(line, col), buf);
line++;
line %= length;
if (line == 0) {
col++;
col %= columns;
}
if (dont_fold && c != '\n' && c != EOF) EAT(filep);
lines--; /* line ready for output */
if (c == EOF) {
maxcol = columns - lines / length;
}
} while (c != EOF && lines);
print_page(page_number, maxcol);
} while (c != EOF);
}
void print_page(pagenr, maxcol)
short pagenr, maxcol;
{
short pad, i, j;
short width;
char *p;
if (minix_number)
linenr = (pagenr - 1) * length + 1;
else
linenr = 1;
if (!no_header) out_header(pagenr);
for (i = 0; i < length; i++) {
for (j = 0; j < maxcol; j++) {
width = cwidth;
if (number && j == 0) { /* first columns */
printf("%7.7d ", linenr++); /* 7 == NUM_WIDTH-1 */
width -= NUM_WIDTH;
}
pad = 0;
if (p = (char *) L_BUF(i, j))
for (; pad < width - 1 && *p; pad++) putchar(*p++);
if (j < maxcol - 1) while (pad++ < width - 1)
putchar(' ');
}
putchar('\n');
}
if (!no_header) printf("\n\n\n\n\n");
}
void print(filep)
FILE *filep;
{
short c = '\0';
short page_number = 0;
short lines;
short cnt;
short w = width;
BOOL pr_number = TRUE; /* only real lines are numbered, not folded
* parts */
linenr = 1;
if (number) w -= NUM_WIDTH;
do {
/* Check printing of page */
page_number++;
if (page_number < start_page && c != EOF) {
pr_number = FALSE;
c = skip_page(length, w, filep);
if (c == '\n') pr_number = TRUE;
continue;
}
if (c == EOF) return;
if (minix_number) linenr = (page_number - 1) * length + 1;
if (page_number == start_page) c = getc(filep);
/* Print the page */
lines = length;
while (lines && c != EOF) {
if (lines == length && !no_header) out_header(page_number);
if (number)
if (pr_number)
printf("%7.7d ", linenr++); /* 7 == NUM_WIDTH-1 */
else
printf("%7c ", ' '); /* 7 == NUM_WIDTH-1 */
pr_number = FALSE;
cnt = 0;
while (c != '\n' && c != EOF && cnt < w) {
if (c == '\t') {
int i, max;
max = TO_TAB(cnt);
for (i = cnt; i < max; i++) putchar(' ');
cnt = max - 1;
} else if (c == '\b' && back_space) {
putchar('\b');
cnt--;
} else
putchar(c);
c = getc(filep);
cnt++;
}
putchar('\n');
if (dont_fold && c != '\n' && c != EOF) EAT(filep);
lines--;
if (c == '\n') {
c = getc(filep);
pr_number = TRUE;
}
}
if (lines == length) /* We never printed anything on this
* page -- */
return; /* even the header, so dont try to fill it up */
if (!no_header) /* print the trailer -- 5 blank lines */
printf("\n\n\n\n\n");
} while (c != EOF);
/* Fill last page */
if (page_number >= start_page) {
while (lines--) putchar('\n');
}
}
static char *myalloc(size)
size_t size; /* How many bytes */
{
void *ptr;
ptr = malloc(size);
if (ptr == NULL) {
fprintf(stderr, "malloc returned NULL\n");
exit(1);
}
return(char *) ptr;
}
void out_header(page)
short page;
{
time_t t;
struct stat buf;
if (strlen(header)) {
stat(header, &buf); /* use last modify time for file */
t = buf.st_mtime;
} else
(void) time(&t); /* use current time for stdin */
print_time(t);
printf(" %s Page %d\n\n\n", header, page);
}
char *moname[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
/* Print the date. */
void print_time(t)
time_t t;
{
struct tm *tm;
tm = localtime(&t);
printf("\n\n%s %2d %2d:%02d %d",
moname[tm->tm_mon],
tm->tm_mday,
tm->tm_hour,
tm->tm_min,
1900 + tm->tm_year
);
}

View file

@ -12,7 +12,7 @@ MAN= ash.1 at.1 \
look.1 lp.1 lspci.1 mail.1 \
mesg.1 mixer.1 \
mkproto.1 mount.1 mt.1 od.1 \
paste.1 ping.1 playwave.1 pr.1 prep.1 \
paste.1 ping.1 playwave.1 prep.1 \
profile.1 ps.1 rcp.1 recwave.1 \
remsync.1 rget.1 rlogin.1 rsh.1 rz.1 \
shar.1 sleep.1 spell.1 \

View file

@ -1,57 +0,0 @@
.TH PR 1
.SH NAME
pr \- print a file
.SH SYNOPSIS
\fBpr\fR [\fB\-Mfnt\fR]\fR [\fB\-h \fIn\fR] [\fB\-l \fIn\fR] [\fB\-w \fIn\fR] [\fB\-\fRcolumns\fR] [\fB+\fIpage\fR] [\fIfile\fR] ...\fR
.br
.de FL
.TP
\\fB\\$1\\fR
\\$2
..
.de EX
.TP 20
\\fB\\$1\\fR
# \\$2
..
.SH OPTIONS
.TP 5
.B \-M
# Use MINIX style line number
.TP 5
.B \-f
# Do not fold long lines
.TP 5
.B \-h
# Take next argument as page header
.TP 5
.B \-l
# Sets page length in lines
.TP 5
.B \-n
# Number the output lines
.TP 5
.B \-t
# Do not print page header or trailer
.TP 5
.B \-w
# Sets line length in characters
.SH EXAMPLES
.TP 20
.B pr \-w85 \-l60 file
# Use 85 character line, 60 line page
.TP 20
.B pr \-3 file
# List \fIfile\fP three columns to a page
.TP 20
.B pr +4 file
# Start printing with page 4
.SH DESCRIPTION
.PP
.I Pr
formats one or more files for printing.
If no files are specified, \fIstdin\fR is printed.
Options are provided for setting the width and height of the page, the
number of columns to use (default 1), and the page to start with, among others.
.SH "SEE ALSO"
.BR lp (1).

View file

@ -189,6 +189,7 @@
2012/10/17 12:00:00,usr.bin/nvi
2010/05/14 17:28:23,usr.bin/newgrp
2012/10/17 12:00:00,usr.bin/passwd
2013/10/24 12:00:00,usr.bin/pr
2013/10/17 12:00:00,usr.bin/printenv
2012/10/17 12:00:00,usr.bin/printf
2013/09/28 12:00:00,usr.bin/rev

View file

@ -19,7 +19,7 @@ SUBDIR= \
mkdep mktemp \
\
nbperf newgrp nice nl nohup nvi \
passwd \
passwd pr \
printenv printf \
rev \
\

12
usr.bin/pr/Makefile Normal file
View file

@ -0,0 +1,12 @@
# $NetBSD: Makefile,v 1.4 2011/08/16 12:05:52 christos Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
PROG= pr
SRCS= pr.c egetopt.c
DPADD+= ${LIBUTIL}
LDADD+= -lutil
COPTS.pr.c += -Wno-format-nonliteral
.include <bsd.prog.mk>

215
usr.bin/pr/egetopt.c Normal file
View file

@ -0,0 +1,215 @@
/* $NetBSD: egetopt.c,v 1.9 2011/09/06 18:26:06 joerg Exp $ */
/*-
* Copyright (c) 1991 Keith Muller.
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
from: static char sccsid[] = "@(#)egetopt.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: egetopt.c,v 1.9 2011/09/06 18:26:06 joerg Exp $");
#endif
#endif /* not lint */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "extern.h"
/*
* egetopt: get option letter from argument vector (an extended
* version of getopt).
*
* Non standard additions to the ostr specs are:
* 1) '?': immediate value following arg is optional (no white space
* between the arg and the value)
* 2) '#': +/- followed by a number (with an optional sign but
* no white space between the arg and the number). The - may be
* combined with other options, but the + cannot.
*/
int eopterr = 1; /* if error message should be printed */
int eoptind = 1; /* index into parent argv vector */
int eoptopt; /* character checked for validity */
char *eoptarg; /* argument associated with option */
#define BADCH (int)'?'
static char EMSG[1] = { '\0' };
int
egetopt(int nargc, char * const *nargv, const char *ostr)
{
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
static int delim; /* which option delimiter */
char *p;
static char savec = '\0';
if (savec != '\0') {
*place = savec;
savec = '\0';
}
if (!*place) {
/*
* update scanning pointer
*/
if ((eoptind >= nargc) ||
((*(place = nargv[eoptind]) != '-') && (*place != '+'))) {
place = EMSG;
return (-1);
}
delim = (int)*place;
if (place[1] && *++place == '-' && !place[1]) {
/*
* found "--"
*/
++eoptind;
place = EMSG;
return (-1);
}
}
/*
* check option letter
*/
if ((eoptopt = (int)*place++) == (int)':' || (eoptopt == (int)'?') ||
!(oli = strchr(ostr, eoptopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1 when by itself.
*/
if ((eoptopt == (int)'-') && !*place)
return (-1);
if (strchr(ostr, '#') && (isdigit(eoptopt) ||
(((eoptopt == (int)'-') || (eoptopt == (int)'+')) &&
isdigit((unsigned char)*place)))) {
/*
* # option: +/- with a number is ok
*/
for (p = place; *p != '\0'; ++p) {
if (!isdigit((unsigned char)*p))
break;
}
eoptarg = place-1;
if (*p == '\0') {
place = EMSG;
++eoptind;
} else {
place = p;
savec = *p;
*place = '\0';
}
return (delim);
}
if (!*place)
++eoptind;
if (eopterr) {
if (!(p = strrchr(*nargv, '/')))
p = *nargv;
else
++p;
(void)fprintf(stderr, "%s: illegal option -- %c\n",
p, eoptopt);
}
return (BADCH);
}
if (delim == (int)'+') {
/*
* '+' is only allowed with numbers
*/
if (!*place)
++eoptind;
if (eopterr) {
if (!(p = strrchr(*nargv, '/')))
p = *nargv;
else
++p;
(void)fprintf(stderr,
"%s: illegal '+' delimiter with option -- %c\n",
p, eoptopt);
}
return (BADCH);
}
++oli;
if ((*oli != ':') && (*oli != '?')) {
/*
* don't need argument
*/
eoptarg = NULL;
if (!*place)
++eoptind;
return (eoptopt);
}
if (*place) {
/*
* no white space
*/
eoptarg = place;
} else if (*oli == '?') {
/*
* no arg, but NOT required
*/
eoptarg = NULL;
} else if (nargc <= ++eoptind) {
/*
* no arg, but IS required
*/
place = EMSG;
if (eopterr) {
if (!(p = strrchr(*nargv, '/')))
p = *nargv;
else
++p;
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n", p,
eoptopt);
}
return (BADCH);
} else {
/*
* arg has white space
*/
eoptarg = nargv[eoptind];
}
place = EMSG;
++eoptind;
return (eoptopt);
}

42
usr.bin/pr/extern.h Normal file
View file

@ -0,0 +1,42 @@
/* $NetBSD: extern.h,v 1.6 2011/09/06 18:26:06 joerg Exp $ */
/*-
* Copyright (c) 1991 Keith Muller.
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)extern.h 8.1 (Berkeley) 6/6/93
* $NetBSD: extern.h,v 1.6 2011/09/06 18:26:06 joerg Exp $
*/
extern int eoptind;
extern char *eoptarg;
int egetopt(int, char * const *, const char *);

361
usr.bin/pr/pr.1 Normal file
View file

@ -0,0 +1,361 @@
.\" $NetBSD: pr.1,v 1.22 2012/08/01 02:36:17 ginsbach Exp $
.\"
.\" Copyright (c) 1991 Keith Muller.
.\" Copyright (c) 1993
.\" The Regents of the University of California. All rights reserved.
.\" Copyright (c) 1994-1995, 1997, 1999-2003, 2009, 2012
.\" The NetBSD Foundation, Inc.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Keith Muller of the University of California, San Diego.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)pr.1 8.1 (Berkeley) 6/6/93
.\"
.Dd July 31, 2012
.Dt PR 1
.Os
.Sh NAME
.Nm pr
.Nd print files
.Sh SYNOPSIS
.Nm
.Op Ar \&+page
.Op Fl Ar column
.Op Fl adFfmprt
.Oo
.Fl e Ns Oo Ar char Oc Ns Op Ar gap
.Oc
.Op Fl h Ar header
.Oo
.Fl i Ns Oo Ar char Oc Ns Op Ar gap
.Oc
.Op Fl l Ar lines
.Oo
.Fl n Ns Oo Ar char Oc Ns Op Ar width
.Oc
.Op Fl o Ar offset
.Oo
.Fl s Ns Op Ar char
.Oc
.Op Fl T Ar timefmt
.Op Fl w Ar width
.Op -
.Op Ar file ...
.Sh DESCRIPTION
The
.Nm
utility is a printing and pagination filter for text files.
When multiple input files are specified, each is read, formatted,
and written to standard output.
By default, the input is separated into 66-line pages, each with
.Bl -bullet
.It
A 5-line header with the page number, date, time, and
the pathname of the file.
.It
A 5-line trailer consisting of blank lines.
.El
.Pp
If standard output is associated with a terminal,
diagnostic messages are suppressed until the
.Nm
utility has completed processing.
.Pp
When multiple column output is specified,
text columns are of equal width.
By default text columns are separated by at least one
.Aq Em blank .
Input lines that do not fit into a text column are truncated.
Lines are not truncated under single column output.
.Sh OPTIONS
In the following option descriptions, column, lines, offset, page, and
width are positive decimal integers and gap is a nonnegative decimal integer.
.Bl -tag -width 4n
.It Ar \&+page
Begin output at page number
.Ar page
of the formatted input.
.It Fl Ar column
Produce output that is
.Ar columns
wide (default is 1) that is written vertically
down each column in the order in which the text
is received from the input file.
The options
.Fl e
and
.Fl i
are assumed.
This option should not be used with
.Fl m .
When used with
.Fl t ,
the minimum number of lines is used to display the output.
.It Fl a
Modify the effect of the
.Fl column
option so that the columns are filled across the page in a round-robin order
(e.g., when column is 2, the first input line heads column
1, the second heads column 2, the third is the second line
in column 1, etc.).
This option requires the use of the
.Fl column
option.
.It Fl d
Produce output that is double spaced.
An extra
.Aq Em newline
character is output following every
.Aq newline
found in the input.
.It Fl e Ns Oo Ar char Oc Ns Op Ar gap
Expand each input
.Aq tab
to the next greater column
position specified by the formula
.Ar n*gap+1 ,
where
.Em n
is an integer \*[Gt] 0.
If
.Ar gap
is zero or is omitted the default is 8.
All
.Aq Em tab
characters in the input are expanded into the appropriate
number of
.Ao Em space Ac Ns s .
If any nondigit character,
.Ar char ,
is specified, it is used as the input tab character.
If the first character of
.Ar char
is a digit then
.Ar char
is treated as
.Ar gap .
.It Fl F
Use a
.Aq Em form-feed
character for new pages,
instead of the default behavior that uses a
sequence of
.Aq Em newline
characters.
.It Fl f
Same as
.Fl F .
Additionally pause before beginning the first page
if the standard output is associated with a terminal.
.It Fl h Ar header
Use the string
.Ar header
to replace the
.Ar file name
in the header line.
.It Fl i Ns Oo Ar char Oc Ns Op Ar gap
In output, replace multiple
.Ao space Ac Ns s
with
.Ao tab Ac Ns s
whenever two or more
adjacent
.Ao space Ac Ns s
reach column positions
.Ar gap+1 ,
.Ar 2*gap+1 ,
etc.
If
.Ar gap
is zero or omitted, default
.Aq Em tab
settings at every eighth column position
is used.
If any nondigit character,
.Ar char ,
is specified, it is used as the output
.Aq Em tab
character.
If the first character of
.Ar char
is a digit then
.Ar char
is treated as
.Ar gap .
.It Fl l Ar lines
Override the 66 line default and reset the page length to
.Ar lines .
If
.Ar lines
is not greater than the sum of both the header and trailer
depths (in lines), the
.Nm
utility suppresses output of both the header and trailer, as if the
.Fl t
option were in effect.
.It Fl m
Merge the contents of multiple files.
One line from each file specified by a file operand is
written side by side into text columns of equal fixed widths, in
terms of the number of column positions.
The number of text columns depends on the number of
file operands successfully opened.
The maximum number of files merged depends on page width and the
per process open file limit.
The options
.Fl e
and
.Fl i
are assumed.
.It Fl n Ns Oo Ar char Oc Ns Op Ar width
Provide
.Ar width
digit line numbering.
The default for
.Ar width ,
if not specified, is 5.
The number occupies the first
.Ar width
column positions of each text column or each line of
.Fl m
output.
If
.Ar char
(any nondigit character) is given, it is appended to the line number to
separate it from whatever follows.
The default for
.Ar char
is a
.Aq Em tab .
Line numbers longer than
.Ar width
columns are truncated.
.It Fl o Ar offset
Each line of output is preceded by
.Ar offset
.Ao Em space Ac Ns s .
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 associated with a terminal.
.Nm
will write an
.Aq Em alert
to standard error and wait for a
.Aq Em carriage-return
to be read on
.Pa /dev/tty .
.It Fl r
Write no diagnostic reports on failure to open a file.
.It Fl s Ns Op Ar char
Separate text columns by the single character
.Ar char
instead of by the appropriate number of
.Ao Em space Ac Ns s
(default for
.Ar char
is the
.Aq Em tab
character).
.It Fl T
Specify an
.Xr strftime 3
format string to be used to format the date and time information in the page
header.
.It Fl t
Print neither the five-line identifying
header nor the five-line trailer usually supplied for each page.
Quit printing after the last line of each file without spacing to the
end of the page.
.It Fl w Ar width
Set the width of the line to
.Ar width
column positions for multiple text-column output only.
If the
.Fl w
option is not specified and the
.Fl s
option is not specified, the default width is 72.
If the
.Fl w
option is not specified and the
.Fl s
option is specified, the default width is 512.
.It Ar file
A pathname of a file to be printed.
If no
.Ar file
operands are specified, or if a
.Ar file
operand is
.Sq Fl ,
the standard input is used.
The standard input is used only if no
.Ar file
operands are specified, or if a
.Ar file
operand is
.Sq Fl .
.El
.Pp
The
.Fl s
option does not allow the option letter to be separated from its
argument, and the options
.Fl e ,
.Fl i ,
and
.Fl n
require that both arguments, if present, not be separated from the option
letter.
.Sh ERRORS
If
.Nm
receives an interrupt while printing to a terminal, it
flushes all accumulated error messages to the screen before
terminating.
.Pp
The
.Nm
utility exits 0 on success, and 1 if an error occurs.
.Pp
Error messages are written to standard error during the printing
process (if output is redirected) or after all successful
file printing is complete (when printing to a terminal).
.Sh SEE ALSO
.Xr cat 1 ,
.Xr more 1 ,
.Xr strftime 3
.Sh STANDARDS
The
.Nm
utility is
.St -p1003.1-2008
compatible.

1901
usr.bin/pr/pr.c Normal file

File diff suppressed because it is too large Load diff

79
usr.bin/pr/pr.h Normal file
View file

@ -0,0 +1,79 @@
/* $NetBSD: pr.h,v 1.5 2012/07/24 02:13:04 ginsbach Exp $ */
/*-
* Copyright (c) 1991 Keith Muller.
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
* Copyright (c) 2012
* The NetBSD Foundation, Inc.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)pr.h 8.1 (Berkeley) 6/6/93
* $NetBSD: pr.h,v 1.5 2012/07/24 02:13:04 ginsbach Exp $
*/
/*
* parameter defaults
*/
#define CLCNT 1
#define INCHAR '\t'
#define INGAP 8
#define OCHAR '\t'
#define OGAP 8
#define LINES 66
#define NMWD 5
#define NMCHAR '\t'
#define SCHAR '\t'
#define PGWD 72
#define SPGWD 512
/*
* misc default values
*/
#define HDFMT "%s %s Page %d\n\n\n"
#define HEADLEN 5
#define TAILLEN 5
#define TIMEFMT "%b %e %H:%M %Y"
#define FNAME ""
#define LBUF 8192
#define HDBUF 512
/* when to pause before (for -f and -p options) */
#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 {
char *pt; /* ptr to col */
int cnt; /* char count */
};