Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/head/head.c
Show All 35 Lines | |||||
#ifndef lint | #ifndef lint | ||||
#if 0 | #if 0 | ||||
static char sccsid[] = "@(#)head.c 8.2 (Berkeley) 5/4/95"; | static char sccsid[] = "@(#)head.c 8.2 (Berkeley) 5/4/95"; | ||||
#endif | #endif | ||||
#endif /* not lint */ | #endif /* not lint */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/capsicum.h> | |||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <capsicum_helpers.h> | |||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | |||||
#include <inttypes.h> | #include <inttypes.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
/* | /* | ||||
* head - give the first few lines of a stream or of each of a set of files | * head - give the first few lines of a stream or of each of a set of files | ||||
* | * | ||||
* Bill Joy UCB August 24, 1977 | * Bill Joy UCB August 24, 1977 | ||||
*/ | */ | ||||
static const char *abspath(const char *); | |||||
static void head(FILE *, int); | static void head(FILE *, int); | ||||
static void head_bytes(FILE *, off_t); | static void head_bytes(FILE *, off_t); | ||||
static void obsolete(char *[]); | static void obsolete(char *[]); | ||||
static void usage(void); | static void usage(void); | ||||
static char cwd[PATH_MAX]; | |||||
static size_t cwdlen; | |||||
int | int | ||||
main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||
{ | { | ||||
int ch; | int ch, rootfd, fd; | ||||
FILE *fp; | FILE *fp; | ||||
int first, linecnt = -1, eval = 0; | int first, linecnt = -1, eval = 0; | ||||
off_t bytecnt = -1; | off_t bytecnt = -1; | ||||
char *ep; | char *ep; | ||||
if (getcwd(cwd, sizeof(cwd)) == NULL) | |||||
err(1, "getcwd"); | |||||
cwdlen = strlen(cwd); | |||||
rootfd = open("/", O_RDONLY); | |||||
if (rootfd < 0) | |||||
err(1, "open"); | |||||
/* | |||||
* Cache NLS data, for strerror, for err(3), before entering capability | |||||
* mode. | |||||
*/ | |||||
caph_cache_catpages(); | |||||
if (caph_limit_stream(rootfd, CAPH_READ | CAPH_LOOKUP) < 0 || | |||||
caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS)) | |||||
err(1, "unable to enter capability mode"); | |||||
obsolete(argv); | obsolete(argv); | ||||
while ((ch = getopt(argc, argv, "n:c:")) != -1) | while ((ch = getopt(argc, argv, "n:c:")) != -1) | ||||
switch(ch) { | switch(ch) { | ||||
case 'c': | case 'c': | ||||
bytecnt = strtoimax(optarg, &ep, 10); | bytecnt = strtoimax(optarg, &ep, 10); | ||||
if (*ep || bytecnt <= 0) | if (*ep || bytecnt <= 0) | ||||
errx(1, "illegal byte count -- %s", optarg); | errx(1, "illegal byte count -- %s", optarg); | ||||
break; | break; | ||||
case 'n': | case 'n': | ||||
linecnt = strtol(optarg, &ep, 10); | linecnt = strtol(optarg, &ep, 10); | ||||
if (*ep || linecnt <= 0) | if (*ep || linecnt <= 0) | ||||
errx(1, "illegal line count -- %s", optarg); | errx(1, "illegal line count -- %s", optarg); | ||||
break; | break; | ||||
case '?': | case '?': | ||||
default: | default: | ||||
usage(); | usage(); | ||||
} | } | ||||
argc -= optind; | argc -= optind; | ||||
argv += optind; | argv += optind; | ||||
if (linecnt != -1 && bytecnt != -1) | if (linecnt != -1 && bytecnt != -1) | ||||
errx(1, "can't combine line and byte counts"); | errx(1, "can't combine line and byte counts"); | ||||
if (linecnt == -1 ) | if (linecnt == -1 ) | ||||
linecnt = 10; | linecnt = 10; | ||||
if (*argv) { | if (*argv) { | ||||
for (first = 1; *argv; ++argv) { | for (first = 1; *argv; ++argv) { | ||||
if ((fp = fopen(*argv, "r")) == NULL) { | fd = openat(rootfd, abspath(*argv), O_RDONLY); | ||||
if (fd < 0) { | |||||
warn("%s", *argv); | warn("%s", *argv); | ||||
eval = 1; | eval = 1; | ||||
continue; | continue; | ||||
} | } | ||||
if (caph_limit_stream(fd, CAPH_READ) < 0) | |||||
err(1, "caph_limit_stream"); | |||||
if ((fp = fdopen(fd, "r")) == NULL) { | |||||
warn("fdopen"); | |||||
eval = 1; | |||||
continue; | |||||
} | |||||
if (argc > 1) { | if (argc > 1) { | ||||
(void)printf("%s==> %s <==\n", | (void)printf("%s==> %s <==\n", | ||||
first ? "" : "\n", *argv); | first ? "" : "\n", *argv); | ||||
first = 0; | first = 0; | ||||
} | } | ||||
if (bytecnt == -1) | if (bytecnt == -1) | ||||
head(fp, linecnt); | head(fp, linecnt); | ||||
else | else | ||||
head_bytes(fp, bytecnt); | head_bytes(fp, bytecnt); | ||||
(void)fclose(fp); | (void)fclose(fp); | ||||
} | } | ||||
} else if (bytecnt == -1) | } else if (bytecnt == -1) | ||||
head(stdin, linecnt); | head(stdin, linecnt); | ||||
else | else | ||||
head_bytes(stdin, bytecnt); | head_bytes(stdin, bytecnt); | ||||
exit(eval); | exit(eval); | ||||
} | |||||
static const char * | |||||
abspath(const char *path) | |||||
{ | |||||
if (*path == '/') | |||||
return (&path[1]); | |||||
if (cwdlen == sizeof(cwd) - 1 || | |||||
cwdlen + 1 + strlen(path) >= sizeof(cwd)) | |||||
err(1, "path too long"); | |||||
cwd[cwdlen] = '/'; | |||||
strlcpy(&cwd[cwdlen + 1], path, sizeof(cwd) - cwdlen - 1); | |||||
return (&cwd[1]); | |||||
} | } | ||||
static void | static void | ||||
head(FILE *fp, int cnt) | head(FILE *fp, int cnt) | ||||
{ | { | ||||
char *cp; | char *cp; | ||||
size_t error, readlen; | size_t error, readlen; | ||||
▲ Show 20 Lines • Show All 53 Lines • Show Last 20 Lines |