1 /* $OpenBSD: hotplugd.c,v 1.11 2009/06/26 01:06:04 kurt Exp $ */
3 * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
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.
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.
19 * Devices hot plugging daemon.
22 #include <sys/types.h>
23 #include <sys/device.h>
24 #include <sys/hotplug.h>
40 #define _PATH_DEV_HOTPLUG "/dev/hotplug"
41 #define _PATH_ETC_HOTPLUG "/etc/hotplug"
42 #define _PATH_ETC_HOTPLUG_ATTACH _PATH_ETC_HOTPLUG "/attach"
43 #define _PATH_ETC_HOTPLUG_DETACH _PATH_ETC_HOTPLUG "/detach"
44 #define _LOG_TAG "hotplugd"
45 #define _LOG_FACILITY LOG_DAEMON
46 #define _LOG_OPT (LOG_NDELAY | LOG_PID)
48 volatile sig_atomic_t quit
= 0;
49 char *device
= _PATH_DEV_HOTPLUG
;
52 void exec_script(const char *, int, char *);
55 __dead
void usage(void);
58 main(int argc
, char *argv
[])
61 struct sigaction sact
;
62 struct hotplug_event he
;
64 while ((ch
= getopt(argc
, argv
, "d:")) != -1)
80 if ((devfd
= open(device
, O_RDONLY
)) == -1)
83 bzero(&sact
, sizeof(sact
));
84 sigemptyset(&sact
.sa_mask
);
86 sact
.sa_handler
= sigquit
;
87 sigaction(SIGINT
, &sact
, NULL
);
88 sigaction(SIGQUIT
, &sact
, NULL
);
89 sigaction(SIGTERM
, &sact
, NULL
);
90 sact
.sa_handler
= SIG_IGN
;
91 sigaction(SIGHUP
, &sact
, NULL
);
92 sact
.sa_handler
= sigchild
;
93 sact
.sa_flags
= SA_NOCLDSTOP
;
94 sigaction(SIGCHLD
, &sact
, NULL
);
96 openlog(_LOG_TAG
, _LOG_OPT
, _LOG_FACILITY
);
97 if (daemon(0, 0) == -1)
100 syslog(LOG_INFO
, "started");
103 if (read(devfd
, &he
, sizeof(he
)) == -1) {
107 syslog(LOG_ERR
, "read: %m");
111 switch (he
.he_type
) {
113 syslog(LOG_INFO
, "%s attached, class %d",
114 he
.he_devname
, he
.he_devclass
);
115 exec_script(_PATH_ETC_HOTPLUG_ATTACH
, he
.he_devclass
,
119 syslog(LOG_INFO
, "%s detached, class %d",
120 he
.he_devname
, he
.he_devclass
);
121 exec_script(_PATH_ETC_HOTPLUG_DETACH
, he
.he_devclass
,
125 syslog(LOG_NOTICE
, "unknown event (0x%x)", he
.he_type
);
129 syslog(LOG_INFO
, "terminated");
138 exec_script(const char *file
, int class, char *name
)
143 snprintf(strclass
, sizeof(strclass
), "%d", class);
145 if (access(file
, X_OK
| R_OK
)) {
146 syslog(LOG_ERR
, "could not access %s", file
);
150 if ((pid
= fork()) == -1) {
151 syslog(LOG_ERR
, "fork: %m");
156 execl(file
, basename(file
), strclass
, name
, (char *)NULL
);
157 syslog(LOG_ERR
, "execl %s: %m", file
);
167 struct syslog_data sdata
= SYSLOG_DATA_INIT
;
168 int saved_errno
, status
;
173 sdata
.log_tag
= _LOG_TAG
;
174 sdata
.log_fac
= _LOG_FACILITY
;
175 sdata
.log_stat
= _LOG_OPT
;
177 while ((pid
= waitpid(WAIT_ANY
, &status
, WNOHANG
)) != 0) {
182 syslog_r(LOG_ERR
, &sdata
, "waitpid: %m");
186 if (WIFEXITED(status
)) {
187 if (WEXITSTATUS(status
) != 0) {
188 syslog_r(LOG_NOTICE
, &sdata
,
189 "child exit status: %d",
190 WEXITSTATUS(status
));
193 syslog_r(LOG_NOTICE
, &sdata
,
194 "child is terminated abnormally");
211 extern char *__progname
;
213 fprintf(stderr
, "usage: %s [-d device]\n", __progname
);