/*
* 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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* syseventconfd - The sysevent conf daemon
*
* This daemon is a companion to the sysevent_conf_mod module.
*
* The sysevent_conf_mod module receives events from syseventd,
* and compares those events against event specs in the
* sysevent.conf files. For each matching event spec, the
* specified command is invoked.
*
* The events and associated nvlist are delivered via a door upcall
* from sysevent_conf_mod. Arriving events are queued, and the
* main thread of this daemon dequeues events one by one, and
*
* Since sysevent_conf_mod is running in the context of syseventd,
* from the kernel delivering events to syseventd. We avoid a
* major performance bottleneck in this fashion.
*/
#include <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <strings.h>
#include <unistd.h>
#include <synch.h>
#include <syslog.h>
#include <pthread.h>
#include <door.h>
#include <libsysevent.h>
#include <limits.h>
#include <locale.h>
#include <sys/systeminfo.h>
#include "syseventconfd.h"
#include "syseventconfd_door.h"
#include "message_confd.h"
static int debug_level = 0;
static char *prog;
extern char *optarg;
/*
* Support for door server thread handling
*/
static int cnt_servers = 0;
static void
usage() {
exit(2);
}
static void
{
exit(2);
}
}
int
{
int c;
int fd;
(void) textdomain(TEXT_DOMAIN);
if (getuid() != 0) {
exit(1);
}
} else {
prog++;
}
switch (c) {
case 'd':
break;
case 'r':
/*
* Private flag for suninstall to run
* daemon during install.
*/
break;
case '?':
default:
usage();
}
}
if (fork()) {
exit(0);
}
(void) chdir("/");
(void) setsid();
if (debug_level <= 1) {
closefrom(0);
}
printmsg(1,
"syseventconfd started, debug level = %d\n", debug_level);
/*
* Block all signals to all threads include the main thread.
* The sigwait_thr thread will catch and process all signals.
*/
(void) sigfillset(&set);
/* Create signal catching thread */
exit(2);
}
/*
* done without blocking the door upcall.
*/
/*
* Open communication channel from sysevent_conf_mod
*/
if (open_channel() == NULL) {
exit(1);
}
/*
* main thread to wait for events to arrive and be placed
* on the queue. As events are queued, dequeue them
*/
(void) mutex_lock(&cmd_list_lock);
for (;;) {
(void) mutex_unlock(&cmd_list_lock);
(void) mutex_lock(&cmd_list_lock);
}
/* NOTREACHED */
return (0);
}
/*
* Events sent via the door call from sysevent_conf_mod arrive
* here. Queue each event for the main thread to invoke, and
* context of the door call.
*/
/*ARGSUSED*/
static void
{
return;
}
(void) mutex_lock(&cmd_list_lock);
} else {
}
(void) cond_signal(&cmd_list_cv);
(void) mutex_unlock(&cmd_list_lock);
}
}
/*
* All command attributes are packed into the nvlist bundled with
* the delivered event.
*/
static void
{
char *path;
char *cmdline;
char *file;
int line;
char *user;
char *lp;
char *p;
int i;
return;
}
return;
}
return;
}
return;
}
return;
}
"gid", (int *)&gid) != 0) {
return;
}
} else {
uid = 0;
gid = 0;
}
return;
}
}
if (debug_level >= DBG_EXEC) {
}
if (debug_level >= DBG_EXEC_ARGS) {
}
}
goto again;
return;
}
return;
}
/*
* The child
*/
(void) close(0);
(void) close(1);
(void) close(2);
(void) dup2(0, 1);
(void) dup2(0, 2);
if (i == 0)
if (i != 0) {
_exit(0);
}
}
/*
* Unblock all signals in the child
*/
_exit(0);
}
}
/*
* Thread to handle in-coming signals
*/
static void
{
int sig;
/*
* SIGCHLD is ignored by default, and we need to handle this
* signal to reap the status of all children spawned by
* this daemon.
*/
for (;;) {
(void) sigfillset(&signal_set);
/*
* Block all signals until the signal handler completes
*/
(void) sigfillset(&signal_set);
} else {
}
}
}
/* NOTREACHED */
}
/*
* reapchild - reap the status of each child as it exits
*/
/*ARGSUSED*/
static void
{
char *signam;
int err;
for (;;) {
if (err == -1) {
return;
return;
}
if (debug_level >= DBG_CHILD) {
}
} else {
signam = "";
} else {
}
}
}
}
}
/*
* Fault handler for other signals caught
*/
/*ARGSUSED*/
static void
{
switch (sig) {
case SIGINT:
case SIGSTOP:
case SIGTERM:
case SIGHUP:
exit(1);
/*NOTREACHED*/
}
}
static arg_t *
{
return (NULL);
return (arglist);
}
static void
{
}
}
static int
{
char **new_args;
int len;
return (1);
}
return (0);
}
/*
* next_arg() is used to break up a command line
* into the arguments for execv(2). Break up
* arguments separated by spaces, but respecting
*/
static char *
{
char *start;
char quote;
cp++;
if (*cp == 0) {
*cpp = 0;
return (NULL);
}
cp++;
}
if (*cp == 0) {
*cpp = 0;
return (NULL);
} else {
cp++;
}
} else {
cp++;
}
}
if (*cp != 0)
*cp++ = 0;
return (start);
}
static struct cmd *
{
if (cmd) {
return (NULL);
}
}
return (cmd);
}
static void
{
}
static void *
{
void *p;
p = malloc(n);
if (p == NULL) {
}
return (p);
}
static void *
{
p = realloc(p, n);
if (p == NULL) {
}
return (p);
}
/*
* syserrsg - print error messages to the terminal if not
* yet daemonized or to syslog.
*/
/*PRINTFLIKE1*/
static void
{
}
/*
* printmsg - print messages to the terminal or to syslog
* the following levels are implemented:
*/
/*PRINTFLIKE2*/
static void
{
if (level > debug_level) {
return;
}
}
/* ARGSUSED */
static void *
{
return (NULL);
}
/*
* Control creation of door server threads
*
* If first creation of server thread fails there is nothing
* we can do about. Doors would not work.
*/
/* ARGSUSED */
static void
{
(void) mutex_lock(&create_cnt_lock);
if (++cnt_servers > MAX_SERVER_THREADS) {
cnt_servers--;
(void) mutex_unlock(&create_cnt_lock);
return;
}
(void) mutex_unlock(&create_cnt_lock);
}
static sysevent_handle_t *
{
const char *subclass_list;
return (NULL);
}
/*
* Setup of door server create function to limit the
* amount of door servers
*/
(void) door_server_create(mk_thr_pool);
return (NULL);
}
return (NULL);
}
!= 0) {
(void) sysevent_unbind_subscriber(handle);
(void) sysevent_close_channel(handle);
return (NULL);
}
return (handle);
}