/* * Determines if a given data store name is valid. */ static boolean_t dd_is_valid_data_store(JNIEnv *env, const char *name) { char **module; int count; int ndx; int rcode; boolean_t isValid = B_FALSE; if (name != NULL) { rcode = enumerate_dd(&module, &count); if (rcode != DSVC_SUCCESS) { throw_libdhcpsvc_exception(env, rcode); } else { for (ndx = 0; !isValid && ndx < count; ndx++) { if (strcmp(module[ndx], name) == 0) { isValid = B_TRUE; } } free_enumerated_dd(module, count); } } return (isValid); }
int main(int argc, char **argv) { dsvcd_datastore_t **ds_table; dsvc_datastore_t dd; dsvc_synchtype_t synchtype; char **modules; unsigned int i, j; int debug_level = 0; boolean_t is_daemon = B_TRUE; boolean_t is_verbose = B_FALSE; int sig, nmodules, nsynchmods, c; sigset_t sigset; char signame[SIG2STR_MAX]; char *progname; void *stackbase; unsigned int stacksize = 16 * 1024; struct rlimit rl; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); /* * Mask all signals except SIGABRT; doing this here ensures that * all threads created through door_create() have them masked too. */ (void) sigfillset(&sigset); (void) sigdelset(&sigset, SIGABRT); (void) thr_sigsetmask(SIG_BLOCK, &sigset, NULL); /* * Figure out our program name; just keep the final piece so that * our dhcpmsg() messages don't get too long. */ progname = strrchr(argv[0], '/'); if (progname != NULL) progname++; else progname = argv[0]; /* * Set the door thread creation procedure so that all of our * threads are created with thread stacks with backing store. */ (void) door_server_create(doorserv_create); while ((c = getopt(argc, argv, "d:fv")) != EOF) { switch (c) { case 'd': debug_level = atoi(optarg); break; case 'f': is_daemon = B_FALSE; break; case 'v': is_verbose = B_TRUE; break; case '?': (void) fprintf(stderr, gettext("usage: %s [-dn] [-f] [-v]\n"), progname); return (EXIT_FAILURE); default: break; } } if (geteuid() != 0) { dhcpmsg_init(progname, B_FALSE, is_verbose, debug_level); dhcpmsg(MSG_ERROR, "must be super-user"); dhcpmsg_fini(); return (EXIT_FAILURE); } if (is_daemon && daemonize() == 0) { dhcpmsg_init(progname, B_FALSE, is_verbose, debug_level); dhcpmsg(MSG_ERROR, "cannot become daemon, exiting"); dhcpmsg_fini(); return (EXIT_FAILURE); } dhcpmsg_init(progname, is_daemon, is_verbose, debug_level); (void) atexit(dhcpmsg_fini); /* * Max out the number available descriptors since we need to * allocate two per held lock. */ rl.rlim_cur = RLIM_INFINITY; rl.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_NOFILE, &rl) == -1) dhcpmsg(MSG_ERR, "setrlimit failed"); (void) enable_extended_FILE_stdio(-1, -1); if (enumerate_dd(&modules, &nmodules) != DSVC_SUCCESS) { dhcpmsg(MSG_ERROR, "cannot enumerate public modules, exiting"); return (EXIT_FAILURE); } /* * NOTE: this code assumes that a module that needs dsvclockd will * always need it (even as the container version is ramped). If * this becomes bogus in a future release, we'll have to make this * logic more sophisticated. */ nsynchmods = nmodules; for (i = 0; i < nmodules; i++) { dd.d_resource = modules[i]; dd.d_conver = DSVC_CUR_CONVER; dd.d_location = ""; if (module_synchtype(&dd, &synchtype) != DSVC_SUCCESS) { dhcpmsg(MSG_WARNING, "cannot determine synchronization " "type for `%s', skipping", modules[i]); free(modules[i]); modules[i] = NULL; nsynchmods--; continue; } if ((synchtype & DSVC_SYNCH_STRATMASK) != DSVC_SYNCH_DSVCD) { free(modules[i]); modules[i] = NULL; nsynchmods--; } } if (nsynchmods == 0) { dhcpmsg(MSG_INFO, "no public modules need synchronization"); return (EXIT_SUCCESS); } /* * Allocate the datastore table; include one extra entry so that * the table is NULL-terminated. */ ds_table = calloc(nsynchmods + 1, sizeof (dsvcd_datastore_t *)); if (ds_table == NULL) { dhcpmsg(MSG_ERR, "cannot allocate datastore table, exiting"); return (EXIT_FAILURE); } ds_table[nsynchmods] = NULL; /* * Create the datastores (which implicitly creates the doors). * then sit around and wait for requests to come in on the doors. */ for (i = 0, j = 0; i < nmodules; i++) { if (modules[i] != NULL) { ds_table[j] = ds_create(modules[i], svc_lock); if (ds_table[j] == NULL) { while (j-- > 0) ds_destroy(ds_table[j]); return (EXIT_FAILURE); } free(modules[i]); j++; } } free(modules); stackbase = stack_create(&stacksize); if (stackbase == NULL) dhcpmsg(MSG_ERR, "cannot create reaper stack; containers " "will not be reaped"); else { errno = thr_create(stackbase, stacksize, reaper, ds_table, THR_DAEMON, NULL); if (errno != 0) { dhcpmsg(MSG_ERR, "cannot create reaper thread; " "containers will not be reaped"); stack_destroy(stackbase, stacksize); } } /* * Synchronously wait for a QUIT, TERM, or INT, then shutdown. */ (void) sigemptyset(&sigset); (void) sigaddset(&sigset, SIGQUIT); (void) sigaddset(&sigset, SIGTERM); (void) sigaddset(&sigset, SIGINT); (void) sigwait(&sigset, &sig); if (sig != SIGTERM && sig != SIGQUIT && sig != SIGINT) dhcpmsg(MSG_WARNING, "received unexpected signal"); if (sig2str(sig, signame) == -1) (void) strlcpy(signame, "???", sizeof (signame)); dhcpmsg(MSG_INFO, "shutting down via SIG%s", signame); for (i = 0; i < nsynchmods; i++) ds_destroy(ds_table[i]); return (EXIT_SUCCESS); }