Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/tee/tee.c
Show All 39 Lines | |||||
static const char rcsid[] = | static const char rcsid[] = | ||||
"$FreeBSD$"; | "$FreeBSD$"; | ||||
#endif /* not lint */ | #endif /* not lint */ | ||||
#include <sys/capsicum.h> | #include <sys/capsicum.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <capsicum_helpers.h> | |||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <signal.h> | #include <signal.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <termios.h> | |||||
#include <unistd.h> | #include <unistd.h> | ||||
typedef struct _list { | typedef struct _list { | ||||
struct _list *next; | struct _list *next; | ||||
int fd; | int fd; | ||||
const char *name; | const char *name; | ||||
} LIST; | } LIST; | ||||
static LIST *head; | static LIST *head; | ||||
static void add(int, const char *); | static void add(int, const char *); | ||||
static void usage(void); | static void usage(void); | ||||
int | int | ||||
main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||
{ | { | ||||
LIST *p; | LIST *p; | ||||
int n, fd, rval, wval; | int n, fd, rval, wval; | ||||
char *bp; | char *bp; | ||||
int append, ch, exitval; | int append, ch, exitval; | ||||
char *buf; | char *buf; | ||||
cap_rights_t rights; | |||||
unsigned long cmd; | |||||
#define BSIZE (8 * 1024) | #define BSIZE (8 * 1024) | ||||
append = 0; | append = 0; | ||||
while ((ch = getopt(argc, argv, "ai")) != -1) | while ((ch = getopt(argc, argv, "ai")) != -1) | ||||
switch((char)ch) { | switch((char)ch) { | ||||
case 'a': | case 'a': | ||||
append = 1; | append = 1; | ||||
break; | break; | ||||
case 'i': | case 'i': | ||||
(void)signal(SIGINT, SIG_IGN); | (void)signal(SIGINT, SIG_IGN); | ||||
break; | break; | ||||
case '?': | case '?': | ||||
default: | default: | ||||
usage(); | usage(); | ||||
} | } | ||||
argv += optind; | argv += optind; | ||||
argc -= optind; | argc -= optind; | ||||
if ((buf = malloc(BSIZE)) == NULL) | if ((buf = malloc(BSIZE)) == NULL) | ||||
err(1, "malloc"); | err(1, "malloc"); | ||||
cap_rights_init(&rights, CAP_READ, CAP_FSTAT); | if (caph_limit_stdin() == -1 || caph_limit_stderr() == -1) | ||||
if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS) | err(EXIT_FAILURE, "unable to limit stdio"); | ||||
err(EXIT_FAILURE, "unable to limit rights for stdin"); | |||||
cap_rights_init(&rights, CAP_WRITE, CAP_FSTAT, CAP_IOCTL); | |||||
if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) | |||||
err(EXIT_FAILURE, "unable to limit rights for stderr"); | |||||
cmd = TIOCGETA; | |||||
if (cap_ioctls_limit(STDERR_FILENO, &cmd, 1) < 0 && errno != ENOSYS) | |||||
err(EXIT_FAILURE, "unable to limit ioctls for stderr"); | |||||
add(STDOUT_FILENO, "stdout"); | add(STDOUT_FILENO, "stdout"); | ||||
for (exitval = 0; *argv; ++argv) | for (exitval = 0; *argv; ++argv) | ||||
if ((fd = open(*argv, append ? O_WRONLY|O_CREAT|O_APPEND : | if ((fd = open(*argv, append ? O_WRONLY|O_CREAT|O_APPEND : | ||||
O_WRONLY|O_CREAT|O_TRUNC, DEFFILEMODE)) < 0) { | O_WRONLY|O_CREAT|O_TRUNC, DEFFILEMODE)) < 0) { | ||||
warn("%s", *argv); | warn("%s", *argv); | ||||
exitval = 1; | exitval = 1; | ||||
Show All 27 Lines | usage(void) | ||||
exit(1); | exit(1); | ||||
} | } | ||||
static void | static void | ||||
add(int fd, const char *name) | add(int fd, const char *name) | ||||
{ | { | ||||
LIST *p; | LIST *p; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
unsigned long cmd; | |||||
if (fd == STDOUT_FILENO) | if (fd == STDOUT_FILENO) { | ||||
cap_rights_init(&rights, CAP_WRITE, CAP_FSTAT, CAP_IOCTL); | if (caph_limit_stdout() == -1) | ||||
else | err(EXIT_FAILURE, "unable to limit stdout"); | ||||
} else { | |||||
cap_rights_init(&rights, CAP_WRITE, CAP_FSTAT); | cap_rights_init(&rights, CAP_WRITE, CAP_FSTAT); | ||||
if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) | if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) | ||||
err(EXIT_FAILURE, "unable to limit rights"); | err(EXIT_FAILURE, "unable to limit rights"); | ||||
if (fd == STDOUT_FILENO) { | |||||
cmd = TIOCGETA; | |||||
if (cap_ioctls_limit(fd, &cmd, 1) < 0 && errno != ENOSYS) | |||||
err(EXIT_FAILURE, "unable to limit ioctls for stdout"); | |||||
} | } | ||||
if ((p = malloc(sizeof(LIST))) == NULL) | if ((p = malloc(sizeof(LIST))) == NULL) | ||||
err(1, "malloc"); | err(1, "malloc"); | ||||
p->fd = fd; | p->fd = fd; | ||||
p->name = name; | p->name = name; | ||||
p->next = head; | p->next = head; | ||||
head = p; | head = p; | ||||
} | } |