int _nscd_setup_child_server(int did) { int errnum; int fd; nscd_rc_t rc; char *me = "_nscd_setup_child_server"; /* Re-establish our own server thread pool */ (void) door_server_create(server_create); if (thr_keycreate(&server_key, server_destroy) != 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) (me, "thr_keycreate failed: %s", strerror(errnum)); return (-1); } /* * Create a new door. * Keep DOOR_REFUSE_DESC (self-cred nscds don't fork) */ (void) close(did); if ((fd = door_create(switcher, NAME_SERVICE_DOOR_COOKIE, DOOR_REFUSE_DESC|DOOR_UNREF|DOOR_NO_CANCEL)) < 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) (me, "door_create failed: %s", strerror(errnum)); return (-1); } /* * kick off routing socket monitor thread */ if (thr_create(NULL, NULL, (void *(*)(void *))rts_mon, 0, 0, NULL) != 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "thr_create (routing socket monitor): %s\n", strerror(errnum)); (void) door_revoke(fd); return (-1); } /* * start monitoring the states of the name service clients */ rc = _nscd_init_smf_monitor(); if (rc != NSCD_SUCCESS) { _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "unable to start the SMF monitor (rc = %d)\n", rc); (void) door_revoke(fd); return (-1); } return (fd); }
int main(void) { int res = 1; int did = -1; struct sigaction sa; sa.sa_sigaction = signal_handler; sa.sa_flags = SA_RESTART; if (sigfillset(&sa.sa_mask)) { perror("sigfillset"); return 1; } if (sigaction(SIGINT, &sa, NULL)) { perror("sigaction"); return 1; } door_server_create(create_door_thread); if ((did = door_create(server_procedure, NULL, 0)) < 0) { perror("door_create"); return 1; } /* Let the server thread to run. */ sleep(2); /* Send a signal to the server thread that should be already created and blocked in door_return. */ if (_lwp_kill(server_lwpid, SIGINT)) { perror("_lwp_kill"); goto out; } /* Let the other thread to run. */ sleep(2); res = 0; out: if (did >= 0 && door_revoke(did)) perror("door_revoke"); return res; }
/* * Create the picld door */ static int setup_door(void) { struct stat stbuf; (void) door_server_create(picld_server_create_fn); (void) pthread_mutex_lock(&door_mutex); /* * Create the door */ door_id = door_create(picld_door_handler, PICLD_DOOR_COOKIE, DOOR_REFUSE_DESC | DOOR_NO_CANCEL | DOOR_PRIVATE); if (door_id < 0) { (void) pthread_mutex_unlock(&door_mutex); return (-1); } else { (void) pthread_cond_signal(&door_cv); (void) pthread_mutex_unlock(&door_mutex); } if (stat(PICLD_DOOR, &stbuf) < 0) { int newfd; mode_t old_mask; /* ensure that the door file is world-readable */ old_mask = umask(0); newfd = creat(PICLD_DOOR, 0444); /* restore the file mode creation mask */ (void) umask(old_mask); if (newfd < 0) return (-1); (void) close(newfd); } if (fattach(door_id, PICLD_DOOR) < 0) { if ((errno != EBUSY) || (fdetach(PICLD_DOOR) < 0) || (fattach(door_id, PICLD_DOOR) < 0)) return (-1); } return (0); }
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); }
void fmd_run(fmd_t *dp, int pfd) { char *nodc_key[] = { FMD_FLT_NODC, NULL }; char nodc_str[128]; struct sigaction act; int status = FMD_EXIT_SUCCESS; const char *name; fmd_conf_path_t *pap; fmd_event_t *e; int dbout, err; /* * Cache all the current debug property settings in d_fmd_debug, * d_fmd_dbout, d_hdl_debug, and d_hdl_dbout. If a given debug mask * is non-zero and the corresponding dbout mask is zero, set dbout * to a sensible default value based on whether we have daemonized. */ (void) fmd_conf_getprop(dp->d_conf, "dbout", &dbout); if (dp->d_fmd_debug != 0 && dbout == 0) dp->d_fmd_dbout = dp->d_fg? FMD_DBOUT_STDERR : FMD_DBOUT_SYSLOG; else dp->d_fmd_dbout = dbout; (void) fmd_conf_getprop(dp->d_conf, "client.debug", &dp->d_hdl_debug); (void) fmd_conf_getprop(dp->d_conf, "client.dbout", &dbout); if (dp->d_hdl_debug != 0 && dbout == 0) dp->d_hdl_dbout = dp->d_fg? FMD_DBOUT_STDERR : FMD_DBOUT_SYSLOG; else dp->d_hdl_dbout = dbout; /* * Initialize remaining major program data structures such as the * clock, dispatch queues, log files, module hash collections, etc. * This work is done here rather than in fmd_create() to permit the -o * command-line option to modify properties after fmd_create() is done. */ name = dp->d_rootdir != NULL && *dp->d_rootdir != '\0' ? dp->d_rootdir : NULL; if ((dp->d_topo = topo_open(TOPO_VERSION, name, &err)) == NULL) { fmd_error(EFMD_EXIT, "failed to initialize " "topology library: %s\n", topo_strerror(err)); } dp->d_clockptr = dp->d_clockops->fto_init(); dp->d_xprt_ids = fmd_idspace_create("xprt_ids", 1, INT_MAX); fmd_xprt_suspend_all(); (void) door_server_create(fmd_door); fmd_dr_init(); dp->d_rmod->mod_timerids = fmd_idspace_create(dp->d_pname, 1, 16); dp->d_timers = fmd_timerq_create(); dp->d_disp = fmd_dispq_create(); dp->d_cases = fmd_case_hash_create(); /* * The root module's mod_queue is created with limit zero, making it * act like /dev/null; anything inserted here is simply ignored. */ dp->d_rmod->mod_queue = fmd_eventq_create(dp->d_rmod, &dp->d_rmod->mod_stats->ms_evqstat, &dp->d_rmod->mod_stats_lock, 0); /* * Once our subsystems that use signals have been set up, install the * signal handler for the fmd_thr_signal() API. Verify that the signal * being used for this purpose doesn't conflict with something else. */ (void) fmd_conf_getprop(dp->d_conf, "client.thrsig", &dp->d_thr_sig); if (sigaction(dp->d_thr_sig, NULL, &act) != 0) { fmd_error(EFMD_EXIT, "invalid signal selected for " "client.thrsig property: %d\n", dp->d_thr_sig); } if (act.sa_handler != SIG_IGN && act.sa_handler != SIG_DFL) { fmd_error(EFMD_EXIT, "signal selected for client.thrsig " "property is already in use: %d\n", dp->d_thr_sig); } act.sa_handler = fmd_signal; act.sa_flags = 0; (void) sigemptyset(&act.sa_mask); (void) sigaction(dp->d_thr_sig, &act, NULL); (void) fmd_conf_getprop(dp->d_conf, "schemedir", &name); dp->d_schemes = fmd_scheme_hash_create(dp->d_rootdir, name); (void) fmd_conf_getprop(dp->d_conf, "log.rsrc", &name); dp->d_asrus = fmd_asru_hash_create(dp->d_rootdir, name); (void) fmd_conf_getprop(dp->d_conf, "log.error", &name); dp->d_errlog = fmd_log_open(dp->d_rootdir, name, FMD_LOG_ERROR); (void) fmd_conf_getprop(dp->d_conf, "log.fault", &name); dp->d_fltlog = fmd_log_open(dp->d_rootdir, name, FMD_LOG_FAULT); if (dp->d_asrus == NULL || dp->d_errlog == NULL || dp->d_fltlog == NULL) fmd_error(EFMD_EXIT, "failed to initialize log files\n"); /* * Before loading modules, create an empty control event which will act * as a global barrier for module event processing. Each module we * load successfully will insert it at their head of their event queue, * and then pause inside of fmd_ctl_rele() after dequeuing the event. * This module barrier is required for two reasons: * * (a) During module loading, the restoration of case checkpoints may * result in a list.* event being recreated for which the intended * subscriber has not yet loaded depending on the load order. Such * events could then result in spurious "no subscriber" errors. * * (b) During errlog replay, a sequence of errors from a long time ago * may be replayed, and the module may attempt to install relative * timers associated with one or more of these events. If errlog * replay were "racing" with active module threads, an event E1 * that resulted in a relative timer T at time E1 + N nsec could * fire prior to an event E2 being enqueued, even if the relative * time ordering was E1 < E2 < E1 + N, causing mis-diagnosis. */ dp->d_mod_event = e = fmd_event_create(FMD_EVT_CTL, FMD_HRT_NOW, NULL, fmd_ctl_init(NULL)); fmd_event_hold(e); /* * Once all data structures are initialized, we load all of our modules * in order according to class in order to load up any subscriptions. * Once built-in modules are loaded, we detach from our waiting parent. */ dp->d_mod_hash = fmd_modhash_create(); if (fmd_builtin_loadall(dp->d_mod_hash) != 0 && !dp->d_fg) fmd_error(EFMD_EXIT, "failed to initialize fault manager\n"); (void) fmd_conf_getprop(dp->d_conf, "self.name", &name); dp->d_self = fmd_modhash_lookup(dp->d_mod_hash, name); if (dp->d_self != NULL && fmd_module_dc_key2code(dp->d_self, nodc_key, nodc_str, sizeof (nodc_str)) == 0) (void) fmd_conf_setprop(dp->d_conf, "nodiagcode", nodc_str); fmd_rpc_init(); dp->d_running = 1; /* we are now officially an active fmd */ /* * Now that we're running, if a pipe fd was specified, write an exit * status to it to indicate that our parent process can safely detach. * Then proceed to loading the remaining non-built-in modules. */ if (pfd >= 0) (void) write(pfd, &status, sizeof (status)); /* * Before loading all modules, repopulate the ASRU cache from its * persistent repository on disk. Then during module loading, the * restoration of checkpoint files will reparent any active cases. */ fmd_asru_hash_refresh(dp->d_asrus); (void) fmd_conf_getprop(dp->d_conf, "plugin.path", &pap); fmd_modhash_loadall(dp->d_mod_hash, pap, &fmd_rtld_ops, ".so"); (void) fmd_conf_getprop(dp->d_conf, "agent.path", &pap); fmd_modhash_loadall(dp->d_mod_hash, pap, &fmd_proc_ops, NULL); /* * With all modules loaded, replay fault events from the ASRU cache for * any ASRUs that must be retired, replay error events from the errlog * that did not finish processing the last time ran, and then release * the global module barrier by executing a final rele on d_mod_event. */ fmd_asru_hash_replay(dp->d_asrus); (void) pthread_rwlock_rdlock(&dp->d_log_lock); fmd_log_replay(dp->d_errlog, (fmd_log_f *)fmd_err_replay, dp); fmd_log_update(dp->d_errlog); (void) pthread_rwlock_unlock(&dp->d_log_lock); dp->d_mod_event = NULL; fmd_event_rele(e); /* * Finally, awaken any threads associated with receiving events from * open transports and tell them to proceed with fmd_xprt_recv(). */ fmd_xprt_resume_all(); fmd_gc(dp, 0, 0); dp->d_booted = 1; }
int _nscd_setup_server(char *execname, char **argv) { int fd; int errnum; int bind_failed = 0; mode_t old_mask; struct stat buf; sigset_t myset; struct sigaction action; char *me = "_nscd_setup_server"; main_execname = execname; main_argv = argv; /* Any nscd process is to ignore SIGPIPE */ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "signal (SIGPIPE): %s\n", strerror(errnum)); return (-1); } keep_open_dns_socket(); /* * the max number of server threads should be fixed now, so * set flag to indicate that no in-flight change is allowed */ max_servers_set = 1; (void) thr_keycreate(&lookup_state_key, NULL); (void) sema_init(&common_sema, frontend_cfg_g.common_worker_threads, USYNC_THREAD, 0); /* Establish server thread pool */ (void) door_server_create(server_create); if (thr_keycreate(&server_key, server_destroy) != 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "thr_keycreate (server thread): %s\n", strerror(errnum)); return (-1); } /* Create a door */ if ((fd = door_create(switcher, NAME_SERVICE_DOOR_COOKIE, DOOR_UNREF | DOOR_NO_CANCEL)) < 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "door_create: %s\n", strerror(errnum)); return (-1); } /* if not main nscd, no more setup to do */ if (_whoami != NSCD_MAIN) return (fd); /* bind to file system */ if (is_system_labeled() && (getzoneid() == GLOBAL_ZONEID)) { if (stat(TSOL_NAME_SERVICE_DOOR, &buf) < 0) { int newfd; /* make sure the door will be readable by all */ old_mask = umask(0); if ((newfd = creat(TSOL_NAME_SERVICE_DOOR, 0444)) < 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "Cannot create %s: %s\n", TSOL_NAME_SERVICE_DOOR, strerror(errnum)); bind_failed = 1; } /* rstore the old file mode creation mask */ (void) umask(old_mask); (void) close(newfd); } if (symlink(TSOL_NAME_SERVICE_DOOR, NAME_SERVICE_DOOR) != 0) { if (errno != EEXIST) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "Cannot symlink %s: %s\n", NAME_SERVICE_DOOR, strerror(errnum)); bind_failed = 1; } } } else if (stat(NAME_SERVICE_DOOR, &buf) < 0) { int newfd; /* make sure the door will be readable by all */ old_mask = umask(0); if ((newfd = creat(NAME_SERVICE_DOOR, 0444)) < 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "Cannot create %s: %s\n", NAME_SERVICE_DOOR, strerror(errnum)); bind_failed = 1; } /* rstore the old file mode creation mask */ (void) umask(old_mask); (void) close(newfd); } if (bind_failed == 1) { (void) door_revoke(fd); return (-1); } if (fattach(fd, NAME_SERVICE_DOOR) < 0) { if ((errno != EBUSY) || (fdetach(NAME_SERVICE_DOOR) < 0) || (fattach(fd, NAME_SERVICE_DOOR) < 0)) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "fattach: %s\n", strerror(errnum)); (void) door_revoke(fd); return (-1); } } /* * kick off routing socket monitor thread */ if (thr_create(NULL, NULL, (void *(*)(void *))rts_mon, 0, 0, NULL) != 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "thr_create (routing socket monitor): %s\n", strerror(errnum)); (void) door_revoke(fd); return (-1); } /* * set up signal handler for SIGHUP */ action.sa_handler = dozip; action.sa_flags = 0; (void) sigemptyset(&action.sa_mask); (void) sigemptyset(&myset); (void) sigaddset(&myset, SIGHUP); if (sigaction(SIGHUP, &action, NULL) < 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "sigaction (SIGHUP): %s\n", strerror(errnum)); (void) door_revoke(fd); return (-1); } return (fd); }
int main(int argc, char ** argv) { int did; int opt; int errflg = 0; int showstats = 0; int doset = 0; int dofg = 0; struct stat buf; sigset_t myset; struct sigaction sighupaction; static void client_killserver(); int debug_level = 0; /* setup for localization */ (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); openlog("ldap_cachemgr", LOG_PID, LOG_DAEMON); if (chdir(NSLDAPDIRECTORY) < 0) { (void) fprintf(stderr, gettext("chdir(\"%s\") failed: %s\n"), NSLDAPDIRECTORY, strerror(errno)); exit(1); } /* * Correctly set file mode creation mask, so to make the new files * created for door calls being readable by all. */ (void) umask(0); /* * Special case non-root user here - he/she/they/it can just print * stats */ if (geteuid()) { if (argc != 2 || strcmp(argv[1], "-g")) { (void) fprintf(stderr, gettext("Must be root to use any option " "other than -g.\n\n")); usage(argv[0]); } if ((__ns_ldap_cache_ping() != SUCCESS) || (client_getadmin(¤t_admin) != 0)) { (void) fprintf(stderr, gettext("%s doesn't appear to be running.\n"), argv[0]); exit(1); } (void) client_showstats(¤t_admin); exit(0); } /* * Determine if there is already a daemon running */ will_become_server = (__ns_ldap_cache_ping() != SUCCESS); /* * load normal config file */ if (will_become_server) { static const ldap_stat_t defaults = { 0, /* stat */ DEFAULTTTL}; /* ttl */ current_admin.ldap_stat = defaults; (void) strcpy(current_admin.logfile, LOGFILE); } else { if (client_getadmin(¤t_admin)) { (void) fprintf(stderr, gettext("Cannot contact %s " "properly(?)\n"), argv[0]); exit(1); } } #ifndef SLP while ((opt = getopt(argc, argv, "fKgl:r:d:")) != EOF) { #else while ((opt = getopt(argc, argv, "fKgs:l:r:d:")) != EOF) { #endif /* SLP */ ldap_stat_t *cache; switch (opt) { case 'K': client_killserver(); exit(0); break; case 'g': showstats++; break; case 'f': dofg++; break; case 'r': doset++; cache = getcacheptr("ldap"); if (!optarg) { errflg++; break; } cache->ldap_ttl = atoi(optarg); break; case 'l': doset++; (void) strlcpy(current_admin.logfile, optarg, sizeof (current_admin.logfile)); break; case 'd': doset++; debug_level = atoi(optarg); break; #ifdef SLP case 's': /* undocumented: use dynamic (SLP) config */ use_slp = 1; break; #endif /* SLP */ default: errflg++; break; } } if (errflg) usage(argv[0]); /* * will not show statistics if no daemon running */ if (will_become_server && showstats) { (void) fprintf(stderr, gettext("%s doesn't appear to be running.\n"), argv[0]); exit(1); } if (!will_become_server) { if (showstats) { (void) client_showstats(¤t_admin); } if (doset) { current_admin.debug_level = debug_level; if (client_setadmin(¤t_admin) < 0) { (void) fprintf(stderr, gettext("Error during admin call\n")); exit(1); } } if (!showstats && !doset) { (void) fprintf(stderr, gettext("%s already running....use '%s " "-K' to stop\n"), argv[0], argv[0]); } exit(0); } /* * daemon from here on */ if (debug_level) { /* * we're debugging... */ if (strlen(current_admin.logfile) == 0) /* * no specified log file */ (void) strcpy(current_admin.logfile, LOGFILE); else (void) cachemgr_set_lf(¤t_admin, current_admin.logfile); /* * validate the range of debug level number * and set the number to current_admin.debug_level */ if (cachemgr_set_dl(¤t_admin, debug_level) < 0) { /* * print error messages to the screen * cachemgr_set_dl prints msgs to cachemgr.log * only */ (void) fprintf(stderr, gettext("Incorrect Debug Level: %d\n" "It should be between %d and %d\n"), debug_level, DBG_OFF, MAXDEBUG); exit(-1); } } else { if (strlen(current_admin.logfile) == 0) (void) strcpy(current_admin.logfile, "/dev/null"); (void) cachemgr_set_lf(¤t_admin, current_admin.logfile); } if (dofg == 0) detachfromtty(argv[0]); /* * perform some initialization */ initialize_lookup_clearance(); if (getldap_init() != 0) exit(-1); /* * Establish our own server thread pool */ (void) door_server_create(server_create); if (thr_keycreate(&server_key, server_destroy) != 0) { logit("thr_keycreate() call failed\n"); syslog(LOG_ERR, gettext("ldap_cachemgr: thr_keycreate() call failed")); perror("thr_keycreate"); exit(-1); } /* * Create a door */ if ((did = door_create(switcher, LDAP_CACHE_DOOR_COOKIE, DOOR_UNREF | DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) { logit("door_create() call failed\n"); syslog(LOG_ERR, gettext( "ldap_cachemgr: door_create() call failed")); perror("door_create"); exit(-1); } /* * bind to file system */ if (stat(LDAP_CACHE_DOOR, &buf) < 0) { int newfd; if ((newfd = creat(LDAP_CACHE_DOOR, 0444)) < 0) { logit("Cannot create %s:%s\n", LDAP_CACHE_DOOR, strerror(errno)); exit(1); } (void) close(newfd); } if (fattach(did, LDAP_CACHE_DOOR) < 0) { if ((errno != EBUSY) || (fdetach(LDAP_CACHE_DOOR) < 0) || (fattach(did, LDAP_CACHE_DOOR) < 0)) { logit("fattach() call failed\n"); syslog(LOG_ERR, gettext( "ldap_cachemgr: fattach() call failed")); perror("fattach"); exit(2); } } /* catch SIGHUP revalid signals */ sighupaction.sa_handler = getldap_revalidate; sighupaction.sa_flags = 0; (void) sigemptyset(&sighupaction.sa_mask); (void) sigemptyset(&myset); (void) sigaddset(&myset, SIGHUP); if (sigaction(SIGHUP, &sighupaction, NULL) < 0) { logit("sigaction() call failed\n"); syslog(LOG_ERR, gettext("ldap_cachemgr: sigaction() call failed")); perror("sigaction"); exit(1); } if (thr_sigsetmask(SIG_BLOCK, &myset, NULL) < 0) { logit("thr_sigsetmask() call failed\n"); syslog(LOG_ERR, gettext("ldap_cachemgr: thr_sigsetmask() call failed")); perror("thr_sigsetmask"); exit(1); } /* * kick off revalidate threads only if ttl != 0 */ if (thr_create(NULL, NULL, (void *(*)(void*))getldap_refresh, 0, 0, NULL) != 0) { logit("thr_create() call failed\n"); syslog(LOG_ERR, gettext("ldap_cachemgr: thr_create() call failed")); perror("thr_create"); exit(1); } /* * kick off the thread which refreshes the server info */ if (thr_create(NULL, NULL, (void *(*)(void*))getldap_serverInfo_refresh, 0, 0, NULL) != 0) { logit("thr_create() call failed\n"); syslog(LOG_ERR, gettext("ldap_cachemgr: thr_create() call failed")); perror("thr_create"); exit(1); } #ifdef SLP if (use_slp) { /* kick off SLP discovery thread */ if (thr_create(NULL, NULL, (void *(*)(void *))discover, (void *)&refresh, 0, NULL) != 0) { logit("thr_create() call failed\n"); syslog(LOG_ERR, gettext("ldap_cachemgr: thr_create() " "call failed")); perror("thr_create"); exit(1); } } #endif /* SLP */ if (thr_sigsetmask(SIG_UNBLOCK, &myset, NULL) < 0) { logit("thr_sigsetmask() call failed\n"); syslog(LOG_ERR, gettext("ldap_cachemgr: the_sigsetmask() call failed")); perror("thr_sigsetmask"); exit(1); } /*CONSTCOND*/ while (1) { (void) pause(); } /* NOTREACHED */ /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/ } /* * Before calling the alloca() function we have to be sure that we won't get * beyond the stack. Since we don't know the precise layout of the stack, * the address of an automatic of the function gives us a rough idea, plus/minus * a bit. We also need a bit more of stackspace after the call to be able * to call further functions. Even something as simple as making a system call * from within this function can take ~100 Bytes of stackspace. */ #define SAFETY_BUFFER 32 * 1024 /* 32KB */ static size_t get_data_size(LineBuf *config_info, int *err_code) { size_t configSize = sizeof (ldap_return_t); dataunion *buf = NULL; /* For the 'sizeof' purpose */ if (config_info->str != NULL && config_info->len >= sizeof (buf->data.ldap_ret.ldap_u.config)) { configSize = sizeof (buf->space) + config_info->len - sizeof (buf->data.ldap_ret.ldap_u.config); if (!stack_inbounds((char *)&buf - (configSize + SAFETY_BUFFER))) { /* * We do not have enough space on the stack * to accomodate the whole DUAProfile */ logit("The DUAProfile is too big. There is not enough " "space to process it. Ignoring it.\n"); syslog(LOG_ERR, gettext("ldap_cachemgr: The DUAProfile " "is too big. There is not enough space " "to process it. Ignoring it.")); *err_code = SERVERERROR; free(config_info->str); config_info->str = NULL; config_info->len = 0; configSize = sizeof (ldap_return_t); } } return (configSize); }