X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=utils%2Fpb-event.c;h=10bf4f59ab3857b8ab6af8ef50ff012871c5a76e;hp=5ef811513c0eea5c079136ed9be02d4ea6ebf6fa;hb=d0c069b5acfacd853873bb6623ede94d4d1fe10e;hpb=cf3593ef4be341aace4843148a7999c5660e8b2b diff --git a/utils/pb-event.c b/utils/pb-event.c index 5ef8115..10bf4f5 100644 --- a/utils/pb-event.c +++ b/utils/pb-event.c @@ -20,8 +20,8 @@ #include "config.h" #endif -#define _GNU_SOURCE #include +#include #include #include #include @@ -40,43 +40,103 @@ static inline int __attribute__ ((format (printf, 1, 2))) DBG( __attribute__((unused)) const char *fmt, ...) {return 0; } #endif -int main(void) +static void print_version(void) { - int result; - struct sockaddr_un addr; - char buf[PBOOT_USER_EVENT_SIZE]; - ssize_t len; - int s; + printf("pb-event (" PACKAGE_NAME ") " PACKAGE_VERSION "\n"); +} + +static void print_usage(void) +{ + print_version(); + printf( +"Usage: pb-event [-h] [event...]\n" +"\n" +" Send a single petitboot user event to the petitboot discover server.\n" +" Events can be read from stdin, or provided on the command line.\n" +" User events must have the following format:\n" +"\n" +" (add|remove|boot|sync)@device-id [name=value] [image=value] [args=value]\n" +"\n" +" When read from stdin, components are separated by NUL chars\n" +"\n" +"Examples:\n" +"\n" +" args:\n" +" pb-event add@/net/eth0 name=netboot image=tftp://192.168.1.10/vmlinux\n" +" pb-event remove@/net/eth0\n" +"\n" +" stdin:\n" +" printf 'add@/net/eth0\\0name=netboot\\0image=tftp://10.0.0.2/vmlinux\\0' \\\n" +" | pb-event\n" +" printf 'remove@/net/eth0\\0' | pb-event\n" +"\n"); +} + +static const char *err_max_size = "pb-event: message too large " + "(%zu byte max)\n"; + +static ssize_t parse_event_args(int n, char * const * args, + char *buf, size_t max_len) +{ + ssize_t arg_len, total_len; + const char *arg; int i; - s = socket(PF_UNIX, SOCK_DGRAM, 0); + total_len = 0; - if (s < 0) { - fprintf(stderr, "pb-event: socket: %s\n", strerror(errno)); - return EXIT_FAILURE; + for (i = 0; i < n; i++) { + arg = args[i]; + arg_len = strlen(arg); + + if (total_len + (size_t)i + 1 > max_len) { + fprintf(stderr, err_max_size, max_len); + return -1; + } + + memcpy(buf + total_len, arg, arg_len); + total_len += arg_len; + + buf[total_len] = '\0'; + total_len++; } - result = EXIT_SUCCESS; + return total_len; + +} + +static ssize_t parse_event_file(FILE *filp, char *buf, size_t max_len) +{ + int len; - len = fread(buf, 1, sizeof(buf), stdin); + len = fread(buf, 1, max_len, filp); - if (!feof(stdin)) { - fprintf(stderr, "pb-event: msg too big (%u byte max)\n", - sizeof(buf)); - result = EXIT_FAILURE; - /* continue on and try to write msg */ + if (!feof(filp)) { + fprintf(stderr, err_max_size, max_len); + return -1; } if (!len) - return result; + return -1; + + return len; +} + +static int send_event(char *buf, ssize_t len) +{ + struct sockaddr_un addr; + int sd, i; + + sd = socket(PF_UNIX, SOCK_DGRAM, 0); + if (sd < 0) + err(EXIT_FAILURE, "socket"); memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, PBOOT_USER_EVENT_SOCKET); for (i = 10; i; i--) { - ssize_t sent = sendto(s, buf, len, 0, (struct sockaddr *)&addr, - SUN_LEN(&addr)); + ssize_t sent = sendto(sd, buf, len, 0, + (struct sockaddr *)&addr, SUN_LEN(&addr)); if (sent == len) break; @@ -85,11 +145,37 @@ int main(void) sleep(1); } - if (!i) { - fprintf(stderr, "pb-event: send: %s\n", strerror(errno)); - return EXIT_FAILURE; + close(sd); + + if (!i) + err(EXIT_FAILURE, "send"); + + DBG("pb-event: wrote %zu bytes\n", len); + + return 0; +} + +int main(int argc, char *argv[]) +{ + char buf[PBOOT_USER_EVENT_SIZE]; + ssize_t len; + + if (argc >= 2 && !strcmp(argv[1], "-h")) { + print_usage(); + return EXIT_SUCCESS; } - DBG("pb-event: wrote %u bytes\n", len); - return result; + if (argc > 1) { + len = parse_event_args(argc - 1, argv + 1, + buf, sizeof(buf)); + } else { + len = parse_event_file(stdin, buf, sizeof(buf)); + } + + if (len < 0) + return EXIT_FAILURE; + + send_event(buf, len); + + return EXIT_SUCCESS; }