1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <sys/param.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <sys/sysevent/eventdefs.h>
32 #include <sys/sysevent/dr.h>
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <syslog.h>
39 #include <string.h>
40 #include <fcntl.h>
41 #include <errno.h>
42 #include <time.h>
43 #include <config_admin.h>
44 #include <libsysevent.h>
45
46
47 /* Signal handler type */
48 typedef void (SigHandler)(int);
49 /* oplhpd process id file descriptor */
50 static int pid_fd;
51
52 /* Program Name */
53 char *oplhpd_prog_name = "";
54
55 /* Macros */
56 #define OPLHPD_DEV_DIR "/devices" /* device base dir */
57 #define OPLHPD_PID_FILE "/var/run/oplhpd.pid" /* lock file path */
58 #define OPLHPD_PROG_NAME oplhpd_prog_name
59
60 /* Event handler to get information */
61 static sysevent_handle_t *oplhpd_hdl;
62
63
64 /*
65 * Function Prototypes
66 */
67 void quit_daemon(int signo);
68 SigHandler *set_sig_handler(int sig, SigHandler *handler);
69 void init_daemon(void);
70 void oplhpd_init(void);
71 void oplhpd_fini(void);
72 static void oplhpd_event(sysevent_t *ev);
73
74 extern void notify_scf_of_hotplug(sysevent_t *ev);
75
76
77 /*
78 * Terminate and Quit Daemon Process.
79 * signo = 0 ... normal quit
80 * > 0 ... signaled quit
81 * < 0 ... failure quit
82 */
83 void
quit_daemon(int signo)84 quit_daemon(int signo)
85 {
86 int status = 0;
87 id_t pgid;
88
89 syslog(LOG_DEBUG, "*** quit daemon [pid:%d, signal#:%d].\n",
90 getpid(), signo);
91
92 (void) set_sig_handler(SIGTERM, SIG_IGN);
93 pgid = getpgrp();
94 (void) kill(-pgid, SIGTERM);
95
96 (void) close(pid_fd);
97 (void) unlink(OPLHPD_PID_FILE); /* clean up lock file */
98
99 if (signo < 0) {
100 status = signo;
101 }
102 _exit(status);
103 }
104
105 /*
106 * Setting the signal handler utility
107 */
108 SigHandler *
set_sig_handler(int sig,SigHandler * handler)109 set_sig_handler(int sig, SigHandler *handler)
110 {
111 struct sigaction act, oact;
112
113 act.sa_handler = handler;
114 act.sa_flags = 0;
115 if (sig == SIGCHLD && handler == SIG_IGN) {
116 act.sa_flags |= SA_NOCLDWAIT;
117 }
118 (void) sigemptyset(&act.sa_mask);
119 (void) sigemptyset(&oact.sa_mask);
120 if (sigaction(sig, &act, &oact) < 0) {
121 return (SIG_ERR);
122 }
123
124 return (oact.sa_handler);
125 }
126
127 /*
128 * Setup oplhpd daemon
129 */
130 void
init_daemon()131 init_daemon()
132 {
133 int i;
134 int ret;
135 int fd;
136 pid_t pid;
137 char pid_str[32];
138
139 if (geteuid() != 0) {
140 syslog(LOG_ERR, "must be root to execute %s\n",
141 OPLHPD_PROG_NAME);
142 exit(1);
143 }
144
145 /*
146 * Daemonize
147 */
148 if ((pid = fork()) < 0) {
149 perror("fork failed");
150 exit(1);
151 }
152 if (pid > 0) {
153 /* Parent, exit. */
154 exit(0);
155 }
156 (void) setsid();
157 (void) chdir("/");
158 (void) umask(0);
159 (void) closefrom(0);
160 (void) open("/dev/null", O_RDONLY);
161 (void) open("/dev/null", O_WRONLY);
162 (void) dup(1);
163
164 (void) openlog(OPLHPD_PROG_NAME, LOG_PID, LOG_DAEMON);
165
166 /*
167 * Create the lock file for singletonize
168 */
169 if ((pid_fd = open(OPLHPD_PID_FILE, O_RDWR | O_CREAT, 0644)) < 0) {
170 syslog(LOG_ERR, "could not create pid file: %s",
171 strerror(errno));
172 exit(1);
173 }
174 if (lockf(pid_fd, F_TLOCK, 0L) < 0) {
175 if (errno == EACCES || errno == EAGAIN) {
176 syslog(LOG_ERR, "another oplhpd is already running");
177 } else {
178 syslog(LOG_ERR, "could not lock pid file");
179 }
180 exit(1);
181 }
182
183 (void) ftruncate(pid_fd, 0);
184 i = sprintf(pid_str, "%d\n", getpid());
185 while ((ret = write(pid_fd, pid_str, i)) != i) {
186 if (errno == EINTR) {
187 continue;
188 }
189 if (ret < 0) {
190 syslog(LOG_ERR, "pid file write fail: %s",
191 strerror(errno));
192 exit(1);
193 }
194 }
195
196 /*
197 * Set signal handlers
198 */
199 (void) set_sig_handler(SIGTERM, (SigHandler *)quit_daemon);
200 (void) set_sig_handler(SIGQUIT, (SigHandler *)quit_daemon);
201 (void) set_sig_handler(SIGINT, (SigHandler *)quit_daemon);
202 (void) set_sig_handler(SIGCHLD, SIG_IGN);
203 }
204
205 static void
oplhpd_event(sysevent_t * ev)206 oplhpd_event(sysevent_t *ev)
207 {
208 /*
209 * Inform the SCF of the change in the state of the pci hot plug
210 * cassette.
211 */
212 notify_scf_of_hotplug(ev);
213
214 }
215
216 /*
217 * Initialization for hotplug event.
218 * - Bind event handler.
219 * - Subscribe the handler to the hotplug event.
220 */
221 void
oplhpd_init()222 oplhpd_init()
223 {
224 const char *subclass = ESC_DR_AP_STATE_CHANGE;
225
226 syslog(LOG_DEBUG, "oplhpd_init");
227
228 oplhpd_hdl = sysevent_bind_handle(oplhpd_event);
229 if (oplhpd_hdl == NULL) {
230 syslog(LOG_ERR, "event handler bind fail");
231 quit_daemon(-1);
232 }
233
234 if (sysevent_subscribe_event(oplhpd_hdl, EC_DR, &subclass, 1) != 0) {
235 syslog(LOG_ERR, "event handler subscribe fail");
236 sysevent_unbind_handle(oplhpd_hdl);
237 quit_daemon(-1);
238 }
239
240 for (;;) {
241 (void) pause();
242 }
243 }
244
245 void
oplhpd_fini()246 oplhpd_fini()
247 {
248 if (oplhpd_hdl != NULL) {
249 sysevent_unsubscribe_event(oplhpd_hdl, EC_DR);
250 sysevent_unbind_handle(oplhpd_hdl);
251 }
252 }
253
254 int
main(int argc,char * argv[])255 main(int argc, char *argv[])
256 {
257 int opt;
258
259 /* Get Program Name */
260 if ((oplhpd_prog_name = strrchr(argv[0], '/')) == NULL) {
261 oplhpd_prog_name = argv[0];
262 } else {
263 oplhpd_prog_name++;
264 }
265
266 /* Check the daemon running lock and Initialize the signal */
267 init_daemon();
268
269 /* Subscribe to the hotplug event */
270 oplhpd_init();
271
272 /* Unsubscribe the hotplug event */
273 oplhpd_fini();
274
275 return (0);
276 }
277