int main(int argc, char *argv[]) { ERR("power-manager start"); int c; int runflags = 0; /* run as daemon */ unsigned int flags = 0x0; /* 0 : start with noti */ while (1) { int option_index = 0; static struct option long_options[] = { {"foreground", no_argument, NULL, 'f'}, {"direct", no_argument, NULL, 'd'}, {"xdpms", no_argument, NULL, 'x'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "fdx", long_options, &option_index); if (c == -1) break; switch (c) { case 'f': runflags = 1; break; case 'd': flags = flags | WITHOUT_STARTNOTI; /* 0x1 : start without noti */ break; case 'x': flags = flags | FLAG_X_DPMS; /* 0x2 : X control LCD onoff */ break; default: usage(); break; } } if (optind < argc) usage(); if (access(DEFAULT_PID_PATH, F_OK) == 0) { /* pid file exist */ printf ("Check the PM is running. If it isn't, delete \"%s\" and retry.\n", DEFAULT_PID_PATH); return -1; } if (!runflags) daemonize(); writepid(DEFAULT_PID_PATH); /* this function is main loop, defined in pm_core.c */ start_main(flags); unlink(DEFAULT_PID_PATH); return 0; }
/* return 0 as parent, 1 as child */ static int godaemon(void) { uid_t nobody, nogrp; struct passwd *pw; switch (fork()) { case -1: bb_perror_msg_and_die("Could not fork"); case 0: pw = getpwnam(nobodystr); if (pw == NULL) bb_error_msg_and_die("Cannot find uid/gid of user '%s'", nobodystr); nobody = pw->pw_uid; nogrp = pw->pw_gid; writepid(nobody, nogrp); close(0); inetbind(); xsetgid(nogrp); xsetuid(nobody); close(1); close(2); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); /* connection closed when writing (raises ???) */ setsid(); openlog(bb_applet_name, 0, LOG_DAEMON); return 1; } return 0; }
pid_t daemonise(void) { #ifdef THERE_IS_NO_FORK return -1; #else pid_t pid; char buf = '\0'; int sidpipe[2], fd; eloop_timeout_delete(handle_exit_timeout, NULL); if (options & DHCPCD_DAEMONISED || !(options & DHCPCD_DAEMONISE)) return 0; /* Setup a signal pipe so parent knows when to exit. */ if (pipe(sidpipe) == -1) { syslog(LOG_ERR, "pipe: %m"); return -1; } syslog(LOG_DEBUG, "forking to background"); switch (pid = fork()) { case -1: syslog(LOG_ERR, "fork: %m"); exit(EXIT_FAILURE); /* NOTREACHED */ case 0: setsid(); /* Notify parent it's safe to exit as we've detached. */ close(sidpipe[0]); if (write(sidpipe[1], &buf, 1) == -1) syslog(LOG_ERR, "failed to notify parent: %m"); close(sidpipe[1]); if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); close(fd); } break; default: /* Wait for child to detach */ close(sidpipe[1]); if (read(sidpipe[0], &buf, 1) == -1) syslog(LOG_ERR, "failed to read child: %m"); close(sidpipe[0]); break; } /* Done with the fd now */ if (pid != 0) { syslog(LOG_INFO, "forked to background, child pid %d",pid); writepid(pidfd, pid); close(pidfd); pidfd = -1; options |= DHCPCD_FORKED; exit(EXIT_SUCCESS); } options |= DHCPCD_DAEMONISED; return pid; #endif }
static void start_console(int master_fd, int aux_fd, char **argv) { int file; syslog(LOG_DEBUG, "Starting console"); /* Create console log file owned by daemon */ if (access(consolelog, F_OK) != 0) { file = open(consolelog, O_CREAT, 0644); close(file); } chown(consolelog, DAEMON, 0); console_running = RUNNING; switch (fork_and_store(&consolepid)) { case 0: /* Close all file descriptors except stdout/stderr */ close(0); max_fd = sysconf(_SC_OPEN_MAX); for (file = 3; file < max_fd; file++) if (file != master_fd && file != aux_fd) close(file); setsid(); dup2(master_fd, 0); close(master_fd); if (aux_fd != 3) { dup2(aux_fd, 3); close(aux_fd); } setgid(DAEMON); setuid(DAEMON); (void) sigprocmask(SIG_SETMASK, &sig_zero, (sigset_t *) 0); execv(argv[0], argv); fprintf(stderr, "dm: Failed to exec console: %s\n", strerror(errno)); _exit(1); case -1: fprintf(stderr, "dm: Unable to fork to start console: %s\n", strerror(errno)); _exit(1); default: writepid(consolepidf, consolepid); } }
/** This is implemented separately from finishpidfile() to allow errors to be * reported to stderr before we fork off a daemon process. * * @return Success (which is trivially achieved if no pidfile is requested) */ static bool startpidfile(void) { assert(pidfd == -1); if (!make_pidfile) return true; pidfd = open(pidfile, O_WRONLY|O_CREAT|O_EXCL, O_WRONLY); if (unlikely(pidfd == -1)) { if (errno == EEXIST) logm(LOG_ERR, "Daemon already running, or leftover pidfile: '%s'", pidfile); else log_perr_str(LOG_ERR, "Could not create pidfile", pidfile, errno); return false; } have_pidfile = true; // Write temporary process id to pidfile; have to do this again if we fork() return writepid(getpid()); }
static int make_ipc(void) { int err; err = mkdir(RUNDIR, S_IRWXU|S_IRWXG); if (err < 0 && errno != EEXIST) { perror(RUNDIR); return -1; } /* * check and write pidfile */ if (err < 0 && errno == EEXIST ) { pid_t pid = running(); if (pid >= 0) { fprintf(stderr, "Already running: PID %u\n", pid); return -1; } } err = writepid(); if (err < 0) return -1; /* * signal handlers */ signal(SIGUSR1, increment_droppage); signal(SIGUSR2, decrement_droppage); signal(SIGCHLD, allow_all_packets); signal(SIGALRM, disable_all_packets); signal(SIGILL, reset_packet_count); signal(SIGFPE, percent_droppage_mode); signal(SIGURG, packet_droppage_mode); signal(SIGPROF, dump_settings); return 0; }
int rundaemon(char *argv[], char *pidpath) { return writepid(run_async(argv), pidpath); }
int main(int argc, char *argv[]) { SVCXPRT *utransp, *ttransp; struct sockaddr_in addr; DIR *dp; struct direct *d; ni_name tag = NULL; ni_namelist nl; ni_index i; int pid, localonly, nctoken = -1; int log_pri = LOG_NOTICE; struct rlimit rlim; char *netinfod_argv[16]; /* XXX */ int netinfod_argc, x; union wait wait_stat; pid_t child_pid; char *pri; #ifdef _UNIX_BSD_43_ int ttyfd; #endif localonly = 1; netinfod_argc = 0; netinfod_argv[netinfod_argc++] = (char *)NETINFO_PROG; debug = 0; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-n")) { netinfod_argv[netinfod_argc++] = argv[i]; } if (!strcmp(argv[i], "-d")) { debug = 1; log_pri = LOG_DEBUG; if ((argc > (i+1)) && (argv[i+1][0] != '-')) debug = atoi(argv[++i]); } if (!strcmp(argv[i], "-l")) { if ((argc > (i+1)) && (argv[i+1][0] != '-')) log_pri = atoi(argv[++i]); } if (!strcmp(argv[i], "-D")) { netinfod_argv[netinfod_argc++] = "-d"; if ((argc > (i+1)) && (argv[i+1][0] != '-')) { netinfod_argv[netinfod_argc++] = argv[i]; } } if (!strcmp(argv[i], "-L")) { netinfod_argv[netinfod_argc++] = "-l"; if ((argc > (i+1)) && (argv[i+1][0] != '-')) { netinfod_argv[netinfod_argc++] = argv[i]; } else { pri = malloc(sizeof("999")); sprintf(pri, "%d", LOG_DEBUG); netinfod_argv[netinfod_argc++] = pri; } } } if (debug == 1) { system_log_open("nibindd", LOG_NDELAY | LOG_PID, LOG_NETINFO, stderr); system_log_set_max_priority(log_pri); system_log(LOG_DEBUG, "version %s - debug mode\n", _PROJECT_VERSION_); } else { closeall(); system_log_open("nibindd", LOG_NDELAY | LOG_PID, LOG_NETINFO, NULL); system_log_set_max_priority(log_pri); system_log(LOG_DEBUG, "version %s - starting\n", _PROJECT_VERSION_); child_pid = fork(); if (child_pid == -1) { system_log(LOG_ALERT, "fork() failed: %m, aborting"); system_log_close(); exit(1); } else if (child_pid > 0) { signal(SIGTERM, parentexit); system_log(LOG_DEBUG, "parent waiting for child to start"); wait4(child_pid, (_WAIT_TYPE_ *)&wait_stat, 0, 0); if (WIFEXITED(wait_stat)) { system_log(LOG_DEBUG, "unexpected child exit, status=%d", WEXITSTATUS(wait_stat)); } else { system_log(LOG_DEBUG, "unexpected child exit, received signal=%d", WTERMSIG(wait_stat)); } system_log_close(); exit(1); } } restart = 0; rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &rlim); signal(SIGCHLD, catchchild); signal(SIGTERM, killchildren); signal(SIGHUP, catchhup); signal(SIGINT, SIG_IGN); notify_register_signal(NETWORK_CHANGE_NOTIFICATION, SIGHUP, &nctoken); writepid(); /* * cd to netinfo directory, find out which databases should * be served and lock the directory before registering service. */ if (chdir(NETINFO_DIR) < 0) { killparent(); system_log(LOG_ALERT, "cannot chdir to netinfo directory"); exit(1); } dp = opendir(NETINFO_DIR); if (dp == NULL) { killparent(); system_log(LOG_ALERT, "cannot open netinfo directory"); exit(1); } MM_ZERO(&nl); while ((d = readdir(dp))) { if (isnidir(d->d_name, &tag)) { if (ni_namelist_match(nl, tag) == NI_INDEX_NULL) { system_log(LOG_DEBUG, "found database: %s", tag); ni_namelist_insert(&nl, tag, NI_INDEX_NULL); if (strcmp(tag, "local")) localonly = 0; } ni_name_free(&tag); } } #ifdef _NETINFO_FLOCK_ /* * Do not close the directory: keep it locked so another nibindd * won't run. */ if (flock(dp->dd_fd, LOCK_EX|LOCK_NB) < 0) { killparent(); system_log(LOG_ALERT, "nibindd already running"); exit(1); } fcntl(dp->dd_fd, F_SETFD, 1); #else closedir(dp); #endif /* * Register as a SUNRPC service */ memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; if (localonly == 1) addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); pmap_unset(NIBIND_PROG, NIBIND_VERS); utransp = svcudp_bind(RPC_ANYSOCK, addr); if (utransp == NULL) { killparent(); system_log(LOG_ALERT, "cannot start udp service"); exit(1); } if (!svc_register(utransp, NIBIND_PROG, NIBIND_VERS, nibind_prog_1, IPPROTO_UDP)) { killparent(); system_log(LOG_ALERT, "cannot register udp service"); exit(1); } udp_sock = utransp->xp_sock; ttransp = svctcp_bind(RPC_ANYSOCK, addr, 0, 0); if (ttransp == NULL) { killparent(); system_log(LOG_ALERT, "cannot start tcp service"); exit(1); } if (!svc_register(ttransp, NIBIND_PROG, NIBIND_VERS, nibind_prog_1, IPPROTO_TCP)) { killparent(); system_log(LOG_ALERT, "cannot register tcp service"); exit(1); } waitreg = 0; for (i = 0; i < nl.ninl_len; i++) { netinfod_argv[netinfod_argc] = nl.ninl_val[i]; netinfod_argv[netinfod_argc + 1] = NULL; system_log(LOG_DEBUG, "starting netinfod %s", nl.ninl_val[i]); system_log(LOG_DEBUG, "execv debug 0: %s", NETINFO_PROG); for (x = 0; netinfod_argv[x] != NULL; x++) { system_log(LOG_DEBUG, "execv debug %d: %s", x, netinfod_argv[x]); } pid = fork(); if (pid == 0) { /* child */ execv(NETINFO_PROG, netinfod_argv); exit(-1); } #ifdef DEBUG system_log(LOG_DEBUG, "netinfod %s pid = %d", nl.ninl_val[i], pid); #endif if (pid > 0) { waitreg++; storepid(pid, nl.ninl_val[i]); } else { system_log(LOG_ERR, "server for tag %s failed to start", nl.ninl_val[i]); } } ni_namelist_free(&nl); /* * Detach from controlling tty. * Do this AFTER starting netinfod so "type c to continue..." works. */ #ifdef _UNIX_BSD_43_ ttyfd = open("/dev/tty", O_RDWR, 0); if (ttyfd > 0) { ioctl(ttyfd, TIOCNOTTY, NULL); close(ttyfd); } setpgrp(0, getpid()); #else if (setsid() < 0) syslog(LOG_ERR, "nibindd: setsid() failed: %m"); #endif system_log(LOG_DEBUG, "starting RPC service"); nibind_svc_run(); system_log(LOG_ALERT, "svc_run returned"); system_log_close(); exit(1); }
int main(int argc, char *argv[]) { int set = 1; int status; int version = 0; int list_c; char ainfo_port_string[16]; struct addrinfo ai_req, *ai_ans, *cur_ans; int address_found; int new_connection_fd; pthread_t PollThd; config_handle *cha; config_entry *ret; char *pidfile=NULL; int nocheck=0; int c; static int help; static int short_help; int loop_interval=DEFAULT_LOOP_INTERVAL; while (1) { static struct option long_options[] = { {"help", no_argument, &help, 1}, {"usage", no_argument, &short_help, 1}, {"nocheck", no_argument, 0, 'n'}, {"nodaemon", no_argument, 0, 'o'}, {"version", no_argument, 0, 'v'}, {"prefix", required_argument, 0, 'p'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long (argc, argv, "vnop:",long_options, &option_index); if (c == -1){ break; } switch (c) { case 0: if (long_options[option_index].flag != 0){ break; } case 'v': version=1; break; case 'n': nocheck=1; break; case 'o': nodmn=1; break; case 'p': break; case '?': break; default: abort (); } } if(help){ usage(); } if(short_help){ short_usage(); } argv0 = argv[0]; /*Ignore sigpipe*/ signal(SIGPIPE, SIG_IGN); signal(SIGHUP,sighup); if(version) { printf("%s Version: %s\n",progname,VERSION); exit(EXIT_SUCCESS); } /* Checking configuration */ if(!nocheck){ check_config_file("NOTIFIER"); } /* Reading configuration */ cha = config_read(NULL); if (cha == NULL) { fprintf(stderr,"Error reading config: "); perror(""); exit(EXIT_FAILURE); } config_setenv(NULL); ret = config_get("bnotifier_debug_level",cha); if (ret != NULL){ debug=atoi(ret->value); } ret = config_get("bnotifier_debug_logfile",cha); if (ret != NULL){ debuglogname=strdup(ret->value); if(debuglogname == NULL){ sysfatal("strdup failed for debuglogname in main: %r"); } } if(debug <=0){ debug=0; } if(debuglogname){ if((debuglogfile = fopen(debuglogname, "a+"))==0){ debug = 0; } }else{ debug = 0; } ret = config_get("job_registry",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key job_registry not found\n",argv0); sysfatal("job_registry not defined. Exiting"); } else { registry_file=strdup(ret->value); if(registry_file == NULL){ sysfatal("strdup failed for registry_file in main: %r"); } } ret = config_get("async_notification_port",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key async_notification_port not found\n",argv0); } else { async_notif_port =atoi(ret->value); } ret = config_get("bnotifier_loop_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key bnotifier_loop_interval not found using the default:%d\n",argv0,loop_interval); } else { loop_interval=atoi(ret->value); } ret = config_get("bnotifier_pidfile",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key bnotifier_pidfile not found\n",argv0); } else { pidfile=strdup(ret->value); if(pidfile == NULL){ sysfatal("strdup failed for pidfile in main: %r"); } } remupd_conf = config_get("job_registry_add_remote",cha); if (remupd_conf == NULL){ do_log(debuglogfile, debug, 1, "%s: key job_registry_add_remote not found\n",argv0); } /* create listening socket for Cream */ if ( !async_notif_port ) { sysfatal("Invalid port supplied for Cream: %r"); } ai_req.ai_flags = AI_PASSIVE; ai_req.ai_family = PF_UNSPEC; ai_req.ai_socktype = SOCK_STREAM; ai_req.ai_protocol = 0; /* Any stream protocol is OK */ sprintf(ainfo_port_string,"%5d",async_notif_port); if (getaddrinfo(NULL, ainfo_port_string, &ai_req, &ai_ans) != 0) { sysfatal("Error getting address of passive SOCK_STREAM socket: %r"); } address_found = 0; for (cur_ans = ai_ans; cur_ans != NULL; cur_ans = cur_ans->ai_next) { if ((list_c = socket(cur_ans->ai_family, cur_ans->ai_socktype, cur_ans->ai_protocol)) == -1) { continue; } if(setsockopt(list_c, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(set)) < 0) { close(list_c); syserror("setsockopt() failed: %r"); } if (bind(list_c,cur_ans->ai_addr, cur_ans->ai_addrlen) == 0) { address_found = 1; break; } close(list_c); } freeaddrinfo(ai_ans); if ( address_found == 0 ) { sysfatal("Error creating and binding socket: %r"); } if ( listen(list_c, LISTENQ) < 0 ) { sysfatal("Error calling listen() in main: %r"); } if( !nodmn ) daemonize(); if( pidfile ){ writepid(pidfile); free(pidfile); } config_free(cha); pthread_create(&PollThd, NULL, (void *(*)(void *))PollDB, (void *)NULL); for ( ;; ) { /* FIXME: exit condition??? */ do_log(debuglogfile, debug, 1, "Listening for new connection\n"); if ( (new_connection_fd = accept(list_c, NULL, NULL) ) < 0 ) { do_log(debuglogfile, debug, 1, "Fatal Error:Error calling accept() on list_c\n"); sysfatal("Error calling accept(): %r"); } if (add_cream_connection(new_connection_fd) != 0) { do_log(debuglogfile, debug, 1, "connection table full: unable to add the new connection\n"); close(new_connection_fd); } } pthread_join(PollThd, (void **)&status); pthread_exit(NULL); }
int main(int argc, char **argv) { options_t *options; int userclasses = 0; int opt; int option_index = 0; char *prefix; pid_t pid; int debug = 0; int i; int pidfd = -1; int sig = 0; /* Close any un-needed fd's */ for (i = getdtablesize() - 1; i >= 3; --i) close (i); openlog (PACKAGE, LOG_PID, LOG_LOCAL0); options = xmalloc (sizeof (options_t)); memset (options, 0, sizeof (options_t)); options->script = (char *) DEFAULT_SCRIPT; snprintf (options->classid, CLASS_ID_MAX_LEN, "%s %s", PACKAGE, VERSION); options->classid_len = strlen (options->classid); options->doarp = true; options->dodns = true; options->domtu = true; options->donis = true; options->dontp = true; options->dogateway = true; options->daemonise = true; options->doinform = false; options->doipv4ll = true; options->timeout = DEFAULT_TIMEOUT; gethostname (options->hostname, sizeof (options->hostname)); if (strcmp (options->hostname, "(none)") == 0 || strcmp (options->hostname, "localhost") == 0) memset (options->hostname, 0, sizeof (options->hostname)); /* Don't set any optional arguments here so we retain POSIX * compatibility with getopt */ while ((opt = getopt_long(argc, argv, EXTRA_OPTS "c:dh:i:kl:m:npr:s:t:u:xAEF:GHI:LMNRTY", longopts, &option_index)) != -1) { switch (opt) { case 0: if (longopts[option_index].flag) break; logger (LOG_ERR, "option `%s' should set a flag", longopts[option_index].name); exit (EXIT_FAILURE); break; case 'c': options->script = optarg; break; case 'd': debug++; switch (debug) { case 1: setloglevel (LOG_DEBUG); break; case 2: options->daemonise = false; break; } break; #ifdef THERE_IS_NO_FORK case 'f': options->daemonised = true; close_fds (); break; case 'g': dhcpcd_skiproutes = xstrdup (optarg); break; #endif case 'h': if (! optarg) memset (options->hostname, 0, sizeof (options->hostname)); else if (strlen (optarg) > MAXHOSTNAMELEN) { logger (LOG_ERR, "`%s' too long for HostName string, max is %d", optarg, MAXHOSTNAMELEN); exit (EXIT_FAILURE); } else strlcpy (options->hostname, optarg, sizeof (options->hostname)); break; case 'i': if (! optarg) { memset (options->classid, 0, sizeof (options->classid)); options->classid_len = 0; } else if (strlen (optarg) > CLASS_ID_MAX_LEN) { logger (LOG_ERR, "`%s' too long for ClassID string, max is %d", optarg, CLASS_ID_MAX_LEN); exit (EXIT_FAILURE); } else options->classid_len = strlcpy (options->classid, optarg, sizeof (options->classid)); break; case 'k': sig = SIGHUP; break; case 'l': STRINGINT (optarg, options->leasetime); if (options->leasetime <= 0) { logger (LOG_ERR, "leasetime must be a positive value"); exit (EXIT_FAILURE); } break; case 'm': STRINGINT (optarg, options->metric); break; case 'n': sig = SIGALRM; break; case 'p': options->persistent = true; break; case 's': options->doinform = true; options->doarp = false; if (! optarg || strlen (optarg) == 0) { options->request_address.s_addr = 0; break; } else { char *slash = strchr (optarg, '/'); if (slash) { int cidr; /* nullify the slash, so the -r option can read the * address */ *slash++ = '\0'; if (sscanf (slash, "%d", &cidr) != 1 || inet_cidrtoaddr (cidr, &options->request_netmask) != 0) { logger (LOG_ERR, "`%s' is not a valid CIDR", slash); exit (EXIT_FAILURE); } } /* fall through */ } case 'r': if (! options->doinform) options->dorequest = true; if (strlen (optarg) > 0 && ! inet_aton (optarg, &options->request_address)) { logger (LOG_ERR, "`%s' is not a valid IP address", optarg); exit (EXIT_FAILURE); } break; case 't': STRINGINT (optarg, options->timeout); if (options->timeout < 0) { logger (LOG_ERR, "timeout must be a positive value"); exit (EXIT_FAILURE); } break; case 'u': { int offset = 0; for (i = 0; i < userclasses; i++) offset += (int) options->userclass[offset] + 1; if (offset + 1 + strlen (optarg) > USERCLASS_MAX_LEN) { logger (LOG_ERR, "userclass overrun, max is %d", USERCLASS_MAX_LEN); exit (EXIT_FAILURE); } userclasses++; memcpy (options->userclass + offset + 1 , optarg, strlen (optarg)); options->userclass[offset] = strlen (optarg); options->userclass_len += (strlen (optarg)) + 1; } break; case 'x': sig = SIGTERM; break; case 'A': #ifndef ENABLE_ARP logger (LOG_ERR, "arp support not compiled into dhcpcd"); exit (EXIT_FAILURE); #endif options->doarp = false; break; case 'E': #ifndef ENABLE_INFO logger (LOG_ERR, "info support not compiled into dhcpcd"); exit (EXIT_FAILURE); #endif options->dolastlease = true; break; case 'F': if (strncmp (optarg, "none", strlen (optarg)) == 0) options->fqdn = FQDN_NONE; else if (strncmp (optarg, "ptr", strlen (optarg)) == 0) options->fqdn = FQDN_PTR; else if (strncmp (optarg, "both", strlen (optarg)) == 0) options->fqdn = FQDN_BOTH; else { logger (LOG_ERR, "invalid value `%s' for FQDN", optarg); exit (EXIT_FAILURE); } break; case 'G': options->dogateway = false; break; case 'H': options->dohostname++; break; case 'I': if (optarg) { if (strlen (optarg) > CLIENT_ID_MAX_LEN) { logger (LOG_ERR, "`%s' is too long for ClientID, max is %d", optarg, CLIENT_ID_MAX_LEN); exit (EXIT_FAILURE); } options->clientid_len = strlcpy (options->clientid, optarg, sizeof (options->clientid)); /* empty string disabled duid */ if (options->clientid_len == 0) options->clientid_len = -1; } else { memset (options->clientid, 0, sizeof (options->clientid)); options->clientid_len = -1; } break; case 'L': options->doipv4ll = false; break; case 'M': options->domtu = false; break; case 'N': options->dontp = false; break; case 'R': options->dodns = false; break; case 'T': #ifndef ENABLE_INFO logger (LOG_ERR, "info support not compiled into dhcpcd"); exit (EXIT_FAILURE); #endif options->test = true; options->persistent = true; break; case 'Y': options->donis = false; break; case '?': usage (); exit (EXIT_FAILURE); default: usage (); exit (EXIT_FAILURE); } } if (doversion) { printf (""PACKAGE" "VERSION"\n"); printf ("Compile time options:" #ifdef ENABLE_ARP " ARP" #endif #ifdef ENABLE_DUID " DUID" #endif #ifdef ENABLE_INFO " INFO" #endif #ifdef ENABLE_INFO_COMPAT " INFO_COMPAT" #endif #ifdef ENABLE_IPV4LL " IPV4LL" #endif #ifdef ENABLE_NIS " NIS" #endif #ifdef ENABLE_NTP " NTP" #endif #ifdef THERE_IS_NO_FORK " THERE_IS_NO_FORK" #endif "\n"); } if (dohelp) usage (); #ifdef THERE_IS_NO_FORK dhcpcd_argv = argv; dhcpcd_argc = argc; /* We need the full path to the dhcpcd */ if (*argv[0] == '/') strlcpy (dhcpcd, argv[0], sizeof (dhcpcd)); else { char pwd[PATH_MAX]; if (! getcwd (pwd, PATH_MAX)) { logger (LOG_ERR, "getcwd: %s", strerror (errno)); exit (EXIT_FAILURE); } snprintf (dhcpcd, sizeof (dhcpcd), "%s/%s", pwd, argv[0]); } #endif if (optind < argc) { if (strlen (argv[optind]) > IF_NAMESIZE) { logger (LOG_ERR, "`%s' is too long for an interface name (max=%d)", argv[optind], IF_NAMESIZE); exit (EXIT_FAILURE); } strlcpy (options->interface, argv[optind], sizeof (options->interface)); } else { /* If only version was requested then exit now */ if (doversion || dohelp) exit (EXIT_SUCCESS); logger (LOG_ERR, "no interface specified"); exit (EXIT_FAILURE); } if (strchr (options->hostname, '.')) { if (options->fqdn == FQDN_DISABLE) options->fqdn = FQDN_BOTH; } else options->fqdn = FQDN_DISABLE; if (options->request_address.s_addr == 0 && options->doinform) { if ((options->request_address.s_addr = get_address (options->interface)) != 0) options->keep_address = true; } if (IN_LINKLOCAL (options->request_address.s_addr)) { logger (LOG_ERR, "you are not allowed to request a link local address"); exit (EXIT_FAILURE); } if (geteuid ()) { logger (LOG_ERR, "you need to be root to run "PACKAGE); exit (EXIT_FAILURE); } prefix = xmalloc (sizeof (char) * (IF_NAMESIZE + 3)); snprintf (prefix, IF_NAMESIZE, "%s: ", options->interface); setlogprefix (prefix); snprintf (options->pidfile, sizeof (options->pidfile), PIDFILE, options->interface); free (prefix); chdir ("/"); umask (022); if (mkdir (CONFIGDIR, S_IRUSR |S_IWUSR |S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) && errno != EEXIST ) { logger (LOG_ERR, "mkdir(\"%s\",0): %s\n", CONFIGDIR, strerror (errno)); exit (EXIT_FAILURE); } if (mkdir (ETCDIR, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) && errno != EEXIST ) { logger (LOG_ERR, "mkdir(\"%s\",0): %s\n", ETCDIR, strerror (errno)); exit (EXIT_FAILURE); } if (options->test) { if (options->dorequest || options->doinform) { logger (LOG_ERR, "cannot test with --inform or --request"); exit (EXIT_FAILURE); } if (options->dolastlease) { logger (LOG_ERR, "cannot test with --lastlease"); exit (EXIT_FAILURE); } if (sig != 0) { logger (LOG_ERR, "cannot test with --release or --renew"); exit (EXIT_FAILURE); } } if (sig != 0) { int killed = -1; pid = read_pid (options->pidfile); if (pid != 0) logger (LOG_INFO, "sending signal %d to pid %d", sig, pid); if (! pid || (killed = kill (pid, sig))) logger (sig == SIGALRM ? LOG_INFO : LOG_ERR, ""PACKAGE" not running"); if (pid != 0 && (sig != SIGALRM || killed != 0)) unlink (options->pidfile); if (killed == 0) exit (EXIT_SUCCESS); if (sig != SIGALRM) exit (EXIT_FAILURE); } if (! options->test && ! options->daemonised) { if ((pid = read_pid (options->pidfile)) > 0 && kill (pid, 0) == 0) { logger (LOG_ERR, ""PACKAGE" already running on pid %d (%s)", pid, options->pidfile); exit (EXIT_FAILURE); } pidfd = open (options->pidfile, O_WRONLY | O_CREAT | O_NONBLOCK, 0660); if (pidfd == -1) { logger (LOG_ERR, "open `%s': %s", options->pidfile, strerror (errno)); exit (EXIT_FAILURE); } /* Lock the file so that only one instance of dhcpcd runs on an interface */ if (flock (pidfd, LOCK_EX | LOCK_NB) == -1) { logger (LOG_ERR, "flock `%s': %s", options->pidfile, strerror (errno)); exit (EXIT_FAILURE); } /* dhcpcd.sh should not interhit this fd */ if ((i = fcntl (pidfd, F_GETFD, 0)) == -1 || fcntl (pidfd, F_SETFD, i | FD_CLOEXEC) == -1) logger (LOG_ERR, "fcntl: %s", strerror (errno)); writepid (pidfd, getpid ()); logger (LOG_INFO, PACKAGE " " VERSION " starting"); } /* Seed random */ srandomdev (); i = EXIT_FAILURE; if (dhcp_run (options, &pidfd) == 0) i = EXIT_SUCCESS; /* If we didn't daemonise then we need to punt the pidfile now */ if (pidfd > -1) { close (pidfd); unlink (options->pidfile); } free (options); #ifdef THERE_IS_NO_FORK /* There may have been an error before the dhcp_run function * clears this, so just do it here to be safe */ free (dhcpcd_skiproutes); #endif logger (LOG_INFO, "exiting"); exit (i); }
int main(int argc, char *argv[]){ FILE *fd; job_registry_entry *en; time_t now; time_t purge_time=0; char constraint[JOBID_MAX_LEN+1]; char constraint2[5]; char *query=NULL; char *queryStates=NULL; char *query_err=NULL; char *pidfile=NULL; char string_now[11]; char *tpath; int version=0; int tmptim; int finstr_len=0; int loop_interval=DEFAULT_LOOP_INTERVAL; int fsq_ret=0; int c; int confirm_time=0; static int help; static int short_help; while (1) { static struct option long_options[] = { {"help", no_argument, &help, 1}, {"usage", no_argument, &short_help, 1}, {"nodaemon", no_argument, 0, 'o'}, {"version", no_argument, 0, 'v'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long (argc, argv, "vo",long_options, &option_index); if (c == -1){ break; } switch (c) { case 0: if (long_options[option_index].flag != 0){ break; } case 'v': version=1; break; case 'o': nodmn=1; break; case '?': break; default: abort (); } } //check if another instance is running char **ptr; char out[3]; fgets(out, sizeof(out),popen("ps -d | grep -c BUpdaterSGE","r")); strtoken(out,'\n',&ptr); if (strcmp(ptr[0],"1")!=0){ fprintf(stderr,"There is another instance of BUpdaterSGE running.\nExiting ...\n"); return -1; } freetoken(&ptr,1); if(help){ usage(); } if(short_help){ short_usage(); } argv0 = argv[0]; signal(SIGHUP,sighup); if(version) { printf("%s Version: %s\n",progname,VERSION); exit(EXIT_SUCCESS); } /* Checking configuration */ check_config_file("UPDATER"); cha = config_read(NULL); if (cha == NULL) { fprintf(stderr,"Error reading config: "); perror(""); return -1; } config_setenv(NULL); ret = config_get("bupdater_child_poll_timeout",cha); if (ret != NULL){ tmptim=atoi(ret->value); if (tmptim > 0) bfunctions_poll_timeout = tmptim*1000; } ret = config_get("bupdater_debug_level",cha); if (ret != NULL){ debug=atoi(ret->value); } ret = config_get("bupdater_debug_logfile",cha); if (ret != NULL){ debuglogname=strdup(ret->value); if(debuglogname == NULL){ sysfatal("strdup failed for debuglogname in main: %r"); } } if(debug <=0){ debug=0; } if(debuglogname){ if((debuglogfile = fopen(debuglogname, "a+"))==0){ debug = 0; } }else{ debug = 0; } ret = config_get("debug_level",cha); if (ret != NULL){ debug=atoi(ret->value); } ret = config_get("debug_logfile",cha); if (ret != NULL){ debuglogname=strdup(ret->value); if(debuglogname == NULL){ sysfatal("strdup failed for debuglogname in main: %r"); } } if(debug <=0){ debug=0; } if(debuglogname){ if((debuglogfile = fopen(debuglogname, "a+"))==0){ debug = 0; } }else{ debug = 0; } ret = config_get("sge_binpath",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key sge_binpath not found\n",argv0); } else { sge_binpath=strdup(ret->value); if(sge_binpath == NULL){ sysfatal("strdup failed for sge_binpath in main: %r"); } } ret = config_get("sge_rootpath",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key sge_rootpath not found\n",argv0); } else { sge_rootpath=strdup(ret->value); if(sge_rootpath == NULL){ sysfatal("strdup failed for sge_rootpath in main: %r"); } tpath=make_message("%s",sge_rootpath); if (opendir(tpath)==NULL){ do_log(debuglogfile, debug, 1, "%s: dir %s does not exist or is not readable\n",argv0,tpath); sysfatal("dir %s does not exist or is not readable: %r",tpath); } free(tpath); } ret = config_get("sge_cellname",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key sge_cellname not found\n",argv0); } else { sge_cellname=strdup(ret->value); if(sge_cellname == NULL){ sysfatal("strdup failed for sge_cellname in main: %r"); } } ret = config_get("sge_rootpath",cha); if (ret == NULL){ if(debug){ fprintf(debuglogfile, "%s: key sge_rootpath not found\n",argv0); fflush(debuglogfile); } } else { sge_rootpath=strdup(ret->value); if(sge_rootpath == NULL){ sysfatal("strdup failed for sge_rootpath in main: %r"); } } ret = config_get("sge_cellname",cha); if (ret == NULL){ if(debug){ fprintf(debuglogfile, "%s: key sge_cellname not found\n",argv0); fflush(debuglogfile); } } else { sge_cellname=strdup(ret->value); if(sge_cellname == NULL){ sysfatal("strdup failed for sge_cellname in main: %r"); } } ret = config_get("job_registry",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key job_registry not found\n",argv0); sysfatal("job_registry not defined. Exiting"); } else { reg_file=strdup(ret->value); if(reg_file == NULL){ sysfatal("strdup failed for reg_file in main: %r"); } } ret = config_get("purge_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key purge_interval not found using the default:%d\n",argv0,purge_interval); } else { purge_interval=atoi(ret->value); } ret = config_get("finalstate_query_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key finalstate_query_interval not found using the default:%d\n",argv0,finalstate_query_interval); } else { finalstate_query_interval=atoi(ret->value); } ret = config_get("alldone_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key alldone_interval not found using the default:%d\n",argv0,alldone_interval); } else { alldone_interval=atoi(ret->value); } ret = config_get("bupdater_loop_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key bupdater_loop_interval not found using the default:%d\n",argv0,loop_interval); } else { loop_interval=atoi(ret->value); } ret = config_get("bupdater_pidfile",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key bupdater_pidfile not found\n",argv0); } else { pidfile=strdup(ret->value); if(pidfile == NULL){ sysfatal("strdup failed for pidfile in main: %r"); } } ret = config_get("job_registry_use_mmap",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key job_registry_use_mmap not found. Default is NO\n",argv0); } else { do_log(debuglogfile, debug, 1, "%s: key job_registry_use_mmap is set to %s\n",argv0,ret->value); } if( !nodmn ) daemonize(); if( pidfile ){ writepid(pidfile); free(pidfile); } config_free(cha); rha=job_registry_init(reg_file, BY_BATCH_ID); if (rha == NULL){ do_log(debuglogfile, debug, 1, "%s: Error initialising job registry %s\n",argv0,reg_file); fprintf(stderr,"%s: Error initialising job registry %s :",argv0,reg_file); perror(""); } for(;;){ /* Purge old entries from registry */ now=time(0); if(now - purge_time > 86400){ if(job_registry_purge(reg_file, now-purge_interval,0)<0){ do_log(debuglogfile, debug, 1, "%s: Error purging job registry %s\n",argv0,reg_file); fprintf(stderr,"%s: Error purging job registry %s :",argv0,reg_file); perror(""); }else{ purge_time=time(0); } } //IntStateQuery(); fd = job_registry_open(rha, "r"); if (fd == NULL) { do_log(debuglogfile, debug, 1, "%s: Error opening job registry %s\n",argv0,reg_file); fprintf(stderr,"%s: Error opening job registry %s :",argv0,reg_file); perror(""); sleep(loop_interval); } if (job_registry_rdlock(rha, fd) < 0) { do_log(debuglogfile, debug, 1, "%s: Error read locking job registry %s\n",argv0,reg_file); fprintf(stderr,"%s: Error read locking job registry %s :",argv0,reg_file); perror(""); sleep(loop_interval); } job_registry_firstrec(rha,fd); fseek(fd,0L,SEEK_SET); if((query=calloc(STR_CHARS*2,1)) == 0){ sysfatal("can't malloc query %r"); } if((queryStates=calloc(STR_CHARS*2,1)) == 0){ sysfatal("can't malloc query %r"); } query[0]=' '; queryStates[0]=' '; while ((en = job_registry_get_next(rha, fd)) != NULL) { if(((now - en->mdate) > finalstate_query_interval) && en->status!=3 && en->status!=4) { /* create the constraint that will be used in condor_history command in FinalStateQuery*/ snprintf(constraint, sizeof(constraint), " %s",en->batch_id); if (en->status==0) snprintf(constraint2, sizeof(constraint2), " u"); if (en->status==1) snprintf(constraint2, sizeof(constraint2), " q"); if (en->status==2) snprintf(constraint2, sizeof(constraint2), " r"); if (en->status==5) snprintf(constraint2, sizeof(constraint2), " h"); query=realloc(query,strlen(query)+strlen(constraint)+1); queryStates=realloc(queryStates,strlen(queryStates)+strlen(constraint2)+1); strcat(query,constraint); strcat(queryStates,constraint2); runfinal=TRUE; } /* Assign Status=4 and ExitStatus=-1 to all entries that after alldone_interval are still not in a final state(3 or 4) */ if((now - en->mdate > alldone_interval) && en->status!=3 && en->status!=4 && !runfinal) { time_t now; now=time(0); snprintf(string_now,sizeof(string_now),"%d",now); AssignState(en->batch_id,"4" ,"-1","\0","\0",string_now); } free(en); } if(runfinal){ if((query_err=calloc((int)strlen(query),1)) == 0) sysfatal("can't malloc query_err %r"); FinalStateQuery(query,queryStates,query_err); free(query_err); } free(query); free(queryStates); fclose(fd); if (runfinal){ runfinal=FALSE; } sleep (loop_interval); } //for job_registry_destroy(rha); return(0); }
static int run_daemon(void) { FILE *info; uint32_t rxb, txb, rxp, txp; uint32_t udp, tcp, other; uint16_t rate; uint8_t rssi, noise; float lf1, lf5, lf15; char line[1024]; char ifname[16]; int i; void *iw; struct sigaction sa; struct stat s; const char *ipc = stat("/proc/net/nf_conntrack", &s) ? "/proc/net/ip_conntrack" : "/proc/net/nf_conntrack"; switch (fork()) { case -1: perror("fork()"); return -1; case 0: if (chdir("/") < 0) { perror("chdir()"); exit(1); } close(0); close(1); close(2); break; default: return 0; } /* setup USR1 signal handler to reset timer */ sa.sa_handler = reset_countdown; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); sigaction(SIGUSR1, &sa, NULL); /* write pid */ if (writepid()) { fprintf(stderr, "Failed to write pid file: %s\n", strerror(errno)); return 1; } /* initialize iwinfo */ iw = iwinfo_open(); /* go */ for (reset_countdown(0); countdown >= 0; countdown--) { /* alter progname for ps, top */ memset(progname, 0, prognamelen); snprintf(progname, prognamelen, "luci-bwc %d", countdown); if ((info = fopen("/proc/net/dev", "r")) != NULL) { while (fgets(line, sizeof(line), info)) { if (strchr(line, '|')) continue; if (sscanf(line, IF_SCAN_PATTERN, ifname, &rxb, &rxp, &txb, &txp)) { if (strncmp(ifname, "lo", sizeof(ifname))) update_ifstat(ifname, rxb, rxp, txb, txp); } } fclose(info); } if (iw) { for (i = 0; i < 5; i++) { #define iwinfo_checkif(pattern) \ do { \ snprintf(ifname, sizeof(ifname), pattern, i); \ if (iwinfo_update(iw, ifname, &rate, &rssi, &noise)) \ { \ update_radiostat(ifname, rate, rssi, noise); \ continue; \ } \ } while(0) iwinfo_checkif("wlan%d"); iwinfo_checkif("ath%d"); iwinfo_checkif("wl%d"); } } if ((info = fopen(ipc, "r")) != NULL) { udp = 0; tcp = 0; other = 0; while (fgets(line, sizeof(line), info)) { if (strstr(line, "TIME_WAIT")) continue; if (sscanf(line, "%*s %*d %s", ifname) || sscanf(line, "%s %*d", ifname)) { if (!strcmp(ifname, "tcp")) tcp++; else if (!strcmp(ifname, "udp")) udp++; else other++; } } update_cnstat(udp, tcp, other); fclose(info); } if ((info = fopen("/proc/loadavg", "r")) != NULL) { if (fscanf(info, LD_SCAN_PATTERN, &lf1, &lf5, &lf15)) { update_ldstat((uint16_t)(lf1 * 100), (uint16_t)(lf5 * 100), (uint16_t)(lf15 * 100)); } fclose(info); } sleep(STEP_TIME); } unlink(PID_PATH); if (iw) iwinfo_close(iw); return 0; }
int main(int argc, char **argv) { char *consoletty, *p; char **dmargv, **xargv, **consoleargv = NULL, **loginargv; char xpidf[256], line[16], buf[256]; fd_set readfds; int pgrp, file, tries, count, redir = TRUE; char dpyacl[40]; Display *dpy; XHostAddress *hosts, localhost; int nhosts, dpynum = 0; struct stat hostsinfo; Bool state; time_t now, last_console_failure = 0; struct sigaction sigact; sigset_t mask; #if defined(SRIOCSREDIR) || defined(TIOCCONS) int on; #endif int fd; int conspipe[2]; XIOErrorHandler xioerror_handler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; (void) sigemptyset(&sig_zero); /* Create a localhost entity for access control purposes. */ localhost.family = FamilyLocalHost; localhost.length = 0; localhost.address = ""; /* * Note about setting environment variables in dm: * * All environment variables passed to dm and set in dm are * subsequently passed to any children of dm. This is usually * true of processes that exec in children, so that's not a * big surprise. * * However, xlogin is one of the children dm forks, and it goes * to lengths to ensure that the environments of users logging in * are ISOLATED from xlogin's own environment. Therefore, do not * expect that setting an environment variable here will reach the * user unless you have gone to lengths to make sure that xlogin * passes it on. Put another way, if you set a new environment * variable here, consider whether or not it should be seen by the * user. If it should, go modify verify.c as well. Consider also * whether the variable should be seen _only_ by the user. If so, * make the change only in xlogin, and not here. * * As an added complication, xlogin _does_ pass environment variables * on to the pre-login options. Therefore, if you set an environment * variable that should _not_ be seen, you must filter it in xlogin.c. * * Confused? Too bad. I'm in a nasty, if verbose, mood this year. * * General summary: * * If you add an environment variable here there are three likely * possibilities: * * 1. It's for the user only, not needed by any of dm's children. * --> Don't set it here. Set it in verify.c for users and in * --> xlogin.c for the pre-login options, if appropriate. * * 2. It's for dm and its children only, and _should not_ be seen * by the user or pre-login options. * --> You must filter the option from the pre-login options * --> in xlogin.c. No changes to verify.c are required. * * 3. It's for dm and the user and the pre-login options. * --> You must pass the option explicitly to the user in * --> verify.c. No changes to xlogin.c are required. * * --- cfields */ #ifdef notdef putenv("LD_LIBRARY_PATH=/usr/openwin/lib"); putenv("OPENWINHOME=/usr/openwin"); #endif if (argc < 2) { fprintf(stderr, "dm: first argument must be configuration file\n"); sleep(60); exit(1); } conf = argv[1]; if (argc != 4 && (argc != 5 || strcmp(argv[3], "-noconsole"))) { fprintf(stderr, "usage: %s configfile logintty [-noconsole] consoletty\n", argv[0]); console_login(conf, NULL); } if (argc == 5) redir = FALSE; /* parse argument lists */ /* ignore argv[2] */ consoletty = argv[argc - 1]; #ifdef SOLARIS /* On Solaris, use the console tty name for the utmp line field, * as the Solaris finger requires an actual device name there. * Elsewhere, we will use the display name (see below). */ utmp_line = consoletty; #endif openlog("dm", 0, LOG_USER); /* We use options from the config file rather than taking * them from the command line because the current command * line form is gross (why???), and I don't see a good way * to extend it without making things grosser or breaking * backwards compatibility. So, we take a line from the * config file and use real parsing. */ p = getconf(conf, "dm"); if (p != NULL) { dmargv = parseargs(p, NULL, NULL, NULL); while (*dmargv) { if (!strcmp(*dmargv, "-display")) { dmargv++; if (*dmargv) { dpynum = atoi(*(dmargv) + 1); dmargv++; } } else dmargv++; } } p = getconf(conf, "X"); if (p == NULL) console_login(conf, "\ndm: Can't find X command line\n"); xargv = parseargs(p, NULL, NULL, NULL); p = getconf(conf, "console"); if (p == NULL) console_login(conf, "\ndm: Can't find console command line\n"); /* We will pass the read side of the pipe created below to console * on descriptor 3. */ consoleargv = parseargs(p, "-inputfd", "3", NULL); /* Signal Setup */ sigact.sa_handler = SIG_IGN; sigaction(SIGTSTP, &sigact, NULL); sigaction(SIGTTIN, &sigact, NULL); sigaction(SIGTTOU, &sigact, NULL); /* so that X pipe errors don't nuke us */ sigaction(SIGPIPE, &sigact, NULL); sigact.sa_handler = shutdown; sigaction(SIGFPE, &sigact, NULL); sigact.sa_handler = die; sigaction(SIGHUP, &sigact, NULL); sigaction(SIGINT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); sigact.sa_handler = child; sigaction(SIGCHLD, &sigact, NULL); sigact.sa_handler = catchalarm; sigaction(SIGALRM, &sigact, NULL); strcpy(line, "/dev/"); strcat(line, consoletty); fd = open(line, O_RDWR); if (fd == -1) { syslog(LOG_ERR, "Cannot open %s: %m", line); /* This probably won't work, but it seems to be the appropriate punt location. */ console_login(conf, "Cannot open tty.\n"); } if (login_tty(fd) == -1) syslog(LOG_ERR, "Cannot set the console as a login terminal (%s)", strerror(errno)); else { /* Set the console characteristics so we don't lose later */ setpgid(0, pgrp = getpid()); /* Reset the tty pgrp */ if (tcsetpgrp(0, pgrp) == -1) syslog(LOG_ERR, "tcsetpgrp failed for console terminal (%s)", strerror(errno)); } /* save our pid file */ writepid(dmpidf, getpid()); /* Fire up X */ xpid = 0; for (tries = 0; tries < 3; tries++) { syslog(LOG_DEBUG, "Starting X, try #%d", tries + 1); x_running = STARTUP; sigact.sa_handler = xready; sigaction(SIGUSR1, &sigact, NULL); switch (fork_and_store(&xpid)) { case 0: if (fcntl(2, F_SETFD, 1) == -1) close(2); (void) sigprocmask(SIG_SETMASK, &sig_zero, (sigset_t *) 0); /* ignoring SIGUSR1 will cause the server to send us a SIGUSR1 * when it is ready to accept connections */ sigact.sa_handler = SIG_IGN; sigaction(SIGUSR1, &sigact, NULL); p = *xargv; *xargv = "X"; execv(p, xargv); fprintf(stderr, "dm: X server failed exec: %s\n", strerror(errno)); _exit(1); case -1: fprintf(stderr, "dm: Unable to fork to start X server: %s\n", strerror(errno)); break; default: sprintf(xpidf, xpids, dpynum); writepid(xpidf, xpid); if (x_running == STARTUP) { alarm(X_START_WAIT); alarm_running = RUNNING; sigsuspend(&sig_zero); } if (x_running != RUNNING) { syslog(LOG_DEBUG, "X failed to start; alarm_running=%d", alarm_running); if (alarm_running == NONEXISTENT) fprintf(stderr, "dm: Unable to start X\n"); else fprintf(stderr, "dm: X failed to become ready\n"); /* If X wouldn't run, it could be that an existing X * process hasn't shut down. Wait X_STOP_WAIT seconds * for that to happen. */ x_stop_wait(); } sigact.sa_handler = SIG_IGN; sigaction(SIGUSR1, &sigact, NULL); } if (x_running == RUNNING) break; } alarm(0); if (x_running != RUNNING) { syslog(LOG_DEBUG, "Giving up on starting X."); console_login(conf, "\nUnable to start X, doing console login " "instead.\n"); } /* Tighten up security a little bit. Remove all hosts from X's * access control list, assuming /etc/X0.hosts does not exist or * has zero length. If it does exist with nonzero length, this * behavior is not wanted. The desired effect of removing all hosts * is that only connections from the Unix domain socket will be * allowed. * More secure code using Xau also exists, but there wasn't * time to completely flesh it out and resolve a couple of * issues. This code is probably good enough, but we'll see. * Maybe next time. * This code has the added benefit of leaving an X display * connection open, owned by dm. This provides a less-hacky * solution to the config_console problem, where if config_console * is the first program run on user login, it causes the only * X app running at the time, console, to exit, thus resetting * the X server. Thus this code also allows the removal of the * hack in xlogin that attempts to solve the same problem, but * fails on the RS/6000 for reasons unexplored. * P.S. Don't run this code under Solaris 2.2- (2.3 is safe). * Removing all hosts from the acl on that server results in * no connections, not even from the Unix domain socket, being * allowed. --- cfields */ sprintf(dpyacl, xhosts, dpynum); sprintf(dpyname, ":%d", dpynum); #ifndef SOLARIS /* Use the display name for the utmp line field, except on Solaris. */ utmp_line = dpyname; #endif /* Put in our own error handler, open the display, then reset the handler. */ xioerror_handler = XSetIOErrorHandler(handle_xioerror); dpy = XOpenDisplay(dpyname); XSetIOErrorHandler(xioerror_handler); if (dpy != NULL && (stat(dpyacl, &hostsinfo) || hostsinfo.st_size == 0)) { hosts = XListHosts(dpy, &nhosts, &state); if (hosts != NULL) { XRemoveHosts(dpy, hosts, nhosts); XFree(hosts); } XAddHost(dpy, &localhost); XFlush(dpy); } /* else if (dpy == NULL) * Could've sworn the X server was running now. * Follow the original code path. No need introducing new bugs * to this hairy code, just preserve the old behavior as though * this code had never been added. */ /* set up the console pty */ if (openpty(&console_master_fd, &console_slave_fd, NULL, NULL, NULL) == -1) console_login(conf, "Cannot allocate pseudo-terminal\n"); if (redir) { /* Redirect /dev/console output to the pty slave. */ #ifdef SRIOCSREDIR on = open("/dev/console", O_RDONLY); if (on >= 0) { ioctl(on, SRIOCSREDIR, console_slave_fd); close(on); } #else #ifdef TIOCCONS on = 1; ioctl(console_slave_fd, TIOCCONS, &on); #endif #endif } /* Set up the console pipe. */ if (pipe(conspipe) == -1) console_login(conf, "Cannot create pipe for console\n"); /* start up console */ start_console(console_master_fd, conspipe[0], consoleargv); /* Set up to invoke xlogin. */ p = getconf(conf, "login"); if (p == NULL) console_login(conf, "\ndm: Can't find login command line\n"); loginargv = parseargs(p, "-line", utmp_line, NULL); /* Fire up the X login */ for (tries = 0; tries < 3; tries++) { syslog(LOG_DEBUG, "Starting xlogin, try #%d", tries + 1); login_running = STARTUP; sigact.sa_handler = loginready; sigaction(SIGUSR1, &sigact, NULL); switch (fork_and_store(&loginpid)) { case 0: max_fd = sysconf(_SC_OPEN_MAX); for (file = 3; file < max_fd; file++) { if (file != conspipe[1]) close(file); } setsid(); file = open("/dev/null", O_RDONLY); if (file >= 0) { dup2(file, 0); if (file != 0) close(file); } file = conspipe[1]; if (file == -1) file = open("/dev/null", O_WRONLY); if (file >= 0) { if (file != 1) dup2(file, 1); if (file != 2) dup2(file, 2); if (file != 1 && file != 2) close(file); } (void) sigprocmask(SIG_SETMASK, &sig_zero, (sigset_t *) 0); /* ignoring SIGUSR1 will cause xlogin to send us a SIGUSR1 * when it is ready */ sigact.sa_handler = SIG_IGN; sigaction(SIGUSR1, &sigact, NULL); /* dm ignores sigpipe; because of this, all of the children (ie, */ /* the entire session) inherit this unless we fix it now */ sigact.sa_handler = SIG_DFL; sigaction(SIGPIPE, &sigact, NULL); execv(loginargv[0], loginargv); fprintf(stderr, "dm: X login failed exec: %s\n", strerror(errno)); _exit(1); case -1: fprintf(stderr, "dm: Unable to fork to start X login: %s\n", strerror(errno)); break; default: alarm(LOGIN_START_WAIT); alarm_running = RUNNING; while (login_running == STARTUP && alarm_running == RUNNING) sigsuspend(&sig_zero); if (login_running != RUNNING) { syslog(LOG_DEBUG, "xlogin failed to start; alarm_running=%d", alarm_running); kill(loginpid, SIGKILL); if (alarm_running != NONEXISTENT) fprintf(stderr, "dm: Unable to start Xlogin\n"); else fprintf(stderr, "dm: Xlogin failed to become ready\n"); } } if (login_running == RUNNING) break; } sigact.sa_handler = SIG_IGN; sigaction(SIGUSR1, &sigact, NULL); alarm(0); if (login_running != RUNNING) { syslog(LOG_DEBUG, "Giving up on starting xlogin."); console_login(conf, "\nUnable to start xlogin, doing console login " "instead.\n"); } /* main loop. Wait for SIGCHLD, waking up every minute anyway. */ (void) sigemptyset(&sig_cur); (void) sigaddset(&sig_cur, SIGCHLD); (void) sigprocmask(SIG_BLOCK, &sig_cur, NULL); while (1) { /* Wait for something to hapen */ if (console_failed) { /* if no console is running, we must copy bits from the console * (master side of pty) to the real console to appear as black * bar messages. */ FD_ZERO(&readfds); FD_SET(console_master_fd, &readfds); (void) sigprocmask(SIG_SETMASK, &sig_zero, &mask); count = select(console_master_fd + 1, &readfds, NULL, NULL, NULL); (void) sigprocmask(SIG_BLOCK, &mask, NULL); if (count > 0 && FD_ISSET(console_master_fd, &readfds)) { file = read(console_master_fd, buf, sizeof(buf)); if (file != -1) write(1, buf, file); } } else { alarm(60); sigsuspend(&sig_zero); } if (login_running == STARTUP) { (void) sigprocmask(SIG_SETMASK, &sig_zero, NULL); console_login(conf, "\nConsole login requested.\n"); } if (console_running == FAILED) { console_running = NONEXISTENT; time(&now); if (now - last_console_failure <= 3) { /* Give up on console. Set the console characteristics so * we don't lose later. */ syslog(LOG_ERR, "Giving up on the console"); setpgid(0, pgrp = getpid()); /* Reset the tty pgrp */ tcsetpgrp(0, pgrp); console_failed = TRUE; } else last_console_failure = now; } if (console_running == NONEXISTENT && !console_failed) start_console(console_master_fd, conspipe[0], consoleargv); if (login_running == NONEXISTENT || x_running == NONEXISTENT) { syslog(LOG_DEBUG, "login_running=%d, x_running=%d, quitting", login_running, x_running); (void) sigprocmask(SIG_SETMASK, &sig_zero, NULL); cleanup(utmp_line); _exit(0); } } }
int main(int argc, char **argv) { int interval = 30, i; const char *prog = xbasename(argv[0]); time_t now, nextpoll = 0; const char *user = NULL; struct passwd *new_uid = NULL; const char *pidfilebase = prog; logformat = DEFAULT_LOGFORMAT; user = RUN_AS_USER; printf("Network UPS Tools %s %s\n", prog, UPS_VERSION); while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:")) != -1) { switch(i) { case 'h': help(prog); break; case 's': monhost = optarg; break; case 'l': logfn = optarg; break; case 'i': interval = atoi(optarg); break; case 'f': logformat = optarg; break; case 'u': user = optarg; break; case 'V': exit(EXIT_SUCCESS); case 'p': pidfilebase = optarg; break; } } argc -= optind; argv += optind; /* not enough args for the old way? */ if ((argc == 1) || (argc == 2)) help(prog); /* see if it's being called in the old style - 3 or 4 args */ /* <system> <logfn> <interval> [<format>] */ if (argc >= 3) { monhost = argv[0]; logfn = argv[1]; interval = atoi(argv[2]); } if (argc >= 4) { /* read out the remaining argv entries to the format string */ logformat = xmalloc(LARGEBUF); memset(logformat, '\0', LARGEBUF); for (i = 3; i < argc; i++) snprintfcat(logformat, LARGEBUF, "%s ", argv[i]); } if (!monhost) fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s <system>"); if (!logfn) fatalx(EXIT_FAILURE, "No filename defined for logging - use -l <file>"); /* shouldn't happen */ if (!logformat) fatalx(EXIT_FAILURE, "No format defined - but this should be impossible"); printf("logging status of %s to %s (%is intervals)\n", monhost, logfn, interval); if (upscli_splitname(monhost, &upsname, &hostname, &port) != 0) { fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required format: upsname[@hostname[:port]]\n"); } if (upscli_connect(&ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0) fprintf(stderr, "Warning: initial connect failed: %s\n", upscli_strerror(&ups)); if (strcmp(logfn, "-") == 0) logfile = stdout; else logfile = fopen(logfn, "a"); if (logfile == NULL) fatal_with_errno(EXIT_FAILURE, "could not open logfile %s", logfn); /* now drop root if we have it */ new_uid = get_user_pwent(user); open_syslog(prog); if (logfile != stdout) background(); setup_signals(); writepid(pidfilebase); become_user(new_uid); compile_format(); while (exit_flag == 0) { time(&now); if (nextpoll > now) { /* there is still time left, so sleep it off */ sleep(difftime(nextpoll, now)); nextpoll += interval; } else { /* we spent more time in polling than the interval allows */ nextpoll = now + interval; } if (reopen_flag) { upslogx(LOG_INFO, "Signal %d: reopening log file", reopen_flag); reopen_log(); reopen_flag = 0; } /* reconnect if necessary */ if (upscli_fd(&ups) < 0) { upscli_connect(&ups, hostname, port, 0); } run_flist(); /* don't keep connection open if we don't intend to use it shortly */ if (interval > 30) { upscli_disconnect(&ups); } } upslogx(LOG_INFO, "Signal %d: exiting", exit_flag); if (logfile != stdout) fclose(logfile); upscli_disconnect(&ups); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]){ FILE *fd; job_registry_entry *en; time_t now; time_t purge_time=0; time_t last_consistency_check=0; char *pidfile=NULL; char *final_string=NULL; char *cp=NULL; char *tpath; char *tspooldir; char *first_duplicate=NULL; struct pollfd *remupd_pollset = NULL; int remupd_nfds; int version=0; int first=TRUE; int tmptim; int finstr_len=0; int loop_interval=DEFAULT_LOOP_INTERVAL; int fsq_ret=0; int c; pthread_t RecUpdNetThd; int confirm_time=0; static int help; static int short_help; bact.njobs = 0; bact.jobs = NULL; while (1) { static struct option long_options[] = { {"help", no_argument, &help, 1}, {"usage", no_argument, &short_help, 1}, {"nodaemon", no_argument, 0, 'o'}, {"version", no_argument, 0, 'v'}, {"prefix", required_argument, 0, 'p'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long (argc, argv, "vop:",long_options, &option_index); if (c == -1){ break; } switch (c) { case 0: if (long_options[option_index].flag != 0){ break; } case 'v': version=1; break; case 'o': nodmn=1; break; case 'p': break; case '?': break; default: abort (); } } if(help){ usage(); } if(short_help){ short_usage(); } argv0 = argv[0]; signal(SIGHUP,sighup); if(version) { printf("%s Version: %s\n",progname,VERSION); exit(EXIT_SUCCESS); } /* Checking configuration */ check_config_file("UPDATER"); cha = config_read(NULL); if (cha == NULL) { fprintf(stderr,"Error reading config: "); perror(""); return -1; } ret = config_get("bupdater_child_poll_timeout",cha); if (ret != NULL){ tmptim=atoi(ret->value); if (tmptim > 0) bfunctions_poll_timeout = tmptim*1000; } ret = config_get("bupdater_debug_level",cha); if (ret != NULL){ debug=atoi(ret->value); } ret = config_get("bupdater_debug_logfile",cha); if (ret != NULL){ debuglogname=strdup(ret->value); if(debuglogname == NULL){ sysfatal("strdup failed for debuglogname in main: %r"); } } if(debug <=0){ debug=0; } if(debuglogname){ if((debuglogfile = fopen(debuglogname, "a+"))==0){ debug = 0; } }else{ debug = 0; } ret = config_get("pbs_binpath",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key pbs_binpath not found\n",argv0); } else { pbs_binpath=strdup(ret->value); if(pbs_binpath == NULL){ sysfatal("strdup failed for pbs_binpath in main: %r"); } } ret = config_get("pbs_spoolpath",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key pbs_spoolpath not found\n",argv0); } else { pbs_spoolpath=strdup(ret->value); if(pbs_spoolpath == NULL){ sysfatal("strdup failed for pbs_spoolpath in main: %r"); } tpath=make_message("%s/server_logs",pbs_spoolpath); if (opendir(tpath)==NULL){ do_log(debuglogfile, debug, 1, "%s: dir %s does not exist or is not readable. Trying now pbs commands\n",argv0,tpath); tspooldir=GetPBSSpoolPath(pbs_binpath); free(tpath); tpath=make_message("%s/server_logs",tspooldir); free(tspooldir); if (opendir(tpath)==NULL){ do_log(debuglogfile, debug, 1, "dir %s does not exist or is not readable (using pbs commands)",tpath); sysfatal("dir %s does not exist or is not readable (using pbs commands): %r",tpath); } } free(tpath); } ret = config_get("job_registry",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key job_registry not found\n",argv0); sysfatal("job_registry not defined. Exiting"); } else { registry_file=strdup(ret->value); if(registry_file == NULL){ sysfatal("strdup failed for registry_file in main: %r"); } } ret = config_get("purge_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key purge_interval not found using the default:%d\n",argv0,purge_interval); } else { purge_interval=atoi(ret->value); } ret = config_get("finalstate_query_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key finalstate_query_interval not found using the default:%d\n",argv0,finalstate_query_interval); } else { finalstate_query_interval=atoi(ret->value); } ret = config_get("alldone_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key alldone_interval not found using the default:%d\n",argv0,alldone_interval); } else { alldone_interval=atoi(ret->value); } ret = config_get("tracejob_logs_to_read",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key tracejob_logs_to_read not found using the default:%d\n",argv0,tracejob_logs_to_read); } else { tracejob_logs_to_read=atoi(ret->value); } ret = config_get("bupdater_loop_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key bupdater_loop_interval not found using the default:%d\n",argv0,loop_interval); } else { loop_interval=atoi(ret->value); } ret = config_get("bupdater_consistency_check_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key bupdater_consistency_check_interval not found using the default:%d\n",argv0,bupdater_consistency_check_interval); } else { bupdater_consistency_check_interval=atoi(ret->value); } ret = config_get("bupdater_pidfile",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key bupdater_pidfile not found\n",argv0); } else { pidfile=strdup(ret->value); if(pidfile == NULL){ sysfatal("strdup failed for pidfile in main: %r"); } } ret = config_get("pbs_batch_caching_enabled",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key pbs_batch_caching_enabled not found using default\n",argv0,pbs_batch_caching_enabled); } else { pbs_batch_caching_enabled=strdup(ret->value); if(pbs_batch_caching_enabled == NULL){ sysfatal("strdup failed for pbs_batch_caching_enabled in main: %r"); } } ret = config_get("batch_command_caching_filter",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key batch_command_caching_filter not found using default\n",argv0,batch_command_caching_filter); } else { batch_command_caching_filter=strdup(ret->value); if(batch_command_caching_filter == NULL){ sysfatal("strdup failed for batch_command_caching_filter in main: %r"); } } batch_command=(strcmp(pbs_batch_caching_enabled,"yes")==0?make_message("%s ",batch_command_caching_filter):make_message("")); ret = config_get("job_registry_use_mmap",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key job_registry_use_mmap not found. Default is NO\n",argv0); } else { do_log(debuglogfile, debug, 1, "%s: key job_registry_use_mmap is set to %s\n",argv0,ret->value); } ret = config_get("tracejob_max_output",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key tracejob_max_output not found using default\n",argv0,tracejob_max_output); } else { tracejob_max_output==atoi(ret->value); } remupd_conf = config_get("job_registry_add_remote",cha); if (remupd_conf == NULL){ do_log(debuglogfile, debug, 1, "%s: key job_registry_add_remote not found\n",argv0); }else{ if (job_registry_updater_setup_receiver(remupd_conf->values,remupd_conf->n_values,&remupd_head) < 0){ do_log(debuglogfile, debug, 1, "%s: Cannot set network receiver(s) up for remote update\n",argv0); fprintf(stderr,"%s: Cannot set network receiver(s) up for remote update \n",argv0); } if (remupd_head == NULL){ do_log(debuglogfile, debug, 1, "%s: Cannot find values for network endpoints in configuration file (attribute 'job_registry_add_remote').\n",argv0); fprintf(stderr,"%s: Cannot find values for network endpoints in configuration file (attribute 'job_registry_add_remote').\n", argv0); } if ((remupd_nfds = job_registry_updater_get_pollfd(remupd_head, &remupd_pollset)) < 0){ do_log(debuglogfile, debug, 1, "%s: Cannot setup poll set for receiving data.\n",argv0); fprintf(stderr,"%s: Cannot setup poll set for receiving data.\n", argv0); } if (remupd_pollset == NULL || remupd_nfds == 0){ do_log(debuglogfile, debug, 1, "%s: No poll set available for receiving data.\n",argv0); fprintf(stderr,"%s: No poll set available for receiving data.\n",argv0); } } if( !nodmn ) daemonize(); if( pidfile ){ writepid(pidfile); free(pidfile); } rha=job_registry_init(registry_file, BY_BATCH_ID); if (rha == NULL){ do_log(debuglogfile, debug, 1, "%s: Error initialising job registry %s\n",argv0,registry_file); fprintf(stderr,"%s: Error initialising job registry %s :",argv0,registry_file); perror(""); } if (remupd_conf != NULL){ pthread_create(&RecUpdNetThd, NULL, (void *(*)(void *))ReceiveUpdateFromNetwork, (void *)NULL); if (job_registry_updater_setup_sender(remupd_conf->values,remupd_conf->n_values,0,&remupd_head_send) < 0){ do_log(debuglogfile, debug, 1, "%s: Cannot set network sender(s) up for remote update\n",argv0); fprintf(stderr,"%s: Cannot set network sender(s) up for remote update \n",argv0); } if (remupd_head_send == NULL){ do_log(debuglogfile, debug, 1, "%s: Cannot find values for network endpoints in configuration file (attribute 'job_registry_add_remote').\n",argv0); fprintf(stderr,"%s: Cannot find values for network endpoints in configuration file (attribute 'job_registry_add_remote').\n", argv0); } } config_free(cha); for(;;){ /* Purge old entries from registry */ now=time(0); if(now - purge_time > 86400){ if(job_registry_purge(registry_file, now-purge_interval,0)<0){ do_log(debuglogfile, debug, 1, "%s: Error purging job registry %s\n",argv0,registry_file); fprintf(stderr,"%s: Error purging job registry %s :",argv0,registry_file); perror(""); }else{ purge_time=time(0); } } now=time(0); if(now - last_consistency_check > bupdater_consistency_check_interval){ if(job_registry_check_index_key_uniqueness(rha,&first_duplicate)==JOB_REGISTRY_FAIL){ do_log(debuglogfile, debug, 1, "%s: Found job registry duplicate entry. The first one is:%s\n",argv0,first_duplicate); fprintf(stderr,"%s: Found job registry duplicate entry. The first one is:%s",argv0,first_duplicate); }else{ last_consistency_check=time(0); } } IntStateQuery(); fd = job_registry_open(rha, "r"); if (fd == NULL){ do_log(debuglogfile, debug, 1, "%s: Error opening job registry %s\n",argv0,registry_file); fprintf(stderr,"%s: Error opening job registry %s :",argv0,registry_file); perror(""); sleep(loop_interval); continue; } if (job_registry_rdlock(rha, fd) < 0){ do_log(debuglogfile, debug, 1, "%s: Error read locking job registry %s\n",argv0,registry_file); fprintf(stderr,"%s: Error read locking job registry %s :",argv0,registry_file); perror(""); sleep(loop_interval); continue; } job_registry_firstrec(rha,fd); fseek(fd,0L,SEEK_SET); first=TRUE; while ((en = job_registry_get_next(rha, fd)) != NULL){ if((bupdater_lookup_active_jobs(&bact, en->batch_id) != BUPDATER_ACTIVE_JOBS_SUCCESS) && en->status!=REMOVED && en->status!=COMPLETED){ confirm_time=atoi(en->updater_info); if(confirm_time==0){ confirm_time=en->mdate; } /* Assign Status=4 and ExitStatus=999 to all entries that after alldone_interval are still not in a final state(3 or 4)*/ if(now-confirm_time>alldone_interval){ AssignFinalState(en->batch_id); free(en); continue; } if((now-confirm_time>finalstate_query_interval) && (now > next_finalstatequery)){ if((final_string=realloc(final_string,finstr_len + strlen(en->batch_id) + 2)) == 0){ sysfatal("can't malloc final_string: %r"); } else { if (finstr_len == 0) final_string[0] = '\000'; } strcat(final_string,en->batch_id); strcat(final_string,":"); finstr_len=strlen(final_string); runfinal=TRUE; } } free(en); } if(runfinal){ if (final_string[finstr_len-1] == ':' && (cp = strrchr (final_string, ':')) != NULL){ *cp = '\0'; } if(fsq_ret != 0){ fsq_ret=FinalStateQuery(final_string,tracejob_logs_to_read); }else{ fsq_ret=FinalStateQuery(final_string,1); } runfinal=FALSE; } if (final_string != NULL){ free(final_string); final_string = NULL; finstr_len = 0; } fclose(fd); sleep(loop_interval); } job_registry_destroy(rha); return 0; }
int main(int ac, char **av) { const char *pathName = "/var/run/vknet"; const char *tapName = "auto"; const char *bridgeName = NULL; int net_fd; int connectOpt = 0; int c; ioinfo_t tap_info; pthread_t dummy_td; while ((c = getopt(ac, av, "b:cdp:i:t:U")) != -1) { switch (c) { case 'U': SecureOpt = 0; break; case 'b': bridgeName = optarg; break; case 'd': DebugOpt = 1; break; case 'p': pathName = optarg; break; case 'i': pidfile = optarg; break; case 't': tapName = optarg; break; case 'c': connectOpt = 1; break; default: usage(); } } av += optind; ac -= optind; if (ac) SetAddrOpt = 1; /* * Special connect/debug mode */ if (connectOpt) { net_fd = vknet_connect(pathName); if (net_fd < 0) { perror("connect"); exit(1); } vknet_monitor(net_fd); exit(0); } /* * In secure mode (the default), a network address/mask must be * specified. e.g. 10.1.0.0/16. Any traffic going out the TAP * interface will be filtered. * * If non-secure mode the network address/mask is optional. */ if (SecureOpt || SetAddrOpt) { char *str; int masklen; u_int32_t mask; if (ac == 0 || strchr(av[0], '/') == NULL) usage(); str = strdup(av[0]); if (inet_pton(AF_INET, strtok(str, "/"), &NetAddress) <= 0) usage(); masklen = strtoul(strtok(NULL, "/"), NULL, 10); mask = (1 << (32 - masklen)) - 1; NetMask.s_addr = htonl(~mask); } /* * Normal operation, create the tap/bridge and listener. This * part is not threaded. */ mac_init(); if ((tap_info = vknet_tap(tapName, bridgeName)) == NULL) { perror("tap: "); exit(1); } if ((net_fd = vknet_listener(pathName)) < 0) { perror("listener: "); exit(1); } /* * Now make us a demon and start the threads going. */ if (DebugOpt == 0) daemon(1, 0); writepid(); signal(SIGINT, cleanup); signal(SIGHUP, cleanup); signal(SIGTERM, cleanup); pthread_mutex_init(&BridgeMutex, NULL); pthread_create(&dummy_td, NULL, vknet_io, tap_info); vknet_acceptor(net_fd); exit(0); }
int main(int argc, char **argv) { int verdict; unsigned char buf[BUFSIZE]; struct ipq_handle *h; int cfd; int daemonize = 1; if (argc > 1) { if (!strcmp(argv[1], "-nd")) { daemonize = 0; } } srand(0); cfd = make_ipc(); if ( cfd < 0 ) exit(1); printhelp(); h = make_ipq(); if (daemonize) { FILE *logfile = 0; int pid; logfile = fopen(LOGFILE, "a"); if (!logfile) { perror("Failed to open " LOGFILE); exit(1); } if ( daemon(0, 0) < 0 ) { perror("Failed to daemonize"); exit(1); } if ( dup2(fileno(logfile), STDERR_FILENO) < 0 ) abort(); fclose(logfile); pid = writepid(); if (pid < 0) return -1; /* disable low water mark check for io pages */ if (setpriority(PRIO_PROCESS, pid, PRIO_SPECIAL_IO)) { perror("Unable to prioritize tapdisk proc"); exit(1); } TRACE("Start pfilter PID %d\n", pid); } do { ssize_t status; int type; status = ipq_read(h, buf, BUFSIZE, 0); if (status < 0) fail_retry(&h); type = ipq_message_type(buf); switch (type) { case NLMSG_ERROR: TRACE("pfilter: Received error message %d\n", ipq_get_msgerr(buf)); break; case IPQM_PACKET: { ipq_packet_msg_t *m = ipq_get_packet(buf); verdict = filter(); status = ipq_set_verdict(h, m->packet_id, verdict, 0, NULL); if (status < 0) fail_retry(&h); trace_data(verdict); break; } default: TRACE("pfilter: Unknown message type: %d\n", type); break; } } while (1); ipq_destroy_handle(h); return 0; }
int main(int argc, char *argv[]) { assert(sizeof(localbuf) >= getpagesize()); close(STDIN_FILENO); setlocale(LC_ALL, "C"); if (!configure(argc, argv)) return EXIT_FAILURE; if (unlikely(!read_proc_swaps()) || unlikely(!activate_old_swaps()) || unlikely(!check_memory_status())) return EXIT_FAILURE; if (erase) return retire_all() ? EXIT_SUCCESS : EXIT_FAILURE; install_sigs(); if (unlikely(!startpidfile())) return EXIT_FAILURE; /* Do a first iteration here so we can report any startup errors, and if we're * going to run as a daemon, we can do so in a steady state. */ handle_requirements(); /* If we're going to fork(), this is the last chance to read /proc/swaps in a * nonempty state before we do so. Make one last attempt to check its format. */ if (!proc_swaps_parsed()) { if (!read_proc_swaps()) return EXIT_FAILURE; #ifndef NO_CONFIG if (!quiet && !proc_swaps_parsed()) fputs("[/proc/swaps is empty, so cannot check its format]\n", stderr); #endif } if (godaemon) { #ifndef NO_CONFIG if (verbose) logm(LOG_DEBUG, "daemonizing..."); #endif const pid_t pid = daemonize(); if (unlikely(pid < 0)) { rmpidfile(); return EXIT_FAILURE; } if (pid > 0) { /* New process, so new pid. Parent process rewrites pidfile. We do this * from the parent, not the child process so that we're sure that the * pidfile is in a stable state when the parent exits. */ lseek(pidfd, 0, SEEK_SET); #ifndef NO_CONFIG if (verbose) logm(LOG_DEBUG, "got process id %d", pid); #endif return writepid(pid) ? EXIT_SUCCESS : EXIT_FAILURE; } } finishpidfile(); if (godaemon) { close(STDERR_FILENO); close(STDOUT_FILENO); // From here on std output is pointless in daemon mode. Use syslog instead. log_start(argv[0]); } // Central loop for (++runclock; !stop; ++runclock) { if (unlikely(print_status)) print_status = false, dump_stats(); else if (unlikely(adjust_swap)) adjust_swap = false, request_diet(); else handle_requirements(); sleep(1); } int result = EXIT_SUCCESS; #ifndef NO_CONFIG /* If we're worried about attackers getting unguarded access to the disk, we * need to retire and erase all swap files to keep them secret. */ if (paranoid && !retire_all()) result = EXIT_FAILURE; #endif rmpidfile(); log_close(); return result; }
/************************* Proces principal *************************/ int main () { // Variables per a recordar el pid de principal i hores. Tambe minuts, per a tenir-ho controlat. int pidP; int pidH; int mm; // Variables per a rebre interrupcions de sortida de proces. sigset_t mask, oldmask; // Inicialitzant whilemain per continuar adequadament. whilemain = 1; // Diem quins senyals volem fer cas: signal ( SIGCONT, minut ); signal ( SIGTERM, killing ); // Escrivim el nostre pid, si hi ha un problema, ho diem i acabem. if ( writepid ( "minutos.pid" ) ) return 1; // Espera a rebre nova senyal. Suposarem que si s'ha enviat una senyal abans, no i farem cas. // El usuari ho podra saber perque no ha aparegut per pantalla el "Llegint el pid dels demes". // I normalment, aixo no pasara, ja que ha d'inicialitzar tots els altres procesos. pause (); // Ara toca llegir de principal i hores, si hi ha un problema, ho diem i acabem. if ( readpid ( "principal.pid", &pidP, "minutos" ) ) return 1; if ( readpid ( "horas.pid", &pidH, "minutos" ) ) return 1; // Inicialitzem les variables abans d'entrar dins el while. mm = 0; // Ajustant l'espera a senyals. sigemptyset ( &mask ); sigaddset ( &mask, SIGTERM ); // Ara fara que nomes rebra la senyal de SIGTERM quan estigui dins de 'sigsuspend'. sigprocmask ( SIG_BLOCK, &mask, &oldmask ); // Comenza el programa en si while ( whilemain ) { // Es un pause, menys per SIGTERM, que nomes el rebra quan la crida sigui feta. sigsuspend ( &oldmask ); // Nomes envia un sol senyal per minut. // Aixo es degut a haver-me trobat errors: // - 0:59:59 >> 0:60: 0 // - 0:59:59 >> 1: 1: 0 // Per evitar aquests dos possibles errors, nomes enviem una senyal. if ( ++mm == 60 ) { mm = 0; kill ( pidH, SIGCONT ); } else kill ( pidP, SIGUSR2 ); } return 0; }
int main(int argc, char *argv[]) { const char *prog = xbasename(argv[0]); int i, cmd = 0, checking_flag = 0; printf("Network UPS Tools %s %s\n", prog, UPS_VERSION); /* if no configuration file is specified on the command line, use default */ configfile = xmalloc(SMALLBUF); snprintf(configfile, SMALLBUF, "%s/upsmon.conf", confpath()); configfile = xrealloc(configfile, strlen(configfile) + 1); run_as_user = xstrdup(RUN_AS_USER); while ((i = getopt(argc, argv, "+Dhic:f:pu:VK46")) != -1) { switch (i) { case 'c': if (!strncmp(optarg, "fsd", strlen(optarg))) cmd = SIGCMD_FSD; if (!strncmp(optarg, "stop", strlen(optarg))) cmd = SIGCMD_STOP; if (!strncmp(optarg, "reload", strlen(optarg))) cmd = SIGCMD_RELOAD; /* bad command name given */ if (cmd == 0) help(argv[0]); break; case 'D': nut_debug_level++; break; case 'f': free(configfile); configfile = xstrdup(optarg); break; case 'h': help(argv[0]); break; case 'K': checking_flag = 1; break; case 'p': use_pipe = 0; break; case 'u': free(run_as_user); run_as_user = xstrdup(optarg); break; case 'V': /* just show the banner */ exit(EXIT_SUCCESS); case '4': opt_af = AF_INET; break; case '6': opt_af = AF_INET6; break; default: help(argv[0]); break; } } if (cmd) { sendsignal(prog, cmd); exit(EXIT_SUCCESS); } /* otherwise, we are being asked to start. * so check if a previous instance is running by sending signal '0' * (Ie 'kill <pid> 0') */ if (sendsignal(prog, 0) == 0) { printf("Fatal error: A previous upsmon instance is already running!\n"); printf("Either stop the previous instance first, or use the 'reload' command.\n"); exit(EXIT_FAILURE); } argc -= optind; argv += optind; open_syslog(prog); loadconfig(); if (checking_flag) exit(check_pdflag()); if (shutdowncmd == NULL) printf("Warning: no shutdown command defined!\n"); /* we may need to get rid of a flag from a previous shutdown */ if (powerdownflag != NULL) clear_pdflag(); /* FIXME (else): POWERDOWNFLAG is not defined!! * => fallback to a default value */ if (totalpv < minsupplies) { printf("\nFatal error: insufficient power configured!\n\n"); printf("Sum of power values........: %d\n", totalpv); printf("Minimum value (MINSUPPLIES): %d\n", minsupplies); printf("\nEdit your upsmon.conf and change the values.\n"); exit(EXIT_FAILURE); } if (nut_debug_level < 1) { background(); } else { upsdebugx(1, "debug level is '%d'", nut_debug_level); } /* only do the pipe stuff if the user hasn't disabled it */ if (use_pipe) { struct passwd *new_uid = get_user_pwent(run_as_user); /* === root parent and unprivileged child split here === */ start_pipe(); /* write the pid file now, as we will soon lose root */ writepid(prog); become_user(new_uid); } else { upslogx(LOG_INFO, "Warning: running as one big root process by request (upsmon -p)"); writepid(prog); } /* prep our signal handlers */ setup_signals(); /* reopen the log for the child process */ closelog(); open_syslog(prog); while (exit_flag == 0) { utype_t *ups; /* check flags from signal handlers */ if (userfsd) forceshutdown(); if (reload_flag) reload_conf(); for (ups = firstups; ups != NULL; ups = ups->next) pollups(ups); recalc(); /* make sure the parent hasn't died */ if (use_pipe) check_parent(); /* reap children that have exited */ waitpid(-1, NULL, WNOHANG); sleep(sleepval); } upslogx(LOG_INFO, "Signal %d: exiting", exit_flag); upsmon_cleanup(); exit(EXIT_SUCCESS); }
int fakeidentd_main(int argc, char **argv) { int fd; pid_t pid; /* FD_ZERO(&G.readfds); - in bss, already zeroed */ FD_SET(0, &G.readfds); /* handle -b <ip> parameter */ getopt32(argc, argv, "b:", &bind_ip_address); /* handle optional REPLY STRING */ if (optind < argc) G.identuser = argv[optind]; else G.identuser = "******"; writepid(); signal(SIGTERM, handlexitsigs); signal(SIGINT, handlexitsigs); signal(SIGQUIT, handlexitsigs); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); /* ignore closed connections when writing */ fd = create_and_bind_stream_or_die(bind_ip_address, bb_lookup_port("identd", "tcp", 113)); xlisten(fd, 5); pid = fork(); if (pid < 0) bb_perror_msg_and_die("fork"); if (pid != 0) /* parent */ exit(0); /* child */ setsid(); movefd(fd, 0); while (fd) close(fd--); openlog(applet_name, 0, LOG_DAEMON); logmode = LOGMODE_SYSLOG; /* main loop where we process all events and never exit */ while (1) { fd_set rfds = G.readfds; struct timeval tv = { 15, 0 }; int i; int tim = time(NULL); select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL); for (i = G.conncnt - 1; i >= 0; i--) { int s = i + FCS; if (FD_ISSET(s, &rfds)) { char *buf = conns[i].buf; unsigned len = conns[i].len; unsigned l; l = read(s, buf + len, sizeof(conns[0].buf) - len); if (l > 0) { if (checkInput(buf, len, l)) { reply(s, buf); goto deleteconn; } else if (len + l >= sizeof(conns[0].buf)) { replyError(s, "X-INVALID-REQUEST"); goto deleteconn; } else { conns[i].len += l; } } else { goto deleteconn; } conns[i].lasttime = tim; continue; deleteconn: deleteConn(s); } else { /* implement as time_after() in linux kernel sources ... */ if (conns[i].lasttime + MAXIDLETIME <= tim) { replyError(s, "X-TIMEOUT"); deleteConn(s); } } } if (FD_ISSET(0, &rfds)) { int s = accept(0, NULL, 0); if (s < 0) { if (errno != EINTR) bb_perror_msg("accept"); } else { if (G.conncnt == MAXCONNS) i = closeOldest(); else i = G.conncnt++; movefd(s, i + FCS); /* move if not already there */ FD_SET(i + FCS, &G.readfds); conns[i].len = 0; conns[i].lasttime = time(NULL); } } } /* end of while (1) */ return 0; }
int main(int argc, char *argv[]) { ni_status status; ni_name myname = argv[0]; int create = 0; int log_pri = LOG_NOTICE; ni_name dbsource_name = NULL; ni_name dbsource_addr = NULL; ni_name dbsource_tag = NULL; struct rlimit rlim; char *str; unsigned db_checksum; FILE *logf; int nctoken; logf = NULL; forcedIsRoot = 0; Argv = argv; /* Save program and argument information for setproctitle */ Argc = argc; argc--; argv++; while (argc > 0 && **argv == '-') { if (strcmp(*argv, "-d") == 0) { debug = 1; log_pri = LOG_DEBUG; if (argc < 2) logf = stderr; else { debug = atoi(argv[1]); argc -= 1; argv += 1; } } else if (strcmp(*argv, "-l") == 0) { if (argc < 2) usage(myname); else { log_pri = atoi(argv[1]); argc -= 1; argv += 1; } } else if (strcmp(*argv, "-n") == 0) forcedIsRoot = 1; else if (strcmp(*argv, "-s") == 0) standalone = 1; else if (strcmp(*argv, "-m") == 0) create++; else if (strcmp(*argv, "-c") == 0) { if (argc < 4) usage(myname); create++; dbsource_name = argv[1]; dbsource_addr = argv[2]; dbsource_tag = argv[3]; argc -= 3; argv += 3; } else usage(myname); argc--; argv++; } if (argc != 1) usage(myname); if (debug == 0) { closeall(); if (standalone == 1) daemon(1, 1); } db_tag = malloc(strlen(argv[0]) + 1); strcpy(db_tag, argv[0]); str = malloc(strlen("netinfod ") + strlen(db_tag) + 1); sprintf(str, "netinfod %s", db_tag); system_log_open(str, (LOG_NDELAY | LOG_PID), LOG_NETINFO, logf); free(str); system_log_set_max_priority(log_pri); system_log(LOG_DEBUG, "version %s (pid %d) - starting", _PROJECT_VERSION_, getpid()); rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &rlim); rlim.rlim_cur = rlim.rlim_max = FD_SETSIZE; setrlimit(RLIMIT_NOFILE, &rlim); umask(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); srandom(gethostid() ^ time(NULL)); readall_syslock = syslock_new(0); lockup_syslock= syslock_new(0); cleanupwait = CLEANUPWAIT; auth_count[GOOD] = 0; auth_count[BAD] = 0; auth_count[WGOOD] = 0; auth_count[WBAD] = 0; if (create) { if (dbsource_addr == NULL) { system_log(LOG_DEBUG, "creating master"); status = dir_mastercreate(db_tag); } else { system_log(LOG_DEBUG, "creating clone"); status = dir_clonecreate(db_tag, dbsource_name, dbsource_addr, dbsource_tag); } if (status != NI_OK) { system_log_close(); exit(status); } } nctoken = -1; notify_register_signal(NETWORK_CHANGE_NOTIFICATION, SIGHUP, &nctoken); if (standalone == 0) signal(SIGTERM, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, (void *)catch_sighup); signal(SIGCHLD, (void *)readall_catcher); if (debug == 0) { signal(SIGINT, (void *)dblock_catcher); if (standalone == 0) { if (setsid() < 0) syslog(LOG_WARNING, "setsid failed: %m"); } } writepid(db_tag); status = start_service(db_tag); if (status != NI_OK) { system_log(LOG_ERR, "start_service failed: %s - exiting", ni_error(status)); system_log_close(); exit(status); } setproctitle("netinfod %s (%s)", db_tag, i_am_clone ? "clone" : "master"); if (i_am_clone) { system_log(LOG_DEBUG, "checking clone"); cloneReadallResponseOK = get_clone_readall(db_ni); dir_clonecheck(); if (get_sanitycheck(db_ni)) sanitycheck(db_tag); system_log(LOG_DEBUG, "finished clone check"); } else { system_log(LOG_DEBUG, "setting up master server"); promote_admins = get_promote_admins(db_ni); get_readall_info(db_ni, &max_readall_proxies, &strict_proxies); max_subthreads = get_max_subthreads(db_ni); update_latency_secs = get_update_latency(db_ni); /* Tracking readall proxy pids uses ObjC, so isolate it */ initialize_readall_proxies(-1 == max_readall_proxies ? MAX_READALL_PROXIES : max_readall_proxies); system_log(LOG_DEBUG, "starting notify thread"); (void) notify_start(); } /* Shutdown gracefully after this point */ if (standalone == 1) signal(SIGTERM, (void *)sig_shutdown); signal(SIGUSR1, (void *)sig_shutdown); system_log(LOG_DEBUG, "starting RPC service"); ni_svc_run(_rpc_dtablesize() - (FD_SLOPSIZE + max_subthreads)); system_log(LOG_DEBUG, "shutting down"); /* * Tell the readall proxies to shut down */ if (readall_proxies > 0) { system_log(LOG_INFO, "killing %d readall prox%s", readall_proxies, 1 == readall_proxies ? "y" : "ies"); if (!kill_proxies()) system_log(LOG_WARNING, "some readall proxies still running"); } db_checksum = ni_getchecksum(db_ni); ni_shutdown(db_ni, db_checksum); system_log(LOG_INFO, "exiting; checksum %u", db_checksum); system_log_close(); exit(0); }
/** daemonize, drop user privileges and chroot if needed */ static void perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode, const char** cfgfile, int need_pidfile) { #ifdef HAVE_KILL int pidinchroot; #endif #ifdef HAVE_GETPWNAM struct passwd *pwd = NULL; if(cfg->username && cfg->username[0]) { if((pwd = getpwnam(cfg->username)) == NULL) fatal_exit("user '%s' does not exist.", cfg->username); /* endpwent below, in case we need pwd for setusercontext */ } #endif #ifdef UB_ON_WINDOWS w_config_adjust_directory(cfg); #endif /* read ssl keys while superuser and outside chroot */ #ifdef HAVE_SSL if(!(daemon->rc = daemon_remote_create(cfg))) fatal_exit("could not set up remote-control"); if(cfg->ssl_service_key && cfg->ssl_service_key[0]) { if(!(daemon->listen_sslctx = listen_sslctx_create( cfg->ssl_service_key, cfg->ssl_service_pem, NULL))) fatal_exit("could not set up listen SSL_CTX"); if(cfg->tls_ciphers && cfg->tls_ciphers[0]) { if (!SSL_CTX_set_cipher_list(daemon->listen_sslctx, cfg->tls_ciphers)) { fatal_exit("failed to set tls-cipher %s", cfg->tls_ciphers); } } #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES if(cfg->tls_ciphersuites && cfg->tls_ciphersuites[0]) { if (!SSL_CTX_set_ciphersuites(daemon->listen_sslctx, cfg->tls_ciphersuites)) { fatal_exit("failed to set tls-ciphersuites %s", cfg->tls_ciphersuites); } } #endif if(cfg->tls_session_ticket_keys.first && cfg->tls_session_ticket_keys.first->str[0] != 0) { if(!listen_sslctx_setup_ticket_keys(daemon->listen_sslctx, cfg->tls_session_ticket_keys.first)) { fatal_exit("could not set session ticket SSL_CTX"); } } } if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL, cfg->tls_cert_bundle, cfg->tls_win_cert))) fatal_exit("could not set up connect SSL_CTX"); #endif /* init syslog (as root) if needed, before daemonize, otherwise * a fork error could not be printed since daemonize closed stderr.*/ if(cfg->use_syslog) { log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); } /* if using a logfile, we cannot open it because the logfile would * be created with the wrong permissions, we cannot chown it because * we cannot chown system logfiles, so we do not open at all. * So, using a logfile, the user does not see errors unless -d is * given to unbound on the commandline. */ #ifdef HAVE_KILL /* true if pidfile is inside chrootdir, or nochroot */ pidinchroot = need_pidfile && (!(cfg->chrootdir && cfg->chrootdir[0]) || (cfg->chrootdir && cfg->chrootdir[0] && strncmp(cfg->pidfile, cfg->chrootdir, strlen(cfg->chrootdir))==0)); /* check old pid file before forking */ if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) { /* calculate position of pidfile */ if(cfg->pidfile[0] == '/') daemon->pidfile = strdup(cfg->pidfile); else daemon->pidfile = fname_after_chroot(cfg->pidfile, cfg, 1); if(!daemon->pidfile) fatal_exit("pidfile alloc: out of memory"); checkoldpid(daemon->pidfile, pidinchroot); } #endif /* daemonize because pid is needed by the writepid func */ if(!debug_mode && cfg->do_daemonize) { detach(); } /* write new pidfile (while still root, so can be outside chroot) */ #ifdef HAVE_KILL if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) { writepid(daemon->pidfile, getpid()); if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 && pidinchroot) { # ifdef HAVE_CHOWN if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) { verbose(VERB_QUERY, "cannot chown %u.%u %s: %s", (unsigned)cfg_uid, (unsigned)cfg_gid, daemon->pidfile, strerror(errno)); } # endif /* HAVE_CHOWN */ } } #else (void)daemon; (void)need_pidfile; #endif /* HAVE_KILL */ /* Set user context */ #ifdef HAVE_GETPWNAM if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1) { #ifdef HAVE_SETUSERCONTEXT /* setusercontext does initgroups, setuid, setgid, and * also resource limits from login config, but we * still call setresuid, setresgid to be sure to set all uid*/ if(setusercontext(NULL, pwd, cfg_uid, (unsigned) LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0) log_warn("unable to setusercontext %s: %s", cfg->username, strerror(errno)); #endif /* HAVE_SETUSERCONTEXT */ } #endif /* HAVE_GETPWNAM */ /* box into the chroot */ #ifdef HAVE_CHROOT if(cfg->chrootdir && cfg->chrootdir[0]) { if(chdir(cfg->chrootdir)) { fatal_exit("unable to chdir to chroot %s: %s", cfg->chrootdir, strerror(errno)); } verbose(VERB_QUERY, "chdir to %s", cfg->chrootdir); if(chroot(cfg->chrootdir)) fatal_exit("unable to chroot to %s: %s", cfg->chrootdir, strerror(errno)); if(chdir("/")) fatal_exit("unable to chdir to / in chroot %s: %s", cfg->chrootdir, strerror(errno)); verbose(VERB_QUERY, "chroot to %s", cfg->chrootdir); if(strncmp(*cfgfile, cfg->chrootdir, strlen(cfg->chrootdir)) == 0) (*cfgfile) += strlen(cfg->chrootdir); /* adjust stored pidfile for chroot */ if(daemon->pidfile && daemon->pidfile[0] && strncmp(daemon->pidfile, cfg->chrootdir, strlen(cfg->chrootdir))==0) { char* old = daemon->pidfile; daemon->pidfile = strdup(old+strlen(cfg->chrootdir)); free(old); if(!daemon->pidfile) log_err("out of memory in pidfile adjust"); } daemon->chroot = strdup(cfg->chrootdir); if(!daemon->chroot) log_err("out of memory in daemon chroot dir storage"); } #else (void)cfgfile; #endif /* change to working directory inside chroot */ if(cfg->directory && cfg->directory[0]) { char* dir = cfg->directory; if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(dir, cfg->chrootdir, strlen(cfg->chrootdir)) == 0) dir += strlen(cfg->chrootdir); if(dir[0]) { if(chdir(dir)) { fatal_exit("Could not chdir to %s: %s", dir, strerror(errno)); } verbose(VERB_QUERY, "chdir to %s", dir); } } /* drop permissions after chroot, getpwnam, pidfile, syslog done*/ #ifdef HAVE_GETPWNAM if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1) { # ifdef HAVE_INITGROUPS if(initgroups(cfg->username, cfg_gid) != 0) log_warn("unable to initgroups %s: %s", cfg->username, strerror(errno)); # endif /* HAVE_INITGROUPS */ # ifdef HAVE_ENDPWENT endpwent(); # endif #ifdef HAVE_SETRESGID if(setresgid(cfg_gid,cfg_gid,cfg_gid) != 0) #elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID) if(setregid(cfg_gid,cfg_gid) != 0) #else /* use setgid */ if(setgid(cfg_gid) != 0) #endif /* HAVE_SETRESGID */ fatal_exit("unable to set group id of %s: %s", cfg->username, strerror(errno)); #ifdef HAVE_SETRESUID if(setresuid(cfg_uid,cfg_uid,cfg_uid) != 0) #elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID) if(setreuid(cfg_uid,cfg_uid) != 0) #else /* use setuid */ if(setuid(cfg_uid) != 0) #endif /* HAVE_SETRESUID */ fatal_exit("unable to set user id of %s: %s", cfg->username, strerror(errno)); verbose(VERB_QUERY, "drop user privileges, run as %s", cfg->username); } #endif /* HAVE_GETPWNAM */ /* file logging inited after chroot,chdir,setuid is done so that * it would succeed on SIGHUP as well */ if(!cfg->use_syslog) log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); }
int main(int argc, char *argv[]){ FILE *fd; job_registry_entry *en; time_t now; time_t purge_time=0; time_t last_consistency_check=0; char *pidfile=NULL; char *first_duplicate=NULL; struct pollfd *remupd_pollset = NULL; int remupd_nfds; int version=0; int first=TRUE; int tmptim; time_t finalquery_start_date; int loop_interval=DEFAULT_LOOP_INTERVAL; int rc; int c; pthread_t RecUpdNetThd; int confirm_time=0; static int help; static int short_help; bact.njobs = 0; bact.jobs = NULL; while (1) { static struct option long_options[] = { {"help", no_argument, &help, 1}, {"usage", no_argument, &short_help, 1}, {"nodaemon", no_argument, 0, 'o'}, {"version", no_argument, 0, 'v'}, {"prefix", required_argument, 0, 'p'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long (argc, argv, "vop:",long_options, &option_index); if (c == -1){ break; } switch (c) { case 0: if (long_options[option_index].flag != 0){ break; } case 'v': version=1; break; case 'o': nodmn=1; break; case 'p': break; case '?': break; default: abort (); } } if(help){ usage(); } if(short_help){ short_usage(); } argv0 = argv[0]; signal(SIGHUP,sighup); if(version) { printf("%s Version: %s\n",progname,VERSION); exit(EXIT_SUCCESS); } /* Checking configuration */ check_config_file("UPDATER"); cha = config_read(NULL); if (cha == NULL) { fprintf(stderr,"Error reading config: "); perror(""); return -1; } config_setenv(NULL); ret = config_get("bupdater_child_poll_timeout",cha); if (ret != NULL){ tmptim=atoi(ret->value); if (tmptim > 0) bfunctions_poll_timeout = tmptim*1000; } ret = config_get("bupdater_debug_level",cha); if (ret != NULL){ debug=atoi(ret->value); } ret = config_get("bupdater_debug_logfile",cha); if (ret != NULL){ debuglogname=strdup(ret->value); if(debuglogname == NULL){ sysfatal("strdup failed for debuglogname in main: %r"); } } if(debug <=0){ debug=0; } if(debuglogname){ if((debuglogfile = fopen(debuglogname, "a+"))==0){ debug = 0; } } else { debug = 0; } ret = config_get("slurm_binpath",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key slurm_binpath not found\n",argv0); } else { slurm_binpath=strdup(ret->value); if(slurm_binpath == NULL){ sysfatal("strdup failed for slurm_binpath in main: %r"); } } ret = config_get("job_registry",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key job_registry not found\n",argv0); sysfatal("job_registry not defined. Exiting"); } else { registry_file=strdup(ret->value); if(registry_file == NULL){ sysfatal("strdup failed for registry_file in main: %r"); } } ret = config_get("purge_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key purge_interval not found using the default:%d\n",argv0,purge_interval); } else { purge_interval=atoi(ret->value); } ret = config_get("finalstate_query_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key finalstate_query_interval not found using the default:%d\n",argv0,finalstate_query_interval); } else { finalstate_query_interval=atoi(ret->value); } ret = config_get("alldone_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key alldone_interval not found using the default:%d\n",argv0,alldone_interval); } else { alldone_interval=atoi(ret->value); } ret = config_get("bupdater_consistency_check_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key bupdater_consistency_check_interval not found using the default:%d\n",argv0,bupdater_consistency_check_interval); } else { bupdater_consistency_check_interval=atoi(ret->value); } ret = config_get("bupdater_pidfile",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key bupdater_pidfile not found\n",argv0); } else { pidfile=strdup(ret->value); if(pidfile == NULL){ sysfatal("strdup failed for pidfile in main: %r"); } } ret = config_get("bupdater_loop_interval",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key bupdater_loop_interval not found - using the default:%d\n",argv0,loop_interval); } else { loop_interval=atoi(ret->value); } ret = config_get("job_registry_use_mmap",cha); if (ret == NULL){ do_log(debuglogfile, debug, 1, "%s: key job_registry_use_mmap not found. Default is NO\n",argv0); } else { do_log(debuglogfile, debug, 1, "%s: key job_registry_use_mmap is set to %s\n",argv0,ret->value); } remupd_conf = config_get("job_registry_add_remote",cha); if (remupd_conf == NULL){ do_log(debuglogfile, debug, 1, "%s: key job_registry_add_remote not found\n",argv0); }else{ if (job_registry_updater_setup_receiver(remupd_conf->values,remupd_conf->n_values,&remupd_head) < 0){ do_log(debuglogfile, debug, 1, "%s: Cannot set network receiver(s) up for remote update\n",argv0); fprintf(stderr,"%s: Cannot set network receiver(s) up for remote update \n",argv0); } if (remupd_head == NULL){ do_log(debuglogfile, debug, 1, "%s: Cannot find values for network endpoints in configuration file (attribute 'job_registry_add_remote').\n",argv0); fprintf(stderr,"%s: Cannot find values for network endpoints in configuration file (attribute 'job_registry_add_remote').\n", argv0); } if ((remupd_nfds = job_registry_updater_get_pollfd(remupd_head, &remupd_pollset)) < 0){ do_log(debuglogfile, debug, 1, "%s: Cannot setup poll set for receiving data.\n",argv0); fprintf(stderr,"%s: Cannot setup poll set for receiving data.\n", argv0); } if (remupd_pollset == NULL || remupd_nfds == 0){ do_log(debuglogfile, debug, 1, "%s: No poll set available for receiving data.\n",argv0); fprintf(stderr,"%s: No poll set available for receiving data.\n",argv0); } } if( !nodmn ) daemonize(); if( pidfile ){ writepid(pidfile); free(pidfile); } rha=job_registry_init(registry_file, BY_BATCH_ID); if (rha == NULL){ do_log(debuglogfile, debug, 1, "%s: Error initialising job registry %s\n",argv0,registry_file); fprintf(stderr,"%s: Error initialising job registry %s :",argv0,registry_file); perror(""); } if (remupd_conf != NULL){ pthread_create(&RecUpdNetThd, NULL, (void *(*)(void *))ReceiveUpdateFromNetwork, (void *)NULL); if (job_registry_updater_setup_sender(remupd_conf->values,remupd_conf->n_values,0,&remupd_head_send) < 0){ do_log(debuglogfile, debug, 1, "%s: Cannot set network sender(s) up for remote update\n",argv0); fprintf(stderr,"%s: Cannot set network sender(s) up for remote update \n",argv0); } if (remupd_head_send == NULL){ do_log(debuglogfile, debug, 1, "%s: Cannot find values for network endpoints in configuration file (attribute 'job_registry_add_remote').\n",argv0); fprintf(stderr,"%s: Cannot find values for network endpoints in configuration file (attribute 'job_registry_add_remote').\n", argv0); } } config_free(cha); for(;;){ /* Purge old entries from registry */ now=time(0); if(now - purge_time > 86400){ if((rc=job_registry_purge(registry_file, now-purge_interval,0))<0){ do_log(debuglogfile, debug, 1, "%s: Error purging job registry %s:%d\n",argv0,registry_file,rc); fprintf(stderr,"%s: Error purging job registry %s :",argv0,registry_file); perror(""); } purge_time=time(0); } now=time(0); if(now - last_consistency_check > bupdater_consistency_check_interval){ if(job_registry_check_index_key_uniqueness(rha,&first_duplicate)==JOB_REGISTRY_FAIL){ do_log(debuglogfile, debug, 1, "%s: Found job registry duplicate entry. The first one is:%s.\nJobid should be removed or registry directory should be removed.\n",argv0,first_duplicate); fprintf(stderr,"%s: Found job registry duplicate entry. The first one is:%s.\nJobid should be removed or registry directory should be removed.",argv0,first_duplicate); } last_consistency_check=time(0); } IntStateQuery(); fd = job_registry_open(rha, "r"); if (fd == NULL){ do_log(debuglogfile, debug, 1, "%s: Error opening job registry %s\n",argv0,registry_file); fprintf(stderr,"%s: Error opening job registry %s :",argv0,registry_file); perror(""); sleep(loop_interval); continue; } if (job_registry_rdlock(rha, fd) < 0){ do_log(debuglogfile, debug, 1, "%s: Error read locking job registry %s\n",argv0,registry_file); fprintf(stderr,"%s: Error read locking job registry %s :",argv0,registry_file); perror(""); sleep(loop_interval); continue; } job_registry_firstrec(rha,fd); fseek(fd,0L,SEEK_SET); first=TRUE; finalquery_start_date = time(0); while ((en = job_registry_get_next(rha, fd)) != NULL){ if((bupdater_lookup_active_jobs(&bact,en->batch_id) != BUPDATER_ACTIVE_JOBS_SUCCESS) && en->status!=REMOVED && en->status!=COMPLETED){ do_log(debuglogfile, debug, 3, "%s: bupdater_lookup_active_jobs returned: %d for jobid: %s\n",argv0,bupdater_lookup_active_jobs(&bact,en->batch_id),en->batch_id); confirm_time=atoi(en->updater_info); if(confirm_time==0){ confirm_time=en->mdate; } /* Assign Status=4 and ExitStatus=999 to all entries that after alldone_interval are still not in a final state(3 or 4)*/ if(now-confirm_time>alldone_interval){ AssignFinalState(en->batch_id); free(en); continue; } if(en->status==IDLE && strlen(en->updater_info)>0){ if (en->mdate < finalquery_start_date){ finalquery_start_date=en->mdate; } do_log(debuglogfile, debug, 2, "%s: FinalStateQuery needed for jobid=%s with status=%d\n",argv0,en->batch_id,en->status); runfinal=TRUE; }else if((now-confirm_time>finalstate_query_interval) && (now > next_finalstatequery)){ if (en->mdate < finalquery_start_date){ finalquery_start_date=en->mdate; } do_log(debuglogfile, debug, 2, "%s: FinalStateQuery needed for jobid=%s with status=%d\n",argv0,en->batch_id,en->status); runfinal=TRUE; } } free(en); } if(runfinal_oldlogs){ FinalStateQuery(0,1); runfinal_oldlogs=FALSE; runfinal=FALSE; }else if(runfinal){ FinalStateQuery(finalquery_start_date,1); runfinal=FALSE; } fclose(fd); sleep(loop_interval); } job_registry_destroy(rha); return 0; }
int main(int argc, char* argv[]) { const char** local = NULL; int n_local = 0; const char* pidfile = NULL; int daemonize = 1; char ch; char* t; #ifdef TEST test(argc, argv); return 1; #endif /* Initialize the state stuff */ memset(&g_state, 0, sizeof(g_state)); g_state.rrddir = DEFAULT_WORK; g_state.confdir = DEFAULT_CONFIG; g_state.retries = DEFAULT_RETRIES; g_state.timeout = DEFAULT_TIMEOUT; /* Parse the arguments nicely */ while((ch = getopt(argc, argv, "b:c:d:m:Mp:r:t:w:V")) != -1) { switch(ch) { /* Bind address */ case 'b': local = xrealloc (local, sizeof (char*) * (n_local + 2)); local[n_local] = optarg; local[++n_local] = NULL; break; /* Config directory */ case 'c': g_state.confdir = optarg; break; /* Don't daemonize */ case 'd': daemonize = 0; debug_level = strtol(optarg, &t, 10); if(*t || debug_level > 4) errx(1, "invalid debug log level: %s", optarg); debug_level += LOG_ERR; break; /* mib directory */ case 'm': mib_directory = optarg; break; /* MIB load warnings */ case 'M': mib_warnings = 1; break; /* Write out a pid file */ case 'p': pidfile = optarg; break; /* The number of SNMP retries */ case 'r': g_state.retries = strtol(optarg, &t, 10); if(*t || g_state.retries < 0) errx(1, "invalid number of retries: %s", optarg); break; /* The default timeout */ case 't': g_state.timeout = strtol(optarg, &t, 10); if(*t || g_state.timeout <= 0) errx(1, "invalid timeout (must be above zero): %s", optarg); break; /* The work directory */ case 'w': g_state.rrddir = optarg; break; /* Print version number */ case 'V': version(); break; /* Usage information */ case '?': default: usage(); break; } } argc -= optind; argv += optind; if(argc != 0) usage(); /* No bind addresses specified, use defaults... */ if (local == NULL) { local = xrealloc (local, sizeof (char*) * 3); local[0] = "0.0.0.0"; local[1] = NULL; #ifdef HAVE_INET6 local[1] = "::"; local[2] = NULL; #endif } /* The mainloop server */ server_init(); /* Parse config and setup SNMP system */ rb_config_parse(); /* As an optimization we unload the MIB processing data here */ mib_uninit(); /* Rev up the main engine */ snmp_engine_init (local, g_state.retries); rb_poll_engine_init(); free (local); n_local = 0; local = NULL; if(daemonize) { /* Fork a daemon nicely */ if(daemon(0, 0) == -1) err(1, "couldn't fork as a daemon"); log_debug("running as a daemon"); daemonized = 1; } /* Setup the Async DNS resolver */ if(async_resolver_init() < 0) { log_error("couldn't initialize resolver"); /* Allow things to proceed without resolver */ } /* Handle signals */ signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGINT, on_quit); signal(SIGTERM, on_quit); siginterrupt(SIGINT, 1); siginterrupt(SIGTERM, 1); /* Open the system log */ openlog("rrdbotd", 0, LOG_DAEMON); if(pidfile != NULL) writepid(pidfile); log_info("rrdbotd version " VERSION " started up"); /* Now let it go */ if(server_run() == -1) err(1, "critical failure running SNMP engine"); log_info("rrdbotd stopping"); /* Cleanups */ rb_poll_engine_uninit(); snmp_engine_stop(); rb_config_free(); async_resolver_uninit(); server_uninit(); if(pidfile != NULL) removepid(pidfile); return 0; }
int main(int argc, char * argv[]) { uid_t nobody, nogrp; memset(conns, 0, sizeof conns); memset(&G, 0, sizeof G); FD_ZERO(&G.readfds); FD_SET(0, &G.readfds); if (argv[1]) { if (argv[1][0] == '-') { if (argv[1][1] == 'V') { printversion('.'); return 0; } else { fdprintf(2, "%s: invalid option -- %c\n", argv[0], argv[1][1]); fdprintf(2, "Usage: %s [-V] " IU_IN_USAGESTR "\n", argv[0]); return 1; } } else { SET_IU(argv[1], argc - 1); } } else { SET_IU(nobodystr, 1); } #ifndef DEBUG close(1); /* not debugging, openlog() hopefully uses fd 1. */ #else close(3); /* debugging, TRACE uses fd 1, openlog() hopefully fd 3 */ #endif openlog("identd", LOG_CONS, LOG_DAEMON); { struct passwd * pw = getpwnam(nobodystr); if (pw) { nobody = pw->pw_uid; nogrp = pw->pw_gid; } else { syslog(LOG_CRIT, "Cannot find user `nobody': %s", strerrno()); return -1; } } if (inetbind(getport()) < 0) { return -1; } /* */ { int i; for (i = FCS; i < MAXCONNS + FCS; i++) { close(i); } } #ifdef DEBUG #ifndef LOG_PERROR #define LOG_PERROR 0 #endif openlog("identd", LOG_PERROR, LOG_DAEMON); #else /* not DEBUG */ godaemon(); openlog("identd", 0, LOG_DAEMON); close(2); signal(SIGHUP, SIG_IGN); #endif /* DEBUG */ signal(SIGPIPE, SIG_IGN); /* connection closed when writing (raises ???) */ writepid(nobody, nogrp); setegid(nogrp); setgid(nogrp); setuid(nobody); seteuid(nobody); { int i; for (i = 0; i < 4; i++) { char * id = (char)NULL; unsigned int rv = 0; switch (i) { case 0: rv = (unsigned int)getegid(); id = "egid"; break; case 1: rv = (unsigned int)getgid(); id = "gid"; break; case 2: rv = (unsigned int)geteuid(); id = "euid"; break; case 3: rv = (unsigned int)getuid(); id = "uid"; break; } if (rv == 0) { syslog(LOG_ERR, "Can not drop all root privileges (%s) !!! %s !!!", id, strerrno()); delpidfile(); return -1; } } } while (2) { fd_set rfds = G.readfds; struct timeval tv = { 15, 0 }; int i; int tim = time(NULL); TRACE(("calling select(): n = %d, rfds = 0x%x\n\n", G.conncnt + FCS, *(int *)&rfds)); select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL); for (i = G.conncnt - 1; i >= 0; i--) { int s = i + FCS; if (FD_ISSET(s, &rfds)) { char * buf = conns[i].buf; unsigned int len = conns[i].len; unsigned int l; TRACE(("data socket fd_isset %d\n", s)); if ((int)(l = read(s, buf + len, sizeof conns[0].buf - len)) > 0) { if (checkInput(buf, len, l)) { reply(s, buf); goto deleteconn; } else if (len + l >= sizeof conns[0].buf) { replyError(s, "X-INVALID-REQUEST"); goto deleteconn; } else { conns[i].len += l; } } else { goto deleteconn; } conns[i].lasttime = tim; continue; deleteconn: deleteConn(s); } else { /* implement as time_after() in linux kernel sources ... */ if (conns[i].lasttime + MAXIDLETIME <= tim) { replyError(s, "X-TIMEOUT"); deleteConn(s); } } } if (FD_ISSET(0, &rfds)) { int s = accept(0, NULL, 0); TRACE(("server socket fd_isset, %d accepted\n", s)); if (s < 0) { if (errno != EINTR) /* EINTR */ { syslog(LOG_ERR, "accept: %s", strerrno()); } } else { if (G.conncnt == MAXCONNS) { i = closeOldest(); } else { i = G.conncnt++; } if (s != i + FCS) { movesocket(s, i + FCS); } FD_SET(i + FCS, &G.readfds); conns[i].len = 0; conns[i].lasttime = time(NULL); } } } }
int main(int argc, char *argv[]) { /* Scratch variables... */ int c; pid_t oldpid; size_t i; struct sigaction action; #ifdef HAVE_GETPWNAM struct passwd *pwd = NULL; #endif /* HAVE_GETPWNAM */ struct addrinfo hints[2]; int hints_in_use = 1; char** nodes = NULL; /* array of address strings, size nsd.ifs */ const char *udp_port = 0; const char *tcp_port = 0; const char *configfile = CONFIGFILE; char* argv0 = (argv0 = strrchr(argv[0], '/')) ? argv0 + 1 : argv[0]; log_init(argv0); /* Initialize the server handler... */ memset(&nsd, 0, sizeof(struct nsd)); nsd.region = region_create(xalloc, free); nsd.dbfile = 0; nsd.pidfile = 0; nsd.server_kind = NSD_SERVER_MAIN; memset(&hints, 0, sizeof(*hints)*2); hints[0].ai_family = DEFAULT_AI_FAMILY; hints[0].ai_flags = AI_PASSIVE; hints[1].ai_family = DEFAULT_AI_FAMILY; hints[1].ai_flags = AI_PASSIVE; nsd.identity = 0; nsd.version = VERSION; nsd.username = 0; nsd.chrootdir = 0; nsd.nsid = NULL; nsd.nsid_len = 0; nsd.child_count = 0; nsd.maximum_tcp_count = 0; nsd.current_tcp_count = 0; nsd.grab_ip6_optional = 0; nsd.file_rotation_ok = 0; /* Set up our default identity to gethostname(2) */ if (gethostname(hostname, MAXHOSTNAMELEN) == 0) { nsd.identity = hostname; } else { log_msg(LOG_ERR, "failed to get the host name: %s - using default identity", strerror(errno)); nsd.identity = IDENTITY; } /* Parse the command line... */ while ((c = getopt(argc, argv, "46a:c:df:hi:I:l:N:n:P:p:s:u:t:X:V:v" #ifndef NDEBUG /* <mattthijs> only when configured with --enable-checking */ "F:L:" #endif /* NDEBUG */ )) != -1) { switch (c) { case '4': hints[0].ai_family = AF_INET; break; case '6': #ifdef INET6 hints[0].ai_family = AF_INET6; #else /* !INET6 */ error("IPv6 support not enabled."); #endif /* INET6 */ break; case 'a': add_interface(&nodes, &nsd, optarg); break; case 'c': configfile = optarg; break; case 'd': nsd.debug = 1; break; case 'f': nsd.dbfile = optarg; break; case 'h': usage(); exit(0); case 'i': nsd.identity = optarg; break; case 'I': if (nsd.nsid_len != 0) { /* can only be given once */ break; } if (strncasecmp(optarg, "ascii_", 6) == 0) { nsd.nsid = xalloc(strlen(optarg+6)); nsd.nsid_len = strlen(optarg+6); memmove(nsd.nsid, optarg+6, nsd.nsid_len); } else { if (strlen(optarg) % 2 != 0) { error("the NSID must be a hex string of an even length."); } nsd.nsid = xalloc(strlen(optarg) / 2); nsd.nsid_len = strlen(optarg) / 2; if (hex_pton(optarg, nsd.nsid, nsd.nsid_len) == -1) { error("hex string cannot be parsed '%s' in NSID.", optarg); } } break; case 'l': nsd.log_filename = optarg; break; case 'N': i = atoi(optarg); if (i <= 0) { error("number of child servers must be greater than zero."); } else { nsd.child_count = i; } break; case 'n': i = atoi(optarg); if (i <= 0) { error("number of concurrent TCP connections must greater than zero."); } else { nsd.maximum_tcp_count = i; } break; case 'P': nsd.pidfile = optarg; break; case 'p': if (atoi(optarg) == 0) { error("port argument must be numeric."); } tcp_port = optarg; udp_port = optarg; break; case 's': #ifdef BIND8_STATS nsd.st.period = atoi(optarg); #else /* !BIND8_STATS */ error("BIND 8 statistics not enabled."); #endif /* BIND8_STATS */ break; case 't': #ifdef HAVE_CHROOT nsd.chrootdir = optarg; #else /* !HAVE_CHROOT */ error("chroot not supported on this platform."); #endif /* HAVE_CHROOT */ break; case 'u': nsd.username = optarg; break; case 'V': verbosity = atoi(optarg); break; case 'v': version(); /* version exits */ break; #ifndef NDEBUG case 'F': sscanf(optarg, "%x", &nsd_debug_facilities); break; case 'L': sscanf(optarg, "%d", &nsd_debug_level); break; #endif /* NDEBUG */ case '?': default: usage(); exit(1); } } argc -= optind; /* argv += optind; */ /* Commandline parse error */ if (argc != 0) { usage(); exit(1); } if (strlen(nsd.identity) > UCHAR_MAX) { error("server identity too long (%u characters)", (unsigned) strlen(nsd.identity)); } if(!tsig_init(nsd.region)) error("init tsig failed"); /* Read options */ nsd.options = nsd_options_create(region_create_custom(xalloc, free, DEFAULT_CHUNK_SIZE, DEFAULT_LARGE_OBJECT_SIZE, DEFAULT_INITIAL_CLEANUP_SIZE, 1)); if(!parse_options_file(nsd.options, configfile, NULL, NULL)) { error("could not read config: %s\n", configfile); } if(!parse_zone_list_file(nsd.options)) { error("could not read zonelist file %s\n", nsd.options->zonelistfile); } if(nsd.options->do_ip4 && !nsd.options->do_ip6) { hints[0].ai_family = AF_INET; } #ifdef INET6 if(nsd.options->do_ip6 && !nsd.options->do_ip4) { hints[0].ai_family = AF_INET6; } #endif /* INET6 */ if(nsd.options->ip_addresses) { ip_address_option_type* ip = nsd.options->ip_addresses; while(ip) { add_interface(&nodes, &nsd, ip->address); ip = ip->next; } } if (verbosity == 0) verbosity = nsd.options->verbosity; #ifndef NDEBUG if (nsd_debug_level > 0 && verbosity == 0) verbosity = nsd_debug_level; #endif /* NDEBUG */ if(nsd.options->debug_mode) nsd.debug=1; if(!nsd.dbfile) { if(nsd.options->database) nsd.dbfile = nsd.options->database; else nsd.dbfile = DBFILE; } if(!nsd.pidfile) { if(nsd.options->pidfile) nsd.pidfile = nsd.options->pidfile; else nsd.pidfile = PIDFILE; } if(strcmp(nsd.identity, hostname)==0 || strcmp(nsd.identity,IDENTITY)==0) { if(nsd.options->identity) nsd.identity = nsd.options->identity; } if(nsd.options->version) { nsd.version = nsd.options->version; } if (nsd.options->logfile && !nsd.log_filename) { nsd.log_filename = nsd.options->logfile; } if(nsd.child_count == 0) { nsd.child_count = nsd.options->server_count; } #ifdef SO_REUSEPORT if(nsd.options->reuseport && nsd.child_count > 1) { nsd.reuseport = nsd.child_count; } #endif /* SO_REUSEPORT */ if(nsd.maximum_tcp_count == 0) { nsd.maximum_tcp_count = nsd.options->tcp_count; } nsd.tcp_timeout = nsd.options->tcp_timeout; nsd.tcp_query_count = nsd.options->tcp_query_count; nsd.tcp_mss = nsd.options->tcp_mss; nsd.outgoing_tcp_mss = nsd.options->outgoing_tcp_mss; nsd.ipv4_edns_size = nsd.options->ipv4_edns_size; nsd.ipv6_edns_size = nsd.options->ipv6_edns_size; if(udp_port == 0) { if(nsd.options->port != 0) { udp_port = nsd.options->port; tcp_port = nsd.options->port; } else { udp_port = UDP_PORT; tcp_port = TCP_PORT; } } #ifdef BIND8_STATS if(nsd.st.period == 0) { nsd.st.period = nsd.options->statistics; } #endif /* BIND8_STATS */ #ifdef HAVE_CHROOT if(nsd.chrootdir == 0) nsd.chrootdir = nsd.options->chroot; #ifdef CHROOTDIR /* if still no chrootdir, fallback to default */ if(nsd.chrootdir == 0) nsd.chrootdir = CHROOTDIR; #endif /* CHROOTDIR */ #endif /* HAVE_CHROOT */ if(nsd.username == 0) { if(nsd.options->username) nsd.username = nsd.options->username; else nsd.username = USER; } if(nsd.options->zonesdir && nsd.options->zonesdir[0]) { if(chdir(nsd.options->zonesdir)) { error("cannot chdir to '%s': %s", nsd.options->zonesdir, strerror(errno)); } DEBUG(DEBUG_IPC,1, (LOG_INFO, "changed directory to %s", nsd.options->zonesdir)); } /* EDNS0 */ edns_init_data(&nsd.edns_ipv4, nsd.options->ipv4_edns_size); #if defined(INET6) #if defined(IPV6_USE_MIN_MTU) || defined(IPV6_MTU) edns_init_data(&nsd.edns_ipv6, nsd.options->ipv6_edns_size); #else /* no way to set IPV6 MTU, send no bigger than that. */ if (nsd.options->ipv6_edns_size < IPV6_MIN_MTU) edns_init_data(&nsd.edns_ipv6, nsd.options->ipv6_edns_size); else edns_init_data(&nsd.edns_ipv6, IPV6_MIN_MTU); #endif /* IPV6 MTU) */ #endif /* defined(INET6) */ if (nsd.nsid_len == 0 && nsd.options->nsid) { if (strlen(nsd.options->nsid) % 2 != 0) { error("the NSID must be a hex string of an even length."); } nsd.nsid = xalloc(strlen(nsd.options->nsid) / 2); nsd.nsid_len = strlen(nsd.options->nsid) / 2; if (hex_pton(nsd.options->nsid, nsd.nsid, nsd.nsid_len) == -1) { error("hex string cannot be parsed '%s' in NSID.", nsd.options->nsid); } } edns_init_nsid(&nsd.edns_ipv4, nsd.nsid_len); #if defined(INET6) edns_init_nsid(&nsd.edns_ipv6, nsd.nsid_len); #endif /* defined(INET6) */ /* Number of child servers to fork. */ nsd.children = (struct nsd_child *) region_alloc_array( nsd.region, nsd.child_count, sizeof(struct nsd_child)); for (i = 0; i < nsd.child_count; ++i) { nsd.children[i].kind = NSD_SERVER_BOTH; nsd.children[i].pid = -1; nsd.children[i].child_fd = -1; nsd.children[i].parent_fd = -1; nsd.children[i].handler = NULL; nsd.children[i].need_to_send_STATS = 0; nsd.children[i].need_to_send_QUIT = 0; nsd.children[i].need_to_exit = 0; nsd.children[i].has_exited = 0; #ifdef BIND8_STATS nsd.children[i].query_count = 0; #endif } nsd.this_child = NULL; /* We need at least one active interface */ if (nsd.ifs == 0) { add_interface(&nodes, &nsd, NULL); /* * With IPv6 we'd like to open two separate sockets, * one for IPv4 and one for IPv6, both listening to * the wildcard address (unless the -4 or -6 flags are * specified). * * However, this is only supported on platforms where * we can turn the socket option IPV6_V6ONLY _on_. * Otherwise we just listen to a single IPv6 socket * and any incoming IPv4 connections will be * automatically mapped to our IPv6 socket. */ #ifdef INET6 if (hints[0].ai_family == AF_UNSPEC) { #ifdef IPV6_V6ONLY add_interface(&nodes, &nsd, NULL); hints[0].ai_family = AF_INET6; hints[1].ai_family = AF_INET; hints_in_use = 2; nsd.grab_ip6_optional = 1; #else /* !IPV6_V6ONLY */ hints[0].ai_family = AF_INET6; #endif /* IPV6_V6ONLY */ } #endif /* INET6 */ } /* Set up the address info structures with real interface/port data */ assert(nodes); for (i = 0; i < nsd.ifs; ++i) { int r; const char* node = NULL; const char* service = NULL; int h = ((hints_in_use == 1)?0:i%hints_in_use); /* We don't perform name-lookups */ if (nodes[i] != NULL) hints[h].ai_flags |= AI_NUMERICHOST; get_ip_port_frm_str(nodes[i], &node, &service); hints[h].ai_socktype = SOCK_DGRAM; if ((r=getaddrinfo(node, (service?service:udp_port), &hints[h], &nsd.udp[i].addr)) != 0) { #ifdef INET6 if(nsd.grab_ip6_optional && hints[0].ai_family == AF_INET6) { log_msg(LOG_WARNING, "No IPv6, fallback to IPv4. getaddrinfo: %s", r==EAI_SYSTEM?strerror(errno):gai_strerror(r)); continue; } #endif error("cannot parse address '%s': getaddrinfo: %s %s", nodes[i]?nodes[i]:"(null)", gai_strerror(r), r==EAI_SYSTEM?strerror(errno):""); } hints[h].ai_socktype = SOCK_STREAM; if ((r=getaddrinfo(node, (service?service:tcp_port), &hints[h], &nsd.tcp[i].addr)) != 0) { error("cannot parse address '%s': getaddrinfo: %s %s", nodes[i]?nodes[i]:"(null)", gai_strerror(r), r==EAI_SYSTEM?strerror(errno):""); } } /* Parse the username into uid and gid */ nsd.gid = getgid(); nsd.uid = getuid(); #ifdef HAVE_GETPWNAM /* Parse the username into uid and gid */ if (*nsd.username) { if (isdigit((unsigned char)*nsd.username)) { char *t; nsd.uid = strtol(nsd.username, &t, 10); if (*t != 0) { if (*t != '.' || !isdigit((unsigned char)*++t)) { error("-u user or -u uid or -u uid.gid"); } nsd.gid = strtol(t, &t, 10); } else { /* Lookup the group id in /etc/passwd */ if ((pwd = getpwuid(nsd.uid)) == NULL) { error("user id %u does not exist.", (unsigned) nsd.uid); } else { nsd.gid = pwd->pw_gid; } } } else { /* Lookup the user id in /etc/passwd */ if ((pwd = getpwnam(nsd.username)) == NULL) { error("user '%s' does not exist.", nsd.username); } else { nsd.uid = pwd->pw_uid; nsd.gid = pwd->pw_gid; } } } /* endpwent(); */ #endif /* HAVE_GETPWNAM */ #if defined(HAVE_SSL) key_options_tsig_add(nsd.options); #endif append_trailing_slash(&nsd.options->xfrdir, nsd.options->region); /* Check relativity of pathnames to chroot */ if (nsd.chrootdir && nsd.chrootdir[0]) { /* existing chrootdir: append trailing slash for strncmp checking */ append_trailing_slash(&nsd.chrootdir, nsd.region); append_trailing_slash(&nsd.options->zonesdir, nsd.options->region); /* zonesdir must be absolute and within chroot, * all other pathnames may be relative to zonesdir */ if (strncmp(nsd.options->zonesdir, nsd.chrootdir, strlen(nsd.chrootdir)) != 0) { error("zonesdir %s has to be an absolute path that starts with the chroot path %s", nsd.options->zonesdir, nsd.chrootdir); } else if (!file_inside_chroot(nsd.pidfile, nsd.chrootdir)) { error("pidfile %s is not relative to %s: chroot not possible", nsd.pidfile, nsd.chrootdir); } else if (!file_inside_chroot(nsd.dbfile, nsd.chrootdir)) { error("database %s is not relative to %s: chroot not possible", nsd.dbfile, nsd.chrootdir); } else if (!file_inside_chroot(nsd.options->xfrdfile, nsd.chrootdir)) { error("xfrdfile %s is not relative to %s: chroot not possible", nsd.options->xfrdfile, nsd.chrootdir); } else if (!file_inside_chroot(nsd.options->zonelistfile, nsd.chrootdir)) { error("zonelistfile %s is not relative to %s: chroot not possible", nsd.options->zonelistfile, nsd.chrootdir); } else if (!file_inside_chroot(nsd.options->xfrdir, nsd.chrootdir)) { error("xfrdir %s is not relative to %s: chroot not possible", nsd.options->xfrdir, nsd.chrootdir); } } /* Set up the logging */ log_open(LOG_PID, FACILITY, nsd.log_filename); if (!nsd.log_filename) log_set_log_function(log_syslog); else if (nsd.uid && nsd.gid) { if(chown(nsd.log_filename, nsd.uid, nsd.gid) != 0) VERBOSITY(2, (LOG_WARNING, "chown %s failed: %s", nsd.log_filename, strerror(errno))); } log_msg(LOG_NOTICE, "%s starting (%s)", argv0, PACKAGE_STRING); /* Do we have a running nsd? */ if ((oldpid = readpid(nsd.pidfile)) == -1) { if (errno != ENOENT) { log_msg(LOG_ERR, "can't read pidfile %s: %s", nsd.pidfile, strerror(errno)); } } else { if (kill(oldpid, 0) == 0 || errno == EPERM) { log_msg(LOG_WARNING, "%s is already running as %u, continuing", argv0, (unsigned) oldpid); } else { log_msg(LOG_ERR, "...stale pid file from process %u", (unsigned) oldpid); } } /* Setup the signal handling... */ action.sa_handler = sig_handler; sigfillset(&action.sa_mask); action.sa_flags = 0; sigaction(SIGTERM, &action, NULL); sigaction(SIGHUP, &action, NULL); sigaction(SIGINT, &action, NULL); sigaction(SIGILL, &action, NULL); sigaction(SIGUSR1, &action, NULL); sigaction(SIGALRM, &action, NULL); sigaction(SIGCHLD, &action, NULL); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); /* Initialize... */ nsd.mode = NSD_RUN; nsd.signal_hint_child = 0; nsd.signal_hint_reload = 0; nsd.signal_hint_reload_hup = 0; nsd.signal_hint_quit = 0; nsd.signal_hint_shutdown = 0; nsd.signal_hint_stats = 0; nsd.signal_hint_statsusr = 0; nsd.quit_sync_done = 0; /* Initialize the server... */ if (server_init(&nsd) != 0) { error("server initialization failed, %s could " "not be started", argv0); } #if defined(HAVE_SSL) if(nsd.options->control_enable) { /* read ssl keys while superuser and outside chroot */ if(!(nsd.rc = daemon_remote_create(nsd.options))) error("could not perform remote control setup"); } #endif /* HAVE_SSL */ /* Unless we're debugging, fork... */ if (!nsd.debug) { int fd; /* Take off... */ switch ((nsd.pid = fork())) { case 0: /* Child */ break; case -1: error("fork() failed: %s", strerror(errno)); break; default: /* Parent is done */ server_close_all_sockets(nsd.udp, nsd.ifs); server_close_all_sockets(nsd.tcp, nsd.ifs); exit(0); } /* Detach ourselves... */ if (setsid() == -1) { error("setsid() failed: %s", strerror(errno)); } if ((fd = open("/dev/null", O_RDWR, 0)) != -1) { (void)dup2(fd, STDIN_FILENO); (void)dup2(fd, STDOUT_FILENO); (void)dup2(fd, STDERR_FILENO); if (fd > 2) (void)close(fd); } } /* Get our process id */ nsd.pid = getpid(); /* Set user context */ #ifdef HAVE_GETPWNAM if (*nsd.username) { #ifdef HAVE_SETUSERCONTEXT /* setusercontext does initgroups, setuid, setgid, and * also resource limits from login config, but we * still call setresuid, setresgid to be sure to set all uid */ if (setusercontext(NULL, pwd, nsd.uid, LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0) log_msg(LOG_WARNING, "unable to setusercontext %s: %s", nsd.username, strerror(errno)); #endif /* HAVE_SETUSERCONTEXT */ } #endif /* HAVE_GETPWNAM */ /* Chroot */ #ifdef HAVE_CHROOT if (nsd.chrootdir && nsd.chrootdir[0]) { int l = strlen(nsd.chrootdir)-1; /* ends in trailing slash */ if (file_inside_chroot(nsd.log_filename, nsd.chrootdir)) nsd.file_rotation_ok = 1; /* strip chroot from pathnames if they're absolute */ nsd.options->zonesdir += l; if (nsd.log_filename){ if (nsd.log_filename[0] == '/') nsd.log_filename += l; } if (nsd.pidfile[0] == '/') nsd.pidfile += l; if (nsd.dbfile[0] == '/') nsd.dbfile += l; if (nsd.options->xfrdfile[0] == '/') nsd.options->xfrdfile += l; if (nsd.options->zonelistfile[0] == '/') nsd.options->zonelistfile += l; if (nsd.options->xfrdir[0] == '/') nsd.options->xfrdir += l; /* strip chroot from pathnames of "include:" statements * on subsequent repattern commands */ cfg_parser->chroot = nsd.chrootdir; #ifdef HAVE_TZSET /* set timezone whilst not yet in chroot */ tzset(); #endif if (chroot(nsd.chrootdir)) { error("unable to chroot: %s", strerror(errno)); } if (chdir("/")) { error("unable to chdir to chroot: %s", strerror(errno)); } DEBUG(DEBUG_IPC,1, (LOG_INFO, "changed root directory to %s", nsd.chrootdir)); /* chdir to zonesdir again after chroot */ if(nsd.options->zonesdir && nsd.options->zonesdir[0]) { if(chdir(nsd.options->zonesdir)) { error("unable to chdir to '%s': %s", nsd.options->zonesdir, strerror(errno)); } DEBUG(DEBUG_IPC,1, (LOG_INFO, "changed directory to %s", nsd.options->zonesdir)); } } else #endif /* HAVE_CHROOT */ nsd.file_rotation_ok = 1; DEBUG(DEBUG_IPC,1, (LOG_INFO, "file rotation on %s %sabled", nsd.log_filename, nsd.file_rotation_ok?"en":"dis")); /* Write pidfile */ if (writepid(&nsd) == -1) { log_msg(LOG_ERR, "cannot overwrite the pidfile %s: %s", nsd.pidfile, strerror(errno)); } /* Drop the permissions */ #ifdef HAVE_GETPWNAM if (*nsd.username) { #ifdef HAVE_INITGROUPS if(initgroups(nsd.username, nsd.gid) != 0) log_msg(LOG_WARNING, "unable to initgroups %s: %s", nsd.username, strerror(errno)); #endif /* HAVE_INITGROUPS */ endpwent(); #ifdef HAVE_SETRESGID if(setresgid(nsd.gid,nsd.gid,nsd.gid) != 0) #elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID) if(setregid(nsd.gid,nsd.gid) != 0) #else /* use setgid */ if(setgid(nsd.gid) != 0) #endif /* HAVE_SETRESGID */ error("unable to set group id of %s: %s", nsd.username, strerror(errno)); #ifdef HAVE_SETRESUID if(setresuid(nsd.uid,nsd.uid,nsd.uid) != 0) #elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID) if(setreuid(nsd.uid,nsd.uid) != 0) #else /* use setuid */ if(setuid(nsd.uid) != 0) #endif /* HAVE_SETRESUID */ error("unable to set user id of %s: %s", nsd.username, strerror(errno)); DEBUG(DEBUG_IPC,1, (LOG_INFO, "dropped user privileges, run as %s", nsd.username)); } #endif /* HAVE_GETPWNAM */ xfrd_make_tempdir(&nsd); #ifdef USE_ZONE_STATS options_zonestatnames_create(nsd.options); server_zonestat_alloc(&nsd); #endif /* USE_ZONE_STATS */ #ifdef USE_DNSTAP if(nsd.options->dnstap_enable) { nsd.dt_collector = dt_collector_create(&nsd); dt_collector_start(nsd.dt_collector, &nsd); } #endif /* USE_DNSTAP */ if(nsd.server_kind == NSD_SERVER_MAIN) { server_prepare_xfrd(&nsd); /* xfrd forks this before reading database, so it does not get * the memory size of the database */ server_start_xfrd(&nsd, 0, 0); /* close zonelistfile in non-xfrd processes */ zone_list_close(nsd.options); } if (server_prepare(&nsd) != 0) { unlinkpid(nsd.pidfile); error("server preparation failed, %s could " "not be started", argv0); } if(nsd.server_kind == NSD_SERVER_MAIN) { server_send_soa_xfrd(&nsd, 0); } /* Really take off */ log_msg(LOG_NOTICE, "%s started (%s), pid %d", argv0, PACKAGE_STRING, (int) nsd.pid); if (nsd.server_kind == NSD_SERVER_MAIN) { server_main(&nsd); } else { server_child(&nsd); } /* NOTREACH */ exit(0); }
int main(int argc, char *argv[]) { int err; done = 0; snd_pcm_t *handle; FILE *sound_in_fd = NULL; FILE *sound_out_fd = NULL; int channels; short *buffer = NULL; int buffer_l; int buffer_read; struct serial_state_t *serial = NULL; struct ipc_state_t *ipc = NULL; struct receiver *rx_a = NULL; struct receiver *rx_b = NULL; #ifdef HAVE_PULSEAUDIO pa_simple *pa_dev = NULL; #endif /* command line */ parse_cmdline(argc, argv); /* open syslog, write an initial log message and read configuration */ open_log(logname, 0); hlog(LOG_NOTICE, "Starting up..."); if (read_config()) { hlog(LOG_CRIT, "Initial configuration failed."); exit(1); } /* fork a daemon */ if (fork_a_daemon) { int i = fork(); if (i < 0) { hlog(LOG_CRIT, "Fork to background failed: %s", strerror(errno)); fprintf(stderr, "Fork to background failed: %s\n", strerror(errno)); exit(1); } else if (i == 0) { /* child */ /* write pid file, now that we have our final pid... might fail, which is critical */ hlog(LOG_DEBUG, "Writing pid..."); if (!writepid(pidfile)) exit(1); } else { /* parent, quitting */ hlog(LOG_DEBUG, "Forked daemon process %d, parent quitting", i); exit(0); } } signal(SIGINT, closedown); signal(SIGPIPE, brokenconnection); /* initialize position cache for timed JSON AIS transmission */ if (uplink_config) { hlog(LOG_DEBUG, "Initializing cache..."); if (cache_init()) exit(1); hlog(LOG_DEBUG, "Initializing jsonout..."); if (jsonout_init()) exit(1); } /* initialize serial port for NMEA output */ if (serial_port) serial = serial_init(); /* initialize Unix domain socket for communication with gnuaisgui */ ipc = gnuais_ipc_init(); if(ipc == 0){ hlog(LOG_ERR, "Could not open Unix Domain Socket"); } /* initialize the AIS decoders */ if (sound_channels != SOUND_CHANNELS_MONO) { hlog(LOG_DEBUG, "Initializing demodulator A"); rx_a = init_receiver('A', 2, 0,serial,ipc); hlog(LOG_DEBUG, "Initializing demodulator B"); rx_b = init_receiver('B', 2, 1,serial,ipc); channels = 2; } else { hlog(LOG_DEBUG, "Initializing demodulator A"); rx_a = init_receiver('A', 1, 0,serial,ipc); channels = 1; } #ifdef HAVE_PULSEAUDIO if(sound_device != NULL && ((strcmp("pulse",sound_device) == 0) || (strcmp("pulseaudio",sound_device) == 0))){ if((pa_dev = pulseaudio_initialize()) == NULL){ hlog(LOG_CRIT, "Error opening pulseaudio device"); return -1; } buffer_l = 1024; int extra = buffer_l % 5; buffer_l -= extra; buffer = (short *) hmalloc(buffer_l * sizeof(short) * channels); } else if (sound_device){ #else if (sound_device){ #endif if ((err = snd_pcm_open(&handle, sound_device, SND_PCM_STREAM_CAPTURE, 0)) < 0) { hlog(LOG_CRIT, "Error opening sound device (%s)", sound_device); return -1; } if (input_initialize(handle, &buffer, &buffer_l) < 0) return -1; } else if (sound_in_file) { if ((sound_in_fd = fopen(sound_in_file, "r")) == NULL) { hlog(LOG_CRIT, "Could not open sound file %s: %s", sound_in_file, strerror(errno)); return -1; } hlog(LOG_NOTICE, "Reading audio from file: %s", sound_in_file); buffer_l = 1024; int extra = buffer_l % 5; buffer_l -= extra; buffer = (short *) hmalloc(buffer_l * sizeof(short) * channels); } else { hlog(LOG_CRIT, "Neither sound device or sound file configured."); return -1; } if (sound_out_file) { if ((sound_out_fd = fopen(sound_out_file, "w")) == NULL) { hlog(LOG_CRIT, "Could not open sound output file %s: %s", sound_out_file, strerror(errno)); return -1; } hlog(LOG_NOTICE, "Recording audio to file: %s", sound_out_file); } #ifdef HAVE_MYSQL if (mysql_db) { hlog(LOG_DEBUG, "Saving to MySQL database \"%s\"", mysql_db); if (!(my = myout_init())) return -1; if (mysql_keepsmall) hlog(LOG_DEBUG, "Updating database rows only."); else hlog(LOG_DEBUG, "Inserting data to database."); if (mysql_oldlimit) hlog(LOG_DEBUG, "Deleting data older than %d seconds", mysql_oldlimit); } #endif hlog(LOG_NOTICE, "Started"); while (!done) { if (sound_in_fd) { buffer_read = fread(buffer, channels * sizeof(short), buffer_l, sound_in_fd); if (buffer_read <= 0) done = 1; } #ifdef HAVE_PULSEAUDIO else if (pa_dev){ buffer_read = pulseaudio_read(pa_dev, buffer, buffer_l); } #endif else { buffer_read = input_read(handle, buffer, buffer_l); //printf("read %d\n", buffer_read); } if (buffer_read <= 0) continue; if (sound_out_fd) { fwrite(buffer, channels * sizeof(short), buffer_read, sound_out_fd); } if (sound_channels == SOUND_CHANNELS_MONO) { receiver_run(rx_a, buffer, buffer_read); } if (sound_channels == SOUND_CHANNELS_BOTH || sound_channels == SOUND_CHANNELS_RIGHT) { /* ch a/0/right */ receiver_run(rx_a, buffer, buffer_read); } if (sound_channels == SOUND_CHANNELS_BOTH || sound_channels == SOUND_CHANNELS_LEFT) { /* ch b/1/left */ receiver_run(rx_b, buffer, buffer_read); } } hlog(LOG_NOTICE, "Closing down..."); if (sound_in_fd) { fclose(sound_in_fd); } #ifdef HAVE_PULSEAUDIO else if (pa_dev) { pulseaudio_cleanup(pa_dev); } #endif else { input_cleanup(handle); handle = NULL; } if (sound_out_fd) fclose(sound_out_fd); hfree(buffer); gnuais_ipc_deinit(ipc); if (serial) serial_close(serial); if (uplink_config) jsonout_deinit(); if (cache_positions) cache_deinit(); if (rx_a) { struct demod_state_t *d = rx_a->decoder; hlog(LOG_INFO, "A: Received correctly: %d packets, wrong CRC: %d packets, wrong size: %d packets", d->receivedframes, d->lostframes, d->lostframes2); } if (rx_b) { struct demod_state_t *d = rx_b->decoder; hlog(LOG_INFO, "B: Received correctly: %d packets, wrong CRC: %d packets, wrong size: %d packets", d->receivedframes, d->lostframes, d->lostframes2); } free_receiver(rx_a); free_receiver(rx_b); free_config(); close_log(0); return 0; }