diff options
Diffstat (limited to 'udev')
-rw-r--r-- | udev/udevadm.xml | 12 | ||||
-rw-r--r-- | udev/udevcontrol.c | 345 | ||||
-rw-r--r-- | udev/udevd.c | 24 | ||||
-rw-r--r-- | udev/udevd.h | 13 |
4 files changed, 266 insertions, 128 deletions
diff --git a/udev/udevadm.xml b/udev/udevadm.xml index 670c991457..de0e026e8f 100644 --- a/udev/udevadm.xml +++ b/udev/udevadm.xml @@ -231,7 +231,7 @@ <para>Modify the internal state of the running udev daemon.</para> <variablelist> <varlistentry> - <term><option>--log_priority=<replaceable>value</replaceable></option></term> + <term><option>--log-priority=<replaceable>value</replaceable></option></term> <listitem> <para>Set the internal log level of udevd. Valid values are the numerical syslog priorities or their textual representations: <option>err</option>, @@ -239,20 +239,20 @@ </listitem> </varlistentry> <varlistentry> - <term><option>--stop_exec_queue</option></term> + <term><option>--stop-exec-queue</option></term> <listitem> <para>Signal udevd to stop executing new events. Incoming events will be queued.</para> </listitem> </varlistentry> <varlistentry> - <term><option>--start_exec_queue</option></term> + <term><option>--start-exec-queue</option></term> <listitem> <para>Signal udevd to enable the execution of events.</para> </listitem> </varlistentry> <varlistentry> - <term><option>--reload_rules</option></term> + <term><option>--reload-rules</option></term> <listitem> <para>Signal udevd to reload the rules from the config.</para> </listitem> @@ -264,14 +264,14 @@ </listitem> </varlistentry> <varlistentry> - <term><option>--max_childs=</option><replaceable>value</replaceable></term> + <term><option>--max-childs=</option><replaceable>value</replaceable></term> <listitem> <para>Set the maximum number of events, udevd will handle at the same time.</para> </listitem> </varlistentry> <varlistentry> - <term><option>--max_childs_running=<replaceable>value</replaceable></option></term> + <term><option>--max-childs-running=<replaceable>value</replaceable></option></term> <listitem> <para>Set the maximum number of events, which are allowed to run at the same time.</para> diff --git a/udev/udevcontrol.c b/udev/udevcontrol.c index f4830d8423..5f1952543c 100644 --- a/udev/udevcontrol.c +++ b/udev/udevcontrol.c @@ -25,6 +25,7 @@ #include <stddef.h> #include <string.h> #include <unistd.h> +#include <getopt.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/wait.h> @@ -33,19 +34,144 @@ #include "udev.h" #include "udevd.h" -static int sock = -1; static int udev_log = 0; -int udevcontrol(int argc, char *argv[]) -{ - static struct udevd_ctrl_msg ctrl_msg; +struct udev_ctrl; +extern struct udev_ctrl *udev_ctrl_new_from_socket(const char *socket_path); +extern void udev_ctrl_unref(struct udev_ctrl *uctrl); +extern int udev_ctrl_set_log_level(struct udev_ctrl *uctrl, int priority); +extern int udev_ctrl_stop_exec_queue(struct udev_ctrl *uctrl); +extern int udev_ctrl_start_exec_queue(struct udev_ctrl *uctrl); +extern int udev_ctrl_reload_rules(struct udev_ctrl *uctrl); +extern int udev_ctrl_set_env(struct udev_ctrl *uctrl, const char *key); +extern int udev_ctrl_set_max_childs(struct udev_ctrl *uctrl, int count); +extern int udev_ctrl_set_max_childs_running(struct udev_ctrl *uctrl, int count); + +struct udev_ctrl { + int sock; struct sockaddr_un saddr; socklen_t addrlen; +}; + +struct udev_ctrl *udev_ctrl_new_from_socket(const char *socket_path) +{ + struct udev_ctrl *uctrl; + + uctrl = malloc(sizeof(struct udev_ctrl)); + if (uctrl == NULL) + return NULL; + memset(uctrl, 0x00, sizeof(struct udev_ctrl)); + + uctrl->sock = socket(AF_LOCAL, SOCK_DGRAM, 0); + if (uctrl->sock < 0) { + err("error getting socket: %s\n", strerror(errno)); + free(uctrl); + return NULL; + } + + uctrl->saddr.sun_family = AF_LOCAL; + strcpy(uctrl->saddr.sun_path, socket_path); + uctrl->addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(uctrl->saddr.sun_path); + /* translate leading '@' to abstract namespace */ + if (uctrl->saddr.sun_path[0] == '@') + uctrl->saddr.sun_path[0] = '\0'; + return uctrl; +} + +void udev_ctrl_unref(struct udev_ctrl *uctrl) +{ + if (uctrl == NULL) + return; + close(uctrl->sock); +} + +static int ctrl_send(struct udev_ctrl *uctrl, enum udevd_ctrl_msg_type type, int intval, const char *buf) +{ + struct udevd_ctrl_msg ctrl_msg; + int err; + + memset(&ctrl_msg, 0x00, sizeof(struct udevd_ctrl_msg)); + strcpy(ctrl_msg.magic, UDEVD_CTRL_MAGIC); + ctrl_msg.type = type; + + if (buf != NULL) + strlcpy(ctrl_msg.buf, buf, sizeof(ctrl_msg.buf)); + else + ctrl_msg.intval = intval; + + err = sendto(uctrl->sock, &ctrl_msg, sizeof(ctrl_msg), 0, (struct sockaddr *)&uctrl->saddr, uctrl->addrlen); + if (err == -1) { + err("error sending message: %s\n", strerror(errno)); + } + return err; +} + +int udev_ctrl_set_log_level(struct udev_ctrl *uctrl, int priority) +{ + ctrl_send(uctrl, UDEVD_CTRL_SET_LOG_LEVEL, priority, NULL); + return 0; +} + +int udev_ctrl_stop_exec_queue(struct udev_ctrl *uctrl) +{ + ctrl_send(uctrl, UDEVD_CTRL_STOP_EXEC_QUEUE, 0, NULL); + return 0; +} + +int udev_ctrl_start_exec_queue(struct udev_ctrl *uctrl) +{ + ctrl_send(uctrl, UDEVD_CTRL_START_EXEC_QUEUE, 0, NULL); + return 0; +} + +int udev_ctrl_reload_rules(struct udev_ctrl *uctrl) +{ + ctrl_send(uctrl, UDEVD_CTRL_RELOAD_RULES, 0, NULL); + return 0; +} + +int udev_ctrl_set_env(struct udev_ctrl *uctrl, const char *key) +{ + ctrl_send(uctrl, UDEVD_CTRL_ENV, 0, optarg); + return 0; +} + +int udev_ctrl_set_max_childs(struct udev_ctrl *uctrl, int count) +{ + ctrl_send(uctrl, UDEVD_CTRL_SET_MAX_CHILDS, count, NULL); + return 0; +} + +int udev_ctrl_set_max_childs_running(struct udev_ctrl *uctrl, int count) +{ + ctrl_send(uctrl, UDEVD_CTRL_SET_MAX_CHILDS_RUNNING, count, NULL); + return 0; +} + +int udevcontrol(int argc, char *argv[]) +{ + struct udev_ctrl *uctrl; const char *env; - const char *arg; - const char *val; - int *intval; - int retval = 1; + int rc = 1; + + /* compat values with '_' will be removed in a future release */ + static const struct option options[] = { + { "log-priority", 1, NULL, 'l' }, + { "log_priority", 1, NULL, 'l' + 256 }, + { "stop-exec-queue", 0, NULL, 's' }, + { "stop_exec_queue", 0, NULL, 's' + 256 }, + { "start-exec-queue", 0, NULL, 'S' }, + { "start_exec_queue", 0, NULL, 'S' + 256}, + { "reload-rules", 0, NULL, 'R' }, + { "reload_rules", 0, NULL, 'R' + 256}, + { "env", 1, NULL, 'e' }, + { "max-childs", 1, NULL, 'm' }, + { "max_childs", 1, NULL, 'm' + 256}, + { "max-childs-running", 1, NULL, 'M' }, + { "max_childs_running", 1, NULL, 'M' + 256}, + { "help", 0, NULL, 'h' }, + {} + }; env = getenv("UDEV_LOG"); if (env) @@ -54,114 +180,125 @@ int udevcontrol(int argc, char *argv[]) logging_init("udevcontrol"); dbg("version %s\n", VERSION); - if (argc < 2) { - fprintf(stderr, "missing command\n\n"); + if (getuid() != 0) { + fprintf(stderr, "root privileges required\n"); goto exit; } - memset(&ctrl_msg, 0x00, sizeof(struct udevd_ctrl_msg)); - strcpy(ctrl_msg.magic, UDEVD_CTRL_MAGIC); - arg = argv[1]; - - /* allow instructions passed as options */ - if (strncmp(arg, "--", 2) == 0) - arg += 2; - - if (!strcmp(arg, "stop_exec_queue")) - ctrl_msg.type = UDEVD_CTRL_STOP_EXEC_QUEUE; - else if (!strcmp(arg, "start_exec_queue")) - ctrl_msg.type = UDEVD_CTRL_START_EXEC_QUEUE; - else if (!strcmp(arg, "reload_rules")) - ctrl_msg.type = UDEVD_CTRL_RELOAD_RULES; - else if (!strncmp(arg, "log_priority=", strlen("log_priority="))) { - intval = (int *) ctrl_msg.buf; - val = &arg[strlen("log_priority=")]; - ctrl_msg.type = UDEVD_CTRL_SET_LOG_LEVEL; - *intval = log_priority(val); - info("send log_priority=%i\n", *intval); - } else if (!strncmp(arg, "max_childs=", strlen("max_childs="))) { + + uctrl = udev_ctrl_new_from_socket(UDEVD_CTRL_SOCK_PATH); + if (uctrl == NULL) + goto exit; + + while (1) { + int option; + int i; char *endp; - int count; - - intval = (int *) ctrl_msg.buf; - val = &arg[strlen("max_childs=")]; - ctrl_msg.type = UDEVD_CTRL_SET_MAX_CHILDS; - count = strtoul(val, &endp, 0); - if (endp[0] != '\0' || count < 1) { - fprintf(stderr, "invalid number\n"); - goto exit; + + option = getopt_long(argc, argv, "l:sSRe:m:M:h", options, NULL); + if (option == -1) + break; + + if (option > 255) { + info("udevadm control expects commands without underscore, " + "this will stop working in a future release\n"); + fprintf(stderr, "udevadm control expects commands without underscore, " + "this will stop working in a future release\n"); } - *intval = count; - info("send max_childs=%i\n", *intval); - } else if (!strncmp(arg, "max_childs_running=", strlen("max_childs_running="))) { - char *endp; - int count; - - intval = (int *) ctrl_msg.buf; - val = &arg[strlen("max_childs_running=")]; - ctrl_msg.type = UDEVD_CTRL_SET_MAX_CHILDS_RUNNING; - count = strtoul(val, &endp, 0); - if (endp[0] != '\0' || count < 1) { - fprintf(stderr, "invalid number\n"); + + switch (option) { + case 'l': + case 'l' + 256: + i = log_priority(optarg); + if (i < 0) { + fprintf(stderr, "invalid number '%s'\n", optarg); + goto exit; + } + udev_ctrl_set_log_level(uctrl, log_priority(optarg)); + break; + case 's': + case 's' + 256: + udev_ctrl_stop_exec_queue(uctrl); + break; + case 'S': + case 'S' + 256: + udev_ctrl_start_exec_queue(uctrl); + break; + case 'R': + case 'R' + 256: + udev_ctrl_reload_rules(uctrl); + break; + case 'e': + if (strchr(optarg, '=') == NULL) { + fprintf(stderr, "expect <KEY>=<valaue> instead of '%s'\n", optarg); + goto exit; + } + udev_ctrl_set_env(uctrl, optarg); + break; + case 'm': + case 'm' + 256: + i = strtoul(optarg, &endp, 0); + if (endp[0] != '\0' || i < 1) { + fprintf(stderr, "invalid number '%s'\n", optarg); + goto exit; + } + udev_ctrl_set_max_childs(uctrl, i); + break; + case 'M': + case 'M' + 256: + i = strtoul(optarg, &endp, 0); + if (endp[0] != '\0' || i < 1) { + fprintf(stderr, "invalid number '%s'\n", optarg); + goto exit; + } + udev_ctrl_set_max_childs_running(uctrl, i); + break; + break; + case 'h': + printf("Usage: udevadm control COMMAND\n" + " --log-priority=<level> set the udev log level for the daemon\n" + " --stop-exec-queue keep udevd from executing events, queue only\n" + " --start-exec-queue execute events, flush queue\n" + " --reload-rules reloads the rules files\n" + " --env=<KEY>=<value> set a global environment variable\n" + " --max-childs=<N> maximum number of childs\n" + " --max-childs-running=<N> maximum number of childs running at the same time\n" + " --help print this help text\n\n"); goto exit; - } - *intval = count; - info("send max_childs_running=%i\n", *intval); - } else if (!strncmp(arg, "env", strlen("env"))) { - if (!strncmp(arg, "env=", strlen("env="))) - val = &arg[strlen("env=")]; - else - val = argv[2]; - if (val == NULL) { - fprintf(stderr, "missing key\n"); + default: goto exit; } - ctrl_msg.type = UDEVD_CTRL_ENV; - strlcpy(ctrl_msg.buf, val, sizeof(ctrl_msg.buf)); - info("send env '%s'\n", val); - } else if (strcmp(arg, "help") == 0 || strcmp(arg, "-h") == 0) { - printf("Usage: udevadm control COMMAND\n" - " --log_priority=<level> set the udev log level for the daemon\n" - " --stop_exec_queue keep udevd from executing events, queue only\n" - " --start_exec_queue execute events, flush queue\n" - " --reload_rules reloads the rules files\n" - " --env=<KEY>=<value> set a global environment variable\n" - " --max_childs=<N> maximum number of childs\n" - " --max_childs_running=<N> maximum number of childs running at the same time\n" - " --help print this help text\n\n"); - goto exit; - } else { - fprintf(stderr, "unrecognized command '%s'\n", arg); - goto exit; - } - - if (getuid() != 0) { - fprintf(stderr, "root privileges required\n"); - goto exit; } - sock = socket(AF_LOCAL, SOCK_DGRAM, 0); - if (sock == -1) { - err("error getting socket: %s\n", strerror(errno)); - goto exit; - } + /* compat stuff which will be removed in a future release */ + if (argv[optind] != NULL) { + const char *arg = argv[optind]; - memset(&saddr, 0x00, sizeof(struct sockaddr_un)); - saddr.sun_family = AF_LOCAL; - /* use abstract namespace for socket path */ - strcpy(&saddr.sun_path[1], UDEVD_CTRL_SOCK_PATH); - addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&saddr.sun_path[1]); + fprintf(stderr, "udevadm control commands requires the --<command> format, " + "this will stop working in a future release\n"); + err("udevadm control commands requires the --<command> format, " + "this will stop working in a future release\n"); - retval = sendto(sock, &ctrl_msg, sizeof(ctrl_msg), 0, (struct sockaddr *)&saddr, addrlen); - if (retval == -1) { - err("error sending message: %s\n", strerror(errno)); - retval = 1; - } else { - dbg("sent message type=0x%02x, %u bytes sent\n", ctrl_msg.type, retval); - retval = 0; + if (!strncmp(arg, "log_priority=", strlen("log_priority="))) { + udev_ctrl_set_log_level(uctrl, log_priority(&arg[strlen("log_priority=")])); + } else if (!strcmp(arg, "stop_exec_queue")) { + udev_ctrl_stop_exec_queue(uctrl); + } else if (!strcmp(arg, "start_exec_queue")) { + udev_ctrl_start_exec_queue(uctrl); + } else if (!strcmp(arg, "reload_rules")) { + udev_ctrl_reload_rules(uctrl); + } else if (!strncmp(arg, "max_childs=", strlen("max_childs="))) { + udev_ctrl_set_max_childs(uctrl, strtoul(&arg[strlen("max_childs=")], NULL, 0)); + } else if (!strncmp(arg, "max_childs_running=", strlen("max_childs_running="))) { + udev_ctrl_set_max_childs_running(uctrl, strtoul(&arg[strlen("max_childs_running=")], NULL, 0)); + } else if (!strncmp(arg, "env", strlen("env"))) { + udev_ctrl_set_env(uctrl, &arg[strlen("env=")]); + } else { + fprintf(stderr, "unrecognized command '%s'\n", arg); + err("unrecognized command '%s'\n", arg); + } } - - close(sock); exit: + udev_ctrl_unref(uctrl); logging_close(); - return retval; + return rc; } diff --git a/udev/udevd.c b/udev/udevd.c index 49159494c4..68cf264369 100644 --- a/udev/udevd.c +++ b/udev/udevd.c @@ -664,7 +664,6 @@ static void get_ctrl_msg(void) struct iovec iov; struct ucred *cred; char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; - int *intval; char *pos; memset(&ctrl_msg, 0x00, sizeof(struct udevd_ctrl_msg)); @@ -727,21 +726,18 @@ static void get_ctrl_msg(void) msg_queue_manager(); break; case UDEVD_CTRL_SET_LOG_LEVEL: - intval = (int *) ctrl_msg.buf; - info("udevd message (SET_LOG_PRIORITY) received, udev_log_priority=%i\n", *intval); - udev_log_priority = *intval; + info("udevd message (SET_LOG_PRIORITY) received, udev_log_priority=%i\n", ctrl_msg.intval); + udev_log_priority = ctrl_msg.intval; sprintf(udev_log, "UDEV_LOG=%i", udev_log_priority); putenv(udev_log); break; case UDEVD_CTRL_SET_MAX_CHILDS: - intval = (int *) ctrl_msg.buf; - info("udevd message (UDEVD_SET_MAX_CHILDS) received, max_childs=%i\n", *intval); - max_childs = *intval; + info("udevd message (UDEVD_SET_MAX_CHILDS) received, max_childs=%i\n", ctrl_msg.intval); + max_childs = ctrl_msg.intval; break; case UDEVD_CTRL_SET_MAX_CHILDS_RUNNING: - intval = (int *) ctrl_msg.buf; - info("udevd message (UDEVD_SET_MAX_CHILDS_RUNNING) received, max_childs=%i\n", *intval); - max_childs_running = *intval; + info("udevd message (UDEVD_SET_MAX_CHILDS_RUNNING) received, max_childs_running=%i\n", ctrl_msg.intval); + max_childs_running = ctrl_msg.intval; break; case UDEVD_CTRL_RELOAD_RULES: info("udevd message (RELOAD_RULES) received\n"); @@ -870,9 +866,11 @@ static int init_udevd_socket(void) memset(&saddr, 0x00, sizeof(saddr)); saddr.sun_family = AF_LOCAL; - /* use abstract namespace for socket path */ - strcpy(&saddr.sun_path[1], UDEVD_CTRL_SOCK_PATH); - addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&saddr.sun_path[1]); + strcpy(saddr.sun_path, UDEVD_CTRL_SOCK_PATH); + addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path); + /* translate leading '@' to abstract namespace */ + if (saddr.sun_path[0] == '@') + saddr.sun_path[0] = '\0'; udevd_sock = socket(AF_LOCAL, SOCK_DGRAM, 0); if (udevd_sock == -1) { diff --git a/udev/udevd.h b/udev/udevd.h index 1f4d6e417f..7405704c7a 100644 --- a/udev/udevd.h +++ b/udev/udevd.h @@ -31,24 +31,27 @@ #define UEVENT_BUFFER_SIZE 2048 #define UEVENT_NUM_ENVP 32 -#define UDEVD_CTRL_SOCK_PATH UDEV_PREFIX "/org/kernel/udev/udevd" +#define UDEVD_CTRL_SOCK_PATH "@" UDEV_PREFIX "/org/kernel/udev/udevd" #define UDEVD_CTRL_MAGIC "udevd_" VERSION enum udevd_ctrl_msg_type { UDEVD_CTRL_UNKNOWN, + UDEVD_CTRL_SET_LOG_LEVEL, UDEVD_CTRL_STOP_EXEC_QUEUE, UDEVD_CTRL_START_EXEC_QUEUE, - UDEVD_CTRL_SET_LOG_LEVEL, - UDEVD_CTRL_SET_MAX_CHILDS, - UDEVD_CTRL_SET_MAX_CHILDS_RUNNING, UDEVD_CTRL_RELOAD_RULES, UDEVD_CTRL_ENV, + UDEVD_CTRL_SET_MAX_CHILDS, + UDEVD_CTRL_SET_MAX_CHILDS_RUNNING, }; struct udevd_ctrl_msg { char magic[32]; enum udevd_ctrl_msg_type type; - char buf[256]; + union { + int intval; + char buf[256]; + }; }; struct udevd_uevent_msg { |