]>
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" | |
a82340cc | 43 | " --ping Wait for udev to respond to a ping message\n" |
a04a9027 | 44 | " -t --timeout=SECONDS Maximum time to block for a reply\n" |
5ac0162c | 45 | , program_invocation_short_name); |
bb291b72 YW |
46 | |
47 | return 0; | |
d59f11e1 | 48 | } |
3b47c739 | 49 | |
3d05193e | 50 | int control_main(int argc, char *argv[], void *userdata) { |
8e766630 | 51 | _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL; |
3797776e | 52 | usec_t timeout = 60 * USEC_PER_SEC; |
bb291b72 | 53 | int c, r; |
2b725651 | 54 | |
a82340cc YW |
55 | enum { |
56 | ARG_PING = 0x100, | |
57 | }; | |
58 | ||
912541b0 | 59 | static const struct option options[] = { |
a82340cc YW |
60 | { "exit", no_argument, NULL, 'e' }, |
61 | { "log-priority", required_argument, NULL, 'l' }, | |
62 | { "stop-exec-queue", no_argument, NULL, 's' }, | |
63 | { "start-exec-queue", no_argument, NULL, 'S' }, | |
64 | { "reload", no_argument, NULL, 'R' }, | |
65 | { "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */ | |
66 | { "property", required_argument, NULL, 'p' }, | |
67 | { "env", required_argument, NULL, 'p' }, /* alias for -p */ | |
68 | { "children-max", required_argument, NULL, 'm' }, | |
69 | { "ping", no_argument, NULL, ARG_PING }, | |
70 | { "timeout", required_argument, NULL, 't' }, | |
71 | { "version", no_argument, NULL, 'V' }, | |
72 | { "help", no_argument, NULL, 'h' }, | |
912541b0 KS |
73 | {} |
74 | }; | |
3b47c739 | 75 | |
bb291b72 YW |
76 | r = must_be_root(); |
77 | if (r < 0) | |
78 | return r; | |
79 | ||
c494b739 YW |
80 | if (running_in_chroot() > 0) { |
81 | log_info("Running in chroot, ignoring request."); | |
82 | return 0; | |
83 | } | |
84 | ||
bb291b72 | 85 | if (argc <= 1) |
cf7f5013 YW |
86 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), |
87 | "This command expects one or more options."); | |
2b725651 | 88 | |
100bc5bf YW |
89 | r = udev_ctrl_new(&uctrl); |
90 | if (r < 0) | |
91 | return log_error_errno(r, "Failed to initialize udev control: %m"); | |
2b725651 | 92 | |
5639df9a | 93 | while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0) |
7643ac9a | 94 | switch (c) { |
912541b0 | 95 | case 'e': |
78467aeb YW |
96 | r = udev_ctrl_send_exit(uctrl); |
97 | if (r == -ENOANO) | |
98 | log_warning("Cannot specify --exit after --exit, ignoring."); | |
99 | else if (r < 0) | |
a0b60b8a | 100 | return log_error_errno(r, "Failed to send exit request: %m"); |
912541b0 | 101 | break; |
46f0fbd8 YW |
102 | case 'l': |
103 | r = log_level_from_string(optarg); | |
104 | if (r < 0) | |
105 | return log_error_errno(r, "Failed to parse log priority '%s': %m", optarg); | |
bb291b72 | 106 | |
78467aeb YW |
107 | r = udev_ctrl_send_set_log_level(uctrl, r); |
108 | if (r == -ENOANO) | |
109 | log_warning("Cannot specify --log-priority after --exit, ignoring."); | |
110 | else if (r < 0) | |
a0b60b8a | 111 | return log_error_errno(r, "Failed to send request to set log level: %m"); |
912541b0 | 112 | break; |
912541b0 | 113 | case 's': |
78467aeb YW |
114 | r = udev_ctrl_send_stop_exec_queue(uctrl); |
115 | if (r == -ENOANO) | |
116 | log_warning("Cannot specify --stop-exec-queue after --exit, ignoring."); | |
117 | else if (r < 0) | |
a0b60b8a | 118 | return log_error_errno(r, "Failed to send request to stop exec queue: %m"); |
912541b0 KS |
119 | break; |
120 | case 'S': | |
78467aeb YW |
121 | r = udev_ctrl_send_start_exec_queue(uctrl); |
122 | if (r == -ENOANO) | |
123 | log_warning("Cannot specify --start-exec-queue after --exit, ignoring."); | |
124 | else if (r < 0) | |
a0b60b8a | 125 | return log_error_errno(r, "Failed to send request to start exec queue: %m"); |
912541b0 KS |
126 | break; |
127 | case 'R': | |
78467aeb YW |
128 | r = udev_ctrl_send_reload(uctrl); |
129 | if (r == -ENOANO) | |
130 | log_warning("Cannot specify --reload after --exit, ignoring."); | |
131 | else if (r < 0) | |
a0b60b8a | 132 | return log_error_errno(r, "Failed to send reload request: %m"); |
912541b0 KS |
133 | break; |
134 | case 'p': | |
47c8fcbe YW |
135 | if (!strchr(optarg, '=')) |
136 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "expect <KEY>=<value> instead of '%s'", optarg); | |
137 | ||
78467aeb YW |
138 | r = udev_ctrl_send_set_env(uctrl, optarg); |
139 | if (r == -ENOANO) | |
140 | log_warning("Cannot specify --property after --exit, ignoring."); | |
141 | else if (r < 0) | |
a0b60b8a | 142 | return log_error_errno(r, "Failed to send request to update environment: %m"); |
912541b0 KS |
143 | break; |
144 | case 'm': { | |
bb291b72 | 145 | unsigned i; |
ff2c503d | 146 | |
bb291b72 YW |
147 | r = safe_atou(optarg, &i); |
148 | if (r < 0) | |
149 | return log_error_errno(r, "Failed to parse maximum number of events '%s': %m", optarg); | |
150 | ||
78467aeb YW |
151 | r = udev_ctrl_send_set_children_max(uctrl, i); |
152 | if (r == -ENOANO) | |
153 | log_warning("Cannot specify --children-max after --exit, ignoring."); | |
154 | else if (r < 0) | |
a0b60b8a | 155 | return log_error_errno(r, "Failed to send request to set number of children: %m"); |
912541b0 KS |
156 | break; |
157 | } | |
a82340cc | 158 | case ARG_PING: |
78467aeb YW |
159 | r = udev_ctrl_send_ping(uctrl); |
160 | if (r == -ENOANO) | |
161 | log_error("Cannot specify --ping after --exit, ignoring."); | |
162 | else if (r < 0) | |
163 | return log_error_errno(r, "Failed to send a ping message: %m"); | |
a82340cc | 164 | break; |
3797776e YW |
165 | case 't': |
166 | r = parse_sec(optarg, &timeout); | |
1f1a5e8b | 167 | if (r < 0) |
3797776e | 168 | return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg); |
912541b0 | 169 | break; |
5639df9a | 170 | case 'V': |
51b006e1 | 171 | return print_version(); |
912541b0 | 172 | case 'h': |
bb291b72 YW |
173 | return help(); |
174 | case '?': | |
175 | return -EINVAL; | |
176 | default: | |
177 | assert_not_reached("Unknown option."); | |
912541b0 | 178 | } |
5cc4112e | 179 | |
cf7f5013 YW |
180 | if (optind < argc) |
181 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), | |
182 | "Extraneous argument: %s", argv[optind]); | |
bb291b72 | 183 | |
78467aeb YW |
184 | r = udev_ctrl_wait(uctrl, timeout); |
185 | if (r < 0) | |
186 | return log_error_errno(r, "Failed to wait for daemon to reply: %m"); | |
187 | ||
bb291b72 | 188 | return 0; |
3b47c739 | 189 | } |