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