/* * Use SMF error codes only on return or exit. */ int main(int argc, char *argv[]) { struct sigaction act; sigset_t set; uid_t uid; int pfd = -1; uint_t sigval; struct rlimit rl; int orig_limit; smbd.s_pname = basename(argv[0]); openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); if (smbd_setup_options(argc, argv) != 0) return (SMF_EXIT_ERR_FATAL); if ((uid = getuid()) != smbd.s_uid) { smbd_report("user %d: %s", uid, strerror(EPERM)); return (SMF_EXIT_ERR_FATAL); } if (getzoneid() != GLOBAL_ZONEID) { smbd_report("non-global zones are not supported"); return (SMF_EXIT_ERR_FATAL); } if (is_system_labeled()) { smbd_report("Trusted Extensions not supported"); return (SMF_EXIT_ERR_FATAL); } if (smbd_already_running()) return (SMF_EXIT_OK); /* * Raise the file descriptor limit to accommodate simultaneous user * authentications/file access. */ if ((getrlimit(RLIMIT_NOFILE, &rl) == 0) && (rl.rlim_cur < rl.rlim_max)) { orig_limit = rl.rlim_cur; rl.rlim_cur = rl.rlim_max; if (setrlimit(RLIMIT_NOFILE, &rl) != 0) smbd_report("Failed to raise file descriptor limit" " from %d to %d", orig_limit, rl.rlim_cur); } (void) sigfillset(&set); (void) sigdelset(&set, SIGABRT); (void) sigfillset(&act.sa_mask); act.sa_handler = smbd_sig_handler; act.sa_flags = 0; (void) sigaction(SIGABRT, &act, NULL); (void) sigaction(SIGTERM, &act, NULL); (void) sigaction(SIGHUP, &act, NULL); (void) sigaction(SIGINT, &act, NULL); (void) sigaction(SIGPIPE, &act, NULL); (void) sigaction(SIGUSR1, &act, NULL); (void) sigdelset(&set, SIGTERM); (void) sigdelset(&set, SIGHUP); (void) sigdelset(&set, SIGINT); (void) sigdelset(&set, SIGPIPE); (void) sigdelset(&set, SIGUSR1); if (smbd.s_fg) { (void) sigdelset(&set, SIGTSTP); (void) sigdelset(&set, SIGTTIN); (void) sigdelset(&set, SIGTTOU); if (smbd_service_init() != 0) { smbd_report("service initialization failed"); exit(SMF_EXIT_ERR_FATAL); } } else { /* * "pfd" is a pipe descriptor -- any fatal errors * during subsequent initialization of the child * process should be written to this pipe and the * parent will report this error as the exit status. */ pfd = smbd_daemonize_init(); if (smbd_service_init() != 0) { smbd_report("daemon initialization failed"); exit(SMF_EXIT_ERR_FATAL); } smbd_daemonize_fini(pfd, SMF_EXIT_OK); } (void) atexit(smb_kmod_stop); while (!smbd.s_shutting_down) { if (smbd.s_sigval == 0 && smbd.s_refreshes == 0) (void) sigsuspend(&set); sigval = atomic_swap_uint(&smbd.s_sigval, 0); switch (sigval) { case 0: case SIGPIPE: case SIGABRT: break; case SIGHUP: syslog(LOG_DEBUG, "refresh requested"); (void) pthread_cond_signal(&refresh_cond); break; case SIGUSR1: smb_log_dumpall(); break; default: /* * Typically SIGINT or SIGTERM. */ smbd.s_shutting_down = B_TRUE; break; } } smbd_service_fini(); closelog(); return ((smbd.s_fatal_error) ? SMF_EXIT_ERR_FATAL : SMF_EXIT_OK); }
/* * Use SMF error codes only on return or exit. */ int main(int argc, char *argv[]) { sigset_t set; uid_t uid; int pfd = -1; int sigval; struct rlimit rl; int orig_limit; #ifdef FKSMBD fksmbd_init(); #endif smbd.s_pname = basename(argv[0]); openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); if (smbd_setup_options(argc, argv) != 0) return (SMF_EXIT_ERR_FATAL); if ((uid = getuid()) != smbd.s_uid) { #ifdef FKSMBD /* Can't manipulate privileges in daemonize. */ if (smbd.s_fg == 0) { smbd.s_fg = 1; smbd_report("user %d (forced -f)", uid); } #else /* FKSMBD */ smbd_report("user %d: %s", uid, strerror(EPERM)); return (SMF_EXIT_ERR_FATAL); #endif /* FKSMBD */ } if (is_system_labeled()) { smbd_report("Trusted Extensions not supported"); return (SMF_EXIT_ERR_FATAL); } if (smbd_already_running()) return (SMF_EXIT_OK); /* * Raise the file descriptor limit to accommodate simultaneous user * authentications/file access. */ if ((getrlimit(RLIMIT_NOFILE, &rl) == 0) && (rl.rlim_cur < rl.rlim_max)) { orig_limit = rl.rlim_cur; rl.rlim_cur = rl.rlim_max; if (setrlimit(RLIMIT_NOFILE, &rl) != 0) smbd_report("Failed to raise file descriptor limit" " from %d to %d", orig_limit, rl.rlim_cur); } /* * Block async signals in all threads. */ (void) sigemptyset(&set); (void) sigaddset(&set, SIGHUP); (void) sigaddset(&set, SIGINT); (void) sigaddset(&set, SIGQUIT); (void) sigaddset(&set, SIGPIPE); (void) sigaddset(&set, SIGTERM); (void) sigaddset(&set, SIGUSR1); (void) sigaddset(&set, SIGUSR2); (void) sigprocmask(SIG_SETMASK, &set, NULL); if (smbd.s_fg) { if (smbd_service_init() != 0) { smbd_report("service initialization failed"); exit(SMF_EXIT_ERR_FATAL); } } else { /* * "pfd" is a pipe descriptor -- any fatal errors * during subsequent initialization of the child * process should be written to this pipe and the * parent will report this error as the exit status. */ pfd = smbd_daemonize_init(); if (smbd_service_init() != 0) { smbd_report("daemon initialization failed"); exit(SMF_EXIT_ERR_FATAL); } smbd_daemonize_fini(pfd, SMF_EXIT_OK); } while (!smbd.s_shutting_down) { sigval = sigwait(&set); switch (sigval) { case -1: syslog(LOG_DEBUG, "sigwait failed: %s", strerror(errno)); break; case SIGPIPE: break; case SIGHUP: syslog(LOG_DEBUG, "refresh requested"); smbd_refresh_handler(); break; case SIGUSR1: syslog(LOG_DEBUG, "SIGUSR1 ignored"); break; default: /* * Typically SIGINT or SIGTERM. */ smbd.s_shutting_down = B_TRUE; break; } } /* * Allow termination signals while shutting down. */ (void) sigemptyset(&set); if (smbd.s_fg) { (void) sigaddset(&set, SIGHUP); (void) sigaddset(&set, SIGINT); } (void) sigaddset(&set, SIGTERM); (void) sigprocmask(SIG_UNBLOCK, &set, NULL); smbd_service_fini(); return ((smbd.s_fatal_error) ? SMF_EXIT_ERR_FATAL : SMF_EXIT_OK); }