version 1.11, 2001/11/02 16:25:02 |
version 1.12, 2001/11/19 03:37:33 |
|
|
#include <errno.h> |
#include <errno.h> |
#include <signal.h> |
#include <signal.h> |
#include <stdio.h> |
#include <stdio.h> |
|
#include <stdarg.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include <unistd.h> |
#include <unistd.h> |
|
|
* bugs were noted and fixed in the processs. Some implementations have this |
* bugs were noted and fixed in the processs. Some implementations have this |
* as the as -f, some as -F so we accept either. |
* as the as -f, some as -F so we accept either. |
* |
* |
* The impelmentation of form feeds on top of the existing I/O structure is |
* The implementation of form feeds on top of the existing I/O structure is |
* a bit ideosyncratic. Basically they are treated as temporary end-of-file |
* a bit ideosyncratic. Basically they are treated as temporary end-of-file |
* conditions and an additional level of "loop on form feed" is added to each |
* conditions and an additional level of "loop on form feed" is added to each |
* of the output modes to continue after such a transient end-of-file's. This |
* of the output modes to continue after such a transient end-of-file's. This |
|
|
/* |
/* |
* misc globals |
* misc globals |
*/ |
*/ |
FILE *ferr; /* error message file pointer */ |
int ferr; /* error message delayed */ |
int addone = 0; /* page length is odd with double space */ |
int addone = 0; /* page length is odd with double space */ |
int errcnt = 0; /* error count on file processing */ |
int errcnt = 0; /* error count on file processing */ |
int beheaded = 0; /* header / trailer link */ |
int beheaded = 0; /* header / trailer link */ |
|
|
return(0); |
return(0); |
} |
} |
|
|
|
struct ferrlist { |
|
struct ferrlist *next; |
|
char *buf; |
|
}; |
|
struct ferrlist *ferrhead, *ferrtail; |
|
|
/* |
/* |
|
* flsh_errs(): output saved up diagnostic messages after all normal |
|
* processing has completed |
|
*/ |
|
void |
|
flsh_errs() |
|
{ |
|
struct ferrlist *f; |
|
|
|
if (ferr) { |
|
for (f = ferrhead; f; f = f->next) |
|
(void)write(STDERR_FILENO, f->buf, strlen(f->buf)); |
|
} |
|
} |
|
|
|
void |
|
ferrout(char *fmt, ...) |
|
{ |
|
sigset_t block, oblock; |
|
struct ferrlist *f; |
|
va_list ap; |
|
char *p; |
|
|
|
va_start(ap, fmt); |
|
if (ferr == NULL) |
|
vfprintf(stderr, fmt, ap); |
|
else { |
|
sigemptyset(&block); |
|
sigaddset(&block, SIGINT); |
|
sigprocmask(SIG_BLOCK, &block, &oblock); |
|
|
|
vasprintf(&p, fmt, ap); |
|
f = (struct ferrlist *)malloc(sizeof(*f)); |
|
f->next = NULL; |
|
f->buf = p; |
|
if (ferrhead == NULL) |
|
ferrhead = f; |
|
if (ferrtail) |
|
ferrtail->next = f; |
|
ferrtail = f; |
|
sigprocmask(SIG_SETMASK, &oblock, NULL); |
|
} |
|
} |
|
|
|
/* |
* mulfile: print files with more than one column of output and |
* mulfile: print files with more than one column of output and |
* more than one file concurrently |
* more than one file concurrently |
*/ |
*/ |
|
|
pgwd = ((colwd + 1) * clcnt) - 1; |
pgwd = ((colwd + 1) * clcnt) - 1; |
} |
} |
if (colwd < 1) { |
if (colwd < 1) { |
(void)fprintf(ferr, |
ferrout("pr: page width too small for %d columns\n", clcnt); |
"pr: page width too small for %d columns\n", clcnt); |
|
return(1); |
return(1); |
} |
} |
col = colwd + 1; |
col = colwd + 1; |
|
|
return(inf); |
return(inf); |
if (gettimeofday(&tv, &tz) < 0) { |
if (gettimeofday(&tv, &tz) < 0) { |
++errcnt; |
++errcnt; |
(void)fprintf(ferr, "pr: cannot get time of day, %s\n", |
ferrout("pr: cannot get time of day, %s\n", |
strerror(errno)); |
strerror(errno)); |
eoptind = argc - 1; |
eoptind = argc - 1; |
return(NULL); |
return(NULL); |
|
|
return(inf); |
return(inf); |
if (gettimeofday(&tv, &tz) < 0) { |
if (gettimeofday(&tv, &tz) < 0) { |
++errcnt; |
++errcnt; |
(void)fprintf(ferr, |
ferrout("pr: cannot get time of day, %s\n", |
"pr: cannot get time of day, %s\n", |
|
strerror(errno)); |
strerror(errno)); |
return(NULL); |
return(NULL); |
} |
} |
|
|
++errcnt; |
++errcnt; |
if (nodiag) |
if (nodiag) |
continue; |
continue; |
(void)fprintf(ferr, "pr: Cannot open %s, %s\n", |
ferrout("pr: Cannot open %s, %s\n", |
argv[eoptind], strerror(errno)); |
argv[eoptind], strerror(errno)); |
continue; |
continue; |
} |
} |
|
|
if (dt) { |
if (dt) { |
if (gettimeofday(&tv, &tz) < 0) { |
if (gettimeofday(&tv, &tz) < 0) { |
++errcnt; |
++errcnt; |
(void)fprintf(ferr, |
ferrout("pr: cannot get time of day, %s\n", |
"pr: cannot get time of day, %s\n", |
|
strerror(errno)); |
strerror(errno)); |
return(NULL); |
return(NULL); |
} |
} |
|
|
if (fstat(fileno(inf), &statbuf) < 0) { |
if (fstat(fileno(inf), &statbuf) < 0) { |
++errcnt; |
++errcnt; |
(void)fclose(inf); |
(void)fclose(inf); |
(void)fprintf(ferr, |
ferrout("pr: Cannot stat %s, %s\n", |
"pr: Cannot stat %s, %s\n", |
|
argv[eoptind], strerror(errno)); |
argv[eoptind], strerror(errno)); |
return(NULL); |
return(NULL); |
} |
} |
|
|
++errcnt; |
++errcnt; |
if (inf != stdin) |
if (inf != stdin) |
(void)fclose(inf); |
(void)fclose(inf); |
(void)fputs("pr: time conversion failed\n", ferr); |
ferrout("pr: time conversion failed\n"); |
return(NULL); |
return(NULL); |
} |
} |
return(inf); |
return(inf); |
|
|
terminate(which_sig) |
terminate(which_sig) |
int which_sig; |
int which_sig; |
{ |
{ |
flsh_errs(); /* XXX signal race */ |
flsh_errs(); |
_exit(1); |
_exit(1); |
} |
} |
|
|
|
|
/* |
|
* flsh_errs(): output saved up diagnostic messages after all normal |
|
* processing has completed |
|
*/ |
|
void |
void |
flsh_errs() |
|
{ |
|
char buf[BUFSIZ]; |
|
|
|
(void)fflush(stdout); |
|
(void)fflush(ferr); |
|
if (ferr == stderr) |
|
return; |
|
rewind(ferr); |
|
while (fgets(buf, BUFSIZ, ferr) != NULL) |
|
(void)fputs(buf, stderr); |
|
} |
|
|
|
void |
|
mfail() |
mfail() |
{ |
{ |
(void)fputs("pr: memory allocation failed\n", ferr); |
ferrout("pr: memory allocation failed\n"); |
} |
} |
|
|
void |
void |
pfail() |
pfail() |
{ |
{ |
(void)fprintf(ferr, "pr: write failure, %s\n", strerror(errno)); |
ferrout("pr: write failure, %s\n", strerror(errno)); |
} |
} |
|
|
void |
void |
usage() |
usage() |
{ |
{ |
(void)fputs( |
ferrout( |
"usage: pr [+page] [-col] [-adfFmrt] [-e[ch][gap]] [-h header]\n", ferr); |
"usage: pr [+page] [-col] [-adfFmrt] [-e[ch][gap]] [-h header]\n"); |
(void)fputs( |
ferrout( |
" [-i[ch][gap]] [-l line] [-n[ch][width]] [-o offset]\n", ferr); |
" [-i[ch][gap]] [-l line] [-n[ch][width]] [-o offset]\n"); |
(void)fputs( |
ferrout( |
" [-s[ch]] [-w width] [-] [file ...]\n", ferr); |
" [-s[ch]] [-w width] [-] [file ...]\n", ferr); |
} |
} |
|
|
|
|
int wflag = 0; |
int wflag = 0; |
int cflag = 0; |
int cflag = 0; |
|
|
if (isatty(fileno(stdout))) { |
if (isatty(fileno(stdout))) |
/* |
ferr = 1; |
* defer diagnostics until processing is done |
|
*/ |
|
if ((ferr = tmpfile()) == NULL) { |
|
(void)fputs("Cannot defer diagnostic messages\n",stderr); |
|
return(1); |
|
} |
|
} else |
|
ferr = stderr; |
|
while ((c = egetopt(argc, argv, "#adfFmrte?h:i?l:n?o:s?w:")) != -1) { |
while ((c = egetopt(argc, argv, "#adfFmrte?h:i?l:n?o:s?w:")) != -1) { |
switch (c) { |
switch (c) { |
case '+': |
case '+': |
if ((pgnm = atoi(eoptarg)) < 1) { |
if ((pgnm = atoi(eoptarg)) < 1) { |
(void)fputs("pr: +page number must be 1 or more\n", |
ferrout("pr: +page number must be 1 or more\n"); |
ferr); |
|
return(1); |
return(1); |
} |
} |
++skipping; |
++skipping; |
break; |
break; |
case '-': |
case '-': |
if ((clcnt = atoi(eoptarg)) < 1) { |
if ((clcnt = atoi(eoptarg)) < 1) { |
(void)fputs("pr: -columns must be 1 or more\n",ferr); |
ferrout("pr: -columns must be 1 or more\n"); |
return(1); |
return(1); |
} |
} |
if (clcnt > 1) |
if (clcnt > 1) |
|
|
inchar = INCHAR; |
inchar = INCHAR; |
if ((eoptarg != NULL) && isdigit(*eoptarg)) { |
if ((eoptarg != NULL) && isdigit(*eoptarg)) { |
if ((ingap = atoi(eoptarg)) < 0) { |
if ((ingap = atoi(eoptarg)) < 0) { |
(void)fputs( |
ferrout("pr: -e gap must be 0 or more\n"); |
"pr: -e gap must be 0 or more\n", ferr); |
|
return(1); |
return(1); |
} |
} |
if (ingap == 0) |
if (ingap == 0) |
ingap = INGAP; |
ingap = INGAP; |
} else if ((eoptarg != NULL) && (*eoptarg != '\0')) { |
} else if ((eoptarg != NULL) && (*eoptarg != '\0')) { |
(void)fprintf(ferr, |
ferrout("pr: invalid value for -e %s\n", eoptarg); |
"pr: invalid value for -e %s\n", eoptarg); |
|
return(1); |
return(1); |
} else |
} else |
ingap = INGAP; |
ingap = INGAP; |
|
|
ochar = OCHAR; |
ochar = OCHAR; |
if ((eoptarg != NULL) && isdigit(*eoptarg)) { |
if ((eoptarg != NULL) && isdigit(*eoptarg)) { |
if ((ogap = atoi(eoptarg)) < 0) { |
if ((ogap = atoi(eoptarg)) < 0) { |
(void)fputs( |
ferrout("pr: -i gap must be 0 or more\n"); |
"pr: -i gap must be 0 or more\n", ferr); |
|
return(1); |
return(1); |
} |
} |
if (ogap == 0) |
if (ogap == 0) |
ogap = OGAP; |
ogap = OGAP; |
} else if ((eoptarg != NULL) && (*eoptarg != '\0')) { |
} else if ((eoptarg != NULL) && (*eoptarg != '\0')) { |
(void)fprintf(ferr, |
ferrout("pr: invalid value for -i %s\n", eoptarg); |
"pr: invalid value for -i %s\n", eoptarg); |
|
return(1); |
return(1); |
} else |
} else |
ogap = OGAP; |
ogap = OGAP; |
break; |
break; |
case 'l': |
case 'l': |
if (!isdigit(*eoptarg) || ((lines=atoi(eoptarg)) < 1)) { |
if (!isdigit(*eoptarg) || ((lines=atoi(eoptarg)) < 1)) { |
(void)fputs( |
ferrout("pr: Number of lines must be 1 or more\n"); |
"pr: Number of lines must be 1 or more\n",ferr); |
|
return(1); |
return(1); |
} |
} |
break; |
break; |
|
|
nmchar = NMCHAR; |
nmchar = NMCHAR; |
if ((eoptarg != NULL) && isdigit(*eoptarg)) { |
if ((eoptarg != NULL) && isdigit(*eoptarg)) { |
if ((nmwd = atoi(eoptarg)) < 1) { |
if ((nmwd = atoi(eoptarg)) < 1) { |
(void)fputs( |
ferrout("pr: -n width must be 1 or more\n"); |
"pr: -n width must be 1 or more\n",ferr); |
|
return(1); |
return(1); |
} |
} |
} else if ((eoptarg != NULL) && (*eoptarg != '\0')) { |
} else if ((eoptarg != NULL) && (*eoptarg != '\0')) { |
(void)fprintf(ferr, |
ferrout("pr: invalid value for -n %s\n", eoptarg); |
"pr: invalid value for -n %s\n", eoptarg); |
|
return(1); |
return(1); |
} else |
} else |
nmwd = NMWD; |
nmwd = NMWD; |
break; |
break; |
case 'o': |
case 'o': |
if (!isdigit(*eoptarg) || ((offst = atoi(eoptarg))< 1)){ |
if (!isdigit(*eoptarg) || ((offst = atoi(eoptarg))< 1)){ |
(void)fputs("pr: -o offset must be 1 or more\n", |
ferrout("pr: -o offset must be 1 or more\n"); |
ferr); |
|
return(1); |
return(1); |
} |
} |
break; |
break; |
|
|
else { |
else { |
schar = *eoptarg++; |
schar = *eoptarg++; |
if (*eoptarg != '\0') { |
if (*eoptarg != '\0') { |
(void)fprintf(ferr, |
ferrout("pr: invalid value for -s %s\n", eoptarg); |
"pr: invalid value for -s %s\n", eoptarg); |
|
return(1); |
return(1); |
} |
} |
} |
} |
|
|
case 'w': |
case 'w': |
++wflag; |
++wflag; |
if (!isdigit(*eoptarg) || ((pgwd = atoi(eoptarg)) < 1)){ |
if (!isdigit(*eoptarg) || ((pgwd = atoi(eoptarg)) < 1)){ |
(void)fputs( |
ferrout("pr: -w width must be 1 or more \n"); |
"pr: -w width must be 1 or more \n",ferr); |
|
return(1); |
return(1); |
} |
} |
break; |
break; |
|
|
} |
} |
if (across) { |
if (across) { |
if (clcnt == 1) { |
if (clcnt == 1) { |
(void)fputs("pr: -a flag requires multiple columns\n", |
ferrout("pr: -a flag requires multiple columns\n"); |
ferr); |
|
return(1); |
return(1); |
} |
} |
if (merge) { |
if (merge) { |
(void)fputs("pr: -m cannot be used with -a\n", ferr); |
ferrout("pr: -m cannot be used with -a\n"); |
return(1); |
return(1); |
} |
} |
} |
} |
|
|
} |
} |
if (cflag) { |
if (cflag) { |
if (merge) { |
if (merge) { |
(void)fputs( |
ferrout("pr: -m cannot be used with multiple columns\n"); |
"pr: -m cannot be used with multiple columns\n", ferr); |
|
return(1); |
return(1); |
} |
} |
if (nmwd) { |
if (nmwd) { |
|
|
pgwd = ((colwd + 1) * clcnt) - 1; |
pgwd = ((colwd + 1) * clcnt) - 1; |
} |
} |
if (colwd < 1) { |
if (colwd < 1) { |
(void)fprintf(ferr, |
ferrout("pr: page width is too small for %d columns\n",clcnt); |
"pr: page width is too small for %d columns\n",clcnt); |
|
return(1); |
return(1); |
} |
} |
} |
} |