static int adm_control(struct udev *udev, int argc, char *argv[]) { _cleanup_udev_ctrl_unref_ struct udev_ctrl *uctrl = NULL; int timeout = 60; int rc = 1, c; static const struct option options[] = { { "exit", no_argument, NULL, 'e' }, { "log-priority", required_argument, NULL, 'l' }, { "stop-exec-queue", no_argument, NULL, 's' }, { "start-exec-queue", no_argument, NULL, 'S' }, { "reload", no_argument, NULL, 'R' }, { "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */ { "property", required_argument, NULL, 'p' }, { "env", required_argument, NULL, 'p' }, /* alias for -p */ { "children-max", required_argument, NULL, 'm' }, { "timeout", required_argument, NULL, 't' }, { "version", no_argument, NULL, 'V' }, { "help", no_argument, NULL, 'h' }, {} }; if (must_be_root() < 0) return 1; uctrl = udev_ctrl_new(udev); if (uctrl == NULL) return 2; while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0) switch (c) { case 'e': if (udev_ctrl_send_exit(uctrl, timeout) < 0) rc = 2; else rc = 0; break; case 'l': { int i; i = util_log_priority(optarg); if (i < 0) { log_error("invalid number '%s'", optarg); return rc; } if (udev_ctrl_send_set_log_level(uctrl, util_log_priority(optarg), timeout) < 0) rc = 2; else rc = 0; break; } case 's': if (udev_ctrl_send_stop_exec_queue(uctrl, timeout) < 0) rc = 2; else rc = 0; break; case 'S': if (udev_ctrl_send_start_exec_queue(uctrl, timeout) < 0) rc = 2; else rc = 0; break; case 'R': if (udev_ctrl_send_reload(uctrl, timeout) < 0) rc = 2; else rc = 0; break; case 'p': if (strchr(optarg, '=') == NULL) { log_error("expect <KEY>=<value> instead of '%s'", optarg); return rc; } if (udev_ctrl_send_set_env(uctrl, optarg, timeout) < 0) rc = 2; else rc = 0; break; case 'm': { char *endp; int i; i = strtoul(optarg, &endp, 0); if (endp[0] != '\0' || i < 1) { log_error("invalid number '%s'", optarg); return rc; } if (udev_ctrl_send_set_children_max(uctrl, i, timeout) < 0) rc = 2; else rc = 0; break; } case 't': { usec_t s; int seconds; int r; r = parse_sec(optarg, &s); if (r < 0) return log_error_errno(r, "Failed to parse timeout value '%s'.", optarg); if (((s + USEC_PER_SEC - 1) / USEC_PER_SEC) > INT_MAX) log_error("Timeout value is out of range."); else { seconds = s != USEC_INFINITY ? (int) ((s + USEC_PER_SEC - 1) / USEC_PER_SEC) : INT_MAX; timeout = seconds; rc = 0; } break; } case 'V': print_version(); rc = 0; break; case 'h': print_help(); rc = 0; break; } if (optind < argc) log_error("Extraneous argument: %s", argv[optind]); else if (optind == 1) log_error("Option missing"); return rc; }
int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) { const Verb *verb; const char *name; unsigned i; int left, r; assert(verbs); assert(verbs[0].dispatch); assert(argc >= 0); assert(argv); assert(argc >= optind); left = argc - optind; name = argv[optind]; for (i = 0;; i++) { bool found; /* At the end of the list? */ if (!verbs[i].dispatch) { if (name) log_error("Unknown operation %s.", name); else log_error("Requires operation parameter."); return -EINVAL; } if (name) found = streq(name, verbs[i].verb); else found = !!(verbs[i].flags & VERB_DEFAULT); if (found) { verb = &verbs[i]; break; } } assert(verb); if (!name) left = 1; if (verb->min_args != VERB_ANY && (unsigned) left < verb->min_args) { log_error("Too few arguments."); return -EINVAL; } if (verb->max_args != VERB_ANY && (unsigned) left > verb->max_args) { log_error("Too many arguments."); return -EINVAL; } if ((verb->flags & VERB_ONLINE_ONLY) && running_in_chroot_or_offline()) { if (name) log_info("Running in chroot, ignoring request: %s", name); else log_info("Running in chroot, ignoring request."); return 0; } if (verb->flags & VERB_MUST_BE_ROOT) { r = must_be_root(); if (r < 0) return r; } if (name) return verb->dispatch(left, argv + optind, userdata); else { char* fake[2] = { (char*) verb->verb, NULL }; return verb->dispatch(1, fake, userdata); } }
{ "log-priority", required_argument, NULL, 'l' }, { "stop-exec-queue", no_argument, NULL, 's' }, { "start-exec-queue", no_argument, NULL, 'S' }, { "reload", no_argument, NULL, 'R' }, { "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */ { "property", required_argument, NULL, 'p' }, { "env", required_argument, NULL, 'p' }, /* alias for -p */ { "children-max", required_argument, NULL, 'm' }, { "ping", no_argument, NULL, ARG_PING }, { "timeout", required_argument, NULL, 't' }, { "version", no_argument, NULL, 'V' }, { "help", no_argument, NULL, 'h' }, {} }; r = must_be_root(); if (r < 0) return r; if (running_in_chroot() > 0) { log_info("Running in chroot, ignoring request."); return 0; } if (argc <= 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This command expects one or more options."); r = udev_ctrl_new(&uctrl); if (r < 0) return log_error_errno(r, "Failed to initialize udev control: %m");