rcm_main.c revision 47856d53b04240402f14fafd3c9c7201f4809da4
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Reconfiguration Coordination Daemon
*
* Accept RCM messages in the form of RCM events and process them
* - to build and update the system resource map
* - to allow clients to register/unregister for resource
* - to allow dr initiators to offline a resource before removal
*
* The goal is to enable fully automated Dynamic Reconfiguration and better
* DR information tracking.
*/
#include <librcm_event.h>
#include "rcm_impl.h"
/* will run in daemon mode if debug level < DEBUG_LEVEL_FORK */
#define DEBUG_LEVEL_FORK RCM_DEBUG
#define DAEMON_LOCK_FILE "/var/run/rcm_daemon_lock"
static int hold_daemon_lock;
static int daemon_lock_fd;
static const char *daemon_lock_file = DAEMON_LOCK_FILE;
int debug_level = 0;
static int idle_timeout;
static int logflag = 0;
static char *prog;
static void usage(void);
static void catch_sighup(void);
static void catch_sigusr1(void);
static pid_t enter_daemon_lock(void);
static void exit_daemon_lock(void);
extern void init_poll_thread();
extern void cleanup_poll_thread();
/*
* Print command line syntax for starting rcm_daemon
*/
static void
usage() {
}
/*
*/
static void
rcmd_cleanup(int status)
{
if (status == 0) {
gettext("rcm_daemon normal exit\n"));
} else {
}
if (hold_daemon_lock) {
}
}
void
{
}
/*
* When SIGHUP is received, reload modules at the next safe moment (when
* there is no DR activity.
*/
void
catch_sighup(void)
{
gettext("SIGHUP received, will exit when daemon is idle\n"));
}
/*
* When SIGUSR1 is received, exit the thread
*/
void
catch_sigusr1(void)
{
thr_self());
}
/*
* Use an advisory lock to ensure that only one daemon process is
* active at any point in time.
*/
static pid_t
enter_daemon_lock(void)
{
"enter_daemon_lock: lock file = %s\n", daemon_lock_file);
if (daemon_lock_fd < 0) {
}
hold_daemon_lock = 1;
return (getpid());
}
/* failed to get lock, attempt to find lock owner */
}
/* die a horrible death */
/*NOTREACHED*/
}
/*
* Drop the advisory daemon lock, close lock file
*/
static void
exit_daemon_lock(void)
{
}
(void) close(daemon_lock_fd);
}
/*PRINTFLIKE2*/
static void
{
int log_level;
if (!logflag) {
/*
* RCM_ERROR goes to stderr, others go to stdout
*/
return;
}
/*
* translate RCM_* to LOG_*
*/
switch (level) {
case RCM_ERROR:
break;
case RCM_WARNING:
break;
case RCM_NOTICE:
break;
case RCM_INFO:
break;
case RCM_DEBUG:
break;
default:
/*
* Don't log RCM_TRACEn messages
*/
return;
}
}
/*
* print error messages to the terminal or to syslog
*/
void
{
if (level > debug_level) {
return;
}
}
/*
* Print error messages to the terminal or to syslog.
* Same as rcm_log_message except that it does not check for
* level > debug_level
* allowing callers to override the global debug_level.
*/
void
{
}
/*
* grab daemon_lock and direct messages to syslog
*/
static void
{
(void) chdir("/");
(void) setsid();
(void) close(0);
(void) close(1);
(void) close(2);
(void) dup2(0, 1);
(void) dup2(0, 2);
logflag = 1;
}
int
{
int c;
extern char *optarg;
#ifndef TEXT_DOMAIN
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
} else {
prog++;
}
/*
* process arguments
*/
if (argc > 3) {
usage();
}
switch (c) {
case 'd':
break;
case 't':
break;
case '?':
default:
usage();
/*NOTREACHED*/
}
}
/*
* Check permission
*/
if (getuid() != 0) {
prog);
}
/*
* When rcm_daemon is started by a call to librcm, it inherits file
* descriptors from the DR initiator making a call. The file
* descriptors may correspond to devices that can be removed by DR.
* Since keeping them remain opened is problematic, close everything
*/
closefrom(3);
/*
* When rcm_daemon is started by the caller, it will inherit the
* signal block mask. We unblock all signals to make sure the
* signal handling will work normally.
*/
(void) sigfillset(&mask);
/*
* block SIGUSR1, use it for killing specific threads
*/
(void) sigemptyset(&mask);
/*
* Setup signal handlers for SIGHUP and SIGUSR1
* SIGHUP - causes a "delayed" daemon exit, effectively the same
* as a daemon restart.
* SIGUSR1 - causes a thr_exit(). Unblocked in selected threads.
*/
/*
* ignore SIGPIPE so that the rcm daemon does not exit when it
* attempts to read or write from a pipe whose corresponding
* rcm script process exited.
*/
/*
* run in daemon mode
*/
if (debug_level < DEBUG_LEVEL_FORK) {
if (fork()) {
exit(0);
}
}
/* only one daemon can run at a time */
}
prog, debug_level);
/*
* Set daemon state to block RCM requests before rcm_daemon is
* fully initialized. See rcmd_thr_incr().
*/
/*
* create rcm_daemon door and set permission to 0400
*/
gettext("cannot create door service: %s\n"),
}
init_poll_thread(); /* initialize poll thread related data */
/*
* Initialize database by asking modules to register.
*/
rcmd_db_init();
/*
* Initialize locking, including lock recovery in the event of
* unexpected daemon failure.
*/
/*
* Start accepting normal requests
*/
/*
* Start cleanup thread
*/
/*
* Loop within daemon and return after a period of inactivity.
*/
rcmd_cleanup(0);
return (0);
}