int main(int argc, char **argv) { int i; int config_loaded = 0; int dont_fork = 0; // global initialization get_HZ(); // set the name for logging program_name = "netdata"; // parse the arguments for(i = 1; i < argc ; i++) { if(strcmp(argv[i], "-c") == 0 && (i+1) < argc) { if(load_config(argv[i+1], 1) != 1) { error("Cannot load configuration file %s.", argv[i+1]); exit(1); } else { debug(D_OPTIONS, "Configuration loaded from %s.", argv[i+1]); config_loaded = 1; } i++; } else if(strcmp(argv[i], "-df") == 0 && (i+1) < argc) { config_set("global", "debug flags", argv[i+1]); debug_flags = strtoull(argv[i+1], NULL, 0); i++; } else if(strcmp(argv[i], "-p") == 0 && (i+1) < argc) { config_set("global", "port", argv[i+1]); i++; } else if(strcmp(argv[i], "-u") == 0 && (i+1) < argc) { config_set("global", "run as user", argv[i+1]); i++; } else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) { config_set("global", "history", argv[i+1]); i++; } else if(strcmp(argv[i], "-t") == 0 && (i+1) < argc) { config_set("global", "update every", argv[i+1]); i++; } else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) { config_set("global", "host access prefix", argv[i+1]); i++; } else if(strcmp(argv[i], "-nodaemon") == 0 || strcmp(argv[i], "-nd") == 0) dont_fork = 1; else if(strcmp(argv[i], "--unittest") == 0) { rrd_update_every = 1; if(run_all_mockup_tests()) exit(1); if(unit_test_storage()) exit(1); fprintf(stderr, "\n\nALL TESTS PASSED\n\n"); exit(0); } else { fprintf(stderr, "Cannot understand option '%s'.\n", argv[i]); fprintf(stderr, "\nUSAGE: %s [-d] [-l LINES_TO_SAVE] [-u UPDATE_TIMER] [-p LISTEN_PORT] [-df debug flags].\n\n", argv[0]); fprintf(stderr, " -c CONFIG FILE the configuration file to load. Default: %s.\n", CONFIG_DIR "/" CONFIG_FILENAME); fprintf(stderr, " -l LINES_TO_SAVE can be from 5 to %d lines in JSON data. Default: %d.\n", RRD_HISTORY_ENTRIES_MAX, RRD_DEFAULT_HISTORY_ENTRIES); fprintf(stderr, " -t UPDATE_TIMER can be from 1 to %d seconds. Default: %d.\n", UPDATE_EVERY_MAX, UPDATE_EVERY); fprintf(stderr, " -p LISTEN_PORT can be from 1 to %d. Default: %d.\n", 65535, LISTEN_PORT); fprintf(stderr, " -u USERNAME can be any system username to run as. Default: none.\n"); fprintf(stderr, " -ch path to access host /proc and /sys when running in a container. Default: empty.\n"); fprintf(stderr, " -nd or -nodeamon to disable forking in the background. Default: unset.\n"); fprintf(stderr, " -df FLAGS debug options. Default: 0x%08llx.\n", debug_flags); exit(1); } } if(!config_loaded) load_config(NULL, 0); // prepare configuration environment variables for the plugins setenv("NETDATA_CONFIG_DIR" , config_get("global", "config directory" , CONFIG_DIR) , 1); setenv("NETDATA_PLUGINS_DIR", config_get("global", "plugins directory" , PLUGINS_DIR), 1); setenv("NETDATA_WEB_DIR" , config_get("global", "web files directory", WEB_DIR) , 1); setenv("NETDATA_CACHE_DIR" , config_get("global", "cache directory" , CACHE_DIR) , 1); setenv("NETDATA_LOG_DIR" , config_get("global", "log directory" , LOG_DIR) , 1); setenv("NETDATA_HOST_PREFIX", config_get("global", "host access prefix" , "") , 1); // avoid extended to stat(/etc/localtime) // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux setenv("TZ", ":/etc/localtime", 0); // cd to /tmp to avoid any plugins writing files at random places if(chdir("/tmp")) error("netdata: ERROR: Cannot cd to /tmp"); char *input_log_file = NULL; char *output_log_file = NULL; char *error_log_file = NULL; char *access_log_file = NULL; char *user = NULL; { char buffer[1024]; // -------------------------------------------------------------------- sprintf(buffer, "0x%08llx", 0ULL); char *flags = config_get("global", "debug flags", buffer); setenv("NETDATA_DEBUG_FLAGS", flags, 1); debug_flags = strtoull(flags, NULL, 0); debug(D_OPTIONS, "Debug flags set to '0x%8llx'.", debug_flags); if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) info("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } // -------------------------------------------------------------------- #ifdef MADV_MERGEABLE enable_ksm = config_get_boolean("global", "memory deduplication (ksm)", enable_ksm); #else #warning "Kernel memory deduplication (KSM) is not available" #endif // -------------------------------------------------------------------- global_host_prefix = config_get("global", "host access prefix", ""); setenv("NETDATA_HOST_PREFIX", global_host_prefix, 1); // -------------------------------------------------------------------- output_log_file = config_get("global", "debug log", LOG_DIR "/debug.log"); if(strcmp(output_log_file, "syslog") == 0) { output_log_syslog = 1; output_log_file = NULL; } else if(strcmp(output_log_file, "none") == 0) { output_log_syslog = 0; output_log_file = NULL; } else output_log_syslog = 0; // -------------------------------------------------------------------- error_log_file = config_get("global", "error log", LOG_DIR "/error.log"); if(strcmp(error_log_file, "syslog") == 0) { error_log_syslog = 1; error_log_file = NULL; } else if(strcmp(error_log_file, "none") == 0) { error_log_syslog = 0; error_log_file = NULL; // optimization - do not even generate debug log entries } else error_log_syslog = 0; // -------------------------------------------------------------------- access_log_file = config_get("global", "access log", LOG_DIR "/access.log"); if(strcmp(access_log_file, "syslog") == 0) { access_log_syslog = 1; access_log_file = NULL; } else if(strcmp(access_log_file, "none") == 0) { access_log_syslog = 0; access_log_file = NULL; } else access_log_syslog = 0; // -------------------------------------------------------------------- rrd_memory_mode = rrd_memory_mode_id(config_get("global", "memory mode", rrd_memory_mode_name(rrd_memory_mode))); // -------------------------------------------------------------------- if(gethostname(buffer, HOSTNAME_MAX) == -1) error("WARNING: Cannot get machine hostname."); hostname = config_get("global", "hostname", buffer); debug(D_OPTIONS, "hostname set to '%s'", hostname); // -------------------------------------------------------------------- rrd_default_history_entries = (int) config_get_number("global", "history", RRD_DEFAULT_HISTORY_ENTRIES); if(rrd_default_history_entries < 5 || rrd_default_history_entries > RRD_HISTORY_ENTRIES_MAX) { fprintf(stderr, "Invalid save lines %d given. Defaulting to %d.\n", rrd_default_history_entries, RRD_DEFAULT_HISTORY_ENTRIES); rrd_default_history_entries = RRD_DEFAULT_HISTORY_ENTRIES; } else { debug(D_OPTIONS, "save lines set to %d.", rrd_default_history_entries); } // -------------------------------------------------------------------- rrd_update_every = (int) config_get_number("global", "update every", UPDATE_EVERY); if(rrd_update_every < 1 || rrd_update_every > 600) { fprintf(stderr, "Invalid update timer %d given. Defaulting to %d.\n", rrd_update_every, UPDATE_EVERY_MAX); rrd_update_every = UPDATE_EVERY; } else debug(D_OPTIONS, "update timer set to %d.", rrd_update_every); // let the plugins know the min update_every { char buf[50]; snprintf(buf, 50, "%d", rrd_update_every); setenv("NETDATA_UPDATE_EVERY", buf, 1); } // -------------------------------------------------------------------- for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->config_name) st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled); if(st->enabled && st->init_routine) st->init_routine(); } // -------------------------------------------------------------------- prepare_rundir(); user = config_get("global", "run as user" , (getuid() == 0)?NETDATA_USER:""); web_files_uid(); // -------------------------------------------------------------------- listen_backlog = (int) config_get_number("global", "http port listen backlog", LISTEN_BACKLOG); listen_port = (int) config_get_number("global", "port", LISTEN_PORT); if(listen_port < 1 || listen_port > 65535) { fprintf(stderr, "Invalid listen port %d given. Defaulting to %d.\n", listen_port, LISTEN_PORT); listen_port = LISTEN_PORT; } else debug(D_OPTIONS, "Listen port set to %d.", listen_port); int ip = 0; char *ipv = config_get("global", "ip version", "any"); if(!strcmp(ipv, "any") || !strcmp(ipv, "both") || !strcmp(ipv, "all")) ip = 0; else if(!strcmp(ipv, "ipv4") || !strcmp(ipv, "IPV4") || !strcmp(ipv, "IPv4") || !strcmp(ipv, "4")) ip = 4; else if(!strcmp(ipv, "ipv6") || !strcmp(ipv, "IPV6") || !strcmp(ipv, "IPv6") || !strcmp(ipv, "6")) ip = 6; else fprintf(stderr, "Cannot understand ip version '%s'. Assumming 'any'.", ipv); if(ip == 0 || ip == 6) listen_fd = create_listen_socket6(listen_port, listen_backlog); if(listen_fd < 0) { listen_fd = create_listen_socket4(listen_port, listen_backlog); if(listen_fd >= 0 && ip != 4) fprintf(stderr, "Managed to open an IPv4 socket on port %d.", listen_port); } if(listen_fd < 0) fatal("Cannot listen socket."); } // never become a problem if(nice(20) == -1) error("Cannot lower my CPU priority."); if(become_daemon(dont_fork, 0, user, input_log_file, output_log_file, error_log_file, access_log_file, &access_fd, &stdaccess) == -1) { fatal("Cannot demonize myself."); exit(1); } if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) info("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } if(output_log_syslog || error_log_syslog || access_log_syslog) openlog("netdata", LOG_PID, LOG_DAEMON); info("NetData started on pid %d", getpid()); // catch all signals for (i = 1 ; i < 65 ;i++) { switch(i) { case SIGKILL: // not catchable case SIGSTOP: // not catchable break; case SIGSEGV: case SIGFPE: case SIGCHLD: signal(i, SIG_DFL); break; default: signal(i, sig_handler); break; } } for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->enabled) { st->thread = malloc(sizeof(pthread_t)); if(!st->thread) fatal("Cannot allocate pthread_t memory"); info("Starting thread %s.", st->name); if(pthread_create(st->thread, NULL, st->start_routine, NULL)) error("failed to create new thread for %s.", st->name); else if(pthread_detach(*st->thread)) error("Cannot request detach of newly created %s thread.", st->name); } else info("Not starting thread %s.", st->name); } // for future use - the main thread while(1) { if(netdata_exit != 0) { netdata_exit++; if(netdata_exit > 5) { netdata_cleanup_and_exit(0); exit(0); } } sleep(2); } exit(0); }
/* * Use global *tty_tmp and term_parent */ int main( int argc, char **argv ) { struct cl_args *cl_args; struct term_node *tty_node = NULL; pid_t pid; pid_t parent_id; #if defined(HAVE_PTHREAD_SETCONCURRENCY) && !defined(LINUX) int concurrent; #endif handle_signals_parent(); tcgetattr(0, &term_parent); parent_id = getpid(); if ((pid = fork()) < 0) { exit(1); } else { if (pid != 0) { wait(NULL); tcsetattr(0, TCSANOW, &term_parent); exit(0); } } fatal_error = 4; /* Disable all signals while initializing data...*/ handle_signals(); setvbuf(stdout, NULL, _IONBF, 0); tty_tmp = (struct term_tty *)calloc(1,sizeof(struct term_tty)); if (tty_tmp == NULL) { printf("Out of memory on calloc tty_tmp\n"); clean_exit(); } tty_tmp->term = (struct termios *)calloc(1,sizeof(struct termios)); if (tty_tmp->term == NULL) { printf("Out of memory on calloc tty_tmp->term\n"); clean_exit(); } /* default values */ tty_tmp->interactive = 0; tty_tmp->gtk = 0; tty_tmp->attack = -1; tty_tmp->mac_spoofing = -1; tty_tmp->splash = -1; strncpy(tty_tmp->username, VTY_USER, MAX_USERNAME); strncpy(tty_tmp->password, VTY_PASS, MAX_PASSWORD); strncpy(tty_tmp->e_password, VTY_ENABLE, MAX_PASSWORD); tty_tmp->port = VTY_PORT; tty_tmp->ip_filter = NULL; #ifdef HAVE_GTK tty_tmp->buffer_log = NULL; #endif cl_args = (struct cl_args *)calloc(1,sizeof(struct cl_args)); if (cl_args == NULL) { printf("Out of memory on calloc cl_args\n"); clean_exit(); } if ( argc == 1 ) { printf("GNU %s %s %s\n", PACKAGE, VERSION, "$Date: 2006/03/23 08:40:14 $"); printf("Try '%s -h' to display the help.\n",PACKAGE); clean_exit(); } if (getuid() != 0) { printf("You must be root to run %s %s\n", PACKAGE, VERSION); clean_exit(); } if (term_init() < 0) g00dbye(); /* Register all the protocols */ protocol_init(); cl_args->proto_index = -1; if (parser_initial(tty_tmp, cl_args, argc, argv) < 0) { clean_exit(); } init_log(); #if defined(HAVE_PTHREAD_SETCONCURRENCY) && !defined(LINUX) /* concurrent = pthread_getconcurrency();*/ concurrent = 15;/*(MAX_TERMS*MAX_PROTOCOLS*MAX_THREAD_ATTACK*2)+3;*/ if (pthread_setconcurrency(concurrent) != 0) { thread_error("init pthread_setconcurrency()",errno); g00dbye(); } #endif if (interfaces_init(&terms->pcap_listen_th) < 0 ) g00dbye(); /* Establish TERM signal handler...*/ posix_signal(SIGTERM, final); #ifdef HAVE_REMOTE_ADMIN if (tty_tmp->daemonize) { if (admin_init(tty_tmp) < 0) g00dbye(); } #endif if (thread_create(&terms->uptime_th.id, &th_uptime, (void *)NULL) < 0) g00dbye(); /* Command line and ncurses cannot be choosed simultaneously...*/ if ((!tty_tmp->interactive) && (!tty_tmp->gtk) && (cl_args->proto_index != -1)) { terms->work_state = INITIAL; tty_node = term_type[TERM_TTY].list; if (thread_create(&tty_node[0].thread.id, &th_tty_peer, (void *)cl_args) < 0) g00dbye(); while(terms->work_state != STOPPED) thread_usleep(100000); } #ifdef HAS_CURSES if (tty_tmp->interactive) { terms->work_state = INITIAL; if (thread_create(&terms->gui_th.id, &ncurses_gui, NULL) < 0 ) g00dbye(); /* Wait until the ncurses GUI is over */ while(terms->work_state != STOPPED) thread_usleep(100000); } else { #endif #ifdef HAVE_GTK if (tty_tmp->gtk) { terms->work_state = INITIAL; if (thread_create(&terms->gui_gtk_th.id, >k_gui, NULL) < 0 ) g00dbye(); /* Wait until the GTK GUI is over */ while(terms->work_state != STOPPED) thread_usleep(100000); } #endif #ifdef HAS_CURSES } #endif #ifdef HAVE_REMOTE_ADMIN if (tty_tmp->daemonize) { /* Ok, now that console (ncurses) is finished * we can become a true daemon... */ become_daemon(parent_id); /* Wait until some important thread exits due to fatal_error...*/ while (fatal_error == 4) thread_usleep(100000); } #endif g00dbye(); exit(1); }
/**************************************************************************** ** main program **************************************************************************** */ int main(int argc, const char *argv[]) { pstring logfile; static BOOL opt_interactive; poptContext pc; static char *p_lmhosts = dyn_LMHOSTSFILE; static BOOL no_process_group = False; struct poptOption long_options[] = { POPT_AUTOHELP {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon(default)" }, {"interactive", 'i', POPT_ARG_VAL, &opt_interactive, True, "Run interactive (not a daemon)" }, {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" }, {"no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, {"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 'H', "Load a netbios hosts file"}, {"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" }, POPT_COMMON_SAMBA { NULL } }; load_case_tables(); global_nmb_port = NMB_PORT; pc = poptGetContext("nmbd", argc, argv, long_options, 0); while (poptGetNextOpt(pc) != -1) {}; poptFreeContext(pc); global_in_nmbd = True; StartupTime = time(NULL); sys_srandom(time(NULL) ^ sys_getpid()); if (!override_logfile) { slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE); lp_set_logfile(logfile); } fault_setup((void (*)(void *))fault_continue ); dump_core_setup("nmbd"); /* POSIX demands that signals are inherited. If the invoking process has * these signals masked, we will have problems, as we won't receive them. */ BlockSignals(False, SIGHUP); BlockSignals(False, SIGUSR1); BlockSignals(False, SIGTERM); CatchSignal( SIGHUP, SIGNAL_CAST sig_hup ); CatchSignal( SIGTERM, SIGNAL_CAST sig_term ); #if defined(SIGFPE) /* we are never interested in SIGFPE */ BlockSignals(True,SIGFPE); #endif /* We no longer use USR2... */ #if defined(SIGUSR2) BlockSignals(True, SIGUSR2); #endif if ( opt_interactive ) { Fork = False; log_stdout = True; } if ( log_stdout && Fork ) { DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); exit(1); } setup_logging( argv[0], log_stdout ); reopen_logs(); DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) ); DEBUGADD( 0, ( "%s\n", COPYRIGHT_STARTUP_MESSAGE ) ); if ( !reload_nmbd_services(False) ) return(-1); if(!init_names()) return -1; reload_nmbd_services( True ); if (strequal(lp_workgroup(),"*")) { DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); exit(1); } set_samba_nb_type(); if (!is_daemon && !is_a_socket(0)) { DEBUG(0,("standard input is not a socket, assuming -D option\n")); is_daemon = True; } if (is_daemon && !opt_interactive) { DEBUG( 2, ( "Becoming a daemon.\n" ) ); become_daemon(Fork, no_process_group); } #if HAVE_SETPGID /* * If we're interactive we want to set our own process group for * signal management. */ if (opt_interactive && !no_process_group) setpgid( (pid_t)0, (pid_t)0 ); #endif #ifndef SYNC_DNS /* Setup the async dns. We do it here so it doesn't have all the other stuff initialised and thus chewing memory and sockets */ if(lp_we_are_a_wins_server() && lp_dns_proxy()) { start_async_dns(); } #endif if (!directory_exist(lp_lockdir(), NULL)) { mkdir(lp_lockdir(), 0755); } pidfile_create("nmbd"); message_init(); message_register(MSG_FORCE_ELECTION, nmbd_message_election, NULL); #if 0 /* Until winsrepl is done. */ message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry, NULL); #endif message_register(MSG_SHUTDOWN, nmbd_terminate, NULL); message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services, NULL); message_register(MSG_SEND_PACKET, msg_nmbd_send_packet, NULL); TimeInit(); DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) ); if ( !open_sockets( is_daemon, global_nmb_port ) ) { kill_async_dns_child(); return 1; } /* Determine all the IP addresses we have. */ load_interfaces(); /* Create an nmbd subnet record for each of the above. */ if( False == create_subnets() ) { DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n")); kill_async_dns_child(); exit(1); } /* Load in any static local names. */ load_lmhosts_file(p_lmhosts); DEBUG(3,("Loaded hosts file %s\n", p_lmhosts)); /* If we are acting as a WINS server, initialise data structures. */ if( !initialise_wins() ) { DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) ); kill_async_dns_child(); exit(1); } /* * Register nmbd primary workgroup and nmbd names on all * the broadcast subnets, and on the WINS server (if specified). * Also initiate the startup of our primary workgroup (start * elections if we are setup as being able to be a local * master browser. */ if( False == register_my_workgroup_and_names() ) { DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n")); kill_async_dns_child(); exit(1); } /* We can only take signals in the select. */ BlockSignals( True, SIGTERM ); process(); if (dbf) x_fclose(dbf); kill_async_dns_child(); return(0); }
int main2(int argc,const char *argv[]) { /* shall I run as a daemon */ static BOOL is_daemon = False; static BOOL interactive = False; static BOOL Fork = True; static BOOL no_process_group = False; static BOOL log_stdout = False; static char *ports = NULL; int opt; #ifndef _XBOX poptContext pc; struct poptOption long_options[] = { POPT_AUTOHELP {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" }, {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"}, {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools, etc.)" }, {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" }, {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, POPT_COMMON_SAMBA POPT_COMMON_DYNCONFIG POPT_TABLEEND }; #else interactive = True; log_stdout = True; #endif load_case_tables(); #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); #endif #ifndef _XBOX pc = poptGetContext("smbd", argc, argv, long_options, 0); while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case 'b': build_options(True); /* Display output to screen as well as debug */ exit(0); break; } } poptFreeContext(pc); #endif #ifdef HAVE_SETLUID /* needed for SecureWare on SCO */ setluid(0); #endif sec_init(); set_remote_machine_name("smbd", False); if (interactive) { Fork = False; log_stdout = True; } if (interactive && (DEBUGLEVEL >= 9)) { talloc_enable_leak_report(); } if (log_stdout && Fork) { DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); exit(1); } setup_logging(argv[0],log_stdout); /* we want to re-seed early to prevent time delays causing client problems at a later date. (tridge) */ generate_random_buffer(NULL, 0); /* make absolutely sure we run as root - to handle cases where people are crazy enough to have it setuid */ gain_root_privilege(); gain_root_group_privilege(); #ifndef _XBOX fault_setup((void (*)(void *))exit_server_fault); dump_core_setup("smbd"); #endif CatchSignal(SIGTERM , SIGNAL_CAST sig_term); #ifndef _XBOX CatchSignal(SIGHUP,SIGNAL_CAST sig_hup); /* we are never interested in SIGPIPE */ BlockSignals(True,SIGPIPE); #endif #if defined(SIGFPE) /* we are never interested in SIGFPE */ BlockSignals(True,SIGFPE); #endif #if defined(SIGUSR2) /* We are no longer interested in USR2 */ BlockSignals(True,SIGUSR2); #endif /* POSIX demands that signals are inherited. If the invoking process has * these signals masked, we will have problems, as we won't recieve them. */ #ifndef _XBOX BlockSignals(False, SIGHUP); #endif BlockSignals(False, SIGUSR1); BlockSignals(False, SIGTERM); /* we want total control over the permissions on created files, so set our umask to 0 */ umask(0); init_sec_ctx(); reopen_logs(); DEBUG(0,( "smbd version %s started.\n", SAMBA_VERSION_STRING)); DEBUGADD( 0, ( "%s\n", COPYRIGHT_STARTUP_MESSAGE ) ); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); /* Output the build options to the debug log */ build_options(False); if (sizeof(uint16) < 2 || sizeof(uint32) < 4) { DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); exit(1); } /* * Do this before reload_services. */ if (!reload_services(False)) return(-1); init_structs(); #ifdef WITH_PROFILE if (!profile_setup(False)) { DEBUG(0,("ERROR: failed to setup profiling\n")); return -1; } #endif DEBUG(3,( "loaded services\n")); if (!is_daemon && !is_a_socket(0)) { if (!interactive) DEBUG(0,("standard input is not a socket, assuming -D option\n")); /* * Setting is_daemon here prevents us from eventually calling * the open_sockets_inetd() */ is_daemon = True; } if (is_daemon && !interactive) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); become_daemon(Fork, no_process_group); } #if HAVE_SETPGID /* * If we're interactive we want to set our own process group for * signal management. */ if (interactive && !no_process_group) setpgid( (pid_t)0, (pid_t)0); #endif if (!directory_exist(lp_lockdir(), NULL)) mkdir(lp_lockdir(), 0755); #ifndef _XBOX if (is_daemon) pidfile_create("smbd"); #endif /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ if (!message_init()) exit(1); /* Initialize our global sam sid first -- quite a lot of the other * initialization routines further down depend on it. */ /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ if(!initialize_password_db(False)) exit(1); /* Fail gracefully if we can't open secrets.tdb */ if (!secrets_init()) { DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n")); exit(1); } if(!get_global_sam_sid()) { DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); exit(1); } if (!session_init()) exit(1); if (conn_tdb_ctx() == NULL) exit(1); if (!locking_init(0)) exit(1); namecache_enable(); if (!init_registry()) exit(1); #if 0 if (!init_svcctl_db()) exit(1); #endif #ifndef _XBOX if (!print_backend_init()) exit(1); #endif if (!init_guest_info()) { DEBUG(0,("ERROR: failed to setup guest info.\n")); return -1; } /* Setup the main smbd so that we can get messages. */ /* don't worry about general printing messages here */ claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD); /* only start the background queue daemon if we are running as a daemon -- bad things will happen if smbd is launched via inetd and we fork a copy of ourselves here */ #ifndef _XBOX if ( is_daemon && !interactive ) start_background_queue(); #endif /* Always attempt to initialize DMAPI. We will only use it later if * lp_dmapi_support is set on the share, but we need a single global * session to work with. */ dmapi_init_session(); if (!open_sockets_smbd(is_daemon, interactive, ports)) exit(1); /* * everything after this point is run after the fork() */ static_init_rpc; init_modules(); /* possibly reload the services file. */ reload_services(True); if (!init_account_policy()) { DEBUG(0,("Could not open account policy tdb.\n")); exit(1); } if (*lp_rootdir()) { if (sys_chroot(lp_rootdir()) == 0) DEBUG(2,("Changed root to %s\n", lp_rootdir())); } /* Setup oplocks */ if (!init_oplocks()) exit(1); /* Setup change notify */ if (!init_change_notify()) exit(1); /* Setup aio signal handler. */ initialize_async_io_handler(); /* re-initialise the timezone */ TimeInit(); /* register our message handlers */ message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis); smbd_process(); #ifdef _XBOX xb_DecClientCount(); #endif namecache_shutdown(); exit_server_cleanly(NULL); return(0); }
int main ( int argc, char * argv [] ) { cmd_defaults(&cmd,argv[0]); init_error(); if(!is_path_absolute(argv[0])) { wrn_print("Require execution with absolute path(%s)",argv[0]); terminate(); } cmd_process(argc,argv,&cmd); if(!cmd.no_dump_config) dump_cmd(&cmd); // if( check_creds(&cmd.creds) == -1 ) // wrn_print("check_creds failed, program execution compromised"); if( cmd.kill_running || cmd.rexec_running) { // dbg_print("Sending %s signal",strsignal(cmd.rexec_running ? SIGHUP : cmd.kill_running ? SIGTERM : 0)); KILL_FROM_PID_ERRORS(kill_from_pid_file(cmd.pid_file, cmd.rexec_running ? SIGHUP : SIGTERM)); exit(EXIT_SUCCESS); } if(cmd.logs_enable) if(reopen_files() == -1) { wrn_print("reopen_files failed"); terminate(); } dbg_print("%s started executinon", argv[0]); dbg_print("Running as uid:%ld gid:%ld", (long)getuid(), (long)getgid()); if(cmd.need_daemon) { dbg_print("Demonizing.."); if(become_daemon()) { wrn_print("Can't demonize because of error"); terminate(); } } if(cmd.pid_file) { switch (create_pid_file(cmd.pid_file)) { case -1: wrn_print("creat_pid_file failed"); terminate(); case -2: wrn_print("An instance of %s is already running",cmd.path); exit(EXIT_SUCCESS); } } if(cmd.exit_after_dump) exit(EXIT_SUCCESS); block_all_sigs(); main_loop(); wrn_print("suspicious main_loop return..."); exit(EXIT_FAILURE); }
int main(int argc, char **argv) { char *hostname = "localhost"; int i, check_config = 0; int config_loaded = 0; int dont_fork = 0; size_t wanted_stacksize = 0, stacksize = 0; pthread_attr_t attr; // set the name for logging program_name = "netdata"; // parse depercated options // TODO: Remove this block with the next major release. { i = 1; while(i < argc) { if(strcmp(argv[i], "-pidfile") == 0 && (i+1) < argc) { strncpyz(pidfile, argv[i+1], FILENAME_MAX); fprintf(stderr, "%s: deprecated option -- %s -- please use -P instead.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-nodaemon") == 0 || strcmp(argv[i], "-nd") == 0) { dont_fork = 1; fprintf(stderr, "%s: deprecated option -- %s -- please use -D instead.\n ", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) { config_set("global", "host access prefix", argv[i+1]); fprintf(stderr, "%s: deprecated option -- %s -- please use -s instead.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) { config_set("global", "history", argv[i+1]); fprintf(stderr, "%s: deprecated option -- %s -- This option will be removed with V2.*.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else i++; } } // parse options { int num_opts = sizeof(options) / sizeof(struct option_def); char optstring[(num_opts * 2) + 1]; int string_i = 0; for( i = 0; i < num_opts; i++ ) { optstring[string_i] = options[i].val; string_i++; if(options[i].arg_name) { optstring[string_i] = ':'; string_i++; } } int opt; while( (opt = getopt(argc, argv, optstring)) != -1 ) { switch(opt) { case 'c': if(load_config(optarg, 1) != 1) { error("Cannot load configuration file %s.", optarg); exit(1); } else { debug(D_OPTIONS, "Configuration loaded from %s.", optarg); config_loaded = 1; } break; case 'D': dont_fork = 1; break; case 'h': help(0); break; case 'i': config_set("global", "bind to", optarg); break; case 'k': dont_fork = 1; check_config = 1; break; case 'P': strncpy(pidfile, optarg, FILENAME_MAX); pidfile[FILENAME_MAX] = '\0'; break; case 'p': config_set("global", "default port", optarg); break; case 's': config_set("global", "host access prefix", optarg); break; case 't': config_set("global", "update every", optarg); break; case 'u': config_set("global", "run as user", optarg); break; case 'v': // TODO: Outsource version to makefile which can compute version from git. printf("netdata %s\n", VERSION); return 0; case 'W': { char* stacksize_string = "stacksize="; char* debug_flags_string = "debug_flags="; if(strcmp(optarg, "unittest") == 0) { rrd_update_every = 1; if(run_all_mockup_tests()) exit(1); if(unit_test_storage()) exit(1); fprintf(stderr, "\n\nALL TESTS PASSED\n\n"); exit(0); } else if(strncmp(optarg, stacksize_string, strlen(stacksize_string)) == 0) { optarg += strlen(stacksize_string); config_set("global", "pthread stack size", optarg); } else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) { optarg += strlen(debug_flags_string); config_set("global", "debug flags", optarg); debug_flags = strtoull(optarg, NULL, 0); } } break; default: /* ? */ help(1); break; } } } if(!config_loaded) load_config(NULL, 0); { char *pmax = config_get("global", "glibc malloc arena max for plugins", "1"); if(pmax && *pmax) setenv("MALLOC_ARENA_MAX", pmax, 1); #if defined(HAVE_C_MALLOPT) int i = config_get_number("global", "glibc malloc arena max for netdata", 1); if(i > 0) mallopt(M_ARENA_MAX, 1); #endif char *config_dir = config_get("global", "config directory", CONFIG_DIR); // prepare configuration environment variables for the plugins setenv("NETDATA_CONFIG_DIR" , verify_required_directory(config_dir) , 1); setenv("NETDATA_PLUGINS_DIR", verify_required_directory(config_get("global", "plugins directory" , PLUGINS_DIR)), 1); setenv("NETDATA_WEB_DIR" , verify_required_directory(config_get("global", "web files directory", WEB_DIR)) , 1); setenv("NETDATA_CACHE_DIR" , verify_required_directory(config_get("global", "cache directory" , CACHE_DIR)) , 1); setenv("NETDATA_LIB_DIR" , verify_required_directory(config_get("global", "lib directory" , VARLIB_DIR)) , 1); setenv("NETDATA_LOG_DIR" , verify_required_directory(config_get("global", "log directory" , LOG_DIR)) , 1); setenv("NETDATA_HOST_PREFIX", config_get("global", "host access prefix" , "") , 1); setenv("HOME" , config_get("global", "home directory" , CACHE_DIR) , 1); // disable buffering for python plugins setenv("PYTHONUNBUFFERED", "1", 1); // avoid flood calls to stat(/etc/localtime) // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux setenv("TZ", ":/etc/localtime", 0); // work while we are cd into config_dir // to allow the plugins refer to their config // files using relative filenames if(chdir(config_dir) == -1) fatal("Cannot cd to '%s'", config_dir); char path[1024 + 1], *p = getenv("PATH"); if(!p) p = "/bin:/usr/bin"; snprintfz(path, 1024, "%s:%s", p, "/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin"); setenv("PATH", config_get("plugins", "PATH environment variable", path), 1); } char *user = NULL; { char *flags = config_get("global", "debug flags", "0x00000000"); setenv("NETDATA_DEBUG_FLAGS", flags, 1); debug_flags = strtoull(flags, NULL, 0); debug(D_OPTIONS, "Debug flags set to '0x%8llx'.", debug_flags); if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) error("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); #ifndef __FreeBSD__ prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); #endif /* __FreeBSD__ */ } // -------------------------------------------------------------------- #ifdef MADV_MERGEABLE enable_ksm = config_get_boolean("global", "memory deduplication (ksm)", enable_ksm); #else #warning "Kernel memory deduplication (KSM) is not available" #endif // -------------------------------------------------------------------- global_host_prefix = config_get("global", "host access prefix", ""); setenv("NETDATA_HOST_PREFIX", global_host_prefix, 1); get_system_HZ(); get_system_cpus(); get_system_pid_max(); // -------------------------------------------------------------------- stdout_filename = config_get("global", "debug log", LOG_DIR "/debug.log"); stderr_filename = config_get("global", "error log", LOG_DIR "/error.log"); stdaccess_filename = config_get("global", "access log", LOG_DIR "/access.log"); error_log_throttle_period_backup = error_log_throttle_period = config_get_number("global", "errors flood protection period", error_log_throttle_period); setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get("global", "errors flood protection period" , ""), 1); error_log_errors_per_period = (unsigned long)config_get_number("global", "errors to trigger flood protection", error_log_errors_per_period); setenv("NETDATA_ERRORS_PER_PERIOD" , config_get("global", "errors to trigger flood protection", ""), 1); if(check_config) { stdout_filename = stderr_filename = stdaccess_filename = "system"; error_log_throttle_period = 0; error_log_errors_per_period = 0; } error_log_limit_unlimited(); // -------------------------------------------------------------------- rrd_memory_mode = rrd_memory_mode_id(config_get("global", "memory mode", rrd_memory_mode_name(rrd_memory_mode))); // -------------------------------------------------------------------- { char hostnamebuf[HOSTNAME_MAX + 1]; if(gethostname(hostnamebuf, HOSTNAME_MAX) == -1) error("WARNING: Cannot get machine hostname."); hostname = config_get("global", "hostname", hostnamebuf); debug(D_OPTIONS, "hostname set to '%s'", hostname); setenv("NETDATA_HOSTNAME", hostname, 1); } // -------------------------------------------------------------------- rrd_default_history_entries = (int) config_get_number("global", "history", RRD_DEFAULT_HISTORY_ENTRIES); if(rrd_default_history_entries < 5 || rrd_default_history_entries > RRD_HISTORY_ENTRIES_MAX) { error("Invalid history entries %d given. Defaulting to %d.", rrd_default_history_entries, RRD_DEFAULT_HISTORY_ENTRIES); rrd_default_history_entries = RRD_DEFAULT_HISTORY_ENTRIES; } else { debug(D_OPTIONS, "save lines set to %d.", rrd_default_history_entries); } // -------------------------------------------------------------------- rrd_update_every = (int) config_get_number("global", "update every", UPDATE_EVERY); if(rrd_update_every < 1 || rrd_update_every > 600) { error("Invalid data collection frequency (update every) %d given. Defaulting to %d.", rrd_update_every, UPDATE_EVERY_MAX); rrd_update_every = UPDATE_EVERY; } else debug(D_OPTIONS, "update timer set to %d.", rrd_update_every); // let the plugins know the min update_every { char buf[16]; snprintfz(buf, 15, "%d", rrd_update_every); setenv("NETDATA_UPDATE_EVERY", buf, 1); } // -------------------------------------------------------------------- // block signals while initializing threads. // this causes the threads to block signals. sigset_t sigset; sigfillset(&sigset); if(pthread_sigmask(SIG_BLOCK, &sigset, NULL) == -1) error("Could not block signals for threads"); // Catch signals which we want to use struct sigaction sa; sa.sa_flags = 0; // ingore all signals while we run in a signal handler sigfillset(&sa.sa_mask); // INFO: If we add signals here we have to unblock them // at popen.c when running a external plugin. // Ignore SIGPIPE completely. sa.sa_handler = SIG_IGN; if(sigaction(SIGPIPE, &sa, NULL) == -1) error("Failed to change signal handler for SIGPIPE"); sa.sa_handler = sig_handler_exit; if(sigaction(SIGINT, &sa, NULL) == -1) error("Failed to change signal handler for SIGINT"); sa.sa_handler = sig_handler_exit; if(sigaction(SIGTERM, &sa, NULL) == -1) error("Failed to change signal handler for SIGTERM"); sa.sa_handler = sig_handler_logrotate; if(sigaction(SIGHUP, &sa, NULL) == -1) error("Failed to change signal handler for SIGHUP"); // save database on SIGUSR1 sa.sa_handler = sig_handler_save; if(sigaction(SIGUSR1, &sa, NULL) == -1) error("Failed to change signal handler for SIGUSR1"); // reload health configuration on SIGUSR2 sa.sa_handler = sig_handler_reload_health; if(sigaction(SIGUSR2, &sa, NULL) == -1) error("Failed to change signal handler for SIGUSR2"); // -------------------------------------------------------------------- i = pthread_attr_init(&attr); if(i != 0) fatal("pthread_attr_init() failed with code %d.", i); i = pthread_attr_getstacksize(&attr, &stacksize); if(i != 0) fatal("pthread_attr_getstacksize() failed with code %d.", i); else debug(D_OPTIONS, "initial pthread stack size is %zu bytes", stacksize); wanted_stacksize = (size_t)config_get_number("global", "pthread stack size", (long)stacksize); // -------------------------------------------------------------------- for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->config_name) st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled); if(st->enabled && st->init_routine) st->init_routine(); } // -------------------------------------------------------------------- // get the user we should run // IMPORTANT: this is required before web_files_uid() user = config_get("global", "run as user" , (getuid() == 0)?NETDATA_USER:""); // IMPORTANT: these have to run once, while single threaded web_files_uid(); // IMPORTANT: web_files_uid() before web_files_gid() web_files_gid(); // -------------------------------------------------------------------- if(!check_config) create_listen_sockets(); } // initialize the log files open_all_log_files(); #ifdef NETDATA_INTERNAL_CHECKS if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) error("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); #ifndef __FreeBSD__ prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); #endif /* __FreeBSD__ */ } #endif /* NETDATA_INTERNAL_CHECKS */ // fork, switch user, create pid file, set process priority if(become_daemon(dont_fork, user) == -1) fatal("Cannot daemonize myself."); info("NetData started on pid %d", getpid()); // ------------------------------------------------------------------------ // get default pthread stack size if(stacksize < wanted_stacksize) { i = pthread_attr_setstacksize(&attr, wanted_stacksize); if(i != 0) fatal("pthread_attr_setstacksize() to %zu bytes, failed with code %d.", wanted_stacksize, i); else debug(D_SYSTEM, "Successfully set pthread stacksize to %zu bytes", wanted_stacksize); } // ------------------------------------------------------------------------ // initialize rrd host rrdhost_init(hostname); // ------------------------------------------------------------------------ // initialize the registry registry_init(); // ------------------------------------------------------------------------ // initialize health monitoring health_init(); if(check_config) exit(1); // ------------------------------------------------------------------------ // enable log flood protection error_log_limit_reset(); // ------------------------------------------------------------------------ // spawn the threads web_server_threading_selection(); for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->enabled) { st->thread = mallocz(sizeof(pthread_t)); debug(D_SYSTEM, "Starting thread %s.", st->name); if(pthread_create(st->thread, &attr, st->start_routine, NULL)) error("failed to create new thread for %s.", st->name); else if(pthread_detach(*st->thread)) error("Cannot request detach of newly created %s thread.", st->name); } else debug(D_SYSTEM, "Not starting thread %s.", st->name); } // ------------------------------------------------------------------------ // block signals while initializing threads. sigset_t sigset; sigfillset(&sigset); if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) == -1) { error("Could not unblock signals for threads"); } // Handle flags set in the signal handler. while(1) { pause(); if(netdata_exit) { debug(D_EXIT, "Exit main loop of netdata."); netdata_cleanup_and_exit(0); exit(0); } } }
int main(int argc, char **argv) { const char *sopt = "hVvdm:p:l:f:F::b:s:t:"; const char *method = NULL, *path = NULL; const char *log_filepath = NULL; const char *pid_filepath = QGA_PIDFILE_DEFAULT; #ifdef CONFIG_FSFREEZE const char *fsfreeze_hook = NULL; #endif const char *state_dir = QGA_STATEDIR_DEFAULT; #ifdef _WIN32 const char *service = NULL; #endif const struct option lopt[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "logfile", 1, NULL, 'l' }, { "pidfile", 1, NULL, 'f' }, #ifdef CONFIG_FSFREEZE { "fsfreeze-hook", 2, NULL, 'F' }, #endif { "verbose", 0, NULL, 'v' }, { "method", 1, NULL, 'm' }, { "path", 1, NULL, 'p' }, { "daemonize", 0, NULL, 'd' }, { "blacklist", 1, NULL, 'b' }, #ifdef _WIN32 { "service", 1, NULL, 's' }, #endif { "statedir", 1, NULL, 't' }, { NULL, 0, NULL, 0 } }; int opt_ind = 0, ch, daemonize = 0, i, j, len; GLogLevelFlags log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL; GList *blacklist = NULL; GAState *s; module_call_init(MODULE_INIT_QAPI); while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { switch (ch) { case 'm': method = optarg; break; case 'p': path = optarg; break; case 'l': log_filepath = optarg; break; case 'f': pid_filepath = optarg; break; #ifdef CONFIG_FSFREEZE case 'F': fsfreeze_hook = optarg ? optarg : QGA_FSFREEZE_HOOK_DEFAULT; break; #endif case 't': state_dir = optarg; break; case 'v': /* enable all log levels */ log_level = G_LOG_LEVEL_MASK; break; case 'V': printf("QEMU Guest Agent %s\n", QEMU_VERSION); return 0; case 'd': daemonize = 1; break; case 'b': { char **list_head, **list; if (is_help_option(optarg)) { list_head = list = qmp_get_command_list(); while (*list != NULL) { printf("%s\n", *list); g_free(*list); list++; } g_free(list_head); return 0; } for (j = 0, i = 0, len = strlen(optarg); i < len; i++) { if (optarg[i] == ',') { optarg[i] = 0; blacklist = g_list_append(blacklist, &optarg[j]); j = i + 1; } } if (j < i) { blacklist = g_list_append(blacklist, &optarg[j]); } break; } #ifdef _WIN32 case 's': service = optarg; if (strcmp(service, "install") == 0) { return ga_install_service(path, log_filepath); } else if (strcmp(service, "uninstall") == 0) { return ga_uninstall_service(); } else { printf("Unknown service command.\n"); return EXIT_FAILURE; } break; #endif case 'h': usage(argv[0]); return 0; case '?': g_print("Unknown option, try '%s --help' for more information.\n", argv[0]); return EXIT_FAILURE; } } s = g_malloc0(sizeof(GAState)); s->log_level = log_level; s->log_file = stderr; #ifdef CONFIG_FSFREEZE s->fsfreeze_hook = fsfreeze_hook; #endif g_log_set_default_handler(ga_log, s); g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR); ga_enable_logging(s); s->state_filepath_isfrozen = g_strdup_printf("%s/qga.state.isfrozen", state_dir); s->pstate_filepath = g_strdup_printf("%s/qga.state", state_dir); s->frozen = false; #ifndef _WIN32 /* check if a previous instance of qemu-ga exited with filesystems' state * marked as frozen. this could be a stale value (a non-qemu-ga process * or reboot may have since unfrozen them), but better to require an * uneeded unfreeze than to risk hanging on start-up */ struct stat st; if (stat(s->state_filepath_isfrozen, &st) == -1) { /* it's okay if the file doesn't exist, but if we can't access for * some other reason, such as permissions, there's a configuration * that needs to be addressed. so just bail now before we get into * more trouble later */ if (errno != ENOENT) { g_critical("unable to access state file at path %s: %s", s->state_filepath_isfrozen, strerror(errno)); return EXIT_FAILURE; } } else { g_warning("previous instance appears to have exited with frozen" " filesystems. deferring logging/pidfile creation and" " disabling non-fsfreeze-safe commands until" " guest-fsfreeze-thaw is issued, or filesystems are" " manually unfrozen and the file %s is removed", s->state_filepath_isfrozen); s->frozen = true; } #endif if (ga_is_frozen(s)) { if (daemonize) { /* delay opening/locking of pidfile till filesystem are unfrozen */ s->deferred_options.pid_filepath = pid_filepath; become_daemon(NULL); } if (log_filepath) { /* delay opening the log file till filesystems are unfrozen */ s->deferred_options.log_filepath = log_filepath; } ga_disable_logging(s); ga_disable_non_whitelisted(); } else { if (daemonize) { become_daemon(pid_filepath); } if (log_filepath) { FILE *log_file = ga_open_logfile(log_filepath); if (!log_file) { g_critical("unable to open specified log file: %s", strerror(errno)); goto out_bad; } s->log_file = log_file; } } /* load persistent state from disk */ if (!read_persistent_state(&s->pstate, s->pstate_filepath, ga_is_frozen(s))) { g_critical("failed to load persistent state"); goto out_bad; } if (blacklist) { s->blacklist = blacklist; do { g_debug("disabling command: %s", (char *)blacklist->data); qmp_disable_command(blacklist->data); blacklist = g_list_next(blacklist); } while (blacklist); } s->command_state = ga_command_state_new(); ga_command_state_init(s, s->command_state); ga_command_state_init_all(s->command_state); json_message_parser_init(&s->parser, process_event); ga_state = s; #ifndef _WIN32 if (!register_signal_handlers()) { g_critical("failed to register signal handlers"); goto out_bad; } #endif s->main_loop = g_main_loop_new(NULL, false); if (!channel_init(ga_state, method, path)) { g_critical("failed to initialize guest agent channel"); goto out_bad; } #ifndef _WIN32 g_main_loop_run(ga_state->main_loop); #else if (daemonize) { SERVICE_TABLE_ENTRY service_table[] = { { (char *)QGA_SERVICE_NAME, service_main }, { NULL, NULL } }; StartServiceCtrlDispatcher(service_table); } else { g_main_loop_run(ga_state->main_loop); } #endif ga_command_state_cleanup_all(ga_state->command_state); ga_channel_free(ga_state->channel); if (daemonize) { unlink(pid_filepath); } return 0; out_bad: if (daemonize) { unlink(pid_filepath); } return EXIT_FAILURE; }
int main(int argc, char **argv) { pstring logfile; static BOOL interactive = False; static BOOL Fork = True; static BOOL log_stdout = False; struct poptOption long_options[] = { POPT_AUTOHELP { "stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, { "foreground", 'F', POPT_ARG_VAL, &Fork, False, "Daemon in foreground mode" }, { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" }, { "single-daemon", 'Y', POPT_ARG_VAL, &opt_dual_daemon, False, "Single daemon mode" }, { "no-caching", 'n', POPT_ARG_VAL, &opt_nocache, True, "Disable caching" }, POPT_COMMON_SAMBA POPT_TABLEEND }; poptContext pc; int opt; /* glibc (?) likes to print "User defined signal 1" and exit if a SIGUSR[12] is received before a handler is installed */ CatchSignal(SIGUSR1, SIG_IGN); CatchSignal(SIGUSR2, SIG_IGN); fault_setup((void (*)(void *))fault_quit ); /* Initialise for running in non-root mode */ sec_init(); set_remote_machine_name("winbindd", False); /* Set environment variable so we don't recursively call ourselves. This may also be useful interactively. */ setenv(WINBINDD_DONT_ENV, "1", 1); /* Initialise samba/rpc client stuff */ pc = poptGetContext("winbindd", argc, (const char **)argv, long_options, POPT_CONTEXT_KEEP_FIRST); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { /* Don't become a daemon */ case 'i': interactive = True; log_stdout = True; Fork = False; break; } } if (log_stdout && Fork) { printf("Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n"); poptPrintUsage(pc, stderr, 0); exit(1); } pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE); lp_set_logfile(logfile); setup_logging("winbindd", log_stdout); reopen_logs(); DEBUG(1, ("winbindd version %s started.\n", SAMBA_VERSION_STRING) ); DEBUGADD( 1, ( "Copyright The Samba Team 2000-2004\n" ) ); if (!reload_services_file()) { DEBUG(0, ("error opening config file\n")); exit(1); } /* Setup names. */ if (!init_names()) exit(1); load_interfaces(); if (!secrets_init()) { DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n")); return False; } /* Enable netbios namecache */ namecache_enable(); /* Check winbindd parameters are valid */ ZERO_STRUCT(server_state); /* Winbind daemon initialisation */ if ( (!winbindd_param_init()) || (!winbindd_upgrade_idmap()) || (!idmap_init(lp_idmap_backend())) ) { DEBUG(1, ("Could not init idmap -- netlogon proxy only\n")); idmap_proxyonly(); } generate_wellknown_sids(); /* Unblock all signals we are interested in as they may have been blocked by the parent process. */ BlockSignals(False, SIGINT); BlockSignals(False, SIGQUIT); BlockSignals(False, SIGTERM); BlockSignals(False, SIGUSR1); BlockSignals(False, SIGUSR2); BlockSignals(False, SIGHUP); BlockSignals(False, SIGCHLD); /* Setup signal handlers */ CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */ CatchSignal(SIGQUIT, termination_handler); CatchSignal(SIGTERM, termination_handler); CatchSignal(SIGCHLD, sigchld_handler); CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */ CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */ CatchSignal(SIGHUP, sighup_handler); if (!interactive) become_daemon(Fork); pidfile_create("winbindd"); #if HAVE_SETPGID /* * If we're interactive we want to set our own process group for * signal management. */ if (interactive) setpgid( (pid_t)0, (pid_t)0); #endif if (opt_dual_daemon) { do_dual_daemon(); } /* Initialise messaging system */ if (!message_init()) { DEBUG(0, ("unable to initialise messaging system\n")); exit(1); } /* React on 'smbcontrol winbindd reload-config' in the same way as to SIGHUP signal */ message_register(MSG_SMB_CONF_UPDATED, msg_reload_services); message_register(MSG_SHUTDOWN, msg_shutdown); poptFreeContext(pc); netsamlogon_cache_init(); /* Non-critical */ init_domain_list(); /* Loop waiting for requests */ process_loop(); trustdom_cache_shutdown(); return 0; }
int tcf(void) { #else int main(int argc, char ** argv) { int c; int ind; int daemon = 0; const char * log_name = NULL; const char * log_level = NULL; #endif int interactive = 0; int print_server_properties = 0; const char * url = DEFAULT_SERVER_URL; Protocol * proto; TCFBroadcastGroup * bcg; ini_mdep(); ini_trace(); ini_events_queue(); ini_asyncreq(); #if defined(_WRS_KERNEL) progname = "tcf"; open_log_file("-"); log_mode = 0; #else progname = argv[0]; /* Parse arguments */ for (ind = 1; ind < argc; ind++) { const char * s = argv[ind]; if (*s != '-') { break; } s++; while ((c = *s++) != '\0') { switch (c) { case 'i': interactive = 1; break; case 't': #if ENABLE_RCBP_TEST test_proc(); #endif exit(0); break; case 'd': daemon = 1; break; case 'c': generate_ssl_certificate(); exit(0); break; case 'S': print_server_properties = 1; break; case 'h': show_help(); exit(0); case 'I': case 'l': case 'L': case 's': #if ENABLE_Plugins case 'P': #endif if (*s == '\0') { if (++ind >= argc) { fprintf(stderr, "%s: error: no argument given to option '%c'\n", progname, c); exit(1); } s = argv[ind]; } switch (c) { case 'I': idle_timeout = strtol(s, 0, 0); break; case 'l': log_level = s; parse_trace_mode(log_level, &log_mode); break; case 'L': log_name = s; break; case 's': url = s; break; #if ENABLE_Plugins case 'P': plugins_path = s; break; #endif } s = ""; break; default: fprintf(stderr, "%s: error: illegal option '%c'\n", progname, c); show_help(); exit(1); } } } if (daemon && log_name != NULL && strcmp (log_name, LOG_NAME_STDERR) != 0) { fprintf(stderr, "%s: error: can only log to stderr when in daemon " "mode.\n", progname); exit (1); } if (daemon) become_daemon(); open_log_file(log_name); #endif bcg = broadcast_group_alloc(); proto = protocol_alloc(); /* The static services must be initialised before the plugins */ #if ENABLE_Cmdline if (interactive) ini_cmdline_handler(interactive, proto); #else if (interactive) fprintf(stderr, "Warning: This version does not support interactive mode.\n"); #endif ini_services(proto, bcg); #if !defined(_WRS_KERNEL) /* Reparse log level in case initialization cause additional * levels to be registered */ if (log_level != NULL && parse_trace_mode(log_level, &log_mode) != 0) { fprintf(stderr, "Cannot parse log level: %s\n", log_level); exit(1); } #endif if (ini_server(url, proto, bcg) < 0) { fprintf(stderr, "Cannot create TCF server: %s\n", errno_to_str(errno)); exit(1); } discovery_start(); if (print_server_properties) { ChannelServer * s; char * server_properties; assert(!list_is_empty(&channel_server_root)); s = servlink2channelserverp(channel_server_root.next); server_properties = channel_peer_to_json(s->ps); printf("Server-Properties: %s\n", server_properties); fflush(stdout); trace(LOG_ALWAYS, "Server-Properties: %s", server_properties); loc_free(server_properties); } #if ENABLE_SignalHandlers signal(SIGABRT, signal_handler); signal(SIGILL, signal_handler); signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); #if defined(_WIN32) SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); AddVectoredExceptionHandler(1, VectoredExceptionHandler); #endif #endif /* ENABLE_SignalHandlers */ if (idle_timeout != 0) { add_channel_close_listener(channel_closed); check_idle_timeout(NULL); } /* Process events - must run on the initial thread since ptrace() * returns ECHILD otherwise, thinking we are not the owner. */ run_event_loop(); #if ENABLE_Plugins plugins_destroy(); #endif /* ENABLE_Plugins */ return 0; }
main(int argc,char *argv[]) #endif { int listener_fd, new_fd; int remotelen; int port = 0; int c, on; struct sockaddr_in local_sin, remote_sin; static fd_set fdset, fdset_saved; struct conn_stat *rconn, *wconn; #ifdef STE_WINDOWS u_long param = 0; /* FIONBIO コマンドのパラメータ Non-Blocking ON*/ int nRtn; WSADATA wsaData; stehubstat_t stehubstat[1]; nRtn = WSAStartup(MAKEWORD(1, 1), &wsaData); #endif while ((c = getopt(argc, argv, "p:d:")) != EOF){ switch (c) { case 'p': port = atoi(optarg); break; case 'd': debuglevel = atoi(optarg); break; default: print_usage(argv[0]); } } conn_stat_head->next = NULL; conn_stat_head->fd = 0; if(( listener_fd = socket( AF_INET, SOCK_STREAM,0 )) < 0 ) { SET_ERRNO(); print_err(LOG_ERR,"socket: %s (%d)\n", strerror(errno), errno); exit(1); } on = 1; if((setsockopt(listener_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) <0){ SET_ERRNO(); print_err(LOG_ERR,"setsockopt:%s\n", strerror(errno)); exit(1); } if(port == 0) port = PORT_NO; memset((char *)&remote_sin, 0x0, sizeof(struct sockaddr_in)); memset((char *)&local_sin, 0x0, sizeof(struct sockaddr_in)); local_sin.sin_port = htons((short)port); local_sin.sin_family = AF_INET; local_sin.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(listener_fd,(struct sockaddr *)&local_sin,sizeof(struct sockaddr_in)) < 0 ){ SET_ERRNO(); print_err(LOG_ERR,"bind:%s\n", strerror(errno)); exit(1); } /* * accept() でブロックされるのを防ぐため、non-blocking mode に設定 */ #ifndef STE_WINDOWS if( fcntl (listener_fd, F_SETFL, O_NONBLOCK) < 0) { #else if( ioctlsocket(listener_fd, FIONBIO, ¶m) < 0){ #endif SET_ERRNO(); print_err(LOG_ERR, "Failed to set nonblock: %s (%d)\n",strerror(errno), errno); exit(1); } if(listen(listener_fd, 5) < 0) { SET_ERRNO(); print_err(LOG_ERR,"listen:%s\n", strerror(errno)); exit(1); } FD_ZERO(&fdset_saved); FD_SET(listener_fd, &fdset_saved); /* * syslog のための設定。Facility は LOG_USER とする * Windows の場合はログファイルをオープンする。 */ #ifdef STE_WINDOWS hStedLog = CreateFile(STEHUB_LOG_FILE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ| FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); SetFilePointer(hStedLog, 0, NULL, FILE_END); if(isTerminal == FALSE){ /* サービスとして呼ばれている(コマンドプロンプトから呼ばれていない)場合 */ stehubServiceStatus.dwServiceType = SERVICE_WIN32; stehubServiceStatus.dwCurrentState = SERVICE_START_PENDING; stehubServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; stehubServiceStatus.dwWin32ExitCode = 0; stehubServiceStatus.dwServiceSpecificExitCode = 0; stehubServiceStatus.dwCheckPoint = 0; stehubServiceStatus.dwWaitHint = 0; /* サービスコントロールハンドラーを登録 */ stehubServiceStatusHandle = RegisterServiceCtrlHandlerEx( "Stehub", //LPCTSTR stehub_svc_ctrl_handler, //LPHANDLER_FUNCTION_EX (LPVOID)stehubstat //LPVOID ); if (stehubServiceStatusHandle == (SERVICE_STATUS_HANDLE)0){ return; } stehubServiceStatus.dwCurrentState = SERVICE_RUNNING; stehubServiceStatus.dwCheckPoint = 0; stehubServiceStatus.dwWaitHint = 0; if (!SetServiceStatus (stehubServiceStatusHandle, &stehubServiceStatus)){ // SetServiceStatus が失敗した場合の処理・・ print_err(LOG_ERR, "SetServiceStatus Failed\n"); } } #else openlog(basename(argv[0]),LOG_PID,LOG_USER); #endif /* * ここまではとりあえず、フォアグラウンドで実行。 * ここからは、デバッグレベル 0 (デフォルト)なら、バックグラウンド * で実行し、そうでなければフォアグラウンド続行。 * Windows の場合は、いづれにしてもフォアグラウンドで実行 * し、デバッグレベル 1 以上の場合はログをファイルに書く。 */ if (debuglevel == 0){ #ifndef STE_WINDOWS print_err(LOG_NOTICE,"Going to background mode\n"); if(become_daemon() != 0){ print_err(LOG_ERR,"can't become daemon\n"); print_err(LOG_ERR,"Exit\n"); exit(1); } #else use_log = 1; #endif } print_err(LOG_NOTICE,"Started\n"); /* * メインループ * 仮想 NIC デーモンからの接続要求を待ち、接続後は仮想 NIC デーモン * からのデータを待つ。1つの仮想デーモンからのデータを他方に転送する。 */ for(;;){ fdset = fdset_saved; if( select(FD_SETSIZE, &fdset, NULL, NULL, NULL) < 0){ SET_ERRNO(); print_err(LOG_ERR,"select:%s\n", strerror(errno)); } if(FD_ISSET(listener_fd, &fdset)){ remotelen = sizeof(struct sockaddr_in); if((new_fd = accept(listener_fd,(struct sockaddr *)&remote_sin, &remotelen)) < 0){ SET_ERRNO(); if(errno == EINTR || errno == EWOULDBLOCK || errno == ECONNABORTED){ print_err(LOG_NOTICE, "accept: %s\n", strerror(errno)); continue; } else { print_err(LOG_ERR, "accept: %s\n", strerror(errno)); return(-1); } } FD_SET(new_fd, &fdset_saved); print_err(LOG_NOTICE,"fd%d: connection from %s\n",new_fd, inet_ntoa(remote_sin.sin_addr)); add_conn_stat(new_fd, remote_sin.sin_addr); /* * recv() でブロックされるのを防ぐため、non-blocking mode に設定 */ #ifndef STE_WINDOWS if (fcntl(new_fd, F_SETFL, O_NONBLOCK) < 0 ) { #else if(ioctlsocket(new_fd, FIONBIO, ¶m) < 0){ #endif SET_ERRNO(); print_err(LOG_ERR, "fd%d: Failed to set nonblock: %s (%d)\n", new_fd,strerror(errno),errno); return(-1); } continue; } for( rconn = conn_stat_head->next ; rconn != NULL ; rconn = rconn->next){ int rfd, wfd; rfd = rconn->fd; if (FD_ISSET(rfd, &fdset)){ int rsize; char databuf[SOCKBUFSIZE]; char *bufp; int datalen; bufp = (char *)databuf; rsize = recv(rfd, bufp, SOCKBUFSIZE,0); if(rsize == 0){ /* * コネクションが切断されたようだ。 * socket を close してループを抜ける */ print_err(LOG_ERR,"fd%d: Connection closed by %s\n", rfd, inet_ntoa(rconn->addr)); CLOSE(rfd); print_err(LOG_ERR,"fd%d: closed\n", rfd); FD_CLR(rfd, &fdset_saved); delete_conn_stat(rfd); break; } if(rsize < 0){ SET_ERRNO(); /* * 致命的でない error の場合は無視してループを継続 */ if(errno == EINTR || errno == EWOULDBLOCK){ print_err(LOG_NOTICE, "fd%d: recv: %s\n", rfd, strerror(errno)); continue; } /* * エラーが発生したようだ。 * socket を close して forループを抜ける */ print_err(LOG_ERR,"fd%d: recv: %s\n", rfd,strerror(errno)); CLOSE(rfd); print_err(LOG_ERR,"fd%d: closed\n", rfd); FD_CLR(rfd, &fdset_saved); delete_conn_stat(rfd); break; } /* * 他の仮想 NIC にパケットを転送する。 * 「待ち」が発生すると、パフォーマンスに影響があるので、EWOULDBLOCK * の場合は配送をあきらめる。 */ for(wconn = conn_stat_head->next ; wconn != NULL ; wconn = wconn->next){ wfd = wconn->fd; if (rfd == wfd) continue; if( debuglevel > 1){ print_err(LOG_ERR,"fd%d(%s) ==> ", rfd, inet_ntoa(rconn->addr)); print_err(LOG_ERR,"fd%d(%s)\n", wfd,inet_ntoa(wconn->addr)); } if ( send(wfd, bufp, rsize, 0) < 0){ SET_ERRNO(); if(errno == EINTR || errno == EWOULDBLOCK ){ print_err(LOG_NOTICE,"fd%d: send: %s\n", wfd ,strerror(errno)); continue; } else { print_err(LOG_ERR,"fd%d: send: %s (%d)\n",wfd,strerror(errno), errno); CLOSE(wfd); print_err(LOG_ERR,"fd%d: closed\n", wfd); FD_CLR(wfd, &fdset_saved); delete_conn_stat(wfd); break; } } } /* End of loop for send()ing */ } } /* End of loop for each connection */ } /* End of main loop */ } #ifdef STE_WINDOWS /************************************************************************** * Windows の場合の main() * * 引数が -I もしくは -U だった場合には本プログラム(仮想 HUB デーモン) * を Windows のサービスとして登録/登録解除する。 * それ以外の引数が渡された場合には ste_svc_main() を直接呼び出し、引数も * そのまま ste_svc_main() に渡す。 * * 引数(argvとして): * * -I : サービスとして登録。 * -U : 登録解除 * **************************************************************************/ int WINAPIV main(int argc, char *argv[]) { int c; SERVICE_TABLE_ENTRY DispatchTable[] = { { "Stehub", stehub_svc_main}, { NULL, NULL } }; isTerminal = _isatty(_fileno(stdout))? TRUE:FALSE; // // 引数が無ない場合。 // コマンドプロンプトから呼ばれた時は stehub_svc_main() を呼び、 // そうでなければ StartServiceCtlDispatcher() を呼ぶ。 // if(argc == 1 ){ if(isTerminal == TRUE){ stehub_svc_main(argc, argv); return(0); } else { StartServiceCtrlDispatcher(DispatchTable); return(0); } } while((c = getopt(argc, argv, "IU")) != EOF ){ switch(c){ case 'I': // stehub.exe をサービスとして登録 if(stehub_install_svc()) printf("Service Installed Sucessfully\n"); else printf("Error Installing Service\n"); break; case 'U': // stehub.exe のサービスとして登録を解除 if(stehub_delete_svc()) printf("Service UnInstalled Sucessfully\n"); else printf("Error UnInstalling Service\n"); break; default : // // 引数が -U、-I でなければコマンドプロンプト内で // stehub.exe を起動したいのだと判断し、引数を全て // stehub_svc_main() に渡して呼び出す。 // stehub_svc_main(argc, argv); return(0); } } return(0); } /**************************************** * Windows サービス登録ルーチン * ****************************************/ BOOL stehub_install_svc() { LPCTSTR lpszBinaryPathName; TCHAR strDir[1024]; HANDLE schSCManager,schService; GetCurrentDirectory(1024, strDir); strcat((char *)strDir, "\\stehub.exe"); schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); if (schSCManager == NULL) return FALSE; lpszBinaryPathName=strDir; schService = CreateService(schSCManager,"Stehub", "Stehub Virtual HUB daemon", // 表示用サービス名 SERVICE_ALL_ACCESS, // アクセス SERVICE_WIN32_OWN_PROCESS, // サービスタイプ SERVICE_DEMAND_START, // スタートタイプ SERVICE_ERROR_NORMAL, // エラーコントロールタイプ lpszBinaryPathName, // バイナリへのパス NULL, // No load ordering group NULL, // No tag identifier NULL, // No dependencies NULL, // LocalSystem account NULL);// No password if (schService == NULL) return FALSE; CloseServiceHandle(schService); return TRUE; } /**************************************** * Windows サービス登録解除ルーチン * ****************************************/ BOOL stehub_delete_svc() { HANDLE schSCManager; SC_HANDLE hService; schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); if (schSCManager == NULL) return FALSE; hService=OpenService(schSCManager, "Stehub", SERVICE_ALL_ACCESS); if (hService == NULL) return FALSE; if(DeleteService(hService)==0) return FALSE; if(CloseServiceHandle(hService)==0) return FALSE; return TRUE; } /****************************************************************************** * stehub_svc_ctrl_handler() * * サービスステータスハンドラー * DEVICEEVENT を拾うためには Handler ではなく、HandlerEx じゃないといけないらしい。 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/handlerex.asp * * まったく呼ばれていないような・・? ******************************************************************************/ DWORD WINAPI stehub_svc_ctrl_handler( DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ) { PDEV_BROADCAST_HDR p = (PDEV_BROADCAST_HDR) lpEventData; WPARAM wParam = (WPARAM) dwEventType; stehubstat_t *stehubstat = NULL; stehubstat = (stehubstat_t *)lpContext; if(debuglevel > 1){ print_err(LOG_DEBUG, "Service Status Handler stehub_svc_ctrl_handler called\n"); } switch(dwControl){ case SERVICE_CONTROL_DEVICEEVENT: break; case SERVICE_CONTROL_PAUSE: stehubServiceStatus.dwCurrentState = SERVICE_PAUSED; break; case SERVICE_CONTROL_CONTINUE: stehubServiceStatus.dwCurrentState = SERVICE_RUNNING; break; case SERVICE_CONTROL_STOP: stehubServiceStatus.dwWin32ExitCode = 0; stehubServiceStatus.dwCurrentState = SERVICE_STOPPED; stehubServiceStatus.dwCheckPoint = 0; stehubServiceStatus.dwWaitHint = 0; SetServiceStatus (stehubServiceStatusHandle,&stehubServiceStatus); break; case SERVICE_CONTROL_INTERROGATE: break; } return NO_ERROR; }
int main(int argc, char * argv[]) { char app_instance[INSTANCE_NAME_LEN]; int option_char; int interval = DEFAULT_APPHB_INTERVAL; int apphb_warntime = DEFAULT_APPHB_WARNTIME; char ** client_argv = NULL; pid_t child_tmp = 0; cl_log_set_entity(app_name); cl_log_enable_stderr(TRUE); cl_log_set_facility(HA_LOG_FACILITY); if (argc == 1) { /* no arguments */ printf("%s\n", Simple_helpscreen); exit(LSB_EXIT_EINVAL); } /* * Try to separate the option parameter between myself and the client. * Maybe rewrite the argc and argv. */ separate_argv(&argc, &argv, &client_argv); /* code for debug */ #if 0 { int j; cl_log(LOG_INFO, "client_argv: 0x%08lx", (unsigned long) client_argv); cl_log(LOG_INFO, "Called arg"); for (j=0; argv[j] != NULL; ++j) { cl_log(LOG_INFO, "argv[%d]: %s", j, argv[j]); } for (j=0; client_argv && client_argv[j] != NULL; ++j) { if (ANYDEBUG) { cl_log(LOG_INFO, "client_argv[%d]: %s", j, client_argv[j]); } } } #endif do { option_char = getopt(argc, argv, optstr); if (option_char == -1) { break; } switch (option_char) { case 'r': IS_RECOVERY = TRUE; break; case 'm': if (optarg) { MAGIC_EXIT_CODE = atoi(optarg); } break; case 'i': if (optarg) { interval = atoi(optarg); } else { printf("error.\n"); } break; case 'p': if (optarg) { pidfile = optarg; } break; case 'w': if (optarg) { apphb_warntime = atoi(optarg); } break; case 'l': break; /* information */ return LSB_EXIT_OK; case 'h': printf("%s\n",Simple_helpscreen); return LSB_EXIT_OK; default: cl_log(LOG_ERR, "getopt returned" "character code %c.", option_char); printf("%s\n",Simple_helpscreen); return LSB_EXIT_EINVAL; } } while (1); /* * Now I suppose recovery program only pass the client name via * environment variables. */ if ( (IS_RECOVERY == FALSE) && (client_argv == NULL) ) { cl_log(LOG_ERR, "Please give the program name which will be " "run as a child process of cl_respawn."); printf("%s\n", Simple_helpscreen); exit(LSB_EXIT_EINVAL); } if ((IS_RECOVERY == TRUE ) && ( client_argv == NULL)) { /* * Here the client_argv must be NULL. At least now just * suppose so. */ /* * From the environment variables to acquire the necessary * information set by other daemons like recovery manager. * RSP_PID: the PID of the process which need to be monitored. * RSP_CMD: the command line to restart the program, which is * the same as the input in command line as above. */ if ( getenv("RSP_PID") == NULL ) { cl_log(LOG_ERR, "cannot get monitored PID from the " "environment variable which should be set by " "the recovery program."); exit(LSB_EXIT_EINVAL); } else { monitored_PID = atoi(getenv("RSP_PID")); } /* * client_argv == NULL" indicates no client program passed as * a parameter by others such as a recovery manager, so expect * it will be passed by environment variable RSP_CMD, see as * below. If cannot get it, quit. */ if (client_argv == NULL) { if (getenv("RSP_CMD") == NULL) { cl_log(LOG_ERR, "cannot get the argument of the " "monitored program from the environment " "variable, which should be set by the " "recovery program."); } if (0!=cmd_str_to_argv(getenv("RSP_CMD"), &client_argv)) { cl_log(LOG_ERR, "Failed to transfer the CLI " "string to the argv[] style."); exit(LSB_EXIT_EINVAL); } } } /* Not use the API 'daemon' since it's not a POSIX's */ become_daemon(); /* Code for debug int k = 0; do { cl_log(LOG_INFO,"%s", execv_argv[k]); } while (execv_argv[++k] != NULL); */ set_sigchld_proctrack(G_PRIORITY_HIGH,DEFAULT_MAXDISPATCHTIME); if (( IS_RECOVERY == FALSE )) { child_tmp = run_client_as_child(client_argv); if (child_tmp > 0 ) { cl_log(LOG_NOTICE, "started the monitored program %s, " "whose PID is %d", client_argv[0], child_tmp); } else { exit(LSB_EXIT_GENERIC); } } snprintf(app_instance, INSTANCE_NAME_LEN, "%s_%ldd" , app_name, (long)getpid()); if (apphb_register(app_name, app_instance) != 0) { cl_log(LOG_WARNING, "Failed to register with apphbd."); cl_log(LOG_WARNING, "Maybe apphd isn't running."); REGTO_APPHBD = FALSE; } else { REGTO_APPHBD = TRUE; cl_log(LOG_INFO, "Registered with apphbd."); apphb_setinterval(interval); apphb_setwarn(apphb_warntime); /* To avoid the warning when app_interval is very small. */ apphb_hb(); } Gmain_timeout_add(interval - APPHB_INTVL_DETLA , plumb_client_and_emit_apphb, client_argv); mainloop = g_main_new(FALSE); g_main_run(mainloop); if ( REGTO_APPHBD == TRUE ) { apphb_hb(); apphb_unregister(); } return LSB_EXIT_OK; }
int main(int argc, char *argv[]) { struct sigaction sa; struct rlimit limit; int i, c, rc; int opt_foreground = 0, opt_allow_links = 0; enum startup_state opt_startup = startup_enable; extern char *optarg; extern int optind; struct ev_loop *loop; struct ev_io netlink_watcher; struct ev_signal sigterm_watcher; struct ev_signal sighup_watcher; struct ev_signal sigusr1_watcher; struct ev_signal sigusr2_watcher; struct ev_signal sigchld_watcher; /* Get params && set mode */ while ((c = getopt(argc, argv, "flns:")) != -1) { switch (c) { case 'f': opt_foreground = 1; break; case 'l': opt_allow_links=1; break; case 'n': do_fork = 0; break; case 's': for (i=0; i<startup_INVALID; i++) { if (strncmp(optarg, startup_states[i], strlen(optarg)) == 0) { opt_startup = i; break; } } if (i == startup_INVALID) { fprintf(stderr, "unknown startup mode '%s'\n", optarg); usage(); } break; default: usage(); } } /* check for trailing command line following options */ if (optind < argc) { usage(); } if (opt_allow_links) set_allow_links(1); if (opt_foreground) { config.daemonize = D_FOREGROUND; set_aumessage_mode(MSG_STDERR, DBG_YES); } else { config.daemonize = D_BACKGROUND; set_aumessage_mode(MSG_SYSLOG, DBG_NO); (void) umask( umask( 077 ) | 022 ); } #ifndef DEBUG /* Make sure we are root */ if (getuid() != 0) { fprintf(stderr, "You must be root to run this program.\n"); return 4; } #endif /* Register sighandlers */ sa.sa_flags = 0 ; sigemptyset( &sa.sa_mask ) ; /* Ignore all signals by default */ sa.sa_handler = SIG_IGN; for (i=1; i<NSIG; i++) sigaction( i, &sa, NULL ); atexit(clean_exit); /* Raise the rlimits in case we're being started from a shell * with restrictions. Not a fatal error. */ limit.rlim_cur = RLIM_INFINITY; limit.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_FSIZE, &limit); setrlimit(RLIMIT_CPU, &limit); /* Load the Configuration File */ if (load_config(&config, TEST_AUDITD)) return 6; if (config.priority_boost != 0) { errno = 0; rc = nice((int)-config.priority_boost); if (rc == -1 && errno) { audit_msg(LOG_ERR, "Cannot change priority (%s)", strerror(errno)); return 1; } } /* Daemonize or stay in foreground for debugging */ if (config.daemonize == D_BACKGROUND) { if (become_daemon() != 0) { audit_msg(LOG_ERR, "Cannot daemonize (%s)", strerror(errno)); tell_parent(FAILURE); return 1; } openlog("auditd", LOG_PID, LOG_DAEMON); } /* Init netlink */ if ((fd = audit_open()) < 0) { audit_msg(LOG_ERR, "Cannot open netlink audit socket"); tell_parent(FAILURE); return 1; } /* Init the event handler thread */ write_pid_file(); if (init_event(&config)) { if (pidfile) unlink(pidfile); tell_parent(FAILURE); return 1; } if (init_dispatcher(&config)) { if (pidfile) unlink(pidfile); tell_parent(FAILURE); return 1; } /* Get machine name ready for use */ if (resolve_node(&config)) { if (pidfile) unlink(pidfile); tell_parent(FAILURE); return 1; } /* Write message to log that we are alive */ { struct utsname ubuf; char start[DEFAULT_BUF_SZ]; const char *fmt = audit_lookup_format((int)config.log_format); if (fmt == NULL) fmt = "UNKNOWN"; if (uname(&ubuf) != 0) { if (pidfile) unlink(pidfile); tell_parent(FAILURE); return 1; } if (getsubj(subj)) snprintf(start, sizeof(start), "auditd start, ver=%s format=%s " "kernel=%.56s auid=%u pid=%d subj=%s res=success", VERSION, fmt, ubuf.release, audit_getloginuid(), getpid(), subj); else snprintf(start, sizeof(start), "auditd start, ver=%s format=%s " "kernel=%.56s auid=%u pid=%d res=success", VERSION, fmt, ubuf.release, audit_getloginuid(), getpid()); if (send_audit_event(AUDIT_DAEMON_START, start)) { audit_msg(LOG_ERR, "Cannot send start message"); if (pidfile) unlink(pidfile); shutdown_dispatcher(); tell_parent(FAILURE); return 1; } } /* Tell kernel not to kill us */ avoid_oom_killer(); /* let config manager init */ init_config_manager(); if (opt_startup != startup_nochange && (audit_is_enabled(fd) < 2) && audit_set_enabled(fd, (int)opt_startup) < 0) { char emsg[DEFAULT_BUF_SZ]; if (*subj) snprintf(emsg, sizeof(emsg), "auditd error halt, auid=%u pid=%d subj=%s res=failed", audit_getloginuid(), getpid(), subj); else snprintf(emsg, sizeof(emsg), "auditd error halt, auid=%u pid=%d res=failed", audit_getloginuid(), getpid()); stop = 1; send_audit_event(AUDIT_DAEMON_ABORT, emsg); audit_msg(LOG_ERR, "Unable to set initial audit startup state to '%s', exiting", startup_states[opt_startup]); close_down(); if (pidfile) unlink(pidfile); shutdown_dispatcher(); tell_parent(FAILURE); return 1; } /* Tell the kernel we are alive */ if (audit_set_pid(fd, getpid(), WAIT_YES) < 0) { char emsg[DEFAULT_BUF_SZ]; if (*subj) snprintf(emsg, sizeof(emsg), "auditd error halt, auid=%u pid=%d subj=%s res=failed", audit_getloginuid(), getpid(), subj); else snprintf(emsg, sizeof(emsg), "auditd error halt, auid=%u pid=%d res=failed", audit_getloginuid(), getpid()); stop = 1; send_audit_event(AUDIT_DAEMON_ABORT, emsg); audit_msg(LOG_ERR, "Unable to set audit pid, exiting"); close_down(); if (pidfile) unlink(pidfile); shutdown_dispatcher(); tell_parent(FAILURE); return 1; } /* Depending on value of opt_startup (-s) set initial audit state */ loop = ev_default_loop (EVFLAG_NOENV); ev_io_init (&netlink_watcher, netlink_handler, fd, EV_READ); ev_io_start (loop, &netlink_watcher); ev_signal_init (&sigterm_watcher, term_handler, SIGTERM); ev_signal_start (loop, &sigterm_watcher); ev_signal_init (&sighup_watcher, hup_handler, SIGHUP); ev_signal_start (loop, &sighup_watcher); ev_signal_init (&sigusr1_watcher, user1_handler, SIGUSR1); ev_signal_start (loop, &sigusr1_watcher); ev_signal_init (&sigusr2_watcher, user2_handler, SIGUSR2); ev_signal_start (loop, &sigusr2_watcher); ev_signal_init (&sigchld_watcher, child_handler, SIGCHLD); ev_signal_start (loop, &sigchld_watcher); if (auditd_tcp_listen_init (loop, &config)) { char emsg[DEFAULT_BUF_SZ]; if (*subj) snprintf(emsg, sizeof(emsg), "auditd error halt, auid=%u pid=%d subj=%s res=failed", audit_getloginuid(), getpid(), subj); else snprintf(emsg, sizeof(emsg), "auditd error halt, auid=%u pid=%d res=failed", audit_getloginuid(), getpid()); stop = 1; send_audit_event(AUDIT_DAEMON_ABORT, emsg); tell_parent(FAILURE); } else { /* Now tell parent that everything went OK */ tell_parent(SUCCESS); audit_msg(LOG_NOTICE, "Init complete, auditd %s listening for events (startup state %s)", VERSION, startup_states[opt_startup]); } /* Parent should be gone by now... */ if (do_fork) close(init_pipe[1]); // Init complete, start event loop if (!stop) ev_loop (loop, 0); auditd_tcp_listen_uninit (loop, &config); // Tear down IO watchers Part 1 ev_signal_stop (loop, &sighup_watcher); ev_signal_stop (loop, &sigusr1_watcher); ev_signal_stop (loop, &sigusr2_watcher); ev_signal_stop (loop, &sigterm_watcher); /* Write message to log that we are going down */ rc = audit_request_signal_info(fd); if (rc > 0) { struct audit_reply trep; rc = get_reply(fd, &trep, rc); if (rc > 0) { char txt[MAX_AUDIT_MESSAGE_LENGTH]; snprintf(txt, sizeof(txt), "auditd normal halt, sending auid=%u " "pid=%d subj=%s res=success", trep.signal_info->uid, trep.signal_info->pid, trep.signal_info->ctx); send_audit_event(AUDIT_DAEMON_END, txt); } } if (rc <= 0) send_audit_event(AUDIT_DAEMON_END, "auditd normal halt, sending auid=? " "pid=? subj=? res=success"); free(rep); // Tear down IO watchers Part 2 ev_io_stop (loop, &netlink_watcher); // Give DAEMON_END event a little time to be sent in case // of remote logging usleep(10000); // 10 milliseconds shutdown_dispatcher(); // Tear down IO watchers Part 3 ev_signal_stop (loop, &sigchld_watcher); close_down(); free_config(&config); ev_default_destroy(); return 0; }
int dmon_main (int argc, char **argv) { w_io_t *pidfile_io = NULL; char *opts_env = NULL; bool success; unsigned i, consumed; /* Check for "-C configfile" given in the command line. */ if (argc > 2 && ((argv[1][0] == '-' && argv[1][1] == 'C' && argv[1][2] == '\0') || !strcmp ("--config", argv[1]))) { w_lobj w_io_t *cfg_io = NULL; char *err_msg = NULL; if ((cfg_io = w_io_unix_open (argv[2], O_RDONLY, 0)) == NULL) w_die ("$s: Could not open file '$s', $E\n", argv[0], argv[2]); success = w_opt_parse_io (dmon_options, cfg_io, &err_msg); if (!success || err_msg) w_die ("$s: Error parsing '$s' at line $s\n", argv[0], argv[2], err_msg); replace_args_shift (2, &argc, &argv); } if ((opts_env = getenv ("DMON_OPTIONS")) != NULL) replace_args_string (opts_env, &argc, &argv); i = consumed = w_opt_parse (dmon_options, NULL, NULL, "cmd [cmd-options] [ -- " "log-cmd [log-cmd-options]]", argc, argv); W_DEBUG ("w_opt_parse consumed $I arguments\n", consumed); if (workdir_path) { if (chdir (workdir_path) != 0) w_die ("$s: Cannot use '$s' as work directory, $E\n", argv[0], workdir_path); } if (status_path) { status_io = w_io_unix_open (status_path, O_WRONLY | O_CREAT | O_APPEND, 0666); if (!status_io) w_die ("$s: Cannot open '$s' for writing, $E\n", argv[0], status_path); } if (cmd_interval && success_exit) w_die ("$s: Options '-i' and '-1' cannot be used together.\n", argv[0]); if (load_enabled && almost_zerof (load_low)) load_low = load_high / 2.0f; cmd_task.argv = argv + consumed; /* Skip over until "--" is found */ while (i < (unsigned) argc && strcmp (argv[i], "--") != 0) { cmd_task.argc++; i++; } /* There is a log command */ if (i < (unsigned) argc && strcmp (argv[i], "--") == 0) { log_task.argc = argc - cmd_task.argc - consumed - 1; log_task.argv = argv + argc - log_task.argc; log_task.argv[log_task.argc] = NULL; } cmd_task.argv[cmd_task.argc] = NULL; if (log_task.argc > 0) { if (pipe (log_fds) != 0) { w_die ("$s: Cannot create pipe: $E\n", argv[0]); } W_DEBUG ("pipe_read = $i, pipe_write = $i\n", log_fds[0], log_fds[1]); fd_cloexec (log_fds[0]); fd_cloexec (log_fds[1]); } #ifdef _DEBUG_PRINT { char **xxargv = cmd_task.argv; w_io_format (w_stderr, "cmd:"); while (*xxargv) w_io_format (w_stderr, " $s", *xxargv++); w_io_format (w_stderr, "\n"); if (log_enabled) { char **xxargv = log_task.argv; w_io_format (w_stderr, "log:"); while (*xxargv) w_io_format (w_stderr, " $c", *xxargv++); w_io_format (w_stderr, "\n"); } } #endif /* _DEBUG_PRINT */ if (cmd_task.argc == 0) w_die ("$s: No command to run given.\n", argv[0]); if (pidfile_path) { pidfile_io = w_io_unix_open (pidfile_path, O_TRUNC | O_CREAT | O_WRONLY, 0666); if (!pidfile_io) { w_die ("$s: cannot open '$s' for writing: $E\n", argv[0], pidfile_path); } } if (!nodaemon) become_daemon (); /* We have a valid file descriptor: write PID */ if (pidfile_io) { w_io_result_t r = w_io_format (pidfile_io, "$L\n", (unsigned long) getpid ()); if (w_io_failed (r)) W_WARN ("I/O error writing to PID file: $E\n"); w_obj_unref (pidfile_io); } setup_signals (); alarm (cmd_timeout); cmd_task.write_fd = log_fds[1]; log_task.read_fd = log_fds[0]; while (running) { W_DEBUG (">>> loop iteration\n"); if (check_child) { int retcode = reap_and_check (); /* * Wait the specified timeout but DO NOT use safe_sleep(): here * we want an interruptible sleep-wait so reaction to signals is * quick, which we definitely want for SIGINT/SIGTERM. */ if (cmd_interval && !success_exit && retcode == 0) { int retval; struct timespec ts; ts.tv_sec = cmd_interval; ts.tv_nsec = 0; do { retval = nanosleep (&ts, &ts); W_DEBUGC (" nanosleep -> $i\n", retval); } while (retval == -1 && errno == EINTR && running); } /* * Either handling signals which interrupt the previous loop, * or reap_and_check() may request stopping on successful exit */ if (!running) { task_action_queue (&cmd_task, A_NONE); break; } } task_action_dispatch_and_write_status ("cmd", &cmd_task); if (log_enabled) task_action_dispatch_and_write_status ("log", &log_task); if (load_enabled) { double load_cur; W_DEBUGC (" checking load after sleeping 1s\n"); interruptible_sleep (1); if (getloadavg (&load_cur, 1) == -1) W_WARN ("getloadavg() failed: $E\n"); if (paused) { /* If the current load dropped below load_low -> resume */ if (load_cur <= load_low) { W_DEBUGC (" resuming...\n"); task_signal (&cmd_task, SIGCONT); write_status ("cmd resume $L\n", (unsigned long) cmd_task.pid); paused = 0; } } else { /* If the load went above load_high -> pause */ if (load_cur > load_high) { W_DEBUGC (" pausing...\n"); task_signal (&cmd_task, SIGSTOP); write_status ("cmd pause $L\n", (unsigned long) cmd_task.pid); paused = 1; } } } else { /* Wait for signals to arrive. */ W_DEBUGC (" waiting for signals to come...\n"); pause (); } } W_DEBUG ("exiting gracefully...\n"); if (cmd_task.pid != NO_PID) { write_status ("cmd stop $L\n", (unsigned long) cmd_task.pid); task_action (&cmd_task, A_STOP); } if (log_enabled && log_task.pid != NO_PID) { write_status ("log stop $L\n", (unsigned long) log_task.pid); task_action (&log_task, A_STOP); } if (status_io) { w_obj_unref (status_io); status_io = NULL; } exit (EXIT_SUCCESS); }
/* main server. */ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[]) { bool opt_daemon = false; bool opt_interactive = false; int opt; poptContext pc; #define _MODULE_PROTO(init) extern NTSTATUS init(void); STATIC_service_MODULES_PROTO; init_module_fn static_init[] = { STATIC_service_MODULES }; init_module_fn *shared_init; struct tevent_context *event_ctx; uint16_t stdin_event_flags; NTSTATUS status; const char *model = "standard"; int max_runtime = 0; struct stat st; enum { OPT_DAEMON = 1000, OPT_INTERACTIVE, OPT_PROCESS_MODEL, OPT_SHOW_BUILD }; struct poptOption long_options[] = { POPT_AUTOHELP {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)", NULL }, {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)", NULL}, {"model", 'M', POPT_ARG_STRING, NULL, OPT_PROCESS_MODEL, "Select process model", "MODEL"}, {"maximum-runtime",0, POPT_ARG_INT, &max_runtime, 0, "set maximum runtime of the server process, till autotermination", "seconds"}, {"show-build", 'b', POPT_ARG_NONE, NULL, OPT_SHOW_BUILD, "show build info", NULL }, POPT_COMMON_SAMBA POPT_COMMON_VERSION { NULL } }; pc = poptGetContext(binary_name, argc, argv, long_options, 0); while((opt = poptGetNextOpt(pc)) != -1) { switch(opt) { case OPT_DAEMON: opt_daemon = true; break; case OPT_INTERACTIVE: opt_interactive = true; break; case OPT_PROCESS_MODEL: model = poptGetOptArg(pc); break; case OPT_SHOW_BUILD: show_build(); break; default: fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); poptPrintUsage(pc, stderr, 0); return 1; } } if (opt_daemon && opt_interactive) { fprintf(stderr,"\nERROR: " "Option -i|--interactive is not allowed together with -D|--daemon\n\n"); poptPrintUsage(pc, stderr, 0); return 1; } else if (!opt_interactive) { /* default is --daemon */ opt_daemon = true; } poptFreeContext(pc); talloc_enable_null_tracking(); setup_logging(binary_name, opt_interactive?DEBUG_STDOUT:DEBUG_FILE); setup_signals(); /* we want total control over the permissions on created files, so set our umask to 0 */ umask(0); DEBUG(0,("%s version %s started.\n", binary_name, SAMBA_VERSION_STRING)); DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2016\n")); if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) { DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); DEBUGADD(0,("sizeof(uint16_t) = %u, sizeof(uint32_t) %u, sizeof(uint64_t) = %u\n", (unsigned int)sizeof(uint16_t), (unsigned int)sizeof(uint32_t), (unsigned int)sizeof(uint64_t))); return 1; } if (opt_daemon) { DEBUG(3,("Becoming a daemon.\n")); become_daemon(true, false, false); } cleanup_tmp_files(cmdline_lp_ctx); if (!directory_exist(lpcfg_lock_directory(cmdline_lp_ctx))) { mkdir(lpcfg_lock_directory(cmdline_lp_ctx), 0755); } pidfile_create(lpcfg_pid_directory(cmdline_lp_ctx), binary_name); if (lpcfg_server_role(cmdline_lp_ctx) == ROLE_ACTIVE_DIRECTORY_DC) { if (!open_schannel_session_store(talloc_autofree_context(), cmdline_lp_ctx)) { exit_daemon("Samba cannot open schannel store for secured NETLOGON operations.", EACCES); } } /* make sure we won't go through nss_winbind */ if (!winbind_off()) { exit_daemon("Samba failed to disable recusive winbindd calls.", EACCES); } gensec_init(); /* FIXME: */ ntptr_init(); /* FIXME: maybe run this in the initialization function of the spoolss RPC server instead? */ ntvfs_init(cmdline_lp_ctx); /* FIXME: maybe run this in the initialization functions of the SMB[,2] server instead? */ process_model_init(cmdline_lp_ctx); shared_init = load_samba_modules(NULL, "service"); run_init_functions(static_init); run_init_functions(shared_init); talloc_free(shared_init); /* the event context is the top level structure in smbd. Everything else should hang off that */ event_ctx = s4_event_context_init(talloc_autofree_context()); if (event_ctx == NULL) { exit_daemon("Initializing event context failed", EACCES); } if (opt_interactive) { /* terminate when stdin goes away */ stdin_event_flags = TEVENT_FD_READ; } else { /* stay alive forever */ stdin_event_flags = 0; } /* catch EOF on stdin */ #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif if (fstat(0, &st) != 0) { exit_daemon("Samba failed to set standard input handler", ENOTTY); } if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { tevent_add_fd(event_ctx, event_ctx, 0, stdin_event_flags, server_stdin_handler, discard_const(binary_name)); } if (max_runtime) { DEBUG(0,("Called with maxruntime %d - current ts %llu\n", max_runtime, (unsigned long long) time(NULL))); tevent_add_timer(event_ctx, event_ctx, timeval_current_ofs(max_runtime, 0), max_runtime_handler, discard_const(binary_name)); } if (lpcfg_server_role(cmdline_lp_ctx) != ROLE_ACTIVE_DIRECTORY_DC && !lpcfg_parm_bool(cmdline_lp_ctx, NULL, "server role check", "inhibit", false) && !str_list_check_ci(lpcfg_server_services(cmdline_lp_ctx), "smb") && !str_list_check_ci(lpcfg_dcerpc_endpoint_servers(cmdline_lp_ctx), "remote") && !str_list_check_ci(lpcfg_dcerpc_endpoint_servers(cmdline_lp_ctx), "mapiproxy")) { DEBUG(0, ("At this time the 'samba' binary should only be used for either:\n")); DEBUGADD(0, ("'server role = active directory domain controller' or to access the ntvfs file server with 'server services = +smb' or the rpc proxy with 'dcerpc endpoint servers = remote'\n")); DEBUGADD(0, ("You should start smbd/nmbd/winbindd instead for domain member and standalone file server tasks\n")); exit_daemon("Samba detected misconfigured 'server role' and exited. Check logs for details", EINVAL); }; prime_ldb_databases(event_ctx); status = setup_parent_messaging(event_ctx, cmdline_lp_ctx); if (!NT_STATUS_IS_OK(status)) { exit_daemon("Samba failed to setup parent messaging", NT_STATUS_V(status)); } DEBUG(0,("%s: using '%s' process model\n", binary_name, model)); status = server_service_startup(event_ctx, cmdline_lp_ctx, model, lpcfg_server_services(cmdline_lp_ctx)); if (!NT_STATUS_IS_OK(status)) { exit_daemon("Samba failed to start services", NT_STATUS_V(status)); } if (opt_daemon) { daemon_ready("samba"); } /* wait for events - this is where smbd sits for most of its life */ tevent_loop_wait(event_ctx); /* as everything hangs off this event context, freeing it should initiate a clean shutdown of all services */ talloc_free(event_ctx); return 0; }
int main(int argc, char **argv) { int i; int config_loaded = 0; int dont_fork = 0; size_t wanted_stacksize = 0, stacksize = 0; pthread_attr_t attr; // global initialization get_HZ(); // set the name for logging program_name = "netdata"; // parse the arguments for(i = 1; i < argc ; i++) { if(strcmp(argv[i], "-c") == 0 && (i+1) < argc) { if(load_config(argv[i+1], 1) != 1) { error("Cannot load configuration file %s.", argv[i+1]); exit(1); } else { debug(D_OPTIONS, "Configuration loaded from %s.", argv[i+1]); config_loaded = 1; } i++; } else if(strcmp(argv[i], "-df") == 0 && (i+1) < argc) { config_set("global", "debug flags", argv[i+1]); debug_flags = strtoull(argv[i+1], NULL, 0); i++; } else if(strcmp(argv[i], "-p") == 0 && (i+1) < argc) { config_set("global", "port", argv[i+1]); i++; } else if(strcmp(argv[i], "-u") == 0 && (i+1) < argc) { config_set("global", "run as user", argv[i+1]); i++; } else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) { config_set("global", "history", argv[i+1]); i++; } else if(strcmp(argv[i], "-t") == 0 && (i+1) < argc) { config_set("global", "update every", argv[i+1]); i++; } else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) { config_set("global", "host access prefix", argv[i+1]); i++; } else if(strcmp(argv[i], "-stacksize") == 0 && (i+1) < argc) { config_set("global", "pthread stack size", argv[i+1]); i++; } else if(strcmp(argv[i], "-nodaemon") == 0 || strcmp(argv[i], "-nd") == 0) dont_fork = 1; else if(strcmp(argv[i], "-pidfile") == 0 && (i+1) < argc) { i++; strncpy(pidfile, argv[i], FILENAME_MAX); pidfile[FILENAME_MAX] = '\0'; } else if(strcmp(argv[i], "--unittest") == 0) { rrd_update_every = 1; if(run_all_mockup_tests()) exit(1); if(unit_test_storage()) exit(1); fprintf(stderr, "\n\nALL TESTS PASSED\n\n"); exit(0); } else { fprintf(stderr, "Cannot understand option '%s'.\n", argv[i]); fprintf(stderr, "\nUSAGE: %s [-d] [-l LINES_TO_SAVE] [-u UPDATE_TIMER] [-p LISTEN_PORT] [-df debug flags].\n\n", argv[0]); fprintf(stderr, " -c CONFIG FILE the configuration file to load. Default: %s.\n", CONFIG_DIR "/" CONFIG_FILENAME); fprintf(stderr, " -l LINES_TO_SAVE can be from 5 to %d lines in JSON data. Default: %d.\n", RRD_HISTORY_ENTRIES_MAX, RRD_DEFAULT_HISTORY_ENTRIES); fprintf(stderr, " -t UPDATE_TIMER can be from 1 to %d seconds. Default: %d.\n", UPDATE_EVERY_MAX, UPDATE_EVERY); fprintf(stderr, " -p LISTEN_PORT can be from 1 to %d. Default: %d.\n", 65535, LISTEN_PORT); fprintf(stderr, " -u USERNAME can be any system username to run as. Default: none.\n"); fprintf(stderr, " -ch path to access host /proc and /sys when running in a container. Default: empty.\n"); fprintf(stderr, " -nd or -nodeamon to disable forking in the background. Default: unset.\n"); fprintf(stderr, " -df FLAGS debug options. Default: 0x%08llx.\n", debug_flags); fprintf(stderr, " -stacksize BYTES to overwrite the pthread stack size.\n"); fprintf(stderr, " -pidfile FILENAME to save a pid while running.\n"); exit(1); } } if(!config_loaded) load_config(NULL, 0); // prepare configuration environment variables for the plugins setenv("NETDATA_CONFIG_DIR" , config_get("global", "config directory" , CONFIG_DIR) , 1); setenv("NETDATA_PLUGINS_DIR", config_get("global", "plugins directory" , PLUGINS_DIR), 1); setenv("NETDATA_WEB_DIR" , config_get("global", "web files directory", WEB_DIR) , 1); setenv("NETDATA_CACHE_DIR" , config_get("global", "cache directory" , CACHE_DIR) , 1); setenv("NETDATA_LOG_DIR" , config_get("global", "log directory" , LOG_DIR) , 1); setenv("NETDATA_HOST_PREFIX", config_get("global", "host access prefix" , "") , 1); setenv("HOME" , config_get("global", "home directory" , CACHE_DIR) , 1); // avoid extended to stat(/etc/localtime) // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux setenv("TZ", ":/etc/localtime", 0); // cd to /tmp to avoid any plugins writing files at random places if(chdir("/tmp")) error("netdata: ERROR: Cannot cd to /tmp"); char *input_log_file = NULL; char *output_log_file = NULL; char *error_log_file = NULL; char *access_log_file = NULL; char *user = NULL; { char buffer[1024]; // -------------------------------------------------------------------- sprintf(buffer, "0x%08llx", 0ULL); char *flags = config_get("global", "debug flags", buffer); setenv("NETDATA_DEBUG_FLAGS", flags, 1); debug_flags = strtoull(flags, NULL, 0); debug(D_OPTIONS, "Debug flags set to '0x%8llx'.", debug_flags); if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) info("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } // -------------------------------------------------------------------- #ifdef MADV_MERGEABLE enable_ksm = config_get_boolean("global", "memory deduplication (ksm)", enable_ksm); #else #warning "Kernel memory deduplication (KSM) is not available" #endif // -------------------------------------------------------------------- global_host_prefix = config_get("global", "host access prefix", ""); setenv("NETDATA_HOST_PREFIX", global_host_prefix, 1); // -------------------------------------------------------------------- output_log_file = config_get("global", "debug log", LOG_DIR "/debug.log"); if(strcmp(output_log_file, "syslog") == 0) { output_log_syslog = 1; output_log_file = NULL; } else if(strcmp(output_log_file, "none") == 0) { output_log_syslog = 0; output_log_file = NULL; } else output_log_syslog = 0; // -------------------------------------------------------------------- error_log_file = config_get("global", "error log", LOG_DIR "/error.log"); if(strcmp(error_log_file, "syslog") == 0) { error_log_syslog = 1; error_log_file = NULL; } else if(strcmp(error_log_file, "none") == 0) { error_log_syslog = 0; error_log_file = NULL; // optimization - do not even generate debug log entries } else error_log_syslog = 0; error_log_throttle_period = config_get_number("global", "errors flood protection period", error_log_throttle_period); setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get("global", "errors flood protection period" , ""), 1); error_log_errors_per_period = config_get_number("global", "errors to trigger flood protection", error_log_errors_per_period); setenv("NETDATA_ERRORS_PER_PERIOD" , config_get("global", "errors to trigger flood protection", ""), 1); // -------------------------------------------------------------------- access_log_file = config_get("global", "access log", LOG_DIR "/access.log"); if(strcmp(access_log_file, "syslog") == 0) { access_log_syslog = 1; access_log_file = NULL; } else if(strcmp(access_log_file, "none") == 0) { access_log_syslog = 0; access_log_file = NULL; } else access_log_syslog = 0; // -------------------------------------------------------------------- rrd_memory_mode = rrd_memory_mode_id(config_get("global", "memory mode", rrd_memory_mode_name(rrd_memory_mode))); // -------------------------------------------------------------------- if(gethostname(buffer, HOSTNAME_MAX) == -1) error("WARNING: Cannot get machine hostname."); hostname = config_get("global", "hostname", buffer); debug(D_OPTIONS, "hostname set to '%s'", hostname); // -------------------------------------------------------------------- rrd_default_history_entries = (int) config_get_number("global", "history", RRD_DEFAULT_HISTORY_ENTRIES); if(rrd_default_history_entries < 5 || rrd_default_history_entries > RRD_HISTORY_ENTRIES_MAX) { info("Invalid save lines %d given. Defaulting to %d.", rrd_default_history_entries, RRD_DEFAULT_HISTORY_ENTRIES); rrd_default_history_entries = RRD_DEFAULT_HISTORY_ENTRIES; } else { debug(D_OPTIONS, "save lines set to %d.", rrd_default_history_entries); } // -------------------------------------------------------------------- rrd_update_every = (int) config_get_number("global", "update every", UPDATE_EVERY); if(rrd_update_every < 1 || rrd_update_every > 600) { info("Invalid update timer %d given. Defaulting to %d.", rrd_update_every, UPDATE_EVERY_MAX); rrd_update_every = UPDATE_EVERY; } else debug(D_OPTIONS, "update timer set to %d.", rrd_update_every); // let the plugins know the min update_every { char buf[50]; snprintf(buf, 50, "%d", rrd_update_every); setenv("NETDATA_UPDATE_EVERY", buf, 1); } // -------------------------------------------------------------------- // block signals while initializing threads. // this causes the threads to block signals. sigset_t sigset; sigfillset(&sigset); if(pthread_sigmask(SIG_BLOCK, &sigset, NULL) == -1) { error("Could not block signals for threads"); } // Catch signals which we want to use to quit savely struct sigaction sa; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGHUP); sigaddset(&sa.sa_mask, SIGINT); sigaddset(&sa.sa_mask, SIGTERM); sa.sa_handler = sig_handler; sa.sa_flags = 0; if(sigaction(SIGHUP, &sa, NULL) == -1) { error("Failed to change signal handler for SIGHUP"); } if(sigaction(SIGINT, &sa, NULL) == -1) { error("Failed to change signal handler for SIGINT"); } if(sigaction(SIGTERM, &sa, NULL) == -1) { error("Failed to change signal handler for SIGTERM"); } // Ignore SIGPIPE completely. // INFO: If we add signals here we have to unblock them // at popen.c when running a external plugin. sa.sa_handler = SIG_IGN; if(sigaction(SIGPIPE, &sa, NULL) == -1) { error("Failed to change signal handler for SIGTERM"); } // -------------------------------------------------------------------- i = pthread_attr_init(&attr); if(i != 0) fatal("pthread_attr_init() failed with code %d.", i); i = pthread_attr_getstacksize(&attr, &stacksize); if(i != 0) fatal("pthread_attr_getstacksize() failed with code %d.", i); else debug(D_OPTIONS, "initial pthread stack size is %zu bytes", stacksize); wanted_stacksize = config_get_number("global", "pthread stack size", stacksize); // -------------------------------------------------------------------- for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->config_name) st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled); if(st->enabled && st->init_routine) st->init_routine(); } // -------------------------------------------------------------------- // get the user we should run // IMPORTANT: this is required before web_files_uid() user = config_get("global", "run as user" , (getuid() == 0)?NETDATA_USER:""); // IMPORTANT: these have to run once, while single threaded web_files_uid(); // IMPORTANT: web_files_uid() before web_files_gid() web_files_gid(); // -------------------------------------------------------------------- listen_backlog = (int) config_get_number("global", "http port listen backlog", LISTEN_BACKLOG); listen_port = (int) config_get_number("global", "port", LISTEN_PORT); if(listen_port < 1 || listen_port > 65535) { info("Invalid listen port %d given. Defaulting to %d.", listen_port, LISTEN_PORT); listen_port = LISTEN_PORT; } else debug(D_OPTIONS, "Listen port set to %d.", listen_port); int ip = 0; char *ipv = config_get("global", "ip version", "any"); if(!strcmp(ipv, "any") || !strcmp(ipv, "both") || !strcmp(ipv, "all")) ip = 0; else if(!strcmp(ipv, "ipv4") || !strcmp(ipv, "IPV4") || !strcmp(ipv, "IPv4") || !strcmp(ipv, "4")) ip = 4; else if(!strcmp(ipv, "ipv6") || !strcmp(ipv, "IPV6") || !strcmp(ipv, "IPv6") || !strcmp(ipv, "6")) ip = 6; else info("Cannot understand ip version '%s'. Assuming 'any'.", ipv); if(ip == 0 || ip == 6) listen_fd = create_listen_socket6(config_get("global", "bind socket to IP", "*"), listen_port, listen_backlog); if(listen_fd < 0) { listen_fd = create_listen_socket4(config_get("global", "bind socket to IP", "*"), listen_port, listen_backlog); if(listen_fd >= 0 && ip != 4) info("Managed to open an IPv4 socket on port %d.", listen_port); } if(listen_fd < 0) fatal("Cannot listen socket."); } // never become a problem if(nice(20) == -1) error("Cannot lower my CPU priority."); if(become_daemon(dont_fork, 0, user, input_log_file, output_log_file, error_log_file, access_log_file, &access_fd, &stdaccess) == -1) { fatal("Cannot demonize myself."); exit(1); } if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) info("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } if(output_log_syslog || error_log_syslog || access_log_syslog) openlog("netdata", LOG_PID, LOG_DAEMON); info("NetData started on pid %d", getpid()); // ------------------------------------------------------------------------ // get default pthread stack size if(stacksize < wanted_stacksize) { i = pthread_attr_setstacksize(&attr, wanted_stacksize); if(i != 0) fatal("pthread_attr_setstacksize() to %zu bytes, failed with code %d.", wanted_stacksize, i); else info("Successfully set pthread stacksize to %zu bytes", wanted_stacksize); } // ------------------------------------------------------------------------ // spawn the threads for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->enabled) { st->thread = malloc(sizeof(pthread_t)); if(!st->thread) fatal("Cannot allocate pthread_t memory"); info("Starting thread %s.", st->name); if(pthread_create(st->thread, &attr, st->start_routine, NULL)) error("failed to create new thread for %s.", st->name); else if(pthread_detach(*st->thread)) error("Cannot request detach of newly created %s thread.", st->name); } else info("Not starting thread %s.", st->name); } // ------------------------------------------------------------------------ // block signals while initializing threads. sigset_t sigset; sigfillset(&sigset); if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) == -1) { error("Could not unblock signals for threads"); } // Handle flags set in the signal handler. while(1) { pause(); if(netdata_exit) { info("Exit main loop of netdata."); netdata_cleanup_and_exit(0); exit(0); } } }
int main(int argc, char **argv) { int opt; char *alt_config = NULL; int r = IMAP_NOTFOUND; strarray_t mboxnames = STRARRAY_INITIALIZER; const char *query = NULL; int background = 1; const char *channel = "squatter"; const char *synclogfile = NULL; int init_flags = CYRUSINIT_PERROR; int multi_folder = 0; int user_mode = 0; int compact_flags = 0; const char *fromfile = NULL; strarray_t *srctiers = NULL; const char *desttier = NULL; enum { UNKNOWN, INDEXER, INDEXFROM, SEARCH, ROLLING, SYNCLOG, START_DAEMON, STOP_DAEMON, RUN_DAEMON, COMPACT } mode = UNKNOWN; if ((geteuid()) == 0 && (become_cyrus(/*is_master*/0) != 0)) { fatal("must run as the Cyrus user", EC_USAGE); } setbuf(stdout, NULL); while ((opt = getopt(argc, argv, "C:I:N:RXT:S:Fc:de:f:mn:riavz:t:ouh")) != EOF) { switch (opt) { case 'C': /* alt config file */ alt_config = optarg; break; case 'F': compact_flags |= SEARCH_COMPACT_FILTER; break; case 'X': compact_flags |= SEARCH_COMPACT_REINDEX; break; case 'N': name_starts_from = optarg; break; case 'I': /* indexer, using specified mbox/uids in file */ if (mode != UNKNOWN && mode != INDEXFROM) usage(argv[0]); fromfile = optarg; mode = INDEXFROM; break; case 'R': /* rolling indexer */ if (mode != UNKNOWN) usage(argv[0]); mode = ROLLING; incremental_mode = 1; /* always incremental if rolling */ batch_mode = 1; break; case 'S': /* sleep time in seconds */ sleepmicroseconds = (atof(optarg) * 1000000); break; case 'T': /* temporary root directory for search */ temp_root_dir = optarg; break; /* This option is deliberately undocumented, for testing only */ case 'c': /* daemon control mode */ if (mode != UNKNOWN) usage(argv[0]); if (!strcmp(optarg, "start")) mode = START_DAEMON; else if (!strcmp(optarg, "stop")) mode = STOP_DAEMON; else if (!strcmp(optarg, "run")) mode = RUN_DAEMON; else usage(argv[0]); break; case 'd': /* foreground (with -R) */ background = 0; break; /* This option is deliberately undocumented, for testing only */ case 'e': /* add a search term */ if (mode != UNKNOWN && mode != SEARCH) usage(argv[0]); query = optarg; mode = SEARCH; break; case 'f': /* alternate synclogfile used in SYNCLOG mode */ synclogfile = optarg; mode = SYNCLOG; break; /* This option is deliberately undocumented, for testing only */ case 'm': /* multi-folder in SEARCH mode */ if (mode != UNKNOWN && mode != SEARCH) usage(argv[0]); multi_folder = 1; mode = SEARCH; break; case 'n': /* sync channel name (with -R) */ channel = optarg; break; case 'o': /* copy one DB rather than compressing */ compact_flags |= SEARCH_COMPACT_COPYONE; break; case 'v': /* verbose */ verbose++; break; case 'r': /* recurse */ if (mode != UNKNOWN && mode != INDEXER) usage(argv[0]); recursive_flag = 1; mode = INDEXER; break; case 'i': /* incremental mode */ incremental_mode = 1; break; case 'a': /* use /squat annotation */ if (mode != UNKNOWN && mode != INDEXER) usage(argv[0]); annotation_flag = 1; mode = INDEXER; break; case 'z': if (mode != UNKNOWN && mode != COMPACT) usage(argv[0]); desttier = optarg; mode = COMPACT; break; case 't': if (mode != UNKNOWN && mode != COMPACT) usage(argv[0]); srctiers = strarray_split(optarg, ",", 0); mode = COMPACT; break; case 'u': user_mode = 1; break; case 'h': usage("squatter"); default: usage("squatter"); } } compact_flags |= SEARCH_VERBOSE(verbose); if (mode == UNKNOWN) mode = INDEXER; /* fork and close fds if required */ if (mode == ROLLING && background) { become_daemon(); init_flags &= ~CYRUSINIT_PERROR; } if (mode == COMPACT && (!desttier || !srctiers)) { /* need both src and dest for compact */ usage("squatter"); } cyrus_init(alt_config, "squatter", init_flags, CONFIG_NEED_PARTITION_DATA); /* Set namespace -- force standard (internal) */ if ((r = mboxname_init_namespace(&squat_namespace, 1)) != 0) { fatal(error_message(r), EC_CONFIG); } annotate_init(NULL, NULL); annotatemore_open(); mboxlist_init(0); mboxlist_open(NULL); if (mode == ROLLING || mode == SYNCLOG) { signals_set_shutdown(&shut_down); signals_add_handlers(0); } switch (mode) { case UNKNOWN: break; case INDEXER: /* -r requires at least one mailbox */ if (recursive_flag && optind == argc) usage(argv[0]); expand_mboxnames(&mboxnames, argc-optind, (const char **)argv+optind, user_mode); syslog(LOG_NOTICE, "indexing mailboxes"); r = do_indexer(&mboxnames); syslog(LOG_NOTICE, "done indexing mailboxes"); break; case INDEXFROM: syslog(LOG_NOTICE, "indexing messages"); r = do_indexfrom(fromfile); syslog(LOG_NOTICE, "done indexing messages"); break; case SEARCH: if (recursive_flag && optind == argc) usage(argv[0]); expand_mboxnames(&mboxnames, argc-optind, (const char **)argv+optind, user_mode); r = do_search(query, !multi_folder, &mboxnames); break; case ROLLING: do_rolling(channel); /* never returns */ break; case SYNCLOG: r = do_synclogfile(synclogfile); break; case START_DAEMON: if (optind != argc) usage("squatter"); search_start_daemon(verbose); break; case STOP_DAEMON: if (optind != argc) usage("squatter"); search_stop_daemon(verbose); break; case RUN_DAEMON: if (optind != argc) usage("squatter"); do_run_daemon(); break; case COMPACT: if (recursive_flag && optind == argc) usage(argv[0]); expand_mboxnames(&mboxnames, argc-optind, (const char **)argv+optind, user_mode); r = do_compact(&mboxnames, srctiers, desttier, compact_flags); break; } strarray_fini(&mboxnames); shut_down(r ? EC_TEMPFAIL : 0); }
int main(int argc, const char *argv[]) { static bool is_daemon; static bool opt_interactive; static bool Fork = true; static bool no_process_group; static bool log_stdout; poptContext pc; char *p_lmhosts = NULL; int opt; enum { OPT_DAEMON = 1000, OPT_INTERACTIVE, OPT_FORK, OPT_NO_PROCESS_GROUP, OPT_LOG_STDOUT }; struct poptOption long_options[] = { POPT_AUTOHELP {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon(default)" }, {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)" }, {"foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Run daemon in foreground (for daemontools & etc)" }, {"no-process-group", 0, POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" }, {"log-stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" }, {"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 0, "Load a netbios hosts file"}, {"port", 'p', POPT_ARG_INT, &global_nmb_port, 0, "Listen on the specified port" }, POPT_COMMON_SAMBA { NULL } }; TALLOC_CTX *frame; NTSTATUS status; /* * Do this before any other talloc operation */ talloc_enable_null_tracking(); frame = talloc_stackframe(); setup_logging(argv[0], DEBUG_DEFAULT_STDOUT); load_case_tables(); global_nmb_port = NMB_PORT; pc = poptGetContext("nmbd", argc, argv, long_options, 0); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_DAEMON: is_daemon = true; break; case OPT_INTERACTIVE: opt_interactive = true; break; case OPT_FORK: Fork = false; break; case OPT_NO_PROCESS_GROUP: no_process_group = true; break; case OPT_LOG_STDOUT: log_stdout = true; break; default: d_fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); poptPrintUsage(pc, stderr, 0); exit(1); } }; poptFreeContext(pc); global_in_nmbd = true; StartupTime = time(NULL); sys_srandom(time(NULL) ^ sys_getpid()); if (!override_logfile) { char *lfile = NULL; if (asprintf(&lfile, "%s/log.nmbd", get_dyn_LOGFILEBASE()) < 0) { exit(1); } lp_set_logfile(lfile); SAFE_FREE(lfile); } fault_setup(); dump_core_setup("nmbd", lp_logfile()); /* POSIX demands that signals are inherited. If the invoking process has * these signals masked, we will have problems, as we won't receive them. */ BlockSignals(False, SIGHUP); BlockSignals(False, SIGUSR1); BlockSignals(False, SIGTERM); #if defined(SIGFPE) /* we are never interested in SIGFPE */ BlockSignals(True,SIGFPE); #endif /* We no longer use USR2... */ #if defined(SIGUSR2) BlockSignals(True, SIGUSR2); #endif if ( opt_interactive ) { Fork = False; log_stdout = True; } if ( log_stdout && Fork ) { DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); exit(1); } if (log_stdout) { setup_logging(argv[0], DEBUG_STDOUT); } else { setup_logging( argv[0], DEBUG_FILE); } reopen_logs(); DEBUG(0,("nmbd version %s started.\n", samba_version_string())); DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE)); if (!lp_load_initial_only(get_dyn_CONFIGFILE())) { DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE())); exit(1); } if (nmbd_messaging_context() == NULL) { return 1; } if ( !reload_nmbd_services(False) ) return(-1); if(!init_names()) return -1; reload_nmbd_services( True ); if (strequal(lp_workgroup(),"*")) { DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); exit(1); } set_samba_nb_type(); if (!is_daemon && !is_a_socket(0)) { DEBUG(0,("standard input is not a socket, assuming -D option\n")); is_daemon = True; } if (is_daemon && !opt_interactive) { DEBUG( 2, ( "Becoming a daemon.\n" ) ); become_daemon(Fork, no_process_group, log_stdout); } #if HAVE_SETPGID /* * If we're interactive we want to set our own process group for * signal management. */ if (opt_interactive && !no_process_group) setpgid( (pid_t)0, (pid_t)0 ); #endif if (nmbd_messaging_context() == NULL) { return 1; } #ifndef SYNC_DNS /* Setup the async dns. We do it here so it doesn't have all the other stuff initialised and thus chewing memory and sockets */ if(lp_we_are_a_wins_server() && lp_dns_proxy()) { start_async_dns(); } #endif if (!directory_exist(lp_lockdir())) { mkdir(lp_lockdir(), 0755); } pidfile_create("nmbd"); status = reinit_after_fork(nmbd_messaging_context(), nmbd_event_context(), procid_self(), false); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } if (!nmbd_setup_sig_term_handler()) exit(1); if (!nmbd_setup_sig_hup_handler()) exit(1); /* get broadcast messages */ if (!serverid_register(procid_self(), FLAG_MSG_GENERAL | FLAG_MSG_NMBD | FLAG_MSG_DBWRAP)) { DEBUG(1, ("Could not register myself in serverid.tdb\n")); exit(1); } messaging_register(nmbd_messaging_context(), NULL, MSG_FORCE_ELECTION, nmbd_message_election); #if 0 /* Until winsrepl is done. */ messaging_register(nmbd_messaging_context(), NULL, MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry); #endif messaging_register(nmbd_messaging_context(), NULL, MSG_SHUTDOWN, nmbd_terminate); messaging_register(nmbd_messaging_context(), NULL, MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services); messaging_register(nmbd_messaging_context(), NULL, MSG_SEND_PACKET, msg_nmbd_send_packet); TimeInit(); DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) ); if ( !open_sockets( is_daemon, global_nmb_port ) ) { kill_async_dns_child(); return 1; } /* Determine all the IP addresses we have. */ load_interfaces(); /* Create an nmbd subnet record for each of the above. */ if( False == create_subnets() ) { DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n")); kill_async_dns_child(); exit(1); } /* Load in any static local names. */ if (p_lmhosts) { set_dyn_LMHOSTSFILE(p_lmhosts); } load_lmhosts_file(get_dyn_LMHOSTSFILE()); DEBUG(3,("Loaded hosts file %s\n", get_dyn_LMHOSTSFILE())); /* If we are acting as a WINS server, initialise data structures. */ if( !initialise_wins() ) { DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) ); kill_async_dns_child(); exit(1); } /* * Register nmbd primary workgroup and nmbd names on all * the broadcast subnets, and on the WINS server (if specified). * Also initiate the startup of our primary workgroup (start * elections if we are setup as being able to be a local * master browser. */ if( False == register_my_workgroup_and_names() ) { DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n")); kill_async_dns_child(); exit(1); } if (!initialize_nmbd_proxy_logon()) { DEBUG(0,("ERROR: Failed setup nmbd_proxy_logon.\n")); kill_async_dns_child(); exit(1); } if (!nmbd_init_packet_server()) { kill_async_dns_child(); exit(1); } TALLOC_FREE(frame); process(); kill_async_dns_child(); return(0); }
/* main server. */ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[]) { bool opt_daemon = false; bool opt_interactive = false; int opt; poptContext pc; #define _MODULE_PROTO(init) extern NTSTATUS init(void); STATIC_service_MODULES_PROTO; init_module_fn static_init[] = { STATIC_service_MODULES }; init_module_fn *shared_init; struct tevent_context *event_ctx; uint16_t stdin_event_flags; NTSTATUS status; const char *model = "standard"; int max_runtime = 0; enum { OPT_DAEMON = 1000, OPT_INTERACTIVE, OPT_PROCESS_MODEL, OPT_SHOW_BUILD }; struct poptOption long_options[] = { POPT_AUTOHELP {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)", NULL }, {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)", NULL}, {"model", 'M', POPT_ARG_STRING, NULL, OPT_PROCESS_MODEL, "Select process model", "MODEL"}, {"maximum-runtime",0, POPT_ARG_INT, &max_runtime, 0, "set maximum runtime of the server process, till autotermination", "seconds"}, {"show-build", 'b', POPT_ARG_NONE, NULL, OPT_SHOW_BUILD, "show build info", NULL }, POPT_COMMON_SAMBA POPT_COMMON_VERSION { NULL } }; pc = poptGetContext(binary_name, argc, argv, long_options, 0); while((opt = poptGetNextOpt(pc)) != -1) { switch(opt) { case OPT_DAEMON: opt_daemon = true; break; case OPT_INTERACTIVE: opt_interactive = true; break; case OPT_PROCESS_MODEL: model = poptGetOptArg(pc); break; case OPT_SHOW_BUILD: show_build(); break; default: fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); poptPrintUsage(pc, stderr, 0); return 1; } } if (opt_daemon && opt_interactive) { fprintf(stderr,"\nERROR: " "Option -i|--interactive is not allowed together with -D|--daemon\n\n"); poptPrintUsage(pc, stderr, 0); return 1; } else if (!opt_interactive) { /* default is --daemon */ opt_daemon = true; } poptFreeContext(pc); setup_logging(binary_name, opt_interactive?DEBUG_STDOUT:DEBUG_FILE); setup_signals(); /* we want total control over the permissions on created files, so set our umask to 0 */ umask(0); DEBUG(0,("%s version %s started.\n", binary_name, SAMBA_VERSION_STRING)); DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2011\n")); if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) { DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); DEBUGADD(0,("sizeof(uint16_t) = %u, sizeof(uint32_t) %u, sizeof(uint64_t) = %u\n", (unsigned int)sizeof(uint16_t), (unsigned int)sizeof(uint32_t), (unsigned int)sizeof(uint64_t))); return 1; } if (opt_daemon) { DEBUG(3,("Becoming a daemon.\n")); become_daemon(true, false, false); } cleanup_tmp_files(cmdline_lp_ctx); if (!directory_exist(lpcfg_lockdir(cmdline_lp_ctx))) { mkdir(lpcfg_lockdir(cmdline_lp_ctx), 0755); } pidfile_create(lpcfg_piddir(cmdline_lp_ctx), binary_name); /* Set up a database to hold a random seed, in case we don't * have /dev/urandom */ if (!randseed_init(talloc_autofree_context(), cmdline_lp_ctx)) { return 1; } if (lpcfg_server_role(cmdline_lp_ctx) == ROLE_DOMAIN_CONTROLLER) { if (!open_schannel_session_store(talloc_autofree_context(), lpcfg_private_dir(cmdline_lp_ctx))) { DEBUG(0,("ERROR: Samba cannot open schannel store for secured NETLOGON operations.\n")); exit(1); } } gensec_init(); /* FIXME: */ ntptr_init(); /* FIXME: maybe run this in the initialization function of the spoolss RPC server instead? */ ntvfs_init(cmdline_lp_ctx); /* FIXME: maybe run this in the initialization functions of the SMB[,2] server instead? */ process_model_init(cmdline_lp_ctx); shared_init = load_samba_modules(NULL, "service"); run_init_functions(static_init); run_init_functions(shared_init); talloc_free(shared_init); /* the event context is the top level structure in smbd. Everything else should hang off that */ event_ctx = s4_event_context_init(talloc_autofree_context()); if (event_ctx == NULL) { DEBUG(0,("Initializing event context failed\n")); return 1; } if (opt_interactive) { /* terminate when stdin goes away */ stdin_event_flags = TEVENT_FD_READ; } else { /* stay alive forever */ stdin_event_flags = 0; } /* catch EOF on stdin */ #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif tevent_add_fd(event_ctx, event_ctx, 0, stdin_event_flags, server_stdin_handler, discard_const(binary_name)); if (max_runtime) { DEBUG(0,("Called with maxruntime %d - current ts %llu\n", max_runtime, (unsigned long long) time(NULL))); tevent_add_timer(event_ctx, event_ctx, timeval_current_ofs(max_runtime, 0), max_runtime_handler, discard_const(binary_name)); } prime_ldb_databases(event_ctx); status = setup_parent_messaging(event_ctx, cmdline_lp_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to setup parent messaging - %s\n", nt_errstr(status))); return 1; } DEBUG(0,("%s: using '%s' process model\n", binary_name, model)); status = server_service_startup(event_ctx, cmdline_lp_ctx, model, lpcfg_server_services(cmdline_lp_ctx)); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Starting Services failed - %s\n", nt_errstr(status))); return 1; } /* wait for events - this is where smbd sits for most of its life */ tevent_loop_wait(event_ctx); /* as everything hangs off this event context, freeing it should initiate a clean shutdown of all services */ talloc_free(event_ctx); return 0; }
int main(int argc,const char *argv[]) { /* shall I run as a daemon */ bool is_daemon = false; bool interactive = false; bool Fork = true; bool no_process_group = false; bool log_stdout = false; char *ports = NULL; char *profile_level = NULL; int opt; poptContext pc; bool print_build_options = False; enum { OPT_DAEMON = 1000, OPT_INTERACTIVE, OPT_FORK, OPT_NO_PROCESS_GROUP, OPT_LOG_STDOUT }; struct poptOption long_options[] = { POPT_AUTOHELP {"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON, "Become a daemon (default)" }, {"interactive", 'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE, "Run interactive (not a daemon)"}, {"foreground", 'F', POPT_ARG_NONE, NULL, OPT_FORK, "Run daemon in foreground (for daemontools, etc.)" }, {"no-process-group", '\0', POPT_ARG_NONE, NULL, OPT_NO_PROCESS_GROUP, "Don't create a new process group" }, {"log-stdout", 'S', POPT_ARG_NONE, NULL, OPT_LOG_STDOUT, "Log to stdout" }, {"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" }, {"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"}, {"profiling-level", 'P', POPT_ARG_STRING, &profile_level, 0, "Set profiling level","PROFILE_LEVEL"}, POPT_COMMON_SAMBA POPT_COMMON_DYNCONFIG POPT_TABLEEND }; struct smbd_parent_context *parent = NULL; TALLOC_CTX *frame; NTSTATUS status; uint64_t unique_id; struct tevent_context *ev_ctx; struct messaging_context *msg_ctx; /* * Do this before any other talloc operation */ talloc_enable_null_tracking(); frame = talloc_stackframe(); setup_logging(argv[0], DEBUG_DEFAULT_STDOUT); load_case_tables(); smbd_init_globals(); TimeInit(); #ifdef HAVE_SET_AUTH_PARAMETERS set_auth_parameters(argc,argv); #endif pc = poptGetContext("smbd", argc, argv, long_options, 0); while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_DAEMON: is_daemon = true; break; case OPT_INTERACTIVE: interactive = true; break; case OPT_FORK: Fork = false; break; case OPT_NO_PROCESS_GROUP: no_process_group = true; break; case OPT_LOG_STDOUT: log_stdout = true; break; case 'b': print_build_options = True; break; default: d_fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0), poptStrerror(opt)); poptPrintUsage(pc, stderr, 0); exit(1); } } poptFreeContext(pc); if (interactive) { Fork = False; log_stdout = True; } if (log_stdout) { setup_logging(argv[0], DEBUG_STDOUT); } else { setup_logging(argv[0], DEBUG_FILE); } if (print_build_options) { build_options(True); /* Display output to screen as well as debug */ exit(0); } #ifdef HAVE_SETLUID /* needed for SecureWare on SCO */ setluid(0); #endif set_remote_machine_name("smbd", False); if (interactive && (DEBUGLEVEL >= 9)) { talloc_enable_leak_report(); } if (log_stdout && Fork) { DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); exit(1); } /* we want to re-seed early to prevent time delays causing client problems at a later date. (tridge) */ generate_random_buffer(NULL, 0); /* get initial effective uid and gid */ sec_init(); /* make absolutely sure we run as root - to handle cases where people are crazy enough to have it setuid */ gain_root_privilege(); gain_root_group_privilege(); fault_setup(); dump_core_setup("smbd", lp_logfile()); /* we are never interested in SIGPIPE */ BlockSignals(True,SIGPIPE); #if defined(SIGFPE) /* we are never interested in SIGFPE */ BlockSignals(True,SIGFPE); #endif #if defined(SIGUSR2) /* We are no longer interested in USR2 */ BlockSignals(True,SIGUSR2); #endif /* POSIX demands that signals are inherited. If the invoking process has * these signals masked, we will have problems, as we won't recieve them. */ BlockSignals(False, SIGHUP); BlockSignals(False, SIGUSR1); BlockSignals(False, SIGTERM); /* Ensure we leave no zombies until we * correctly set up child handling below. */ CatchChild(); /* we want total control over the permissions on created files, so set our umask to 0 */ umask(0); reopen_logs(); DEBUG(0,("smbd version %s started.\n", samba_version_string())); DEBUGADD(0,("%s\n", COPYRIGHT_STARTUP_MESSAGE)); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid())); /* Output the build options to the debug log */ build_options(False); if (sizeof(uint16) < 2 || sizeof(uint32) < 4) { DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); exit(1); } if (!lp_load_initial_only(get_dyn_CONFIGFILE())) { DEBUG(0, ("error opening config file '%s'\n", get_dyn_CONFIGFILE())); exit(1); } /* Init the security context and global current_user */ init_sec_ctx(); /* * Initialize the event context. The event context needs to be * initialized before the messaging context, cause the messaging * context holds an event context. * FIXME: This should be s3_tevent_context_init() */ ev_ctx = server_event_context(); if (ev_ctx == NULL) { exit(1); } /* * Init the messaging context * FIXME: This should only call messaging_init() */ msg_ctx = server_messaging_context(); if (msg_ctx == NULL) { exit(1); } /* * Reloading of the printers will not work here as we don't have a * server info and rpc services set up. It will be called later. */ if (!reload_services(NULL, -1, False)) { exit(1); } /* ...NOTE... Log files are working from this point! */ DEBUG(3,("loaded services\n")); init_structs(); #ifdef WITH_PROFILE if (!profile_setup(msg_ctx, False)) { DEBUG(0,("ERROR: failed to setup profiling\n")); return -1; } if (profile_level != NULL) { int pl = atoi(profile_level); struct server_id src; DEBUG(1, ("setting profiling level: %s\n",profile_level)); src.pid = getpid(); set_profile_level(pl, src); } #endif if (!is_daemon && !is_a_socket(0)) { if (!interactive) DEBUG(0,("standard input is not a socket, assuming -D option\n")); /* * Setting is_daemon here prevents us from eventually calling * the open_sockets_inetd() */ is_daemon = True; } if (is_daemon && !interactive) { DEBUG( 3, ( "Becoming a daemon.\n" ) ); become_daemon(Fork, no_process_group, log_stdout); } generate_random_buffer((uint8_t *)&unique_id, sizeof(unique_id)); set_my_unique_id(unique_id); #if HAVE_SETPGID /* * If we're interactive we want to set our own process group for * signal management. */ if (interactive && !no_process_group) setpgid( (pid_t)0, (pid_t)0); #endif if (!directory_exist(lp_lockdir())) mkdir(lp_lockdir(), 0755); if (is_daemon) pidfile_create("smbd"); status = reinit_after_fork(msg_ctx, ev_ctx, procid_self(), false); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } smbd_server_conn->msg_ctx = msg_ctx; smbd_setup_sig_term_handler(); smbd_setup_sig_hup_handler(ev_ctx, msg_ctx); /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */ if (smbd_memcache() == NULL) { exit(1); } memcache_set_global(smbd_memcache()); /* Initialise the password backed before the global_sam_sid to ensure that we fetch from ldap before we make a domain sid up */ if(!initialize_password_db(false, ev_ctx)) exit(1); if (!secrets_init()) { DEBUG(0, ("ERROR: smbd can not open secrets.tdb\n")); exit(1); } if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) { struct loadparm_context *lp_ctx = loadparm_init_s3(NULL, loadparm_s3_context()); if (!open_schannel_session_store(NULL, lp_ctx)) { DEBUG(0,("ERROR: Samba cannot open schannel store for secured NETLOGON operations.\n")); exit(1); } TALLOC_FREE(lp_ctx); } if(!get_global_sam_sid()) { DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); exit(1); } if (!sessionid_init()) { exit(1); } if (!connections_init(True)) exit(1); if (!locking_init()) exit(1); if (!messaging_tdb_parent_init(ev_ctx)) { exit(1); } if (!notify_internal_parent_init(ev_ctx)) { exit(1); } if (!serverid_parent_init(ev_ctx)) { exit(1); } if (!W_ERROR_IS_OK(registry_init_full())) exit(1); /* Open the share_info.tdb here, so we don't have to open after the fork on every single connection. This is a small performance improvment and reduces the total number of system fds used. */ if (!share_info_db_init()) { DEBUG(0,("ERROR: failed to load share info db.\n")); exit(1); } status = init_system_info(); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("ERROR: failed to setup system user info: %s.\n", nt_errstr(status))); return -1; } if (!init_guest_info()) { DEBUG(0,("ERROR: failed to setup guest info.\n")); return -1; } if (!file_init(smbd_server_conn)) { DEBUG(0, ("ERROR: file_init failed\n")); return -1; } /* This MUST be done before start_epmd() because otherwise * start_epmd() forks and races against dcesrv_ep_setup() to * call directory_create_or_exist() */ if (!directory_create_or_exist(lp_ncalrpc_dir(), geteuid(), 0755)) { DEBUG(0, ("Failed to create pipe directory %s - %s\n", lp_ncalrpc_dir(), strerror(errno))); return -1; } if (is_daemon && !interactive) { if (rpc_epmapper_daemon() == RPC_DAEMON_FORK) { start_epmd(ev_ctx, msg_ctx); } } if (!dcesrv_ep_setup(ev_ctx, msg_ctx)) { exit(1); } /* only start other daemons if we are running as a daemon * -- bad things will happen if smbd is launched via inetd * and we fork a copy of ourselves here */ if (is_daemon && !interactive) { if (rpc_lsasd_daemon() == RPC_DAEMON_FORK) { start_lsasd(ev_ctx, msg_ctx); } if (!_lp_disable_spoolss() && (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) { bool bgq = lp_parm_bool(-1, "smbd", "backgroundqueue", true); if (!printing_subsystem_init(ev_ctx, msg_ctx, true, bgq)) { exit(1); } } } else if (!_lp_disable_spoolss() && (rpc_spoolss_daemon() != RPC_DAEMON_DISABLED)) { if (!printing_subsystem_init(ev_ctx, msg_ctx, false, false)) { exit(1); } } if (!is_daemon) { /* inetd mode */ TALLOC_FREE(frame); /* Started from inetd. fd 0 is the socket. */ /* We will abort gracefully when the client or remote system goes away */ smbd_server_conn->sock = dup(0); /* close our standard file descriptors */ if (!debug_get_output_is_stdout()) { close_low_fds(False); /* Don't close stderr */ } #ifdef HAVE_ATEXIT atexit(killkids); #endif /* Stop zombies */ smbd_setup_sig_chld_handler(ev_ctx); smbd_process(ev_ctx, smbd_server_conn); exit_server_cleanly(NULL); return(0); } parent = talloc_zero(ev_ctx, struct smbd_parent_context); if (!parent) { exit_server("talloc(struct smbd_parent_context) failed"); } parent->interactive = interactive; if (!open_sockets_smbd(parent, ev_ctx, msg_ctx, ports)) exit_server("open_sockets_smbd() failed"); /* do a printer update now that all messaging has been set up, * before we allow clients to start connecting */ printing_subsystem_update(ev_ctx, msg_ctx, false); TALLOC_FREE(frame); /* make sure we always have a valid stackframe */ frame = talloc_stackframe(); smbd_parent_loop(ev_ctx, parent); exit_server_cleanly(NULL); TALLOC_FREE(frame); return(0); }
int main(int argc, char * argv[]) { const char * config_file_name = NULL; bool daemon_mode = true; pid_t pid; /* Search command line for config file name * */ for ( int i = 1; i < argc; ++i ) { if ( strncmp(argv[i], "--config=", 9) == 0 ) { config_file_name = argv[i] + 9; } else if ( strcmp(argv[i], "--no-daemon") == 0 ) { daemon_mode = 0; } } /* Read config file * */ if ( !config_file_name ) { config_file_name = ffsrv_find_config_file(); } if ( config_file_name && !ffsrv_read_config_file(config_file_name) ) { return EXIT_FAILURE; } /* Walk over command line again, overriding config file settings * */ for ( int i = 1; i < argc; ++i ) { char keyname[256] = "", keyvalue[256] = ""; sscanf(argv[i], "%255[^=]=%255s", keyname, keyvalue); if ( !ffsrv_parse_option(keyname, keyvalue) ) { return EXIT_FAILURE; } } /* Become daemon if requested * */ if ( daemon_mode ) { if ( (pid = become_daemon()) == -1 ) { fprintf(stderr, "become_daemon() fails: %s", strerror(errno)); return EXIT_FAILURE; } if ( pid != 0 ) { return EXIT_SUCCESS; /* finish parrent process */ } } /* Setup log file name * */ if ( !ffsrv.logfilename || !*ffsrv.logfilename ) { free(ffsrv.logfilename); if ( daemon_mode ) { ffsrv.logfilename = strdup("ffsrv.log"); } else { ffsrv.logfilename = strdup("stderr"); } } set_logfilename(ffsrv.logfilename); /* Setup singal handler * */ if ( !setup_signal_handler() ) { PDBG("setup_signal_handler() fails: %s", strerror(errno)); return EXIT_FAILURE; } /* Start actual server * */ if ( !ffsrv_start() ) { PDBG("ffsrv_start() fails: %s", strerror(errno)); return EXIT_FAILURE; } /* Sleep this thread */ while ( 42 ) { sleep(1); } ffsrv_finish(); return EXIT_SUCCESS; }
int main(int argc, char **argv) { int i; int config_loaded = 0; int dont_fork = 0; size_t default_stacksize; // set the name for logging program_name = "netdata"; // parse depercated options // TODO: Remove this block with the next major release. { i = 1; while(i < argc) { if(strcmp(argv[i], "-pidfile") == 0 && (i+1) < argc) { strncpyz(pidfile, argv[i+1], FILENAME_MAX); fprintf(stderr, "%s: deprecated option -- %s -- please use -P instead.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-nodaemon") == 0 || strcmp(argv[i], "-nd") == 0) { dont_fork = 1; fprintf(stderr, "%s: deprecated option -- %s -- please use -D instead.\n ", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) { config_set(CONFIG_SECTION_GLOBAL, "host access prefix", argv[i+1]); fprintf(stderr, "%s: deprecated option -- %s -- please use -s instead.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) { config_set(CONFIG_SECTION_GLOBAL, "history", argv[i+1]); fprintf(stderr, "%s: deprecated option -- %s -- This option will be removed with V2.*.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else i++; } } // parse options { int num_opts = sizeof(option_definitions) / sizeof(struct option_def); char optstring[(num_opts * 2) + 1]; int string_i = 0; for( i = 0; i < num_opts; i++ ) { optstring[string_i] = option_definitions[i].val; string_i++; if(option_definitions[i].arg_name) { optstring[string_i] = ':'; string_i++; } } // terminate optstring optstring[string_i] ='\0'; optstring[(num_opts *2)] ='\0'; int opt; while( (opt = getopt(argc, argv, optstring)) != -1 ) { switch(opt) { case 'c': if(config_load(optarg, 1) != 1) { error("Cannot load configuration file %s.", optarg); return 1; } else { debug(D_OPTIONS, "Configuration loaded from %s.", optarg); config_loaded = 1; } break; case 'D': dont_fork = 1; break; case 'h': return help(0); case 'i': config_set(CONFIG_SECTION_WEB, "bind to", optarg); break; case 'P': strncpy(pidfile, optarg, FILENAME_MAX); pidfile[FILENAME_MAX] = '\0'; break; case 'p': config_set(CONFIG_SECTION_GLOBAL, "default port", optarg); break; case 's': config_set(CONFIG_SECTION_GLOBAL, "host access prefix", optarg); break; case 't': config_set(CONFIG_SECTION_GLOBAL, "update every", optarg); break; case 'u': config_set(CONFIG_SECTION_GLOBAL, "run as user", optarg); break; case 'v': case 'V': printf("%s %s\n", program_name, program_version); return 0; case 'W': { char* stacksize_string = "stacksize="; char* debug_flags_string = "debug_flags="; if(strcmp(optarg, "unittest") == 0) { if(unit_test_buffer()) return 1; if(unit_test_str2ld()) return 1; //default_rrd_update_every = 1; //default_rrd_memory_mode = RRD_MEMORY_MODE_RAM; //if(!config_loaded) config_load(NULL, 0); get_netdata_configured_variables(); default_rrd_update_every = 1; default_rrd_memory_mode = RRD_MEMORY_MODE_RAM; default_health_enabled = 0; rrd_init("unittest"); default_rrdpush_enabled = 0; if(run_all_mockup_tests()) return 1; if(unit_test_storage()) return 1; fprintf(stderr, "\n\nALL TESTS PASSED\n\n"); return 0; } else if(strcmp(optarg, "simple-pattern") == 0) { if(optind + 2 > argc) { fprintf(stderr, "%s", "\nUSAGE: -W simple-pattern 'pattern' 'string'\n\n" " Checks if 'pattern' matches the given 'string'.\n" " - 'pattern' can be one or more space separated words.\n" " - each 'word' can contain one or more asterisks.\n" " - words starting with '!' give negative matches.\n" " - words are processed left to right\n" "\n" "Examples:\n" "\n" " > match all veth interfaces, except veth0:\n" "\n" " -W simple-pattern '!veth0 veth*' 'veth12'\n" "\n" "\n" " > match all *.ext files directly in /path/:\n" " (this will not match *.ext files in a subdir of /path/)\n" "\n" " -W simple-pattern '!/path/*/*.ext /path/*.ext' '/path/test.ext'\n" "\n" ); return 1; } const char *heystack = argv[optind]; const char *needle = argv[optind + 1]; size_t len = strlen(needle) + 1; char wildcarded[len]; SIMPLE_PATTERN *p = simple_pattern_create(heystack, NULL, SIMPLE_PATTERN_EXACT); int ret = simple_pattern_matches_extract(p, needle, wildcarded, len); simple_pattern_free(p); if(ret) { fprintf(stdout, "RESULT: MATCHED - pattern '%s' matches '%s', wildcarded '%s'\n", heystack, needle, wildcarded); return 0; } else { fprintf(stdout, "RESULT: NOT MATCHED - pattern '%s' does not match '%s', wildcarded '%s'\n", heystack, needle, wildcarded); return 1; } } else if(strncmp(optarg, stacksize_string, strlen(stacksize_string)) == 0) { optarg += strlen(stacksize_string); config_set(CONFIG_SECTION_GLOBAL, "pthread stack size", optarg); } else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) { optarg += strlen(debug_flags_string); config_set(CONFIG_SECTION_GLOBAL, "debug flags", optarg); debug_flags = strtoull(optarg, NULL, 0); } else if(strcmp(optarg, "set") == 0) { if(optind + 3 > argc) { fprintf(stderr, "%s", "\nUSAGE: -W set 'section' 'key' 'value'\n\n" " Overwrites settings of netdata.conf.\n" "\n" " These options interact with: -c netdata.conf\n" " If -c netdata.conf is given on the command line,\n" " before -W set... the user may overwrite command\n" " line parameters at netdata.conf\n" " If -c netdata.conf is given after (or missing)\n" " -W set... the user cannot overwrite the command line\n" " parameters." "\n" ); return 1; } const char *section = argv[optind]; const char *key = argv[optind + 1]; const char *value = argv[optind + 2]; optind += 3; // set this one as the default // only if it is not already set in the config file // so the caller can use -c netdata.conf before or // after this parameter to prevent or allow overwriting // variables at netdata.conf config_set_default(section, key, value); // fprintf(stderr, "SET section '%s', key '%s', value '%s'\n", section, key, value); } else if(strcmp(optarg, "get") == 0) { if(optind + 3 > argc) { fprintf(stderr, "%s", "\nUSAGE: -W get 'section' 'key' 'value'\n\n" " Prints settings of netdata.conf.\n" "\n" " These options interact with: -c netdata.conf\n" " -c netdata.conf has to be given before -W get.\n" "\n" ); return 1; } if(!config_loaded) { fprintf(stderr, "warning: no configuration file has been loaded. Use -c CONFIG_FILE, before -W get. Using default config.\n"); config_load(NULL, 0); } backwards_compatible_config(); get_netdata_configured_variables(); const char *section = argv[optind]; const char *key = argv[optind + 1]; const char *def = argv[optind + 2]; const char *value = config_get(section, key, def); printf("%s\n", value); return 0; } else { fprintf(stderr, "Unknown -W parameter '%s'\n", optarg); return help(1); } } break; default: /* ? */ fprintf(stderr, "Unknown parameter '%c'\n", opt); return help(1); } } } #ifdef _SC_OPEN_MAX // close all open file descriptors, except the standard ones // the caller may have left open files (lxc-attach has this issue) { int fd; for(fd = (int) (sysconf(_SC_OPEN_MAX) - 1); fd > 2; fd--) if(fd_is_valid(fd)) close(fd); } #endif if(!config_loaded) config_load(NULL, 0); // ------------------------------------------------------------------------ // initialize netdata { char *pmax = config_get(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for plugins", "1"); if(pmax && *pmax) setenv("MALLOC_ARENA_MAX", pmax, 1); #if defined(HAVE_C_MALLOPT) i = (int)config_get_number(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for netdata", 1); if(i > 0) mallopt(M_ARENA_MAX, 1); #endif // prepare configuration environment variables for the plugins get_netdata_configured_variables(); set_global_environment(); // work while we are cd into config_dir // to allow the plugins refer to their config // files using relative filenames if(chdir(netdata_configured_config_dir) == -1) fatal("Cannot cd to '%s'", netdata_configured_config_dir); } char *user = NULL; { // -------------------------------------------------------------------- // get the debugging flags from the configuration file char *flags = config_get(CONFIG_SECTION_GLOBAL, "debug flags", "0x0000000000000000"); setenv("NETDATA_DEBUG_FLAGS", flags, 1); debug_flags = strtoull(flags, NULL, 0); debug(D_OPTIONS, "Debug flags set to '0x%" PRIX64 "'.", debug_flags); if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) error("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); #ifdef HAVE_SYS_PRCTL_H prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); #endif } // -------------------------------------------------------------------- // get log filenames and settings log_init(); error_log_limit_unlimited(); // -------------------------------------------------------------------- // load stream.conf { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/stream.conf", netdata_configured_config_dir); appconfig_load(&stream_config, filename, 0); } // -------------------------------------------------------------------- // setup process signals // block signals while initializing threads. // this causes the threads to block signals. signals_block(); // setup the signals we want to use signals_init(); // setup threads configs default_stacksize = netdata_threads_init(); // -------------------------------------------------------------------- // check which threads are enabled and initialize them for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->config_name) st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled); if(st->enabled && st->init_routine) st->init_routine(); } // -------------------------------------------------------------------- // get the user we should run // IMPORTANT: this is required before web_files_uid() if(getuid() == 0) { user = config_get(CONFIG_SECTION_GLOBAL, "run as user", NETDATA_USER); } else { struct passwd *passwd = getpwuid(getuid()); user = config_get(CONFIG_SECTION_GLOBAL, "run as user", (passwd && passwd->pw_name)?passwd->pw_name:""); } // -------------------------------------------------------------------- // create the listening sockets web_client_api_v1_init(); web_server_threading_selection(); if(web_server_mode != WEB_SERVER_MODE_NONE) api_listen_sockets_setup(); } // initialize the log files open_all_log_files(); #ifdef NETDATA_INTERNAL_CHECKS if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) error("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); #ifdef HAVE_SYS_PRCTL_H prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); #endif } #endif /* NETDATA_INTERNAL_CHECKS */ // get the max file limit if(getrlimit(RLIMIT_NOFILE, &rlimit_nofile) != 0) error("getrlimit(RLIMIT_NOFILE) failed"); else info("resources control: allowed file descriptors: soft = %zu, max = %zu", rlimit_nofile.rlim_cur, rlimit_nofile.rlim_max); // fork, switch user, create pid file, set process priority if(become_daemon(dont_fork, user) == -1) fatal("Cannot daemonize myself."); info("netdata started on pid %d.", getpid()); // IMPORTANT: these have to run once, while single threaded // but after we have switched user web_files_uid(); web_files_gid(); netdata_threads_init_after_fork((size_t)config_get_number(CONFIG_SECTION_GLOBAL, "pthread stack size", (long)default_stacksize)); // ------------------------------------------------------------------------ // initialize rrd, registry, health, rrdpush, etc. rrd_init(netdata_configured_hostname); // ------------------------------------------------------------------------ // enable log flood protection error_log_limit_reset(); // ------------------------------------------------------------------------ // spawn the threads web_server_config_options(); for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->enabled) { st->thread = mallocz(sizeof(netdata_thread_t)); debug(D_SYSTEM, "Starting thread %s.", st->name); netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, st); } else debug(D_SYSTEM, "Not starting thread %s.", st->name); } info("netdata initialization completed. Enjoy real-time performance monitoring!"); // ------------------------------------------------------------------------ // unblock signals signals_unblock(); // ------------------------------------------------------------------------ // Handle signals signals_handle(); // should never reach this point // but we need it for rpmlint #2752 return 1; }
int tcf(void) { #else int main(int argc, char ** argv) { int c; int ind; int daemon = 0; const char * log_name = NULL; const char * log_level = NULL; #endif int interactive = 0; int print_server_properties = 0; const char * url = DEFAULT_SERVER_URL; Protocol * proto; TCFBroadcastGroup * bcg; PRE_INIT_HOOK; ini_mdep(); ini_trace(); ini_events_queue(); ini_asyncreq(); PRE_THREADING_HOOK; #if defined(_WRS_KERNEL) progname = "tcf"; open_log_file("-"); log_mode = 0; #else progname = argv[0]; /* Parse arguments */ for (ind = 1; ind < argc; ind++) { char * s = argv[ind]; if (*s++ != '-') break; while (s && (c = *s++) != '\0') { switch (c) { case 'i': interactive = 1; break; case 't': #if ENABLE_RCBP_TEST test_proc(); #endif exit(0); break; case 'd': #if defined(_WIN32) || defined(__CYGWIN__) /* For Windows the only way to detach a process is to * create a new process, so we patch the -d option to * -D for the second time we get invoked so we don't * keep on creating new processes forever. */ s[-1] = 'D'; daemon = 2; break; case 'D': #endif daemon = 1; break; case 'c': generate_ssl_certificate(); exit(0); break; case 'S': print_server_properties = 1; break; case 'h': show_help(); exit(0); case 'I': #if ENABLE_Trace case 'l': #endif case 'L': case 's': case 'g': #if ENABLE_Plugins case 'P': #endif if (*s == '\0') { if (++ind >= argc) { fprintf(stderr, "%s: error: no argument given to option '%c'\n", progname, c); exit(1); } s = argv[ind]; } switch (c) { case 'I': idle_timeout = strtol(s, 0, 0); break; #if ENABLE_Trace case 'l': log_level = s; parse_trace_mode(log_level, &log_mode); break; #endif case 'L': log_name = s; break; case 's': url = s; break; #if ENABLE_DebugContext case 'g': if (ini_gdb_rsp(s) < 0) { fprintf(stderr, "Cannot create GDB server: %s\n", errno_to_str(errno)); exit(1); } break; #endif #if ENABLE_Plugins case 'P': plugins_path = s; break; #endif } s = NULL; break; default: ILLEGAL_OPTION_HOOK; fprintf(stderr, "%s: error: illegal option '%c'\n", progname, c); show_help(); exit(1); } } } POST_OPTION_HOOK; if (daemon) { #if defined(_WIN32) || defined(__CYGWIN__) become_daemon(daemon > 1 ? argv : NULL); #else become_daemon(); #endif } open_log_file(log_name); #endif bcg = broadcast_group_alloc(); proto = protocol_alloc(); /* The static services must be initialised before the plugins */ #if ENABLE_Cmdline if (interactive) ini_cmdline_handler(interactive, proto); #else if (interactive) fprintf(stderr, "Warning: This version does not support interactive mode.\n"); #endif ini_services(proto, bcg); #if !defined(_WRS_KERNEL) /* Reparse log level in case initialization cause additional * levels to be registered */ if (log_level != NULL && parse_trace_mode(log_level, &log_mode) != 0) { fprintf(stderr, "Cannot parse log level: %s\n", log_level); exit(1); } #endif if (ini_server(url, proto, bcg) < 0) { fprintf(stderr, "Cannot create TCF server: %s\n", errno_to_str(errno)); exit(1); } discovery_start(); if (print_server_properties) { ChannelServer * s; char * server_properties; assert(!list_is_empty(&channel_server_root)); s = servlink2channelserverp(channel_server_root.next); server_properties = channel_peer_to_json(s->ps); printf("Server-Properties: %s\n", server_properties); fflush(stdout); trace(LOG_ALWAYS, "Server-Properties: %s", server_properties); loc_free(server_properties); } PRE_DAEMON_HOOK; #if !defined(_WRS_KERNEL) if (daemon) close_out_and_err(); #endif #if ENABLE_SignalHandlers signal(SIGABRT, signal_handler); signal(SIGILL, signal_handler); signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); #if defined(_WIN32) || defined(__CYGWIN__) SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); AddVectoredExceptionHandler(1, VectoredExceptionHandler); #endif #endif /* ENABLE_SignalHandlers */ if (idle_timeout != 0) { add_channel_close_listener(channel_closed); check_idle_timeout(NULL); } /* Process events - must run on the initial thread since ptrace() * returns ECHILD otherwise, thinking we are not the owner. */ run_event_loop(); #if ENABLE_Plugins plugins_destroy(); #endif /* ENABLE_Plugins */ return 0; }