X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=utils%2Fpb-event.c;h=a1affe5243cc4bf270bef92b87fb7595fb97b3d5;hp=a119e21b24622545f99b3648510c36bcaac3dd7c;hb=11284780b9aa525dd659bd85d6374040630db008;hpb=a88618fc1d5828287ce71bb643f8117e51754c88 diff --git a/utils/pb-event.c b/utils/pb-event.c index a119e21..a1affe5 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 @@ -49,63 +49,94 @@ static void print_usage(void) { print_version(); printf( -"Usage: pb-event [-h, --help] [-V, --version]\n" +"Usage: pb-event [-h] [event...]\n" "\n" -" Reads a single petitboot user event on stdin and forwards it to the\n" -" petitboot discover server pb-discover. User events must have the\n" -" following format:\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)@device-id\\0[name=value\\0][image=value\\0][args=value\\0]\n" +" (add|remove)@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" -" echo -ne 'add@/net/eth0\\0name=netboot\\0image=tftp://192.168.1.10/vmlinux\\0args=root=/dev/nfs nfsroot=192.168.1.10:/target\\0' | pb-event\n" -" echo -ne 'remove@/net/eth0\\0' | pb-event\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"); } -int main(int argc, __attribute__((unused)) char *argv[]) +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) { - int result; - struct sockaddr_un addr; - char buf[PBOOT_USER_EVENT_SIZE]; - ssize_t len; - int s; + ssize_t arg_len, total_len; + const char *arg; int i; - - if (argc > 1) { - print_usage(); - return EXIT_FAILURE; - } - - s = socket(PF_UNIX, SOCK_DGRAM, 0); - if (s < 0) { - fprintf(stderr, "pb-event: socket: %s\n", strerror(errno)); - return EXIT_FAILURE; + total_len = 0; + + 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", - (unsigned int)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; @@ -114,11 +145,37 @@ int main(int argc, __attribute__((unused)) char *argv[]) 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; + } + + if (argc > 1) { + len = parse_event_args(argc - 1, argv + 1, + buf, sizeof(buf)); + } else { + len = parse_event_file(stdin, buf, sizeof(buf)); } - DBG("pb-event: wrote %u bytes\n", (unsigned int)len); - return result; + if (len < 0) + return EXIT_FAILURE; + + send_event(buf, len); + + return EXIT_SUCCESS; }