fmd_main.c revision 0166a357ec3216d4c268b281d096985e7b0c9e60
/*
* 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.
*/
#include <sys/resource.h>
#include <priv_utils.h>
#include <signal.h>
#include <unistd.h>
#include <limits.h>
#include <fcntl.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <fmd_error.h>
#include <fmd_string.h>
#include <fmd_conf.h>
#include <fmd_dispq.h>
#include <fmd_subr.h>
#include <fmd.h>
/*
* For DEBUG builds, we define a set of hooks for libumem that provide useful
* default settings for the allocator's debugging facilities.
*/
#ifdef DEBUG
const char *
{
return ("default,verbose"); /* $UMEM_DEBUG setting */
}
const char *
_umem_logging_init(void)
{
return ("fail,contents"); /* $UMEM_LOGGING setting */
}
#endif /* DEBUG */
/*
* We use a two-phase algorithm for becoming a daemon because we want the
* daemon process (the child) to do the work of becoming MT-hot and opening our
* event transport. Since these operations can fail and need to result in the
* daemon failing to start, the parent must wait until fmd_run() completes to
* know whether it can return zero or non-zero status to the invoking command.
* The parent waits on a pipe inside this function to read the exit status.
* The child gets the write-end of the pipe returned by daemonize_init() and
* then fmd_run() uses the pipe to set the exit status and detach the parent.
*/
static int
daemonize_init(void)
{
/*
* Set our per-process core file path to leave core files in our
* and make sure that there is no restriction on core file size.
*/
/*
* Claim all the file descriptors we can.
*/
}
/*
* Reset all of our privilege sets to the minimum set of required
* privileges. We continue to run as root so that files we create
* such as logs and checkpoints are secured in the /var filesystem.
*/
0, 0, /* run as uid 0 and gid 0 */
PRIV_SYS_NET_CONFIG, NULL) != 0)
/*
* Block all signals prior to the fork and leave them blocked in the
* parent so we don't get in a situation where the parent gets SIGINT
* and returns non-zero exit status and the child is actually running.
* In the child, restore the signal mask once we've done our setsid().
*/
(void) sigfillset(&set);
/*
* If we're the parent process, wait for either the child to send us
* the appropriate exit status over the pipe or for the read to fail
* (presumably with 0 for EOF if our child terminated abnormally).
* If the read fails, exit with either the child's exit status if it
* exited or with FMD_EXIT_ERROR if it died from a fatal signal.
*/
if (pid != 0) {
}
(void) setsid();
(void) chdir("/");
(void) umask(022);
return (pfds[1]);
}
static void
daemonize_fini(int fd)
{
}
}
static void
{
}
static int
{
"Usage: %s [-V] [-f file] [-o opt=val] [-R dir]\n", arg0);
return (FMD_EXIT_USAGE);
}
int
{
const char optstr[] = "f:o:R:V";
char *p;
/*
* Parse the command-line once to validate all options and retrieve
* any overrides for our configuration file and root directory.
*/
switch (c) {
case 'f':
break;
case 'o':
break; /* handle -o below */
case 'R':
break;
case 'V':
opt_V++;
break;
default:
}
}
if (opt_V) {
#ifdef DEBUG
const char *debug = " (DEBUG)";
#else
const char *debug = "";
#endif
(void) printf("%s: version %s%s\n",
return (FMD_EXIT_SUCCESS);
}
/*
* Now that we've initialized our global state, parse the command-line
* again for any configuration options specified using -o and set them.
*/
if (c == 'o') {
"option -o %s: option requires value\n",
return (FMD_EXIT_USAGE);
}
*p++ = '\0'; /* strike out the delimiter */
(void) fmd_stresc2chr(++p);
}
"%s: failed to set option -o %s: %s\n",
return (FMD_EXIT_USAGE);
}
}
}
fmd_destroy(&fmd);
return (FMD_EXIT_SUCCESS);
}
/*
* Update the value of fmd.d_fg based on "fg" in case it changed. We
* use this property to decide whether to daemonize below.
*/
/*
* Once we're done setting our global state up, set up signal handlers
* for ensuring orderly termination on SIGTERM. If we are starting in
* the foreground, we also use the same handler for SIGINT and SIGHUP.
*/
(void) sigfillset(&set);
} else
pfd = daemonize_init();
/*
* Prior to this point, we are single-threaded. Once fmd_run() is
* called, we will be multi-threaded from this point on. The daemon's
* main thread will wait at the end of this function for signals.
*/
(void) printf("done ]\n");
} else
(void) sigsuspend(&set);
fmd_destroy(&fmd);
return (FMD_EXIT_SUCCESS);
}