예제 #1
0
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;
}
예제 #2
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;
}
예제 #3
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
}
예제 #4
0
파일: dm.c 프로젝트: mit-athena/dm
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);
    }
}
예제 #5
0
파일: main.c 프로젝트: Tookmund/Swapspace
/** 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());
}
예제 #6
0
파일: pfilter.c 프로젝트: BobBall/sm
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;
}
예제 #7
0
파일: util.c 프로젝트: brunolauze/libinit
int rundaemon(char *argv[], char *pidpath)
{
	return writepid(run_async(argv), pidpath);
}
예제 #8
0
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);
}
예제 #9
0
파일: BNotifier.c 프로젝트: brianhlin/BLAH
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);
 
}
예제 #10
0
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);
}
예제 #11
0
파일: BUpdaterSGE.c 프로젝트: SLIPPIN/BLAH
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);
}
예제 #12
0
파일: luci-bwc.c 프로젝트: 8devices/luci
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;
}
예제 #13
0
파일: dm.c 프로젝트: mit-athena/dm
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);
	}
    }
}
예제 #14
0
파일: upslog.c 프로젝트: alezz/nut
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);
}
예제 #15
0
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;
	
}
예제 #16
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);
}
예제 #17
0
파일: pfilter.c 프로젝트: BobBall/sm
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;
}
예제 #18
0
파일: main.c 프로젝트: Tookmund/Swapspace
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;
}
예제 #20
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
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);
}
예제 #21
0
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;
}
예제 #22
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);
}
예제 #23
0
파일: unbound.c 프로젝트: jedisct1/unbound
/** 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);
}
예제 #24
0
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;
	
}
예제 #25
0
파일: rrdbotd.c 프로젝트: GlenWalker/rrdbot
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;
}
예제 #26
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);
	  }
      }
  }
}
예제 #27
0
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);
}
예제 #28
0
파일: ais.c 프로젝트: FlavioFalcao/gnuais
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;
}