4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 * Copyright (c) 2010, Intel Corporation.
28 * All rights reserved.
31 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/sysevent/eventdefs.h>
35 #include <sys/sysevent/dr.h>
47 #include <config_admin.h>
49 #include <libsysevent.h>
52 /* Signal handler type */
53 typedef void (sig_handler_t
)(int);
55 #define ACPIHPD_PID_FILE "/var/run/acpihpd.pid" /* lock file path */
62 static sysevent_handle_t
*s_acpihpd_hdl
;
64 static int daemon_init(void);
65 static void daemon_quit(int);
66 static int set_sig_handler(int, sig_handler_t
*);
67 static int acpihpd_init(void);
68 static void acpihpd_fini(void);
69 static void acpihpd_event(sysevent_t
*);
70 extern void notify_hotplug(sysevent_t
*ev
);
71 void debug_print(int, const char *, ...);
74 main(int argc
, char *argv
[])
78 /* Get Program Name */
79 if ((g_prog_name
= strrchr(argv
[0], '/')) == NULL
) {
80 g_prog_name
= argv
[0];
85 while ((c
= getopt(argc
, argv
, ":d:")) != -1) {
88 g_debuglevel
= atoi(optarg
);
89 if ((g_debuglevel
< 0) || (g_debuglevel
> 2)) {
96 "missed argument for option %c.", optopt
);
100 syslog(LOG_ERR
, "unrecognized option %c.", optopt
);
105 s_acpihpd_hdl
= NULL
;
107 /* Check the daemon running lock and initialize the signal */
108 if (daemon_init() != 0) {
109 debug_print(0, "%s could not startup!", g_prog_name
);
110 exit(SMF_EXIT_ERR_FATAL
);
113 /* Subscribe to the hotplug event */
114 if (acpihpd_init() != 0) {
115 debug_print(0, "%s could not startup!", g_prog_name
);
116 daemon_quit(SMF_EXIT_ERR_FATAL
);
119 debug_print(2, "daemon is running.");
125 return (SMF_EXIT_OK
);
135 if (geteuid() != 0) {
136 debug_print(0, "must be root to execute %s", g_prog_name
);
140 if ((pid
= fork()) < 0) {
145 /* Parent to exit. */
153 (void) open("/dev/null", O_RDONLY
);
154 (void) open("/dev/null", O_WRONLY
);
156 (void) openlog(g_prog_name
, LOG_PID
, LOG_DAEMON
);
159 * Create the lock file for singleton
161 if ((s_pid_fd
= open(ACPIHPD_PID_FILE
, O_RDWR
| O_CREAT
, 0644)) < 0) {
162 debug_print(0, "could not create pid file: %s",
167 if (lockf(s_pid_fd
, F_TLOCK
, 0L) < 0) {
168 if (errno
== EACCES
|| errno
== EAGAIN
) {
169 debug_print(0, "another acpihpd is already running");
171 debug_print(0, "could not lock pid file");
177 (void) ftruncate(s_pid_fd
, 0);
178 i
= sprintf(pid_str
, "%ld", (long)getpid());
179 while ((ret
= write(s_pid_fd
, pid_str
, i
)) != i
) {
180 if (errno
== EINTR
) {
184 debug_print(0, "pid file write failed: %s",
190 if (set_sig_handler(SIGTERM
, (sig_handler_t
*)daemon_quit
) != 0) {
191 debug_print(2, "could not set signal handler(SIGTERM)");
195 if (set_sig_handler(SIGQUIT
, (sig_handler_t
*)daemon_quit
) != 0) {
196 debug_print(2, "could not set signal handler(SIGQUIT)");
200 if (set_sig_handler(SIGINT
, (sig_handler_t
*)daemon_quit
) != 0) {
201 debug_print(2, "could not set signal handler(SIGINT)");
205 if (set_sig_handler(SIGCHLD
, SIG_IGN
) != 0) {
206 debug_print(2, "could not set signal handler(SIGCHLD)");
214 daemon_quit(int signo
)
219 debug_print(1, "daemon quit [signal#:%d].", signo
);
222 (void) set_sig_handler(SIGTERM
, SIG_IGN
);
224 (void) kill(-pgid
, SIGTERM
);
225 (void) close(s_pid_fd
);
226 (void) unlink(ACPIHPD_PID_FILE
);
235 set_sig_handler(int sig
, sig_handler_t
*handler
)
237 struct sigaction act
;
239 act
.sa_handler
= handler
;
241 if (sig
== SIGCHLD
&& handler
== SIG_IGN
) {
242 act
.sa_flags
|= SA_NOCLDWAIT
;
245 (void) sigemptyset(&act
.sa_mask
);
246 if (sigaction(sig
, &act
, NULL
) < 0) {
256 const char *subclass
= ESC_DR_REQ
;
258 debug_print(2, "acpihpd_init");
260 if ((s_acpihpd_hdl
= sysevent_bind_handle(acpihpd_event
)) == NULL
) {
261 debug_print(2, "could not bind to sysevent.");
265 if (sysevent_subscribe_event(s_acpihpd_hdl
, EC_DR
, &subclass
, 1) != 0) {
266 debug_print(2, "could not subscribe an event.");
267 sysevent_unbind_handle(s_acpihpd_hdl
);
268 s_acpihpd_hdl
= NULL
;
278 debug_print(2, "acpihpd_fini");
280 if (s_acpihpd_hdl
!= NULL
) {
281 sysevent_unsubscribe_event(s_acpihpd_hdl
, EC_DR
);
282 sysevent_unbind_handle(s_acpihpd_hdl
);
287 acpihpd_event(sysevent_t
*ev
)
289 debug_print(2, "*** got an event ***");
291 /* Inform cfgadm of the hot-plug event. */
296 debug_print(int level
, const char *fmt
, ...)
301 if (level
<= g_debuglevel
) {
321 vsyslog(pri
, fmt
, ap
);