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 + -
显示快捷键?