static int main_unix(int argc, char* argv[]) { #if !defined(__vms) && !defined(USE_OS2) int fd; fd=open("/dev/null", O_RDWR); /* open /dev/null before chroot */ if(fd<0) fatal("Could not open /dev/null"); #endif /* standard Unix */ main_initialize(); if(main_configure(argc>1 ? argv[1] : NULL, argc>2 ? argv[2] : NULL)) return 1; if(service_options.next) { /* there are service sections -> daemon mode */ #if !defined(__vms) && !defined(USE_OS2) if(daemonize(fd)) return 1; close(fd); /* create_pid() must be called after drop_privileges() * or it won't be possible to remove the file on exit */ /* create_pid() must be called after daemonize() * since the final pid is not known beforehand */ if(create_pid()) return 1; #endif /* standard Unix */ signal(SIGCHLD, signal_handler); /* handle dead children */ signal(SIGHUP, signal_handler); /* configuration reload */ signal(SIGUSR1, signal_handler); /* log reopen */ signal(SIGPIPE, SIG_IGN); /* ignore broken pipe */ if(signal(SIGTERM, SIG_IGN)!=SIG_IGN) signal(SIGTERM, signal_handler); /* fatal */ if(signal(SIGQUIT, SIG_IGN)!=SIG_IGN) signal(SIGQUIT, signal_handler); /* fatal */ if(signal(SIGINT, SIG_IGN)!=SIG_IGN) signal(SIGINT, signal_handler); /* fatal */ daemon_loop(); } else { /* inetd mode */ #if !defined(__vms) && !defined(USE_OS2) close(fd); #endif /* standard Unix */ signal(SIGCHLD, SIG_IGN); /* ignore dead children */ signal(SIGPIPE, SIG_IGN); /* ignore broken pipe */ client_main(alloc_client_session(&service_options, 0, 1)); } return 0; }
NOEXPORT int main_unix(int argc, char* argv[]) { int configure_status; #if !defined(__vms) && !defined(USE_OS2) int fd; fd=open("/dev/null", O_RDWR); /* open /dev/null before chroot */ if(fd==INVALID_SOCKET) fatal("Could not open /dev/null"); #endif #ifdef WOLFSSL_DEBUG_ON wolfSSL_Debugging_ON(); wolfSSL_SetLoggingCb((wolfSSL_Logging_cb)&wolfSSL_s_log); #endif main_init(); configure_status=main_configure(argc>1 ? argv[1] : NULL, argc>2 ? argv[2] : NULL); switch(configure_status) { case 1: /* error -> exit with 1 to indicate error */ close(fd); return 1; case 2: /* information printed -> exit with 0 to indicate success */ close(fd); return 0; } if(service_options.next) { /* there are service sections -> daemon mode */ #if !defined(__vms) && !defined(USE_OS2) if(daemonize(fd)) { close(fd); return 1; } close(fd); /* create_pid() must be called after drop_privileges() * or it won't be possible to remove the file on exit */ /* create_pid() must be called after daemonize() * since the final pid is not known beforehand */ if(create_pid()) return 1; #endif #ifndef USE_OS2 signal(SIGCHLD, signal_handler); /* handle dead children */ signal(SIGHUP, signal_handler); /* configuration reload */ signal(SIGUSR1, signal_handler); /* log reopen */ signal(SIGPIPE, SIG_IGN); /* ignore broken pipe */ if(signal(SIGTERM, SIG_IGN)!=SIG_IGN) signal(SIGTERM, signal_handler); /* fatal */ if(signal(SIGQUIT, SIG_IGN)!=SIG_IGN) signal(SIGQUIT, signal_handler); /* fatal */ if(signal(SIGINT, SIG_IGN)!=SIG_IGN) signal(SIGINT, signal_handler); /* fatal */ #endif daemon_loop(); } else { /* inetd mode */ #if !defined(__vms) && !defined(USE_OS2) close(fd); #endif /* standard Unix */ #ifndef USE_OS2 signal(SIGCHLD, SIG_IGN); /* ignore dead children */ signal(SIGPIPE, SIG_IGN); /* ignore broken pipe */ #endif set_nonblock(0, 1); /* stdin */ set_nonblock(1, 1); /* stdout */ client_main(alloc_client_session(&service_options, 0, 1)); } return 0; }
static void daemon_loop(void) { SOCKADDR_UNION addr; s_poll_set fds; LOCAL_OPTIONS *opt; get_limits(); s_poll_zero(&fds); #ifndef USE_WIN32 s_poll_add(&fds, signal_pipe_init(), 1, 0); #endif if(!local_options.next) { s_log(LOG_ERR, "No connections defined in config file"); exit(1); } num_clients=0; /* bind local ports */ for(opt=local_options.next; opt; opt=opt->next) { if(!opt->option.accept) /* no need to bind this service */ continue; memcpy(&addr, &opt->local_addr.addr[0], sizeof(SOCKADDR_UNION)); if((opt->fd=socket(addr.sa.sa_family, SOCK_STREAM, 0))<0) { sockerror("local socket"); exit(1); } if(alloc_fd(opt->fd)) exit(1); if(set_socket_options(opt->fd, 0)<0) exit(1); s_ntop(opt->local_address, &addr); if(bind(opt->fd, &addr.sa, addr_len(addr))) { s_log(LOG_ERR, "Error binding %s to %s", opt->servname, opt->local_address); sockerror("bind"); exit(1); } s_log(LOG_DEBUG, "%s bound to %s", opt->servname, opt->local_address); if(listen(opt->fd, 5)) { sockerror("listen"); exit(1); } #ifdef FD_CLOEXEC fcntl(opt->fd, F_SETFD, FD_CLOEXEC); /* close socket in child execvp */ #endif s_poll_add(&fds, opt->fd, 1, 0); } #if !defined (USE_WIN32) && !defined (__vms) if(!(options.option.foreground)) daemonize(); drop_privileges(); create_pid(); #endif /* !defined USE_WIN32 && !defined (__vms) */ /* create exec+connect services */ for(opt=local_options.next; opt; opt=opt->next) { if(opt->option.accept) /* skip ordinary (accepting) services */ continue; enter_critical_section(CRIT_CLIENTS); /* for multi-cpu machines */ num_clients++; leave_critical_section(CRIT_CLIENTS); create_client(-1, -1, alloc_client_session(opt, -1, -1), client); } while(1) { if(s_poll_wait(&fds, -1)<0) /* non-critical error */ log_error(LOG_INFO, get_last_socket_error(), "daemon_loop: s_poll_wait"); else for(opt=local_options.next; opt; opt=opt->next) if(s_poll_canread(&fds, opt->fd)) accept_connection(opt); } s_log(LOG_ERR, "INTERNAL ERROR: End of infinite loop 8-)"); }