File: | src/usr.sbin/hotplugd/hotplugd.c |
Warning: | line 77, column 2 Value stored to 'argv' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: hotplugd.c,v 1.17 2021/07/12 15:09:21 beck Exp $ */ |
2 | /* |
3 | * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> |
4 | * |
5 | * Permission to use, copy, modify, and distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above |
7 | * copyright notice and this permission notice appear in all copies. |
8 | * |
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ |
17 | |
18 | /* |
19 | * Devices hot plugging daemon. |
20 | */ |
21 | |
22 | #include <sys/types.h> |
23 | #include <sys/device.h> |
24 | #include <sys/hotplug.h> |
25 | #include <sys/wait.h> |
26 | |
27 | #include <err.h> |
28 | #include <errno(*__errno()).h> |
29 | #include <fcntl.h> |
30 | #include <libgen.h> |
31 | #include <limits.h> |
32 | #include <signal.h> |
33 | #include <stdarg.h> |
34 | #include <stdio.h> |
35 | #include <stdlib.h> |
36 | #include <string.h> |
37 | #include <syslog.h> |
38 | #include <unistd.h> |
39 | |
40 | #define _PATH_DEV_HOTPLUG"/dev/hotplug" "/dev/hotplug" |
41 | #define _PATH_ETC_HOTPLUG"/etc/hotplug" "/etc/hotplug" |
42 | #define _PATH_ETC_HOTPLUG_ATTACH"/etc/hotplug" "/attach" _PATH_ETC_HOTPLUG"/etc/hotplug" "/attach" |
43 | #define _PATH_ETC_HOTPLUG_DETACH"/etc/hotplug" "/detach" _PATH_ETC_HOTPLUG"/etc/hotplug" "/detach" |
44 | #define _LOG_TAG"hotplugd" "hotplugd" |
45 | #define _LOG_FACILITY(3<<3) LOG_DAEMON(3<<3) |
46 | #define _LOG_OPT(0x08 | 0x01) (LOG_NDELAY0x08 | LOG_PID0x01) |
47 | |
48 | volatile sig_atomic_t quit = 0; |
49 | char *device = _PATH_DEV_HOTPLUG"/dev/hotplug"; |
50 | int devfd = -1; |
51 | |
52 | void exec_script(const char *, int, char *); |
53 | |
54 | void sigchild(int); |
55 | void sigquit(int); |
56 | __dead__attribute__((__noreturn__)) void usage(void); |
57 | |
58 | int |
59 | main(int argc, char *argv[]) |
60 | { |
61 | int ch; |
62 | struct sigaction sact; |
63 | struct hotplug_event he; |
64 | |
65 | while ((ch = getopt(argc, argv, "d:")) != -1) |
66 | switch (ch) { |
67 | case 'd': |
68 | device = optarg; |
69 | break; |
70 | case '?': |
71 | default: |
72 | usage(); |
73 | /* NOTREACHED */ |
74 | } |
75 | |
76 | argc -= optind; |
77 | argv += optind; |
Value stored to 'argv' is never read | |
78 | if (argc > 0) |
79 | usage(); |
80 | |
81 | if (unveil(device, "r") == -1) |
82 | err(1, "unveil %s", device); |
83 | if (unveil(_PATH_ETC_HOTPLUG_ATTACH"/etc/hotplug" "/attach", "rx") == -1) |
84 | err(1, "unveil %s", _PATH_ETC_HOTPLUG_ATTACH"/etc/hotplug" "/attach"); |
85 | if (unveil(_PATH_ETC_HOTPLUG_DETACH"/etc/hotplug" "/detach", "rx") == -1) |
86 | err(1, "unveil %s", _PATH_ETC_HOTPLUG_DETACH"/etc/hotplug" "/detach"); |
87 | if (pledge("stdio rpath proc exec", NULL((void *)0)) == -1) |
88 | err(1, "pledge"); |
89 | |
90 | if ((devfd = open(device, O_RDONLY0x0000 | O_CLOEXEC0x10000)) == -1) |
91 | err(1, "%s", device); |
92 | |
93 | bzero(&sact, sizeof(sact)); |
94 | sigemptyset(&sact.sa_mask); |
95 | sact.sa_flags = 0; |
96 | sact.sa_handler__sigaction_u.__sa_handler = sigquit; |
97 | sigaction(SIGINT2, &sact, NULL((void *)0)); |
98 | sigaction(SIGQUIT3, &sact, NULL((void *)0)); |
99 | sigaction(SIGTERM15, &sact, NULL((void *)0)); |
100 | sact.sa_handler__sigaction_u.__sa_handler = SIG_IGN(void (*)(int))1; |
101 | sigaction(SIGHUP1, &sact, NULL((void *)0)); |
102 | sact.sa_handler__sigaction_u.__sa_handler = sigchild; |
103 | sact.sa_flags = SA_NOCLDSTOP0x0008; |
104 | sigaction(SIGCHLD20, &sact, NULL((void *)0)); |
105 | |
106 | openlog(_LOG_TAG"hotplugd", _LOG_OPT(0x08 | 0x01), _LOG_FACILITY(3<<3)); |
107 | if (daemon(0, 0) == -1) |
108 | err(1, "daemon"); |
109 | |
110 | syslog(LOG_INFO6, "started"); |
111 | |
112 | while (!quit) { |
113 | if (read(devfd, &he, sizeof(he)) == -1) { |
114 | if (errno(*__errno()) == EINTR4) |
115 | /* ignore */ |
116 | continue; |
117 | syslog(LOG_ERR3, "read: %m"); |
118 | exit(1); |
119 | } |
120 | |
121 | switch (he.he_type) { |
122 | case HOTPLUG_DEVAT0x01: |
123 | syslog(LOG_INFO6, "%s attached, class %d", |
124 | he.he_devname, he.he_devclass); |
125 | exec_script(_PATH_ETC_HOTPLUG_ATTACH"/etc/hotplug" "/attach", he.he_devclass, |
126 | he.he_devname); |
127 | break; |
128 | case HOTPLUG_DEVDT0x02: |
129 | syslog(LOG_INFO6, "%s detached, class %d", |
130 | he.he_devname, he.he_devclass); |
131 | exec_script(_PATH_ETC_HOTPLUG_DETACH"/etc/hotplug" "/detach", he.he_devclass, |
132 | he.he_devname); |
133 | break; |
134 | default: |
135 | syslog(LOG_NOTICE5, "unknown event (0x%x)", he.he_type); |
136 | } |
137 | } |
138 | |
139 | syslog(LOG_INFO6, "terminated"); |
140 | |
141 | closelog(); |
142 | close(devfd); |
143 | |
144 | return (0); |
145 | } |
146 | |
147 | void |
148 | exec_script(const char *file, int class, char *name) |
149 | { |
150 | char strclass[8]; |
151 | pid_t pid; |
152 | |
153 | snprintf(strclass, sizeof(strclass), "%d", class); |
154 | |
155 | if (access(file, X_OK0x01 | R_OK0x04) == -1) { |
156 | if (errno(*__errno()) != ENOENT2) |
157 | syslog(LOG_ERR3, "%s: %m", file); |
158 | return; |
159 | } |
160 | |
161 | if ((pid = fork()) == -1) { |
162 | syslog(LOG_ERR3, "fork: %m"); |
163 | return; |
164 | } |
165 | if (pid == 0) { |
166 | /* child process */ |
167 | char filebuf[PATH_MAX1024]; |
168 | |
169 | strlcpy(filebuf, file, sizeof(filebuf)); |
170 | execl(file, basename(filebuf), strclass, name, (char *)NULL((void *)0)); |
171 | syslog(LOG_ERR3, "execl %s: %m", file); |
172 | _exit(1); |
173 | /* NOTREACHED */ |
174 | } |
175 | } |
176 | |
177 | /* ARGSUSED */ |
178 | void |
179 | sigchild(int signum) |
180 | { |
181 | struct syslog_data sdata = SYSLOG_DATA_INIT{0, (const char *)0, (1<<3), 0xff}; |
182 | int saved_errno, status; |
183 | pid_t pid; |
184 | |
185 | saved_errno = errno(*__errno()); |
186 | |
187 | sdata.log_tag = _LOG_TAG"hotplugd"; |
188 | sdata.log_fac = _LOG_FACILITY(3<<3); |
189 | sdata.log_stat = _LOG_OPT(0x08 | 0x01); |
190 | |
191 | while ((pid = waitpid(WAIT_ANY(-1), &status, WNOHANG1)) != 0) { |
192 | if (pid == -1) { |
193 | if (errno(*__errno()) == EINTR4) |
194 | continue; |
195 | if (errno(*__errno()) != ECHILD10) |
196 | syslog_r(LOG_ERR3, &sdata, "waitpid: %m"); |
197 | break; |
198 | } |
199 | |
200 | if (WIFEXITED(status)(((status) & 0177) == 0)) { |
201 | if (WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff) != 0) { |
202 | syslog_r(LOG_NOTICE5, &sdata, |
203 | "child exit status: %d", |
204 | WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff)); |
205 | } |
206 | } else { |
207 | syslog_r(LOG_NOTICE5, &sdata, |
208 | "child is terminated abnormally"); |
209 | } |
210 | } |
211 | |
212 | errno(*__errno()) = saved_errno; |
213 | } |
214 | |
215 | /* ARGSUSED */ |
216 | void |
217 | sigquit(int signum) |
218 | { |
219 | quit = 1; |
220 | } |
221 | |
222 | __dead__attribute__((__noreturn__)) void |
223 | usage(void) |
224 | { |
225 | extern char *__progname; |
226 | |
227 | fprintf(stderr(&__sF[2]), "usage: %s [-d device]\n", __progname); |
228 | exit(1); |
229 | } |