]>
Commit | Line | Data |
---|---|---|
e7145211 | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
3b47c739 | 2 | /* |
55e9959b KS |
3 | * This program is free software: you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by | |
5 | * the Free Software Foundation, either version 2 of the License, or | |
6 | * (at your option) any later version. | |
3b47c739 | 7 | * |
55e9959b KS |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
3b47c739 KS |
12 | */ |
13 | ||
3b47c739 | 14 | #include <errno.h> |
cf0fbc49 TA |
15 | #include <getopt.h> |
16 | #include <stddef.h> | |
3b47c739 KS |
17 | #include <stdio.h> |
18 | #include <stdlib.h> | |
3b47c739 KS |
19 | #include <string.h> |
20 | #include <unistd.h> | |
3b47c739 | 21 | |
bb291b72 | 22 | #include "parse-util.h" |
dccca82b | 23 | #include "process-util.h" |
46f0fbd8 | 24 | #include "syslog-util.h" |
1f1a5e8b | 25 | #include "time-util.h" |
3d05193e | 26 | #include "udevadm.h" |
7d68eb1b YW |
27 | #include "udev-ctrl.h" |
28 | #include "util.h" | |
c494b739 | 29 | #include "virt.h" |
d59f11e1 | 30 | |
bb291b72 | 31 | static int help(void) { |
5639df9a | 32 | printf("%s control OPTION\n\n" |
5ac0162c LP |
33 | "Control the udev daemon.\n\n" |
34 | " -h --help Show this help\n" | |
5639df9a | 35 | " -V --version Show package version\n" |
5ac0162c LP |
36 | " -e --exit Instruct the daemon to cleanup and exit\n" |
37 | " -l --log-priority=LEVEL Set the udev log level for the daemon\n" | |
38 | " -s --stop-exec-queue Do not execute events, queue only\n" | |
39 | " -S --start-exec-queue Execute events, flush queue\n" | |
40 | " -R --reload Reload rules and databases\n" | |
41 | " -p --property=KEY=VALUE Set a global property for all events\n" | |
42 | " -m --children-max=N Maximum number of children\n" | |
a04a9027 | 43 | " -t --timeout=SECONDS Maximum time to block for a reply\n" |
5ac0162c | 44 | , program_invocation_short_name); |
bb291b72 YW |
45 | |
46 | return 0; | |
d59f11e1 | 47 | } |
3b47c739 | 48 | |
3d05193e | 49 | int control_main(int argc, char *argv[], void *userdata) { |
8e766630 | 50 | _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL; |
912541b0 | 51 | int timeout = 60; |
bb291b72 | 52 | int c, r; |
2b725651 | 53 | |
912541b0 | 54 | static const struct option options[] = { |
7643ac9a ZJS |
55 | { "exit", no_argument, NULL, 'e' }, |
56 | { "log-priority", required_argument, NULL, 'l' }, | |
57 | { "stop-exec-queue", no_argument, NULL, 's' }, | |
58 | { "start-exec-queue", no_argument, NULL, 'S' }, | |
59 | { "reload", no_argument, NULL, 'R' }, | |
60 | { "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */ | |
61 | { "property", required_argument, NULL, 'p' }, | |
62 | { "env", required_argument, NULL, 'p' }, /* alias for -p */ | |
63 | { "children-max", required_argument, NULL, 'm' }, | |
64 | { "timeout", required_argument, NULL, 't' }, | |
5639df9a | 65 | { "version", no_argument, NULL, 'V' }, |
7643ac9a | 66 | { "help", no_argument, NULL, 'h' }, |
912541b0 KS |
67 | {} |
68 | }; | |
3b47c739 | 69 | |
bb291b72 YW |
70 | r = must_be_root(); |
71 | if (r < 0) | |
72 | return r; | |
73 | ||
c494b739 YW |
74 | if (running_in_chroot() > 0) { |
75 | log_info("Running in chroot, ignoring request."); | |
76 | return 0; | |
77 | } | |
78 | ||
bb291b72 YW |
79 | if (argc <= 1) |
80 | log_error("Option missing"); | |
2b725651 | 81 | |
2024ed61 | 82 | uctrl = udev_ctrl_new(); |
bb291b72 YW |
83 | if (!uctrl) |
84 | return -ENOMEM; | |
2b725651 | 85 | |
5639df9a | 86 | while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0) |
7643ac9a | 87 | switch (c) { |
912541b0 | 88 | case 'e': |
bb291b72 YW |
89 | r = udev_ctrl_send_exit(uctrl, timeout); |
90 | if (r < 0) | |
91 | return r; | |
912541b0 | 92 | break; |
46f0fbd8 YW |
93 | case 'l': |
94 | r = log_level_from_string(optarg); | |
95 | if (r < 0) | |
96 | return log_error_errno(r, "Failed to parse log priority '%s': %m", optarg); | |
bb291b72 | 97 | |
46f0fbd8 | 98 | r = udev_ctrl_send_set_log_level(uctrl, r, timeout); |
bb291b72 YW |
99 | if (r < 0) |
100 | return r; | |
912541b0 | 101 | break; |
912541b0 | 102 | case 's': |
bb291b72 YW |
103 | r = udev_ctrl_send_stop_exec_queue(uctrl, timeout); |
104 | if (r < 0) | |
105 | return r; | |
912541b0 KS |
106 | break; |
107 | case 'S': | |
bb291b72 YW |
108 | r = udev_ctrl_send_start_exec_queue(uctrl, timeout); |
109 | if (r < 0) | |
110 | return r; | |
912541b0 KS |
111 | break; |
112 | case 'R': | |
bb291b72 YW |
113 | r = udev_ctrl_send_reload(uctrl, timeout); |
114 | if (r < 0) | |
115 | return r; | |
912541b0 KS |
116 | break; |
117 | case 'p': | |
bb291b72 | 118 | if (!strchr(optarg, '=')) { |
1f1a5e8b | 119 | log_error("expect <KEY>=<value> instead of '%s'", optarg); |
bb291b72 | 120 | return -EINVAL; |
912541b0 | 121 | } |
bb291b72 YW |
122 | r = udev_ctrl_send_set_env(uctrl, optarg, timeout); |
123 | if (r < 0) | |
124 | return r; | |
912541b0 KS |
125 | break; |
126 | case 'm': { | |
bb291b72 | 127 | unsigned i; |
ff2c503d | 128 | |
bb291b72 YW |
129 | r = safe_atou(optarg, &i); |
130 | if (r < 0) | |
131 | return log_error_errno(r, "Failed to parse maximum number of events '%s': %m", optarg); | |
132 | ||
133 | r = udev_ctrl_send_set_children_max(uctrl, i, timeout); | |
134 | if (r < 0) | |
135 | return r; | |
912541b0 KS |
136 | break; |
137 | } | |
138 | case 't': { | |
1f1a5e8b | 139 | usec_t s; |
ff2c503d | 140 | |
1f1a5e8b SS |
141 | r = parse_sec(optarg, &s); |
142 | if (r < 0) | |
143 | return log_error_errno(r, "Failed to parse timeout value '%s'.", optarg); | |
144 | ||
be6b0c21 | 145 | if (DIV_ROUND_UP(s, USEC_PER_SEC) > INT_MAX) |
bb291b72 YW |
146 | log_error("Timeout value is out of range, ignoring."); |
147 | else | |
148 | timeout = s != USEC_INFINITY ? (int) DIV_ROUND_UP(s, USEC_PER_SEC) : INT_MAX; | |
912541b0 KS |
149 | break; |
150 | } | |
5639df9a | 151 | case 'V': |
51b006e1 | 152 | return print_version(); |
912541b0 | 153 | case 'h': |
bb291b72 YW |
154 | return help(); |
155 | case '?': | |
156 | return -EINVAL; | |
157 | default: | |
158 | assert_not_reached("Unknown option."); | |
912541b0 | 159 | } |
5cc4112e | 160 | |
bb291b72 | 161 | if (optind < argc) { |
1f1a5e8b | 162 | log_error("Extraneous argument: %s", argv[optind]); |
bb291b72 YW |
163 | return -EINVAL; |
164 | } else if (optind == 1) { | |
1f1a5e8b | 165 | log_error("Option missing"); |
bb291b72 YW |
166 | return -EINVAL; |
167 | } | |
168 | ||
169 | return 0; | |
3b47c739 | 170 | } |