Changeset View
Changeset View
Standalone View
Standalone View
bin/echo/echo.c
Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
#include <capsicum_helpers.h> | #include <capsicum_helpers.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <limits.h> | #include <limits.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
/* | |||||
* Report an error and exit. | |||||
* Use it instead of err(3) to avoid linking-in stdio. | |||||
*/ | |||||
static __dead2 void | |||||
errexit(const char *prog, const char *reason) | |||||
{ | |||||
char *errstr = strerror(errno); | |||||
write(STDERR_FILENO, prog, strlen(prog)); | |||||
write(STDERR_FILENO, ": ", 2); | |||||
write(STDERR_FILENO, reason, strlen(reason)); | |||||
write(STDERR_FILENO, ": ", 2); | |||||
write(STDERR_FILENO, errstr, strlen(errstr)); | |||||
write(STDERR_FILENO, "\n", 1); | |||||
exit(1); | |||||
} | |||||
int | int | ||||
main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||
{ | { | ||||
int nflag; /* if not set, output a trailing newline. */ | int nflag; /* if not set, output a trailing newline. */ | ||||
int veclen; /* number of writev arguments. */ | int veclen; /* number of writev arguments. */ | ||||
struct iovec *iov, *vp; /* Elements to write, current element. */ | struct iovec *iov, *vp; /* Elements to write, current element. */ | ||||
char space[] = " "; | char space[] = " "; | ||||
char newline[] = "\n"; | char newline[] = "\n"; | ||||
char *progname = argv[0]; | |||||
if (caph_limit_stdio() < 0 || caph_enter() < 0) | if (caph_limit_stdio() < 0 || caph_enter() < 0) | ||||
err(1, "capsicum"); | err(1, "capsicum"); | ||||
/* This utility may NOT do getopt(3) option parsing. */ | /* This utility may NOT do getopt(3) option parsing. */ | ||||
if (*++argv && !strcmp(*argv, "-n")) { | if (*++argv && !strcmp(*argv, "-n")) { | ||||
++argv; | ++argv; | ||||
--argc; | --argc; | ||||
nflag = 1; | nflag = 1; | ||||
} else | } else | ||||
nflag = 0; | nflag = 0; | ||||
veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0; | veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0; | ||||
if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL) | if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL) | ||||
errexit(progname, "malloc"); | err(1, "malloc"); | ||||
while (argv[0] != NULL) { | while (argv[0] != NULL) { | ||||
size_t len; | size_t len; | ||||
len = strlen(argv[0]); | len = strlen(argv[0]); | ||||
/* | /* | ||||
* If the next argument is NULL then this is the last argument, | * If the next argument is NULL then this is the last argument, | ||||
Show All 22 Lines | if (!nflag) { | ||||
vp++->iov_len = 1; | vp++->iov_len = 1; | ||||
} | } | ||||
/* assert(veclen == (vp - iov)); */ | /* assert(veclen == (vp - iov)); */ | ||||
while (veclen) { | while (veclen) { | ||||
int nwrite; | int nwrite; | ||||
nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen; | nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen; | ||||
if (writev(STDOUT_FILENO, iov, nwrite) == -1) | if (writev(STDOUT_FILENO, iov, nwrite) == -1) | ||||
errexit(progname, "write"); | err(1, "write"); | ||||
iov += nwrite; | iov += nwrite; | ||||
veclen -= nwrite; | veclen -= nwrite; | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } |