/* If daemonization is configured, then starts daemonization, by forking and * returning in the child process. The parent process hangs around until the * child lets it know either that it completed startup successfully (by calling * daemon_complete()) or that it failed to start up (by exiting with a nonzero * exit code). */ void daemonize_start(void) { daemonize_fd = -1; if (detach) { if (fork_and_wait_for_startup(&daemonize_fd) > 0) { /* Running in parent process. */ exit(0); } /* Running in daemon or monitor process. */ } if (monitor) { int saved_daemonize_fd = daemonize_fd; pid_t daemon_pid; daemon_pid = fork_and_wait_for_startup(&daemonize_fd); if (daemon_pid > 0) { /* Running in monitor process. */ fork_notify_startup(saved_daemonize_fd); close_standard_fds(); monitor_daemon(daemon_pid); } /* Running in daemon process. */ } make_pidfile(); /* Make sure that the unixctl commands for vlog get registered in a * daemon, even before the first log message. */ vlog_init(); }
/* If daemonization is configured, then starts daemonization, by forking and * returning in the child process. The parent process hangs around until the * child lets it know either that it completed startup successfully (by calling * daemon_complete()) or that it failed to start up (by exiting with a nonzero * exit code). */ void daemonize_start(bool access_datapath) { assert_single_threaded(); daemonize_fd = -1; if (switch_user) { daemon_become_new_user__(access_datapath); switch_user = false; } if (detach) { pid_t pid; if (fork_and_wait_for_startup(&daemonize_fd, &pid)) { VLOG_FATAL("could not detach from foreground session"); } if (pid > 0) { /* Running in parent process. */ exit(0); } /* Running in daemon or monitor process. */ setsid(); } if (monitor) { int saved_daemonize_fd = daemonize_fd; pid_t daemon_pid; if (fork_and_wait_for_startup(&daemonize_fd, &daemon_pid)) { VLOG_FATAL("could not initiate process monitoring"); } if (daemon_pid > 0) { /* Running in monitor process. */ fork_notify_startup(saved_daemonize_fd); if (detach) { close_standard_fds(); } monitor_daemon(daemon_pid); } /* Running in daemon process. */ } forbid_forking("running in daemon process"); if (pidfile) { make_pidfile(); } /* Make sure that the unixctl commands for vlog get registered in a * daemon, even before the first log message. */ vlog_init(); }
/* If configured with set_pidfile() or set_detach(), creates the pid file and * detaches from the foreground session. */ void daemonize(void) { if (detach) { char c = 0; int fds[2]; if (pipe(fds) < 0) { ofp_fatal(errno, "pipe failed"); } switch (fork()) { default: /* Parent process: wait for child to create pidfile, then exit. */ close(fds[1]); fatal_signal_fork(); if (read(fds[0], &c, 1) != 1) { ofp_fatal(errno, "daemon child failed to signal startup"); } exit(0); case 0: /* Child process. */ close(fds[0]); make_pidfile(); write(fds[1], &c, 1); close(fds[1]); setsid(); chdir("/"); break; case -1: /* Error. */ ofp_fatal(errno, "could not fork"); break; } } else { make_pidfile(); } }
/* main() for udpxrec module */ int udpxrec_main( int argc, char* const argv[] ) { int rc = 0, ch = 0, custom_log = 0, no_daemon = 0; static const char OPTMASK[] = "vb:e:M:p:B:n:m:l:c:R:u:T"; time_t now = time(NULL); char now_buf[ 32 ] = {0}, sel_buf[ 32 ] = {0}, app_finfo[80] = {0}; extern int optind, optopt; extern const char IPv4_ALL[]; mk_app_info(g_udpxrec_app, g_app_info, sizeof(g_app_info) - 1); if( argc < 2 ) { usage( argv[0], stderr ); return ERR_PARAM; } rc = init_recopt( &g_recopt ); while( (0 == rc) && (-1 != (ch = getopt( argc, argv, OPTMASK ))) ) { switch(ch) { case 'T': no_daemon = 1; break; case 'v': set_verbose( &g_recopt.is_verbose ); break; case 'b': if( (time_t)0 != g_recopt.end_time ) { (void) fprintf( stderr, "Cannot specify start-recording " "time after end-recording time has been set\n" ); } rc = a2time( optarg, &g_recopt.bg_time, time(NULL) ); if( 0 != rc ) { (void) fprintf( stderr, "Invalid time: [%s]\n", optarg ); rc = ERR_PARAM; } else { if( g_recopt.bg_time < now ) { (void)strncpy( now_buf, Zasctime(localtime( &now )), sizeof(now_buf) ); (void)strncpy( sel_buf, Zasctime(localtime( &g_recopt.bg_time )), sizeof(sel_buf) ); (void) fprintf( stderr, "Selected %s time is in the past, " "now=[%s], selected=[%s]\n", "start", now_buf, sel_buf ); rc = ERR_PARAM; } } break; case 'e': if( (time_t)0 == g_recopt.bg_time ) { g_recopt.bg_time = time(NULL); (void)fprintf( stderr, "Start-recording time defaults to now [%s]\n", Zasctime( localtime( &g_recopt.bg_time ) ) ); } rc = a2time( optarg, &g_recopt.end_time, g_recopt.bg_time ); if( 0 != rc ) { (void) fprintf( stderr, "Invalid time: [%s]\n", optarg ); rc = ERR_PARAM; } else { if( g_recopt.end_time < now ) { (void)strncpy( now_buf, Zasctime(localtime( &now )), sizeof(now_buf) ); (void)strncpy( sel_buf, Zasctime(localtime( &g_recopt.end_time )), sizeof(sel_buf) ); (void) fprintf( stderr, "Selected %s time is in the past, " "now=[%s], selected=[%s]\n", "end", now_buf, sel_buf ); rc = ERR_PARAM; } } break; case 'M': rc = a2int64( optarg, &g_recopt.max_fsize ); if( 0 != rc ) { (void) fprintf( stderr, "Invalid file size: [%s]\n", optarg ); rc = ERR_PARAM; } break; case 'p': g_recopt.pidfile = strdup(optarg); break; case 'B': rc = a2size( optarg, &g_recopt.bufsize ); if( 0 != rc ) { (void) fprintf( stderr, "Invalid buffer size: [%s]\n", optarg ); rc = ERR_PARAM; } else if( (g_recopt.bufsize < MIN_MCACHE_LEN) || (g_recopt.bufsize > MAX_MCACHE_LEN)) { (void) fprintf( stderr, "Buffer size must be in [%ld-%ld] bytes range\n", (long)MIN_MCACHE_LEN, (long)MAX_MCACHE_LEN ); rc = ERR_PARAM; } break; case 'n': g_recopt.nice_incr = atoi( optarg ); if( 0 == g_recopt.nice_incr ) { (void) fprintf( stderr, "Invalid nice-value increment: [%s]\n", optarg ); rc = ERR_PARAM; } break; case 'm': rc = get_ipv4_address( optarg, g_recopt.mcast_addr, sizeof(g_recopt.mcast_addr) ); if( 0 != rc ) { (void) fprintf( stderr, "Invalid multicast address: [%s]\n", optarg ); rc = ERR_PARAM; } break; case 'l': g_flog = fopen( optarg, "a" ); if( NULL == g_flog ) { rc = errno; (void) fprintf( stderr, "Error opening logfile [%s]: %s\n", optarg, strerror(rc) ); rc = ERR_PARAM; break; } Setlinebuf( g_flog ); custom_log = 1; break; case 'c': rc = get_addrport( optarg, g_recopt.rec_channel, sizeof( g_recopt.rec_channel ), &g_recopt.rec_port ); if( 0 != rc ) rc = ERR_PARAM; break; case 'R': g_recopt.rbuf_msgs = atoi( optarg ); if( (g_recopt.rbuf_msgs <= 0) && (-1 != g_recopt.rbuf_msgs) ) { (void) fprintf( stderr, "Invalid rcache size: [%s]\n", optarg ); rc = ERR_PARAM; } break; case 'u': g_recopt.waitupd_sec = atoi(optarg); if( g_recopt.waitupd_sec <= 0 ) { (void) fprintf( stderr, "Invalid wait-update value [%s] " "(must be a number > 0)\n", optarg ); rc = ERR_PARAM; } break; case ':': (void) fprintf( stderr, "Option [-%c] requires an argument\n", optopt ); rc = ERR_PARAM; break; case '?': (void) fprintf( stderr, "Unrecognized option: [-%c]\n", optopt ); rc = ERR_PARAM; break; default: usage( argv[0], stderr ); rc = ERR_PARAM; break; } /* switch */ } /* while getopt */ if( 0 == rc ) { if( optind >= argc ) { (void) fputs( "Missing destination file parameter\n", stderr ); rc = ERR_PARAM; } else { g_recopt.dstfile = strdup( argv[optind] ); } if( !(g_recopt.max_fsize > 0 || g_recopt.end_time) ) { (void) fputs( "Must specify either max file [-M] size " "or end time [-e]\n", stderr ); rc = ERR_PARAM; } if( !g_recopt.rec_channel[0] || !g_recopt.rec_port ) { (void) fputs( "Must specify multicast channel to record from\n", stderr ); rc = ERR_PARAM; } } if( rc ) { free_recopt( &g_recopt ); return rc; } do { if( '\0' == g_recopt.mcast_addr[0] ) { (void) strncpy( g_recopt.mcast_addr, IPv4_ALL, sizeof(g_recopt.mcast_addr) - 1 ); } if( !custom_log ) { /* in debug mode output goes to stderr, otherwise to /dev/null */ g_flog = ((uf_TRUE == g_recopt.is_verbose) ? stderr : fopen( "/dev/null", "a" )); if( NULL == g_flog ) { perror("fopen"); rc = ERR_INTERNAL; break; } } if( 0 == geteuid() ) { if( !no_daemon ) { if( stderr == g_flog ) { (void) fprintf( stderr, "Logfile must be specified to run " "in verbose mode in background\n" ); rc = ERR_PARAM; break; } if( NULL == g_recopt.pidfile ) { (void) fprintf( stderr, "pidfile must be specified " "to run as daemon\n" ); rc = ERR_PARAM; break; } if( 0 != (rc = daemonize(0, g_flog)) ) { rc = ERR_INTERNAL; break; } } } /* 0 == geteuid() */ if( NULL != g_recopt.pidfile ) { rc = make_pidfile( g_recopt.pidfile, getpid(), g_flog ); if( 0 != rc ) break; } (void) set_nice( g_recopt.nice_incr, g_flog ); if( 0 != (rc = setup_signals()) ) break; TRACE( fprint_recopt( g_flog, &g_recopt ) ); TRACE( printcmdln( g_flog, g_app_info, argc, argv ) ); if( g_recopt.bg_time ) { if( 0 != (rc = verify_channel()) || g_quit ) break; rc = wait_till( g_recopt.bg_time, g_recopt.waitupd_sec ); if( rc || g_quit ) break; } rc = record(); if( NULL != g_recopt.pidfile ) { if( -1 == unlink(g_recopt.pidfile) ) { mperror( g_flog, errno, "unlink [%s]", g_recopt.pidfile ); } } } while(0); if( g_flog ) { (void)tmfprintf( g_flog, "%s is exiting with rc=[%d]\n", app_finfo, rc ); } if( g_flog && (stderr != g_flog) ) { (void) fclose(g_flog); } free_recopt( &g_recopt ); return rc; }
static int mdmon(char *devnm, int must_fork, int takeover) { int mdfd; struct mdinfo *mdi, *di; struct supertype *container; sigset_t set; struct sigaction act; int pfd[2]; int status; int ignore; pid_t victim = -1; int victim_sock = -1; dprintf("starting mdmon for %s\n", devnm); mdfd = open_dev(devnm); if (mdfd < 0) { pr_err("%s: %s\n", devnm, strerror(errno)); return 1; } if (md_get_version(mdfd) < 0) { pr_err("%s: Not an md device\n", devnm); return 1; } /* Fork, and have the child tell us when they are ready */ if (must_fork) { if (pipe(pfd) != 0) { pr_err("failed to create pipe\n"); return 1; } switch(fork()) { case -1: pr_err("failed to fork: %s\n", strerror(errno)); return 1; case 0: /* child */ close(pfd[0]); break; default: /* parent */ close(pfd[1]); if (read(pfd[0], &status, sizeof(status)) != sizeof(status)) { wait(&status); status = WEXITSTATUS(status); } close(pfd[0]); return status; } } else pfd[0] = pfd[1] = -1; container = xcalloc(1, sizeof(*container)); strcpy(container->devnm, devnm); container->arrays = NULL; container->sock = -1; mdi = sysfs_read(mdfd, container->devnm, GET_VERSION|GET_LEVEL|GET_DEVS); if (!mdi) { pr_err("failed to load sysfs info for %s\n", container->devnm); exit(3); } if (mdi->array.level != UnSet) { pr_err("%s is not a container - cannot monitor\n", devnm); exit(3); } if (mdi->array.major_version != -1 || mdi->array.minor_version != -2) { pr_err("%s does not use external metadata - cannot monitor\n", devnm); exit(3); } container->ss = version_to_superswitch(mdi->text_version); if (container->ss == NULL) { pr_err("%s uses unsupported metadata: %s\n", devnm, mdi->text_version); exit(3); } container->devs = NULL; for (di = mdi->devs; di; di = di->next) { struct mdinfo *cd = xmalloc(sizeof(*cd)); *cd = *di; cd->next = container->devs; container->devs = cd; } sysfs_free(mdi); /* SIGUSR is sent between parent and child. So both block it * and enable it only with pselect. */ sigemptyset(&set); sigaddset(&set, SIGUSR1); sigaddset(&set, SIGTERM); sigprocmask(SIG_BLOCK, &set, NULL); act.sa_handler = wake_me; act.sa_flags = 0; sigaction(SIGUSR1, &act, NULL); act.sa_handler = term; sigaction(SIGTERM, &act, NULL); act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, NULL); victim = mdmon_pid(container->devnm); if (victim >= 0) victim_sock = connect_monitor(container->devnm); ignore = chdir("/"); if (!takeover && victim > 0 && victim_sock >= 0) { if (fping_monitor(victim_sock) == 0) { pr_err("%s already managed\n", container->devnm); exit(3); } close(victim_sock); victim_sock = -1; } if (container->ss->load_container(container, mdfd, devnm)) { pr_err("Cannot load metadata for %s\n", devnm); exit(3); } close(mdfd); /* Ok, this is close enough. We can say goodbye to our parent now. */ if (victim > 0) remove_pidfile(devnm); if (make_pidfile(devnm) < 0) { exit(3); } container->sock = make_control_sock(devnm); status = 0; if (pfd[1] >= 0) { if (write(pfd[1], &status, sizeof(status)) < 0) pr_err("failed to notify our parent: %d\n", getppid()); close(pfd[1]); } mlockall(MCL_CURRENT | MCL_FUTURE); if (clone_monitor(container) < 0) { pr_err("failed to start monitor process: %s\n", strerror(errno)); exit(2); } if (victim > 0) { try_kill_monitor(victim, container->devnm, victim_sock); if (victim_sock >= 0) close(victim_sock); } setsid(); close(0); open("/dev/null", O_RDWR); close(1); ignore = dup(0); #ifndef DEBUG close(2); ignore = dup(0); #endif /* This silliness is to stop the compiler complaining * that we ignore 'ignore' */ if (ignore) ignore++; do_manager(container); exit(0); }
int udpxy_main( int argc, char* const argv[] ) { int rc = 0, ch = 0, port = -1, custom_log = 0, no_daemon = 0; char ipaddr[IPADDR_STR_SIZE] = "\0", mcast_addr[IPADDR_STR_SIZE] = "\0"; char pidfile[ MAXPATHLEN ] = "\0"; u_short MIN_MCAST_REFRESH = 0, MAX_MCAST_REFRESH = 0; /* support for -r -w (file read/write) option is disabled by default; * those features are experimental and for dev debugging ONLY * */ #ifdef UDPXY_FILEIO static const char UDPXY_OPTMASK[] = "TvSa:l:p:m:c:B:n:R:r:w:H:M:"; #else static const char UDPXY_OPTMASK[] = "TvSa:l:p:m:c:B:n:R:H:M:"; #endif struct sigaction qact, iact, cact, oldact; init_app_info(); (void) get_pidstr( PID_RESET, "S" ); rc = init_uopt( &g_uopt ); while( (0 == rc) && (-1 != (ch = getopt(argc, argv, UDPXY_OPTMASK))) ) { switch( ch ) { case 'v': set_verbose( &g_uopt.is_verbose ); break; case 'T': no_daemon = 1; break; case 'S': g_uopt.cl_tpstat = uf_TRUE; break; case 'a': rc = get_ipv4_address( optarg, ipaddr, sizeof(ipaddr) ); if( 0 != rc ) { (void) fprintf( stderr, "Invalid address: [%s]\n", optarg ); rc = ERR_PARAM; } break; case 'p': port = atoi( optarg ); if( port <= 0 ) { (void) fprintf( stderr, "Invalid port number: [%d]\n", port ); rc = ERR_PARAM; } break; case 'm': rc = get_ipv4_address( optarg, mcast_addr, sizeof(mcast_addr) ); if( 0 != rc ) { (void) fprintf( stderr, "Invalid multicast address: " "[%s]\n", optarg ); rc = ERR_PARAM; } break; case 'c': g_uopt.max_clients = atoi( optarg ); if( (g_uopt.max_clients < MIN_CLIENT_COUNT) || (g_uopt.max_clients > MAX_CLIENT_COUNT) ) { (void) fprintf( stderr, "Client count should be between %d and %d\n", MIN_CLIENT_COUNT, MAX_CLIENT_COUNT ); rc = ERR_PARAM; } break; case 'l': g_flog = fopen( optarg, "a" ); if( NULL == g_flog ) { rc = errno; (void) fprintf( stderr, "Error opening logfile " "[%s]: %s\n", optarg, strerror(rc) ); rc = ERR_PARAM; break; } Setlinebuf( g_flog ); custom_log = 1; break; case 'B': rc = a2size(optarg, &g_uopt.rbuf_len); if( 0 != rc ) { (void) fprintf( stderr, "Invalid buffer size: [%s]\n", optarg ); exit( ERR_PARAM ); } else if( (g_uopt.rbuf_len < MIN_MCACHE_LEN) || (g_uopt.rbuf_len > MAX_MCACHE_LEN) ) { fprintf(stderr, "Buffer size " "must be within [%ld-%ld] bytes\n", (long)MIN_MCACHE_LEN, (long)MAX_MCACHE_LEN ); rc = ERR_PARAM; } break; case 'n': g_uopt.nice_incr = atoi( optarg ); if( 0 == g_uopt.nice_incr ) { (void) fprintf( stderr, "Invalid nice-value increment: [%s]\n", optarg ); rc = ERR_PARAM; break; } break; case 'R': g_uopt.rbuf_msgs = atoi( optarg ); if( (g_uopt.rbuf_msgs <= 0) && (-1 != g_uopt.rbuf_msgs) ) { (void) fprintf( stderr, "Invalid Rmsgs size: [%s]\n", optarg ); rc = ERR_PARAM; break; } break; case 'H': g_uopt.dhold_tmout = (time_t)atoi( optarg ); if( (0 == g_uopt.dhold_tmout) || ((g_uopt.dhold_tmout) < 0 && (-1 != g_uopt.dhold_tmout)) ) { (void) fprintf( stderr, "Invalid value for max time " "to hold buffered data: [%s]\n", optarg ); rc = ERR_PARAM; break; } break; #ifdef UDPXY_FILEIO case 'r': if( 0 != access(optarg, R_OK) ) { perror("source file - access"); rc = ERR_PARAM; break; } g_uopt.srcfile = strdup( optarg ); break; case 'w': g_uopt.dstfile = strdup( optarg ); break; #endif /* UDPXY_FILEIO */ case 'M': g_uopt.mcast_refresh = (u_short)atoi( optarg ); MIN_MCAST_REFRESH = 30; MAX_MCAST_REFRESH = 64000; if( g_uopt.mcast_refresh && (g_uopt.mcast_refresh < MIN_MCAST_REFRESH || g_uopt.mcast_refresh > MAX_MCAST_REFRESH )) { (void) fprintf( stderr, "Invalid multicast refresh period [%d] seconds, " "min=[%d] sec, max=[%d] sec\n", (int)g_uopt.mcast_refresh, (int)MIN_MCAST_REFRESH, (int)MAX_MCAST_REFRESH ); rc = ERR_PARAM; break; } break; case ':': (void) fprintf( stderr, "Option [-%c] requires an argument\n", optopt ); rc = ERR_PARAM; break; case '?': (void) fprintf( stderr, "Unrecognized option: [-%c]\n", optopt ); rc = ERR_PARAM; break; default: usage( argv[0], stderr ); rc = ERR_PARAM; break; } } /* while getopt */ if (rc) { free_uopt( &g_uopt ); return rc; } openlog( g_udpxy_app, LOG_CONS | LOG_PID, LOG_LOCAL0 ); do { if( (argc < 2) || (port <= 0) || (rc != 0) ) { usage( argv[0], stderr ); rc = ERR_PARAM; break; } if( '\0' == mcast_addr[0] ) { (void) strncpy( mcast_addr, IPv4_ALL, sizeof(mcast_addr) - 1 ); } if( !custom_log ) { /* in debug mode output goes to stderr, otherwise to /dev/null */ g_flog = ((uf_TRUE == g_uopt.is_verbose) ? stderr : fopen( "/dev/null", "a" )); if( NULL == g_flog ) { perror("fopen"); rc = ERR_INTERNAL; break; } } if( 0 == geteuid() ) { if( !no_daemon ) { if( stderr == g_flog ) { (void) fprintf( stderr, "Logfile must be specified to run " "in verbose mode in background\n" ); rc = ERR_PARAM; break; } if( 0 != (rc = daemonize(0, g_flog)) ) { rc = ERR_INTERNAL; break; } } rc = set_pidfile( g_udpxy_app, port, pidfile, sizeof(pidfile) ); if( 0 != rc ) { mperror( g_flog, errno, "set_pidfile" ); rc = ERR_INTERNAL; break; } if( 0 != (rc = make_pidfile( pidfile, getpid(), g_flog )) ) break; } qact.sa_handler = handle_quitsigs; sigemptyset(&qact.sa_mask); qact.sa_flags = 0; if( (sigaction(SIGTERM, &qact, &oldact) < 0) || (sigaction(SIGQUIT, &qact, &oldact) < 0) || (sigaction(SIGINT, &qact, &oldact) < 0)) { perror("sigaction-quit"); rc = ERR_INTERNAL; break; } iact.sa_handler = SIG_IGN; sigemptyset(&iact.sa_mask); iact.sa_flags = 0; if( (sigaction(SIGPIPE, &iact, &oldact) < 0) ) { perror("sigaction-ignore"); rc = ERR_INTERNAL; break; } cact.sa_handler = handle_sigchld; sigemptyset(&cact.sa_mask); cact.sa_flags = 0; if( sigaction(SIGCHLD, &cact, &oldact) < 0 ) { perror("sigaction-sigchld"); rc = ERR_INTERNAL; break; } syslog( LOG_NOTICE, "%s is starting\n", g_udpxy_finfo ); TRACE( printcmdln( g_flog, g_udpxy_finfo, argc, argv ) ); rc = srv_loop( ipaddr, port, mcast_addr ); syslog( LOG_NOTICE, "%s is exiting with rc=[%d]\n", g_udpxy_finfo, rc); TRACE( tmfprintf( g_flog, "%s is exiting with rc=[%d]\n", g_udpxy_app, rc ) ); TRACE( printcmdln( g_flog, g_udpxy_finfo, argc, argv ) ); } while(0); if( '\0' != pidfile[0] ) { if( -1 == unlink(pidfile) ) { mperror( g_flog, errno, "unlink [%s]", pidfile ); } } if( g_flog && (stderr != g_flog) ) { (void) fclose(g_flog); } closelog(); free_uopt( &g_uopt ); return rc; }
void daemonize_start(void) { if (pidfile) { make_pidfile(); } }
int main(void) { pid_t pid, sid; /* process ID and Session ID */ /* Fork off the parent process */ pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } /* exit the parent process. */ if (pid > 0) { exit(EXIT_SUCCESS); } /* Open any logs here */ /* Create a new SID for the child process */ sid = setsid(); if (sid < 0) { /* Log the failure */ exit(EXIT_FAILURE); } /* Change the current working directory */ if ((chdir("/")) < 0) { /* Log the failure */ exit(EXIT_FAILURE); } /* Close out the standard file descriptors */ close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); /* reopen them pointing to /dev/null */ fd0 = open ("/dev/null", (O_RDONLY | O_NOCTTY | O_NOFOLLOW)); fd1 = open ("/dev/null", (O_WRONLY | O_NOCTTY | O_NOFOLLOW)); fd2 = open ("/dev/null", (O_WRONLY | O_NOCTTY | O_NOFOLLOW)); if (fd0 != 0 || fd1 != 1 || fd2 != 2 ) { /* Log the failure */ exit(EXIT_FAILURE); } /* change user id */ if (setuid(UID) != 0) { /* Log the failure */ exit(EXIT_FAILURE); } /* change group id */ if (setgid(GID) != 0) { /* Log the failure */ exit(EXIT_FAILURE); } /* make PID file */ make_pidfile(PIDFILE); /* Change the file mode mask */ umask(0); /* invoke signal handler */ sa.sa_handler = handle_sighup; sa.sa_flags = 0; if (sigaction(SIGHUP,&sa,NULL)) { /* Log the failure */ exit(EXIT_FAILURE); } sa.sa_handler = handle_sigquit; sa.sa_flags = 0; if (sigaction(SIGQUIT,&sa,NULL)) { /* Log the failure */ exit(EXIT_FAILURE); } /* Daemon-specific initialization goes here */ /* The Big Loop */ while (1) { /* Do some task here ... */ sleep(30); /* wait 30 seconds */ } exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { int ret = EX_OK; primwatch_t primwatch; const char *log_type; const char *log_facility; const char *log_prefix; char log_path[MAXPATHLEN]; const char *pid_file_path; const char *cntrl_addr; const char *cntrl_port; int64_t verbose_level; if (logger_create()) { fprintf(stderr, "failed in create logger"); ret = EX_OSERR; } if (primwatch_initialize(&primwatch)) { fprintf(stderr, "failed in initaizliae"); ret = EX_OSERR; goto last; } parse_args(&primwatch, argc, argv); if (logger_set_foreground(primwatch.foreground)) { fprintf(stderr, "failed in create logger"); ret = EX_OSERR; } if (config_manager_load(primwatch.config_manager, primwatch.config_file)) { LOG(LOG_LV_ERR, "failed in load config file %s", primwatch.config_file); ret = EX_DATAERR; goto last; } if (config_manager_get_string(primwatch.config_manager, &log_type , "logType", NULL)) { LOG(LOG_LV_ERR, "failed in get log type from config"); ret = EX_DATAERR; goto last; } if (config_manager_get_string(primwatch.config_manager, &log_facility , "logFacility", NULL)) { LOG(LOG_LV_ERR, "failed in get log facility from config"); ret = EX_DATAERR; goto last; } if (config_manager_get_string(primwatch.config_manager, &log_prefix , "logPath", NULL)) { LOG(LOG_LV_ERR, "failed in get log path from config"); ret = EX_DATAERR; goto last; } if (config_manager_get_string(primwatch.config_manager, &pid_file_path , "pidFilePath", NULL)) { LOG(LOG_LV_ERR, "failed in get pid file path from config"); ret = EX_DATAERR; goto last; } if (config_manager_get_string(primwatch.config_manager, &cntrl_addr , "controllerAddress", NULL)) { LOG(LOG_LV_ERR, "failed in get controller address from config"); ret = EX_DATAERR; goto last; } if (config_manager_get_string(primwatch.config_manager, &cntrl_port , "controllerPort", NULL)) { LOG(LOG_LV_ERR, "failed in get controller port from config"); ret = EX_DATAERR; goto last; } if (config_manager_get_long(primwatch.config_manager, &verbose_level , "verboseLevel", NULL)) { LOG(LOG_LV_ERR, "failed in get verbose level from config"); ret = EX_DATAERR; goto last; } snprintf(log_path, sizeof(log_path), "%s.daemon", log_prefix); if (logger_open((log_level_t)verbose_level, log_type, PROGIDENT, LOG_PID, log_facility, log_path)) { LOG(LOG_LV_ERR, "failed in open log"); ret = EX_OSERR; goto last; } if (!primwatch.foreground) { if (daemon(1,1)) { LOG(LOG_LV_ERR, "failed in daemon"); ret = EX_OSERR; goto last; } setsid(); } if (primwatch_event_initialize(&primwatch)) { fprintf(stderr, "failed in initaizliae"); ret = EX_OSERR; goto last; } if (make_pidfile(pid_file_path)) { LOG(LOG_LV_ERR, "failed in create file of process id"); ret = EX_OSERR; goto last; } if (watcher_polling_start(primwatch.watcher)) { LOG(LOG_LV_ERR, "failed in initial polling"); ret = EX_OSERR; goto last; } if (controller_start(primwatch.controller, cntrl_addr, cntrl_port)) { LOG(LOG_LV_ERR, "failed in start controller"); ret = EX_OSERR; goto last; } signal_set(&primwatch.sig_int_event, SIGINT, primwatch_terminate, &primwatch); event_priority_set(&primwatch.sig_int_event, DEFAULT_EVENT_PRIORITY + 30); event_base_set(primwatch.event_base, &primwatch.sig_int_event); signal_add(&primwatch.sig_int_event, NULL); signal_set(&primwatch.sig_term_event, SIGTERM, primwatch_terminate, &primwatch); event_priority_set(&primwatch.sig_term_event, DEFAULT_EVENT_PRIORITY + 30); event_base_set(primwatch.event_base, &primwatch.sig_term_event); signal_add(&primwatch.sig_term_event, NULL); signal_set(&primwatch.sig_hup_event, SIGHUP, primwatch_reload, &primwatch); event_priority_set(&primwatch.sig_hup_event, DEFAULT_EVENT_PRIORITY + 30); event_base_set(primwatch.event_base, &primwatch.sig_hup_event); signal_add(&primwatch.sig_hup_event, NULL); signal_set(&primwatch.sig_chld_event, SIGCHLD, primwatch_sigchild, &primwatch); event_priority_set(&primwatch.sig_chld_event, DEFAULT_EVENT_PRIORITY + 30); event_base_set(primwatch.event_base, &primwatch.sig_chld_event); signal_add(&primwatch.sig_chld_event, NULL); if (event_base_dispatch(primwatch.event_base) == -1) { LOG(LOG_LV_ERR, "failed in event base dispatch"); ret = EX_OSERR; goto last; } last: unlink(pid_file_path); logger_close(); logger_destroy(); primwatch_finalize(&primwatch); return ret; }
int main(int argc, char *argv[]) { int i; int err; err = sel_alloc_selector(&ser2net_sel); if (err) { fprintf(stderr, "Could not initialize ser2net selector: '%s'\n", strerror(err)); return -1; } for (i=1; i<argc; i++) { if ((argv[i][0] != '-') || (strlen(argv[i]) != 2)) { fprintf(stderr, "Invalid argument: '%s'\n", argv[i]); arg_error(argv[0]); } switch (argv[i][1]) { case 'n': detach = 0; break; case 'd': detach = 0; debug = 1; break; case 'b': cisco_ios_baud_rates = 1; break; case 'C': /* Get a config line. */ i++; if (i == argc) { fprintf(stderr, "No config line specified with -C\n"); arg_error(argv[0]); } handle_config_line(argv[i]); config_file = NULL; break; case 'c': /* Get a config file. */ i++; if (i == argc) { fprintf(stderr, "No config file specified with -c\n"); arg_error(argv[0]); } config_file = argv[i]; break; case 'p': /* Get the control port. */ i++; if (i == argc) { fprintf(stderr, "No control port specified with -p\n"); arg_error(argv[0]); } config_port = argv[i]; break; case 'P': i++; if (i == argc) { fprintf(stderr, "No pid file specified with -P\n"); arg_error(argv[0]); } pid_file = argv[i]; break; #ifdef USE_UUCP_LOCKING case 'u': uucp_locking_enabled = 0; break; #endif case 'v': printf("%s version %s\n", argv[0], VERSION); exit(0); default: fprintf(stderr, "Invalid option: '%s'\n", argv[i]); arg_error(argv[0]); } } setup_sighup(); if (config_port != NULL) { if (controller_init(config_port) == -1) { fprintf(stderr, "Invalid control port specified with -p\n"); arg_error(argv[0]); } } if (debug && !detach) openlog("ser2net", LOG_PID | LOG_CONS | LOG_PERROR, LOG_DAEMON); if (config_file) { if (readconfig(config_file) == -1) { return 1; } } if (detach) { int pid; /* Detach from the calling terminal. */ openlog("ser2net", LOG_PID | LOG_CONS, LOG_DAEMON); syslog(LOG_NOTICE, "ser2net startup"); if ((pid = fork()) > 0) { exit(0); } else if (pid < 0) { syslog(LOG_ERR, "Error forking first fork"); exit(1); } else { /* setsid() is necessary if we really want to demonize */ setsid(); /* Second fork to really deamonize me. */ if ((pid = fork()) > 0) { exit(0); } else if (pid < 0) { syslog(LOG_ERR, "Error forking second fork"); exit(1); } } /* Close all my standard I/O. */ chdir("/"); close(0); close(1); close(2); } /* write pid file */ make_pidfile(pid_file); /* Ignore SIGPIPEs so they don't kill us. */ signal(SIGPIPE, SIG_IGN); set_sighup_handler(reread_config); sel_select_loop(ser2net_sel); return 0; }