int main(int argc, char *argv[]) { int sflag = 0, s1flag = 0, s2flag = 0, nflag = 0, dflag = 0, eflag = 0; char *options, *value; extern char *optarg; extern int optind; int c, d; struct rlimit rl; int mode = RPC_SVC_MT_AUTO; int maxrecsz = RPC_MAXDATASIZE; void detachfromtty(void); int setmodulus(); int pk_nodefaultkeys(); int svc_create_local_service(); char domainname[MAXNETNAMELEN + 1]; /* * Set our allowed number of file descriptors to the max * of what the system will allow, limited by FD_SETSIZE. */ if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { rlim_t limit; if ((limit = rl.rlim_max) > FD_SETSIZE) limit = FD_SETSIZE; rl.rlim_cur = limit; (void) setrlimit(RLIMIT_NOFILE, &rl); (void) enable_extended_FILE_stdio(-1, -1); } __key_encryptsession_pk_LOCAL = &__key_encrypt_pk_2_svc; __key_decryptsession_pk_LOCAL = &__key_decrypt_pk_2_svc; __key_gendes_LOCAL = &__key_gen_1_svc; /* * Pre-option initialisation */ (void) umask(066); /* paranoia */ if (geteuid() != 0) { (void) fprintf(stderr, "%s must be run as root\n", argv[0]); exit(1); } setmodulus(HEXMODULUS); openlog("keyserv", LOG_PID, LOG_DAEMON); /* * keyserv will not work with a null domainname. */ if (getdomainname(domainname, MAXNETNAMELEN+1) || (domainname[0] == '\0')) { syslog(LOG_ERR, "could not get a valid domainname.\n"); exit(SMF_EXIT_ERR_CONFIG); } /* * Initialise security mechanisms */ cache_size = NULL; cache_options = NULL; if (init_mechs() == -1) { disk_caching = 0; } defaults(); while ((c = getopt(argc, argv, "ndDet:cs:")) != -1) switch (c) { case 'n': nflag++; break; case 'd': dflag++; use_nobody_keys = FALSE; break; case 'e': eflag++; use_nobody_keys = TRUE; break; case 'D': debugging = 1; break; case 't': nthreads = atoi(optarg); break; case 'c': disk_caching = 0; break; case 's': if (!disk_caching) { fprintf(stderr, "missing configuration file"); fprintf(stderr, " or -c option specified\n"); usage(); } sflag++; /* * Which version of [-s] do we have...? */ if (strchr((const char *) optarg, '=') == NULL) { /* * -s <size> */ if (s1flag) { fprintf(stderr, "duplicate" " [-s <size>]\n"); usage(); } s1flag++; default_cache = get_cache_size(optarg); break; } /* * -s <mechtype>=<size>[,...] */ s2flag++; options = optarg; while (*options != '\0') { d = getsubopt(&options, cache_options, &value); if (d == -1) { /* Ignore unknown mechtype */ continue; } if (value == NULL) { fprintf(stderr, "missing cache size for " "mechtype %s\n", cache_options[d]); usage(); } cache_size[d] = get_cache_size(value); } break; default: usage(); break; } if (dflag && eflag) { (void) fprintf(stderr, "specify only one of -d and -e\n"); usage(); } if (use_nobody_keys == FALSE) { pk_nodefaultkeys(); } if (optind != argc) { usage(); } if (!disk_caching && sflag) { fprintf(stderr, "missing configuration file"); fprintf(stderr, " or -c option specified\n"); usage(); } if (debugging) { if (disk_caching) { char **cpp = cache_options; int *ip = cache_size; (void) fprintf(stderr, "default disk cache size: "); if (default_cache < 0) { (void) fprintf(stderr, "%d entries\n", abs(default_cache)); } else { (void) fprintf(stderr, "%dMB\n", default_cache); } (void) fprintf(stderr, "supported mechanisms:\n"); (void) fprintf(stderr, "\talias\t\tdisk cache size\n"); (void) fprintf(stderr, "\t=====\t\t===============\n"); while (*cpp != NULL) { (void) fprintf(stderr, "\t%s\t\t", *cpp++); if (*ip < 0) { (void) fprintf(stderr, "%d entries\n", abs(*ip)); } else { (void) fprintf(stderr, "%dMB\n", *ip); } ip++; } } else { (void) fprintf(stderr, "common key disk caching disabled\n"); } } /* * Post-option initialisation */ if (disk_caching) { int i; for (i = 0; mechs[i]; i++) { if ((AUTH_DES_COMPAT_CHK(mechs[i])) || (mechs[i]->keylen < 0) || (mechs[i]->algtype < 0)) continue; create_cache_file(mechs[i]->keylen, mechs[i]->algtype, cache_size[i] ? cache_size[i] : default_cache); } } getrootkey(&masterkey, nflag); /* * Set MT mode */ if (nthreads > 0) { (void) rpc_control(RPC_SVC_MTMODE_SET, &mode); (void) rpc_control(RPC_SVC_THRMAX_SET, &nthreads); } /* * Enable non-blocking mode and maximum record size checks for * connection oriented transports. */ if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) { syslog(LOG_INFO, "unable to set max RPC record size"); } if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS, "netpath", "keyserv") == 0) { syslog(LOG_ERR, "%s: unable to create service for version %d\n", argv[0], KEY_VERS); exit(1); } if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS2, "netpath", "keyserv") == 0) { syslog(LOG_ERR, "%s: unable to create service for version %d\n", argv[0], KEY_VERS2); exit(1); } if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS3, "netpath", "keyserv") == 0) { syslog(LOG_ERR, "%s: unable to create service for version %d\n", argv[0], KEY_VERS3); exit(1); } if (!debugging) { detachfromtty(); } if (svc_create(keyprogram, KEY_PROG, KEY_VERS, "door") == 0) { syslog(LOG_ERR, "%s: unable to create service over doors for version %d\n", argv[0], KEY_VERS); exit(1); } if (svc_create(keyprogram, KEY_PROG, KEY_VERS2, "door") == 0) { syslog(LOG_ERR, "%s: unable to create service over doors for version %d\n", argv[0], KEY_VERS2); exit(1); } if (svc_create(keyprogram, KEY_PROG, KEY_VERS3, "door") == 0) { syslog(LOG_ERR, "%s: unable to create service over doors for version %d\n", argv[0], KEY_VERS3); exit(1); } svc_run(); abort(); /* NOTREACHED */ return (0); }
int main(int argc, char **argv) { int c; pid_t pid; extern char *optarg; sigset_t mask; struct sigaction act; (void) setlocale(LC_ALL, ""); #ifndef TEXT_DOMAIN #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); if ((prog = strrchr(argv[0], '/')) == NULL) { prog = argv[0]; } else { prog++; } (void) enable_extended_FILE_stdio(-1, -1); /* * process arguments */ if (argc > 3) { usage(); } while ((c = getopt(argc, argv, "d:t:")) != EOF) { switch (c) { case 'd': debug_level = atoi(optarg); break; case 't': idle_timeout = atoi(optarg); break; case '?': default: usage(); /*NOTREACHED*/ } } /* * Check permission */ if (getuid() != 0) { (void) fprintf(stderr, gettext("Must be root to run %s\n"), prog); exit(EPERM); } /* * 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 * but stdin/stdout/stderr. */ 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); (void) thr_sigsetmask(SIG_UNBLOCK, &mask, NULL); /* * block SIGUSR1, use it for killing specific threads */ (void) sigemptyset(&mask); (void) sigaddset(&mask, SIGUSR1); (void) thr_sigsetmask(SIG_BLOCK, &mask, NULL); /* * 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. */ act.sa_flags = 0; act.sa_handler = catch_sighup; (void) sigaction(SIGHUP, &act, NULL); act.sa_handler = catch_sigusr1; (void) sigaction(SIGUSR1, &act, NULL); /* * 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. */ act.sa_handler = SIG_IGN; (void) sigaction(SIGPIPE, &act, NULL); /* * run in daemon mode */ if (debug_level < DEBUG_LEVEL_FORK) { if (fork()) { exit(0); } detachfromtty(); } /* only one daemon can run at a time */ if ((pid = enter_daemon_lock()) != getpid()) { rcm_log_message(RCM_DEBUG, "%s pid %d already running\n", prog, pid); exit(EDEADLK); } rcm_log_message(RCM_TRACE1, "%s started, debug level = %d\n", prog, debug_level); /* * Set daemon state to block RCM requests before rcm_daemon is * fully initialized. See rcmd_thr_incr(). */ rcmd_set_state(RCMD_INIT); /* * create rcm_daemon door and set permission to 0400 */ if (create_event_service(RCM_SERVICE_DOOR, event_service) == -1) { rcm_log_message(RCM_ERROR, gettext("cannot create door service: %s\n"), strerror(errno)); rcmd_exit(errno); } (void) chmod(RCM_SERVICE_DOOR, S_IRUSR); 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. */ rcmd_lock_init(); /* * Start accepting normal requests */ rcmd_set_state(RCMD_NORMAL); /* * Start cleanup thread */ rcmd_db_clean(); /* * Loop within daemon and return after a period of inactivity. */ rcmd_start_timer(idle_timeout); rcmd_cleanup(0); return (0); }
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); }
int main(int argc, char ** argv) { int opt; int errflg = 0; int showstats = 0; int doset = 0; nscd_rc_t rc; char *me = "main()"; char *ret_locale; char *ret_textdomain; char msg[128]; struct rlimit rl; ret_locale = setlocale(LC_ALL, ""); if (ret_locale == NULL) (void) fprintf(stderr, gettext("Unable to set locale\n")); ret_textdomain = textdomain(TEXT_DOMAIN); if (ret_textdomain == NULL) (void) fprintf(stderr, gettext("Unable to set textdomain\n")); /* * The admin model for TX is that labeled zones are managed * in global zone where most trusted configuration database * resides. However, nscd will run in any labeled zone if * file /var/tsol/doors/nscd_per_label exists. */ if (is_system_labeled() && (getzoneid() != GLOBAL_ZONEID)) { struct stat sbuf; if (stat(TSOL_NSCD_PER_LABEL_FILE, &sbuf) < 0) { (void) fprintf(stderr, gettext("With Trusted Extensions nscd runs only in the " "global zone (if nscd_per_label flag not set)\n")); exit(1); } } /* * Special case non-root user here - he can just print stats */ if (geteuid()) { if (argc != 2 || (strcmp(argv[1], "-g") && strcmp(argv[1], "-G"))) { (void) fprintf(stderr, gettext("Must be root to use any option other than -g\n\n")); usage(argv[0]); } if (_nscd_doorcall(NSCD_PING) != NSS_SUCCESS) { (void) fprintf(stderr, gettext("%s doesn't appear to be running.\n"), argv[0]); exit(1); } if (_nscd_client_getadmin(argv[1][1]) != 0) { (void) fprintf(stderr, gettext("unable to get configuration and statistics data\n")); exit(1); } _nscd_client_showstats(); exit(0); } /* * Determine if there is already a daemon (main nscd) running. * If not, will start it. Forker NSCD will always become a * daemon. */ will_become_server = (_nscd_doorcall(NSCD_PING) != NSS_SUCCESS); if (argc >= 2 && strcmp(argv[1], "-F") == 0) { will_become_server = 1; _whoami = NSCD_FORKER; /* * allow time for the main nscd to get ready * to receive the IMHERE door request this * process will send later */ (void) usleep(100000); } /* * first get the config file path. Also detect * invalid option as soon as possible. */ while ((opt = getopt(argc, argv, NSCDOPT)) != EOF) { switch (opt) { case 'f': if ((cfgfile = strdup(optarg)) == NULL) exit(1); break; case 'g': if (will_become_server) { (void) fprintf(stderr, gettext("nscd not running, no statistics to show\n\n")); errflg++; } break; case 'i': if (will_become_server) { (void) fprintf(stderr, gettext("nscd not running, no cache to invalidate\n\n")); errflg++; } break; case '?': errflg++; break; } } if (errflg) usage(argv[0]); /* * perform more initialization and load configuration * if to become server */ if (will_become_server) { /* initialize switch engine and config/stats management */ if ((rc = _nscd_init(cfgfile)) != NSCD_SUCCESS) { (void) fprintf(stderr, gettext("initialization of switch failed (rc = %d)\n"), rc); exit(1); } _nscd_get_log_info(debug_level, sizeof (debug_level), logfile, sizeof (logfile)); /* * initialize cache store */ if ((rc = init_cache(0)) != NSCD_SUCCESS) { (void) fprintf(stderr, gettext("initialization of cache store failed (rc = %d)\n"), rc); exit(1); } } /* * process usual options */ optind = 1; /* this is a rescan */ *msg = '\0'; while ((opt = getopt(argc, argv, NSCDOPT)) != EOF) { switch (opt) { case 'K': /* undocumented feature */ (void) _nscd_doorcall(NSCD_KILLSERVER); exit(0); break; case 'G': case 'g': showstats++; break; case 'p': doset++; if (_nscd_add_admin_mod(optarg, 'p', getcacheopt(optarg), msg, sizeof (msg)) == -1) errflg++; break; case 'n': doset++; if (_nscd_add_admin_mod(optarg, 'n', getcacheopt(optarg), msg, sizeof (msg)) == -1) errflg++; break; case 'c': doset++; if (_nscd_add_admin_mod(optarg, 'c', getcacheopt(optarg), msg, sizeof (msg)) == -1) errflg++; break; case 'i': doset++; if (_nscd_add_admin_mod(optarg, 'i', NULL, msg, sizeof (msg)) == -1) errflg++; break; case 'l': doset++; (void) strlcpy(logfile, optarg, sizeof (logfile)); break; case 'd': doset++; (void) strlcpy(debug_level, optarg, sizeof (debug_level)); break; case 'S': /* silently ignore secure-mode */ break; case 's': /* silently ignore suggested-size */ break; case 'o': /* silently ignore old-data-ok */ break; case 'h': doset++; if (_nscd_add_admin_mod(optarg, 'h', getcacheopt(optarg), msg, sizeof (msg)) == -1) errflg++; break; case 'e': doset++; if (_nscd_add_admin_mod(optarg, 'e', getcacheopt(optarg), msg, sizeof (msg)) == -1) errflg++; break; case 'F': _whoami = NSCD_FORKER; break; default: errflg++; break; } } if (errflg) { if (*msg != '\0') (void) fprintf(stderr, "\n%s: %s\n\n", argv[0], msg); usage(argv[0]); } /* * if main nscd already running and not forker nscd, * can only do admin work */ if (_whoami == NSCD_MAIN) { if (!will_become_server) { if (showstats) { if (_nscd_client_getadmin('g')) { (void) fprintf(stderr, gettext("Cannot contact nscd properly(?)\n")); exit(1); } _nscd_client_showstats(); } if (doset) { if (_nscd_client_setadmin() < 0) { (void) fprintf(stderr, gettext("Error during admin call\n")); exit(1); } } if (!showstats && !doset) { (void) fprintf(stderr, gettext("%s already running.... no administration option specified\n"), argv[0]); } exit(0); } } /* * daemon from here on */ if (_whoami == NSCD_MAIN) { /* save enough info in case need to restart or fork */ saved_argc = argc; saved_argv = argv; save_execname(); /* * if a log file is not specified, set it to * "stderr" or "/dev/null" based on debug level */ if (*logfile == '\0') { if (*debug_level != '\0') /* we're debugging... */ (void) strcpy(logfile, "stderr"); else (void) strcpy(logfile, "/dev/null"); } (void) _nscd_add_admin_mod(NULL, 'l', logfile, msg, sizeof (msg)); (void) _nscd_add_admin_mod(NULL, 'd', debug_level, msg, sizeof (msg)); /* activate command options */ if (_nscd_server_setadmin(NULL) != NSCD_SUCCESS) { (void) fprintf(stderr, gettext("unable to set command line options\n")); exit(1); } if (*debug_level != '\0') { /* we're debugging, no forking of nscd */ /* * forker nscd will be started if self credential * is configured */ _nscd_start_forker(saved_execname, saved_argc, saved_argv); } else { /* * daemonize the nscd (forker nscd will also * be started if self credential is configured) */ detachfromtty(); } } else { /* NSCD_FORKER */ /* * To avoid PUN (Per User Nscd) processes from becoming * zombies after they exit, the forking nscd should * ignore the SIGCLD signal so that it does not * need to wait for every child PUN to exit. */ (void) signal(SIGCLD, SIG_IGN); (void) open("/dev/null", O_RDWR, 0); (void) dup(0); if (_logfd != 2) (void) dup(0); } /* set NOFILE to unlimited */ rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "Cannot set open file limit: %s\n", strerror(errno)); exit(1); } /* set up door and establish our own server thread pool */ if ((_doorfd = _nscd_setup_server(saved_execname, saved_argv)) == -1) { _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "unable to set up door\n"); exit(1); } /* inform the main nscd that this forker is ready */ if (_whoami == NSCD_FORKER) { int ret; for (ret = NSS_ALTRETRY; ret == NSS_ALTRETRY; ) ret = _nscd_doorcall_sendfd(_doorfd, NSCD_IMHERE | (NSCD_FORKER & NSCD_WHOAMI), NULL, 0, NULL); } for (;;) { (void) pause(); (void) _nscd_doorcall(NSCD_REFRESH); } /* NOTREACHED */ /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/ }
int main(int argc, char *const *argv) { struct sockaddr_in bindaddr; socklen_t addrlen; const char *isDA; const char *proxyReg; int connfd; int lfd; const int on = 1; detachfromtty(); openlog("slpd", LOG_PID, LOG_DAEMON); do_args(argc, argv); /* If slpd has been configured to run as a DA, start it and exit */ isDA = SLPGetProperty("net.slp.isDA"); proxyReg = SLPGetProperty("net.slp.serializedRegURL"); if ((isDA && (strcasecmp(isDA, "true") == 0)) || proxyReg) { run_slpd(); return (1); } if ((lfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_ERR, "socket failed: %s", strerror(errno)); cleanup_and_exit(1); } (void) setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)); (void) memset((void *)&bindaddr, 0, sizeof (bindaddr)); bindaddr.sin_family = AF_INET; bindaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); bindaddr.sin_port = htons(427); if (bind(lfd, (const struct sockaddr *)&bindaddr, sizeof (bindaddr)) < 0) { syslog(LOG_ERR, "bind failed: %s", strerror(errno)); cleanup_and_exit(1); } if (listen(lfd, 1) < 0) { syslog(LOG_ERR, "listen failed: %s", strerror(errno)); cleanup_and_exit(1); } addrlen = sizeof (bindaddr); if ((connfd = accept(lfd, (struct sockaddr *)&bindaddr, &addrlen)) < 0) { syslog(LOG_ERR, "accept failed: %s", strerror(errno)); cleanup_and_exit(1); } (void) close(lfd); (void) dup2(connfd, 0); (void) close(connfd); (void) dup2(0, 1); (void) dup2(0, 2); run_slpd(); return (1); }