From: Rusty Russell Date: Fri, 8 Jun 2012 07:37:03 +0000 (+0930) Subject: ccan/err: new err.h-replacing module. X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=4776faf17adfa16ef5b2aeb24414b9d73a5789fc ccan/err: new err.h-replacing module. Seems like Solaris doesn't have err.h, as discovered by Samba. --- diff --git a/ccan/err/_info b/ccan/err/_info new file mode 100644 index 00000000..5a5752bb --- /dev/null +++ b/ccan/err/_info @@ -0,0 +1,37 @@ +#include +#include +#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. + * + * Example: + * #include + * + * int main(int argc, char *argv[]) + * { + * if (argc != 1) + * errx(1, "Expect no arguments"); + * exit(0); + * } + * + * License: Public domain + * Author: Rusty Russell + */ +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/ccan/err/err.h b/ccan/err/err.h new file mode 100644 index 00000000..da9ea0c5 --- /dev/null +++ b/ccan/err/err.h @@ -0,0 +1,69 @@ +#ifndef CCAN_ERR_H +#define CCAN_ERR_H +#include "config.h" + +#if HAVE_ERR_H +#include +#else +#include + +/** + * 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: + * : : \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: + * : \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: + * : : \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: + * : \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/ccan/err/test/run.c b/ccan/err/test/run.c new file mode 100644 index 00000000..c0407a93 --- /dev/null +++ b/ccan/err/test/run.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUFFER_MAX 1024 + +int main(void) +{ + int pfd[2]; + + plan_tests(20); + fflush(stdout); + + /* Test err() in child */ + pipe(pfd); + 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(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")); + 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(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")); + 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(); +} +