diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2012-06-09 15:37:20 +0930 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2012-06-09 15:41:18 +0930 |
commit | d9ce876ea97d59d66c8d2892b43b7cc8392470a0 (patch) | |
tree | 9b75e61a0b9ab13ee598369d4e59abcba5d4e29b /lib/ccan/err | |
parent | 8a338c65a1824ae8a93bef7bc8fac65684c285c8 (diff) | |
download | samba-d9ce876ea97d59d66c8d2892b43b7cc8392470a0.tar.gz samba-d9ce876ea97d59d66c8d2892b43b7cc8392470a0.tar.bz2 samba-d9ce876ea97d59d66c8d2892b43b7cc8392470a0.zip |
ccan: import err module.from ccan revision 5add556a1cb64b49a664506aa76216d885b22c97
This allows us to avoid err.h in failtest.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'lib/ccan/err')
-rw-r--r-- | lib/ccan/err/.depends | 1 | ||||
-rw-r--r-- | lib/ccan/err/_info | 41 | ||||
-rw-r--r-- | lib/ccan/err/err.c | 64 | ||||
-rw-r--r-- | lib/ccan/err/err.h | 87 | ||||
-rw-r--r-- | lib/ccan/err/test/run.c | 153 |
5 files changed, 346 insertions, 0 deletions
diff --git a/lib/ccan/err/.depends b/lib/ccan/err/.depends new file mode 100644 index 0000000000..ee4f1e44d5 --- /dev/null +++ b/lib/ccan/err/.depends @@ -0,0 +1 @@ +ccan/compiler diff --git a/lib/ccan/err/_info b/lib/ccan/err/_info new file mode 100644 index 0000000000..97bc0f9ed4 --- /dev/null +++ b/lib/ccan/err/_info @@ -0,0 +1,41 @@ +#include <stdio.h> +#include <string.h> +#include "config.h" + +/** + * err - err(), errx(), warn() and warnx(), as per BSD's err.h. + * + * A few platforms don't provide err.h; for those, this provides replacements. + * For most, it simple includes the system err.h. + * + * Unfortunately, you have to call err_set_progname() to tell the replacements + * your program name, otherwise it prints "unknown program". + * + * Example: + * #include <ccan/err/err.h> + * + * int main(int argc, char *argv[]) + * { + * err_set_progname(argv[0]); + * if (argc != 1) + * errx(1, "Expect no arguments"); + * exit(0); + * } + * + * License: Public domain + * Author: Rusty Russell <rusty@rustcorp.com.au> + */ +int main(int argc, char *argv[]) +{ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) { +#if !HAVE_ERR_H + printf("ccan/compiler\n"); +#endif + return 0; + } + + return 1; +} diff --git a/lib/ccan/err/err.c b/lib/ccan/err/err.c new file mode 100644 index 0000000000..9e0e20c86f --- /dev/null +++ b/lib/ccan/err/err.c @@ -0,0 +1,64 @@ +#include "err.h" + +#if !HAVE_ERR_H +#include <stdarg.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> + +static const char *progname = "unknown program"; + +void err_set_progname(const char *name) +{ + progname = name; +} + +void NORETURN err(int eval, const char *fmt, ...) +{ + int err_errno = errno; + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, ": %s\n", strerror(err_errno)); + exit(eval); +} + +void NORETURN errx(int eval, const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + exit(eval); +} + +void warn(const char *fmt, ...) +{ + int err_errno = errno; + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, ": %s\n", strerror(err_errno)); +} + +void warnx(const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} +#endif diff --git a/lib/ccan/err/err.h b/lib/ccan/err/err.h new file mode 100644 index 0000000000..58ad91c728 --- /dev/null +++ b/lib/ccan/err/err.h @@ -0,0 +1,87 @@ +#ifndef CCAN_ERR_H +#define CCAN_ERR_H +#include "config.h" + +#if HAVE_ERR_H +#include <err.h> + +/* This is unnecessary with a real err.h. See below */ +#define err_set_progname(name) ((void)name) + +#else +#include <ccan/compiler/compiler.h> + +/** + * err_set_progname - set the program name + * @name: the name to use for err, errx, warn and warnx + * + * The BSD err.h calls know the program name, unfortunately there's no + * portable way for the CCAN replacements to do that on other systems. + * + * If you don't call this with argv[0], it will be "unknown program". + * + * Example: + * err_set_progname(argv[0]); + */ +void err_set_progname(const char *name); + +/** + * err - exit(eval) with message based on format and errno. + * @eval: the exit code + * @fmt: the printf-style format string + * + * The format string is printed to stderr like so: + * <executable name>: <format>: <strerror(errno)>\n + * + * Example: + * char *p = strdup("hello"); + * if (!p) + * err(1, "Failed to strdup 'hello'"); + */ +void NORETURN err(int eval, const char *fmt, ...); + +/** + * errx - exit(eval) with message based on format. + * @eval: the exit code + * @fmt: the printf-style format string + * + * The format string is printed to stderr like so: + * <executable name>: <format>\n + * + * Example: + * if (argc != 1) + * errx(1, "I don't expect any arguments"); + */ +void NORETURN errx(int eval, const char *fmt, ...); + +/** + * warn - print a message to stderr based on format and errno. + * @eval: the exit code + * @fmt: the printf-style format string + * + * The format string is printed to stderr like so: + * <executable name>: <format>: <strerror(errno)>\n + * + * Example: + * char *p = strdup("hello"); + * if (!p) + * warn("Failed to strdup 'hello'"); + */ +void warn(const char *fmt, ...); + +/** + * warnx - print a message to stderr based on format. + * @eval: the exit code + * @fmt: the printf-style format string + * + * The format string is printed to stderr like so: + * <executable name>: <format>\n + * + * Example: + * if (argc != 1) + * warnx("I don't expect any arguments (ignoring)"); + */ +void warnx(const char *fmt, ...); +#endif + +#endif /* CCAN_ERR_H */ diff --git a/lib/ccan/err/test/run.c b/lib/ccan/err/test/run.c new file mode 100644 index 0000000000..242e93f806 --- /dev/null +++ b/lib/ccan/err/test/run.c @@ -0,0 +1,153 @@ +#include <ccan/err/err.c> +#include <ccan/tap/tap.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> + +#define BUFFER_MAX 1024 + +int main(int argc, char *argv[]) +{ + int pfd[2]; + const char *base; + + plan_tests(24); + + err_set_progname(argv[0]); + + /* In case it only prints out the basename of argv[0]. */ + base = strrchr(argv[0], '/'); + if (base) + base++; + else + base = argv[0]; + + /* Test err() in child */ + pipe(pfd); + fflush(stdout); + if (fork()) { + char buffer[BUFFER_MAX+1]; + unsigned int i; + int status; + + /* We are parent. */ + close(pfd[1]); + for (i = 0; i < BUFFER_MAX; i++) { + if (read(pfd[0], buffer + i, 1) == 0) { + buffer[i] = '\0'; + ok1(strstr(buffer, "running err:")); + ok1(strstr(buffer, strerror(ENOENT))); + ok1(strstr(buffer, base)); + ok1(buffer[i-1] == '\n'); + break; + } + } + close(pfd[0]); + ok1(wait(&status) != -1); + ok1(WIFEXITED(status)); + ok1(WEXITSTATUS(status) == 17); + } else { + close(pfd[0]); + dup2(pfd[1], STDERR_FILENO); + errno = ENOENT; + err(17, "running %s", "err"); + abort(); + } + + /* Test errx() in child */ + pipe(pfd); + fflush(stdout); + if (fork()) { + char buffer[BUFFER_MAX+1]; + unsigned int i; + int status; + + /* We are parent. */ + close(pfd[1]); + for (i = 0; i < BUFFER_MAX; i++) { + if (read(pfd[0], buffer + i, 1) == 0) { + buffer[i] = '\0'; + ok1(strstr(buffer, "running errx\n")); + ok1(strstr(buffer, base)); + break; + } + } + close(pfd[0]); + ok1(wait(&status) != -1); + ok1(WIFEXITED(status)); + ok1(WEXITSTATUS(status) == 17); + } else { + close(pfd[0]); + dup2(pfd[1], STDERR_FILENO); + errx(17, "running %s", "errx"); + abort(); + } + + + /* Test warn() in child */ + pipe(pfd); + fflush(stdout); + if (fork()) { + char buffer[BUFFER_MAX+1]; + unsigned int i; + int status; + + /* We are parent. */ + close(pfd[1]); + for (i = 0; i < BUFFER_MAX; i++) { + if (read(pfd[0], buffer + i, 1) == 0) { + buffer[i] = '\0'; + ok1(strstr(buffer, "running warn:")); + ok1(strstr(buffer, strerror(ENOENT))); + ok1(strstr(buffer, base)); + ok1(buffer[i-1] == '\n'); + break; + } + } + close(pfd[0]); + ok1(wait(&status) != -1); + ok1(WIFEXITED(status)); + ok1(WEXITSTATUS(status) == 17); + } else { + close(pfd[0]); + dup2(pfd[1], STDERR_FILENO); + errno = ENOENT; + warn("running %s", "warn"); + exit(17); + } + + /* Test warnx() in child */ + pipe(pfd); + fflush(stdout); + if (fork()) { + char buffer[BUFFER_MAX+1]; + unsigned int i; + int status; + + /* We are parent. */ + close(pfd[1]); + for (i = 0; i < BUFFER_MAX; i++) { + if (read(pfd[0], buffer + i, 1) == 0) { + buffer[i] = '\0'; + ok1(strstr(buffer, "running warnx\n")); + ok1(strstr(buffer, base)); + break; + } + } + close(pfd[0]); + ok1(wait(&status) != -1); + ok1(WIFEXITED(status)); + ok1(WEXITSTATUS(status) == 17); + } else { + close(pfd[0]); + dup2(pfd[1], STDERR_FILENO); + warnx("running %s", "warnx"); + exit(17); + } + return exit_status(); +} + |