pr.c
来自「早期freebsd实现」· C语言 代码 · 共 1,805 行 · 第 1/3 页
C
1,805 行
} return(0);}/* * inskip(): skip over pgcnt pages with lncnt lines per page * file is closed at EOF (if not stdin). * * inf FILE * to read from * pgcnt number of pages to skip * lncnt number of lines per page */intinskip(inf, pgcnt, lncnt) FILE *inf; register int pgcnt; register int lncnt;{ register int c; register int cnt; while(--pgcnt > 0) { cnt = lncnt; while ((c = getc(inf)) != EOF) { if ((c == '\n') && (--cnt == 0)) break; } if (c == EOF) { if (inf != stdin) (void)fclose(inf); return(1); } } return(0);}/* * nxtfile: returns a FILE * to next file in arg list and sets the * time field for this file (or current date). * * buf array to store proper date for the header. * dt if set skips the date processing (used with -m) */FILE *nxtfile(argc, argv, fname, buf, dt) int argc; char **argv; char **fname; char *buf; int dt;{ FILE *inf = NULL; struct timeval tv; struct timezone tz; struct tm *timeptr = NULL; struct stat statbuf; static int twice = -1; ++twice; if (eoptind >= argc) { /* * no file listed; default, use standard input */ if (twice) return(NULL); clearerr(stdin); inf = stdin; if (header != NULL) *fname = header; else *fname = FNAME; if (nohead) return(inf); if (gettimeofday(&tv, &tz) < 0) { ++errcnt; (void)fprintf(err, "pr: cannot get time of day, %s\n", strerror(errno)); eoptind = argc - 1; return(NULL); } timeptr = localtime(&(tv.tv_sec)); } for (; eoptind < argc; ++eoptind) { if (strcmp(argv[eoptind], "-") == 0) { /* * process a "-" for filename */ clearerr(stdin); inf = stdin; if (header != NULL) *fname = header; else *fname = FNAME; ++eoptind; if (nohead || (dt && twice)) return(inf); if (gettimeofday(&tv, &tz) < 0) { ++errcnt; (void)fprintf(err, "pr: cannot get time of day, %s\n", strerror(errno)); return(NULL); } timeptr = localtime(&(tv.tv_sec)); } else { /* * normal file processing */ if ((inf = fopen(argv[eoptind], "r")) == NULL) { ++errcnt; if (nodiag) continue; (void)fprintf(err, "pr: Cannot open %s, %s\n", argv[eoptind], strerror(errno)); continue; } if (header != NULL) *fname = header; else if (dt) *fname = FNAME; else *fname = argv[eoptind]; ++eoptind; if (nohead || (dt && twice)) return(inf); if (dt) { if (gettimeofday(&tv, &tz) < 0) { ++errcnt; (void)fprintf(err, "pr: cannot get time of day, %s\n", strerror(errno)); return(NULL); } timeptr = localtime(&(tv.tv_sec)); } else { if (fstat(fileno(inf), &statbuf) < 0) { ++errcnt; (void)fclose(inf); (void)fprintf(err, "pr: Cannot stat %s, %s\n", argv[eoptind], strerror(errno)); return(NULL); } timeptr = localtime(&(statbuf.st_mtime)); } } break; } if (inf == NULL) return(NULL); /* * set up time field used in header */ if (strftime(buf, HDBUF, timefrmt, timeptr) <= 0) { ++errcnt; if (inf != stdin) (void)fclose(inf); (void)fputs("pr: time conversion failed\n", err); return(NULL); } return(inf);}/* * addnum(): adds the line number to the column * Truncates from the front or pads with spaces as required. * Numbers are right justified. * * buf buffer to store the number * wdth width of buffer to fill * line line number * * NOTE: numbers occupy part of the column. The posix * spec does not specify if -i processing should or should not * occur on number padding. The spec does say it occupies * part of the column. The usage of addnum currently treats * numbers as part of the column so spaces may be replaced. */voidaddnum(buf, wdth, line) register char *buf; register int wdth; register int line;{ register char *pt = buf + wdth; do { *--pt = digs[line % 10]; line /= 10; } while (line && (pt > buf)); /* * pad with space as required */ while (pt > buf) *--pt = ' ';}/* * prhead(): prints the top of page header * * buf buffer with time field (and offset) * cnt number of chars in buf * fname fname field for header * pagcnt page number */intprhead(buf, fname, pagcnt) char *buf; char *fname; int pagcnt;{ int ips = 0; int ops = 0; if ((putchar('\n') == EOF) || (putchar('\n') == EOF)) { pfail(); return(1); } /* * posix is not clear if the header is subject to line length * restrictions. The specification for header line format * in the spec clearly does not limit length. No pr currently * restricts header length. However if we need to truncate in * an reasonable way, adjust the length of the printf by * changing HDFMT to allow a length max as an arguement printf. * buf (which contains the offset spaces and time field could * also be trimmed * * note only the offset (if any) is processed for tab expansion */ if (offst && otln(buf, offst, &ips, &ops, -1)) return(1); (void)printf(HDFMT,buf+offst, fname, pagcnt); return(0);}/* * prtail(): pad page with empty lines (if required) and print page trailer * if requested * * cnt number of lines of padding needed * incomp was a '\n' missing from last line output */intprtail(cnt, incomp) register int cnt; int incomp;{ if (nohead) { /* * only pad with no headers when incomplete last line */ if (!incomp) return(0); if ((dspace && (putchar('\n') == EOF)) || (putchar('\n') == EOF)) { pfail(); return(1); } return(0); } /* * if double space output two \n */ if (dspace) cnt *= 2; /* * if an odd number of lines per page, add an extra \n */ if (addone) ++cnt; /* * pad page */ if (formfeed) { if ((incomp && (putchar('\n') == EOF)) || (putchar('\f') == EOF)) { pfail(); return(1); } return(0); } cnt += TAILLEN; while (--cnt >= 0) { if (putchar('\n') == EOF) { pfail(); return(1); } } return(0);}/* * terminate(): when a SIGINT is recvd */voidterminate(which_sig) int which_sig;{ flsh_errs(); exit(1);}/* * flsh_errs(): output saved up diagnostic messages after all normal * processing has completed */voidflsh_errs(){ char buf[BUFSIZ]; (void)fflush(stdout); (void)fflush(err); if (err == stderr) return; rewind(err); while (fgets(buf, BUFSIZ, err) != NULL) (void)fputs(buf, stderr);}voidmfail(){ (void)fputs("pr: memory allocation failed\n", err);}voidpfail(){ (void)fprintf(err, "pr: write failure, %s\n", strerror(errno));}voidusage(){ (void)fputs( "usage: pr [+page] [-col] [-adFmrt] [-e[ch][gap]] [-h header]\n",err); (void)fputs( " [-i[ch][gap]] [-l line] [-n[ch][width]] [-o offset]\n",err); (void)fputs( " [-s[ch]] [-w width] [-] [file ...]\n", err);}/* * setup: Validate command args, initialize and perform sanity * checks on options */intsetup(argc, argv) register int argc; register char **argv;{ register int c; int eflag = 0; int iflag = 0; int wflag = 0; int cflag = 0; if (isatty(fileno(stdout))) { /* * defer diagnostics until processing is done */ if ((err = tmpfile()) == NULL) { (void)fputs("Cannot defer diagnostic messages\n",stderr); return(1); } } else err = stderr; while ((c = egetopt(argc, argv, "#adFmrte?h:i?l:n?o:s?w:")) != EOF) { switch (c) { case '+': if ((pgnm = atoi(eoptarg)) < 1) { (void)fputs("pr: +page number must be 1 or more\n", err); return(1); } break; case '-': if ((clcnt = atoi(eoptarg)) < 1) { (void)fputs("pr: -columns must be 1 or more\n",err); return(1); } if (clcnt > 1) ++cflag; break; case 'a': ++across; break; case 'd': ++dspace; break; case 'e': ++eflag; if ((eoptarg != NULL) && !isdigit(*eoptarg)) inchar = *eoptarg++; else inchar = INCHAR; if ((eoptarg != NULL) && isdigit(*eoptarg)) { if ((ingap = atoi(eoptarg)) < 0) { (void)fputs( "pr: -e gap must be 0 or more\n", err); return(1); } if (ingap == 0) ingap = INGAP; } else if ((eoptarg != NULL) && (*eoptarg != '\0')) { (void)fprintf(err, "pr: invalid value for -e %s\n", eoptarg); return(1); } else ingap = INGAP; break; case 'F': ++formfeed; break; case 'h': header = eoptarg; break; case 'i': ++iflag; if ((eoptarg != NULL) && !isdigit(*eoptarg)) ochar = *eoptarg++; else ochar = OCHAR; if ((eoptarg != NULL) && isdigit(*eoptarg)) { if ((ogap = atoi(eoptarg)) < 0) { (void)fputs( "pr: -i gap must be 0 or more\n", err); return(1); } if (ogap == 0) ogap = OGAP; } else if ((eoptarg != NULL) && (*eoptarg != '\0')) { (void)fprintf(err, "pr: invalid value for -i %s\n", eoptarg); return(1); } else ogap = OGAP; break; case 'l': if (!isdigit(*eoptarg) || ((lines=atoi(eoptarg)) < 1)) { (void)fputs( "pr: Number of lines must be 1 or more\n",err); return(1); } break; case 'm': ++merge; break; case 'n': if ((eoptarg != NULL) && !isdigit(*eoptarg)) nmchar = *eoptarg++; else nmchar = NMCHAR; if ((eoptarg != NULL) && isdigit(*eoptarg)) { if ((nmwd = atoi(eoptarg)) < 1) { (void)fputs( "pr: -n width must be 1 or more\n",err); return(1); } } else if ((eoptarg != NULL) && (*eoptarg != '\0')) { (void)fprintf(err, "pr: invalid value for -n %s\n", eoptarg); return(1); } else nmwd = NMWD; break; case 'o': if (!isdigit(*eoptarg) || ((offst = atoi(eoptarg))< 1)){ (void)fputs("pr: -o offset must be 1 or more\n", err); return(1); } break; case 'r': ++nodiag; break; case 's': ++sflag; if (eoptarg == NULL) schar = SCHAR; else schar = *eoptarg++; if (*eoptarg != '\0') { (void)fprintf(err, "pr: invalid value for -s %s\n", eoptarg); return(1); } break; case 't': ++nohead; break; case 'w': ++wflag; if (!isdigit(*eoptarg) || ((pgwd = atoi(eoptarg)) < 1)){ (void)fputs( "pr: -w width must be 1 or more \n",err); return(1); } break; case '?': default: return(1); } } /* * default and sanity checks */ if (!clcnt) { if (merge) { if ((clcnt = argc - eoptind) <= 1) { clcnt = CLCNT; merge = 0; } } else clcnt = CLCNT; } if (across) { if (clcnt == 1) { (void)fputs("pr: -a flag requires multiple columns\n", err); return(1); } if (merge) { (void)fputs("pr: -m cannot be used with -a\n", err); return(1); } } if (!wflag) { if (sflag) pgwd = SPGWD; else pgwd = PGWD; } if (cflag || merge) { if (!eflag) { inchar = INCHAR; ingap = INGAP; } if (!iflag) { ochar = OCHAR; ogap = OGAP; } } if (cflag) { if (merge) { (void)fputs( "pr: -m cannot be used with multiple columns\n", err); return(1); } if (nmwd) { colwd = (pgwd + 1 - (clcnt * (nmwd + 2)))/clcnt; pgwd = ((colwd + nmwd + 2) * clcnt) - 1; } else { colwd = (pgwd + 1 - clcnt)/clcnt; pgwd = ((colwd + 1) * clcnt) - 1; } if (colwd < 1) { (void)fprintf(err, "pr: page width is too small for %d columns\n",clcnt); return(1); } } if (!lines) lines = LINES; /* * make sure long enough for headers. if not disable */ if (lines <= HEADLEN + TAILLEN) ++nohead; else if (!nohead) lines -= HEADLEN + TAILLEN; /* * adjust for double space on odd length pages */ if (dspace) { if (lines == 1) dspace = 0; else { if (lines & 1) ++addone; lines /= 2; } } if ((timefrmt = getenv("LC_TIME")) == NULL) timefrmt = TIMEFMT; return(0);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?