Exemple #1
0
/** internal functions implementation starts here **/
int ev_irc_connect(void* dummy1, void* dummy2)
{
    int cr;
    stdlog(L_INFO, "Connecting to IRC server %s:%i", RemoteServer, RemotePort);
    cr = irc_FullConnect(RemoteServer, RemotePort, ServerPass, 0);
    if(cr < 0)
    {
        errlog("Could not connect to IRC server: %s", irc_GetLastMsg());
        exit(1);
    }
    stdlog(L_INFO, "Netjoin complete, %.1d Kbs received", irc_InByteCount()/1024);

    /* not sure if this fork should be on the irc module
       for now lets leave it like this to make sure we only fork after the
       connection is fully established
    */
    if( nofork == 0 )
    {
        fork_process();
        write_pidfile();
    }

    irc_LoopWhileConnected();
    errlog("Disconnected:%s\n", irc_GetLastMsg());

    /* stdlog(L_INFO, "PTlink IRC Services Terminated"); */

    return 0;
}
Exemple #2
0
void
start(const char *cmd, monitor_t *monitor) {
exec: {
  pid = fork();
  int status;

  switch (pid) {
    case -1:
      perror("fork()");
      exit(1);
    case 0:
      log("sh -c \"%s\"", cmd);
      execl("/bin/bash", "bash", "-c", cmd, 0);
      perror("execl()");
      exit(1);
    default:
      log("pid %d", pid);

      // write pidfile
      if (monitor->pidfile) {
        log("write pid to %s", monitor->pidfile);
        write_pidfile(monitor->pidfile, pid);
      }

      // wait for exit
      waitpid(pid, &status, 0);

      // signalled
      if (WIFSIGNALED(status)) {
        log("signal(%s)", strsignal(WTERMSIG(status)));
        log("sleep(%d)", monitor->sleepsec);
        sleep(monitor->sleepsec);
        goto error;
      }

      // check status
      if (WEXITSTATUS(status)) {
        log("exit(%d)", WEXITSTATUS(status));
        log("sleep(%d)", monitor->sleepsec);
        sleep(monitor->sleepsec);
        goto error;
      }

      // alerts
      error: {
        if (monitor->on_error) {
          log("on error \"%s\"", monitor->on_error);
          int status = system(monitor->on_error);
          if (status) {
            log("exit(%d)", status);
            log("shutting down");
            exit(status);
          }
        }

        goto exec;
      }
  }
}
}
Exemple #3
0
int daemonize()
{
	pid_t pid = fork();
	if (pid < 0) {
		exit(EXIT_FAILURE);
	}

	if (pid > 0) {
		exit(EXIT_SUCCESS);
	}

	if (write_pidfile() != 0) {
		return -1;
	}

	int ret = setsid();
	if (ret == -1) {
		XLOG_ERR("failed to set session id: %s", strerror(errno));
		unlink(PIDFILE);
		return -1;
	}

	for (int fd = getdtablesize(); fd >= 0; --fd) {
		 close(fd);
	}

	chdir("/");

	int fd = open("/dev/null", O_RDWR);
	dup(fd);
	dup(fd);

	return 0;
}
Exemple #4
0
static void client_background(void)
{
	bb_daemonize(0);
	logmode &= ~LOGMODE_STDIO;
	/* rewrite pidfile, as our pid is different now */
	write_pidfile(client_config.pidfile);
}
Exemple #5
0
void daemonize(const char *pidfile)
{
	pid_t pid, sid;

	/* Return if already a daemon */
	if (getppid() == 1)
		return;

	/* Fork off the parent process */
	pid = fork();
	if (pid < 0) {
		PERROR("fork", errno);
		exit(EXIT_FAILURE);
	}

	/* If we got a good PID, then we can exit the parent process. */
	if (pid > 0) {
		exit(EXIT_SUCCESS);
	}

	/* At this point we are executing as the child process */
	write_pidfile(pidfile);

	/* Change the file mode mask */
	umask(0);

	/* Create a new SID for the child process */
	sid = setsid();
	if (sid < 0) {
		PERROR("setsid", errno);
		exit(EXIT_FAILURE);
	}

	/* Change the current working directory.  This prevents the current
	directory from being locked; hence not being able to remove it. */
	if ((chdir("/")) < 0) {
		PERROR("chdir", errno);
		exit(EXIT_FAILURE);
	}

	/* Redirect standard files to /dev/null */
	if (freopen( "/dev/null", "r", stdin) == NULL) {
		PERROR("freopen: stdin", errno);
	}
	if (freopen( "/dev/null", "w", stdout) == NULL) {
		PERROR("freopen: stdout", errno);
	}
	if (freopen( "/dev/null", "w", stderr) == NULL) {
		PERROR("freopen: stderr", errno);
	}
}
Exemple #6
0
int main(int argc, char *argv[])
{
	char *password;
	int port = DEFAULT_LISTEN_PORT;
	parameters_t pars;
	struct sched_param sched_par;

	openlog("tcpconsole", LOG_CONS|LOG_NDELAY|LOG_NOWAIT|LOG_PID, LOG_DAEMON);

	if (getuid())
		error_exit("This program must be invoked with root-rights.");

	password = read_password("/etc/tcpconsole.pw");

	if (signal(SIGTERM, SIG_IGN) == SIG_ERR)
		error_exit("signal(SIGTERM) failed");

	if (signal(SIGHUP,  SIG_IGN) == SIG_ERR)
		error_exit("signal(SIGHUP) failed");

	pars.sysrq_fd = open_file("/proc/sysrq-trigger", O_WRONLY);
	pars.vcsa0_fd = open_file("/dev/vcsa", O_RDONLY);

	if (setpriority(PRIO_PROCESS, 0, -10) == -1)
		error_exit("Setpriority failed");

	if (nice(-20) == -1)
		error_exit("Failed to set nice-value to -20");

	if (mlockall(MCL_CURRENT) == -1 || mlockall(MCL_FUTURE) == -1)
		error_exit("Failed to lock program in core");

	memset(&sched_par, 0x00, sizeof(sched_par));
	sched_par.sched_priority = sched_get_priority_max(SCHED_RR);
	if (sched_setscheduler(0, SCHED_RR, &sched_par) == -1)
		error_exit("Failed to set scheduler properties for this process");

	syslog(LOG_INFO, "tcpconsole started");

	write_pidfile("/var/run/tcpconsole.pid");

	if ((pars.dmesg_buffer_size = klogctl(10, NULL, 0)) == -1)
		error_exit("klogctl(10) failed");
	pars.dmesg_buffer = (char *)malloc(pars.dmesg_buffer_size + 1);
	if (!pars.dmesg_buffer)
		error_exit("malloc failure");

	listen_on_socket(port, &pars, password);

	return 1;
}
Exemple #7
0
int
main(int argc, char **argv) {
    struct Config *config = NULL;
    const char *config_file = "/etc/sniproxy.conf";
    int background_flag = 1;
    pid_t pid;
    int opt;

    while ((opt = getopt(argc, argv, "fc:")) != -1) {
        switch (opt) {
            case 'c':
                config_file = optarg;
                break;
            case 'f': /* foreground */
                background_flag = 0;
                break;
            default:
                usage();
                exit(EXIT_FAILURE);
        }
    }

    config = init_config(config_file);
    if (config == NULL) {
        fprintf(stderr, "Unable to load %s\n", config_file);
        return 1;
    }

    init_server(config);

    if (background_flag) {
        pid = daemonize(config->user ? config->user : DEFAULT_USERNAME);

        if (pid != 0 && config->pidfile != NULL) {
            /* parent */
            write_pidfile(config->pidfile, pid);
            free_config(config);
            return 0;
        }
    }

    run_server();

    free_config(config);

    return 0;
}
Exemple #8
0
/* Become a SysV daemon */
int become_daemon(void)
{
    int fd;
    long maxfd, i;

    switch (fork()) {
        case -1: return -1;             /* error */
        case 0: break;                  /* child process created */
        default: exit(EXIT_FAILURE);    /* parent receives child's PID */
    }

    /* Detach from any terminal and create an independent session. */
    if (setsid() == -1) return -1;

    /* Ensure that the daemon can never re-acquire a terminal again. */
    switch (fork()) {
        case -1: return -1;
        case 0: break;
        default: exit(EXIT_FAILURE);
    }

    /* Reset file mode creation mask. */
    umask(0);

    /* Change current directory to root directory (/) */
    if (chdir("/") == -1) return -1;

    /* Find maximum open file descriptors */
    maxfd = sysconf(_SC_OPEN_MAX);
    if (maxfd == -1) maxfd = MAX_OPEN;

    /* Close all open file descriptors */
    for (i = 0; i < maxfd; i++) close(i);

    /* Connect /dev/null to stdin, stdout, stderr */
    close(STDIN_FILENO);

    fd = open("/dev/null", O_RDWR);
    if (fd != STDIN_FILENO) return -1;
    if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO) return -1;
    if (dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) return -1;

    /* Write PID file in /var/run/ */
    if (write_pidfile() == -1) return -1;

    return 0;
}
Exemple #9
0
int
main(int argc, char **argv){
  monitor_t monitor;
  monitor.pidfile = NULL;
  monitor.mon_pidfile = NULL;
  monitor.on_error = NULL;
  monitor.logfile = "mon.log";
  monitor.daemon = 0;
  monitor.sleepsec = 1;

  command_t program;
  program.data = &monitor;
  command_init(&program, "mon", VERSION);
  command_option(&program, "-l", "--log <path>", "specify logfile [mon.log]", on_log);
  command_option(&program, "-s", "--sleep <sec>", "sleep seconds before re-executing [1]", on_sleep);
  command_option(&program, "-S", "--status", "check status of --pidfile", on_status);
  command_option(&program, "-p", "--pidfile <path>", "write pid to <path>", on_pidfile);
  command_option(&program, "-m", "--mon-pidfile <path>", "write mon(1) pid to <path>", on_mon_pidfile);
  command_option(&program, "-P", "--prefix <str>", "add a log prefix", on_prefix);
  command_option(&program, "-d", "--daemonize", "daemonize the program", on_daemonize);
  command_option(&program, "-e", "--on-error <cmd>", "execute <cmd> on errors", on_error);
  command_parse(&program, argc, argv);

  // command required
  if (!program.argc) error("<cmd> required");
  const char *cmd = program.argv[0];
  
  // signals
  signal(SIGTERM, graceful_exit);
  signal(SIGQUIT, graceful_exit);
  
  // daemonize
  if (monitor.daemon) {
    daemonize();
    redirect_stdio_to(monitor.logfile);
  }
  
  // write mon pidfile
  if (monitor.mon_pidfile) {
    log("write mon pid to %s", monitor.mon_pidfile);
    write_pidfile(monitor.mon_pidfile, getpid());
  }
  
  start(cmd, &monitor);

  return 0;
}
int
main(void)
{
	const pid_t pid = getpid();
	write_pidfile(pid);

	wait_for_peer_invocation();

	static const char dir[] = "attach-p-cmd.test cmd";
	int rc = chdir(dir);

	printf("%-5d chdir(\"%s\") = %s\n"
	       "%-5d +++ exited with 0 +++\n",
	       pid, dir, sprintrc(rc), pid);

	return 0;
}
Exemple #11
0
/// <summary>Our raspicomm daemon specific work gets done.</summary>
void do_work(void)
{
  /* setup the syslog for logging */
  init_syslog();

  /* read the settings from the settings file */
  Settings settings; int ret;
  if ((ret = load_settings(&settings)) < 0)
  {
    //syslog(LOG_ERR, "loading settings failed (%i)", ret); 
    exit(EXIT_FAILURE);
  }
    
  if (settings.log)
  {
    syslog(LOG_INFO, "starting...");

    syslog(LOG_INFO, "using %s: port '%i' and pidfile '%s' and log=%i", 
      ret == 0 ? "default configuration" : "configurationfile",
      settings.port, 
      settings.pidfile,
      settings.log);
  }  

  /* write the pidfile */
  if ( write_pidfile(settings.pidfile) != 0)
    if (settings.log)
      syslog(LOG_ERR, "writing PIDFILE '%s' failed", settings.pidfile);

  /* use the settings to initialize the raspicomm */
  if (daemon_init_raspicomm(&settings) != SUCCESS)
    exit(EXIT_FAILURE);

  /* init the pipe */
  if (init_pipe() != 0)
    if (settings.log)
      syslog(LOG_ERR, "init_pipe failed");

  /* block and work */
  enter_main_loop(&settings);
  
  /* tear down raspicomm */
  daemon_shutdown();

}
Exemple #12
0
/*
  Detach from current terminal, write pidfile, kill parent
*/
bool detach(void) {
	setup_signals();

	/* First check if we can open a fresh new pidfile */

#ifndef HAVE_MINGW
	if(!write_pidfile())
		return false;

	/* If we succeeded in doing that, detach */

	closelogger();
#endif

	if(do_detach) {
#ifndef HAVE_MINGW
		if(daemon(0, 0)) {
			fprintf(stderr, "Couldn't detach from terminal: %s",
					strerror(errno));
			return false;
		}

		/* Now UPDATE the pid in the pidfile, because we changed it... */

		if(!write_pid(pidfilename)) {
			fprintf(stderr, "Could not write pid file %s: %s\n", pidfilename, strerror(errno));
			return false;
		}
#else
		if(!statushandle)
			exit(install_service());
#endif
	}

	openlogger(identname, use_logfile?LOGMODE_FILE:(do_detach?LOGMODE_SYSLOG:LOGMODE_STDERR));

	logger(LOG_NOTICE, "tincd %s (%s %s) starting, debug level %d",
			   VERSION, __DATE__, __TIME__, debug_level);

	xalloc_fail_func = memory_full;

	return true;
}
Exemple #13
0
static void client_background(void)
{
#ifdef __uClinux__
	bb_error_msg("cannot background in uclinux (yet)");
/* ... mainly because udhcpc calls client_background()
 * in _the _middle _of _udhcpc _run_, not at the start!
 * If that will be properly disabled for NOMMU, client_background()
 * will work on NOMMU too */
#else
// chdir(/) is problematic. Imagine that e.g. pidfile name is RELATIVE! what will unlink do then, eh?
	bb_daemonize(DAEMON_CHDIR_ROOT);
	/* rewrite pidfile, as our pid is different now */
	if (client_config.pidfile)
		write_pidfile(client_config.pidfile);
	logmode &= ~LOGMODE_STDIO;
#endif
	client_config.foreground = 1; /* Do not fork again. */
	client_config.background_if_no_lease = 0;
}
Exemple #14
0
bool daemonize(const char* pid_path)
{
  /* Double fork. */
  pid_t ret;

  ret = fork();
  if (ret == -1) {
    err(EXIT_FAILURE, "fork()");
  } else if (ret > 0) {
    waitpid(ret, NULL, 0);
    return false;
  }

  ret = fork();
  if (ret == -1) {
    err(EXIT_FAILURE, "fork()");
  } else if (ret > 0) {
    exit(EXIT_SUCCESS);
  }

  /* Write PID. */
  if (!write_pidfile(pid_path))
    err(EXIT_FAILURE, "%s", pid_path);

  /* Change directory. */
  if (chdir("/") == -1)
    warn("%s", "/");

  /* Create new session ID. */
  if (setsid() == -1)
    warn("setsid()");

  /* Close standard streams. */
  if (int fd = open("/dev/null", O_RDWR) > 0)
    for (int i = 0; i < 3; ++i)
      dup2(fd, i);

  return true;
}
Exemple #15
0
int
main (int argc, char **argv)
{
    int c;
    char *config_dir = DEFAULT_CONFIG_DIR;
    char *seafile_dir = NULL;
    char *central_config_dir = NULL;
    char *logfile = NULL;
    const char *debug_str = NULL;
    int daemon_mode = 1;
    int is_master = 0;
    CcnetClient *client;
    char *ccnet_debug_level_str = "info";
    char *seafile_debug_level_str = "debug";
    int cloud_mode = 0;

#ifdef WIN32
    argv = get_argv_utf8 (&argc);
#endif

    while ((c = getopt_long (argc, argv, short_options, 
                             long_options, NULL)) != EOF)
    {
        switch (c) {
        case 'h':
            exit (1);
            break;
        case 'v':
            exit (1);
            break;
        case 'c':
            config_dir = optarg;
            break;
        case 'd':
            seafile_dir = g_strdup(optarg);
            break;
        case 'F':
            central_config_dir = g_strdup(optarg);
            break;
        case 'f':
            daemon_mode = 0;
            break;
        case 'l':
            logfile = g_strdup(optarg);
            break;
        case 'D':
            debug_str = optarg;
            break;
        case 'g':
            ccnet_debug_level_str = optarg;
            break;
        case 'G':
            seafile_debug_level_str = optarg;
            break;
        case 'm':
            is_master = 1;
            break;
        case 'P':
            pidfile = optarg;
            break;
        case 'C':
            cloud_mode = 1;
            break;
        default:
            usage ();
            exit (1);
        }
    }

    argc -= optind;
    argv += optind;

#ifndef WIN32
    if (daemon_mode) {
#ifndef __APPLE__
        daemon (1, 0);
#else   /* __APPLE */
        /* daemon is deprecated under APPLE
         * use fork() instead
         * */
        switch (fork ()) {
          case -1:
              seaf_warning ("Failed to daemonize");
              exit (-1);
              break;
          case 0:
              /* all good*/
              break;
          default:
              /* kill origin process */
              exit (0);
        }
#endif  /* __APPLE */
    }
#endif /* !WIN32 */

    cdc_init ();

#if !GLIB_CHECK_VERSION(2, 35, 0)
    g_type_init();
#endif
#if !GLIB_CHECK_VERSION(2,32,0)
    g_thread_init (NULL);
#endif

    if (!debug_str)
        debug_str = g_getenv("SEAFILE_DEBUG");
    seafile_debug_set_flags_string (debug_str);

    if (seafile_dir == NULL)
        seafile_dir = g_build_filename (config_dir, "seafile", NULL);
    if (logfile == NULL)
        logfile = g_build_filename (seafile_dir, "seafile.log", NULL);

    if (seafile_log_init (logfile, ccnet_debug_level_str,
                          seafile_debug_level_str) < 0) {
        seaf_warning ("Failed to init log.\n");
        exit (1);
    }

    client = ccnet_init (central_config_dir, config_dir);
    if (!client)
        exit (1);

    register_processors (client);

    start_rpc_service (client, cloud_mode);

    create_sync_rpc_clients (central_config_dir, config_dir);
    create_async_rpc_clients (client);

    seaf = seafile_session_new (central_config_dir, seafile_dir, client);
    if (!seaf) {
        seaf_warning ("Failed to create seafile session.\n");
        exit (1);
    }
    seaf->is_master = is_master;
    seaf->ccnetrpc_client = ccnetrpc_client;
    seaf->async_ccnetrpc_client = async_ccnetrpc_client;
    seaf->ccnetrpc_client_t = ccnetrpc_client_t;
    seaf->async_ccnetrpc_client_t = async_ccnetrpc_client_t;
    seaf->client_pool = ccnet_client_pool_new (central_config_dir, config_dir);
    seaf->cloud_mode = cloud_mode;

    load_history_config ();

    g_free (seafile_dir);
    g_free (logfile);

    set_signal_handlers (seaf);

    /* init seaf */
    if (seafile_session_init (seaf) < 0)
        exit (1);

    if (seafile_session_start (seaf) < 0)
        exit (1);

    if (pidfile) {
        if (write_pidfile (pidfile) < 0) {
            ccnet_message ("Failed to write pidfile\n");
            return -1;
        }
    }
    atexit (on_seaf_server_exit);

    /* Create a system default repo to contain the tutorial file. */
    schedule_create_system_default_repo (seaf);

    ccnet_main (client);

    return 0;
}
Exemple #16
0
int main(int argc, char *argv[])
{
  struct sockaddr_in me;
#ifdef ENABLE_IPV6
  struct sockaddr_in6 me6;
#endif /* ENABLE_IPV6 */
  curl_socket_t sock = CURL_SOCKET_BAD;
  curl_socket_t msgsock = CURL_SOCKET_BAD;
  int wrotepidfile = 0;
  int flag;
  unsigned short port = DEFAULT_PORT;
  char *pidname= (char *)".rtsp.pid";
  struct httprequest req;
  int rc;
  int error;
  int arg=1;
  long pid;

  while(argc>arg) {
    if(!strcmp("--version", argv[arg])) {
      printf("rtspd IPv4%s"
             "\n"
             ,
#ifdef ENABLE_IPV6
             "/IPv6"
#else
             ""
#endif
             );
      return 0;
    }
    else if(!strcmp("--pidfile", argv[arg])) {
      arg++;
      if(argc>arg)
        pidname = argv[arg++];
    }
    else if(!strcmp("--logfile", argv[arg])) {
      arg++;
      if(argc>arg)
        serverlogfile = argv[arg++];
    }
    else if(!strcmp("--ipv4", argv[arg])) {
#ifdef ENABLE_IPV6
      ipv_inuse = "IPv4";
      use_ipv6 = FALSE;
#endif
      arg++;
    }
    else if(!strcmp("--ipv6", argv[arg])) {
#ifdef ENABLE_IPV6
      ipv_inuse = "IPv6";
      use_ipv6 = TRUE;
#endif
      arg++;
    }
    else if(!strcmp("--port", argv[arg])) {
      arg++;
      if(argc>arg) {
        char *endptr;
        long lnum = -1;
        lnum = strtol(argv[arg], &endptr, 10);
        if((endptr != argv[arg] + strlen(argv[arg])) ||
           (lnum < 1025L) || (lnum > 65535L)) {
          fprintf(stderr, "rtspd: invalid --port argument (%s)\n",
                  argv[arg]);
          return 0;
        }
        port = (unsigned short)(lnum & 0xFFFFL);
        arg++;
      }
    }
    else if(!strcmp("--srcdir", argv[arg])) {
      arg++;
      if(argc>arg) {
        path = argv[arg];
        arg++;
      }
    }
    else {
      puts("Usage: rtspd [option]\n"
           " --version\n"
           " --logfile [file]\n"
           " --pidfile [file]\n"
           " --ipv4\n"
           " --ipv6\n"
           " --port [port]\n"
           " --srcdir [path]");
      return 0;
    }
  }

#ifdef WIN32
  win32_init();
  atexit(win32_cleanup);
#endif

  install_signal_handlers();

  pid = (long)getpid();

#ifdef ENABLE_IPV6
  if(!use_ipv6)
#endif
    sock = socket(AF_INET, SOCK_STREAM, 0);
#ifdef ENABLE_IPV6
  else
    sock = socket(AF_INET6, SOCK_STREAM, 0);
#endif

  if(CURL_SOCKET_BAD == sock) {
    error = SOCKERRNO;
    logmsg("Error creating socket: (%d) %s",
           error, strerror(error));
    goto server_cleanup;
  }

  flag = 1;
  if (0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
            (void *)&flag, sizeof(flag))) {
    error = SOCKERRNO;
    logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
           error, strerror(error));
    goto server_cleanup;
  }

#ifdef ENABLE_IPV6
  if(!use_ipv6) {
#endif
    memset(&me, 0, sizeof(me));
    me.sin_family = AF_INET;
    me.sin_addr.s_addr = INADDR_ANY;
    me.sin_port = htons(port);
    rc = bind(sock, (struct sockaddr *) &me, sizeof(me));
#ifdef ENABLE_IPV6
  }
  else {
    memset(&me6, 0, sizeof(me6));
    me6.sin6_family = AF_INET6;
    me6.sin6_addr = in6addr_any;
    me6.sin6_port = htons(port);
    rc = bind(sock, (struct sockaddr *) &me6, sizeof(me6));
  }
#endif /* ENABLE_IPV6 */
  if(0 != rc) {
    error = SOCKERRNO;
    logmsg("Error binding socket on port %hu: (%d) %s",
           port, error, strerror(error));
    goto server_cleanup;
  }

  logmsg("Running %s version on port %d", ipv_inuse, (int)port);

  /* start accepting connections */
  rc = listen(sock, 5);
  if(0 != rc) {
    error = SOCKERRNO;
    logmsg("listen() failed with error: (%d) %s",
           error, strerror(error));
    goto server_cleanup;
  }

  /*
  ** As soon as this server writes its pid file the test harness will
  ** attempt to connect to this server and initiate its verification.
  */

  wrotepidfile = write_pidfile(pidname);
  if(!wrotepidfile)
    goto server_cleanup;

  for (;;) {
    msgsock = accept(sock, NULL, NULL);

    if(got_exit_signal)
      break;
    if (CURL_SOCKET_BAD == msgsock) {
      error = SOCKERRNO;
      logmsg("MAJOR ERROR: accept() failed with error: (%d) %s",
             error, strerror(error));
      break;
    }

    /*
    ** As soon as this server acepts a connection from the test harness it
    ** must set the server logs advisor read lock to indicate that server
    ** logs should not be read until this lock is removed by this server.
    */

    set_advisor_read_lock(SERVERLOGS_LOCK);
    serverlogslocked = 1;

    logmsg("====> Client connect");

#ifdef TCP_NODELAY
    /*
     * Disable the Nagle algorithm to make it easier to send out a large
     * response in many small segments to torture the clients more.
     */
    flag = 1;
    if (setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY,
                   (void *)&flag, sizeof(flag)) == -1) {
      logmsg("====> TCP_NODELAY failed");
    }
#endif

    /* initialization of httprequest struct is done in get_request(), but due
       to pipelining treatment the pipelining struct field must be initialized
       previously to FALSE every time a new connection arrives. */

    req.pipelining = FALSE;

    do {
      if(got_exit_signal)
        break;

      if(get_request(msgsock, &req))
        /* non-zero means error, break out of loop */
        break;

      if(prevbounce) {
        /* bounce treatment requested */
        if((req.testno == prevtestno) &&
           (req.partno == prevpartno)) {
          req.partno++;
          logmsg("BOUNCE part number to %ld", req.partno);
        }
        else {
          prevbounce = FALSE;
          prevtestno = -1;
          prevpartno = -1;
        }
      }

      send_doc(msgsock, &req);
      if(got_exit_signal)
        break;

      if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) {
        logmsg("special request received, no persistency");
        break;
      }
      if(!req.open) {
        logmsg("instructed to close connection after server-reply");
        break;
      }

      if(req.open)
        logmsg("=> persistant connection request ended, awaits new request");
      /* if we got a CONNECT, loop and get another request as well! */
    } while(req.open || (req.testno == DOCNUMBER_CONNECT));

    if(got_exit_signal)
      break;

    logmsg("====> Client disconnect");
    sclose(msgsock);
    msgsock = CURL_SOCKET_BAD;

    if(serverlogslocked) {
      serverlogslocked = 0;
      clear_advisor_read_lock(SERVERLOGS_LOCK);
    }

    if (req.testno == DOCNUMBER_QUIT)
      break;
  }

server_cleanup:

  if((msgsock != sock) && (msgsock != CURL_SOCKET_BAD))
    sclose(msgsock);

  if(sock != CURL_SOCKET_BAD)
    sclose(sock);

  if(got_exit_signal)
    logmsg("signalled to die");

  if(wrotepidfile)
    unlink(pidname);

  if(serverlogslocked) {
    serverlogslocked = 0;
    clear_advisor_read_lock(SERVERLOGS_LOCK);
  }

  restore_signal_handlers();

  if(got_exit_signal) {
    logmsg("========> %s rtspd (port: %d pid: %ld) exits with signal (%d)",
           ipv_inuse, (int)port, pid, exit_signal);
    /*
     * To properly set the return status of the process we
     * must raise the same signal SIGINT or SIGTERM that we
     * caught and let the old handler take care of it.
     */
    raise(exit_signal);
  }

  logmsg("========> rtspd quits");
  return 0;
}
Exemple #17
0
int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
{
	unsigned opt;
	char *signame;
	char *startas;
	char *chuid;
#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
//	char *retry_arg = NULL;
//	int retries = -1;
	char *opt_N;
#endif

	INIT_G();

	opt = GETOPT32(argv, "^"
		"KSbqtma:n:s:u:c:x:p:"
		IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:")
			/* -K or -S is required; they are mutually exclusive */
			/* -p is required if -m is given */
			/* -xpun (at least one) is required if -K is given */
			/* -xa (at least one) is required if -S is given */
			/* -q turns off -v */
			"\0"
			"K:S:K--S:S--K:m?p:K?xpun:S?xa"
			IF_FEATURE_START_STOP_DAEMON_FANCY("q-v"),
		LONGOPTS
		&startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile
		IF_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N)
		/* We accept and ignore -R <param> / --retry <param> */
		IF_FEATURE_START_STOP_DAEMON_FANCY(,NULL)
	);

	if (opt & OPT_s) {
		signal_nr = get_signum(signame);
		if (signal_nr < 0) bb_show_usage();
	}

	if (!(opt & OPT_a))
		startas = execname;
	if (!execname) /* in case -a is given and -x is not */
		execname = startas;
	if (execname) {
		G.execname_sizeof = strlen(execname) + 1;
		G.execname_cmpbuf = xmalloc(G.execname_sizeof + 1);
	}

//	IF_FEATURE_START_STOP_DAEMON_FANCY(
//		if (retry_arg)
//			retries = xatoi_positive(retry_arg);
//	)
	//argc -= optind;
	argv += optind;

	if (userspec) {
		user_id = bb_strtou(userspec, NULL, 10);
		if (errno)
			user_id = xuname2uid(userspec);
	}
	/* Both start and stop need to know current processes */
	do_procinit();

	if (opt & CTX_STOP) {
		int i = do_stop();
		return (opt & OPT_OKNODO) ? 0 : (i <= 0);
	}

	if (G.found_procs) {
		if (!QUIET)
			printf("%s is already running\n%u\n", execname, (unsigned)G.found_procs->pid);
		return !(opt & OPT_OKNODO);
	}

#ifdef OLDER_VERSION_OF_X
	if (execname)
		xstat(execname, &G.execstat);
#endif

	*--argv = startas;
	if (opt & OPT_BACKGROUND) {
#if BB_MMU
		bb_daemonize(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS + DAEMON_DOUBLE_FORK);
		/* DAEMON_DEVNULL_STDIO is superfluous -
		 * it's always done by bb_daemonize() */
#else
		/* Daemons usually call bb_daemonize_or_rexec(), but SSD can do
		 * without: SSD is not itself a daemon, it _execs_ a daemon.
		 * The usual NOMMU problem of "child can't run indefinitely,
		 * it must exec" does not bite us: we exec anyway.
		 */
		pid_t pid = xvfork();
		if (pid != 0) {
			/* parent */
			/* why _exit? the child may have changed the stack,
			 * so "return 0" may do bad things */
			_exit(EXIT_SUCCESS);
		}
		/* Child */
		setsid(); /* detach from controlling tty */
		/* Redirect stdio to /dev/null, close extra FDs */
		bb_daemon_helper(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS);
#endif
	}
	if (opt & OPT_MAKEPID) {
		/* User wants _us_ to make the pidfile */
		write_pidfile(pidfile);
	}
	if (opt & OPT_c) {
		struct bb_uidgid_t ugid;
		parse_chown_usergroup_or_die(&ugid, chuid);
		if (ugid.uid != (uid_t) -1L) {
			struct passwd *pw = xgetpwuid(ugid.uid);
			if (ugid.gid != (gid_t) -1L)
				pw->pw_gid = ugid.gid;
			/* initgroups, setgid, setuid: */
			change_identity(pw);
		} else if (ugid.gid != (gid_t) -1L) {
			xsetgid(ugid.gid);
			setgroups(1, &ugid.gid);
		}
	}
#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
	if (opt & OPT_NICELEVEL) {
		/* Set process priority */
		int prio = getpriority(PRIO_PROCESS, 0) + xatoi_range(opt_N, INT_MIN/2, INT_MAX/2);
		if (setpriority(PRIO_PROCESS, 0, prio) < 0) {
			bb_perror_msg_and_die("setpriority(%d)", prio);
		}
	}
#endif
	execvp(startas, argv);
	bb_perror_msg_and_die("can't execute '%s'", startas);
}
Exemple #18
0
int crond_main(int argc UNUSED_PARAM, char **argv)
{
	time_t t2;
	unsigned rescan;
	unsigned sleep_time;
	unsigned opts;

	INIT_G();

	/* "-b after -f is ignored", and so on for every pair a-b */
	opt_complementary = "f-b:b-f:S-L:L-S" IF_FEATURE_CROND_D(":d-l")
			/* -l and -d have numeric param */
			":l+" IF_FEATURE_CROND_D(":d+");
	opts = getopt32(argv, "l:L:fbSc:" IF_FEATURE_CROND_D("d:"),
			&G.log_level, &G.log_filename, &G.crontab_dir_name
			IF_FEATURE_CROND_D(,&G.log_level));
	/* both -d N and -l N set the same variable: G.log_level */

	if (!(opts & OPT_f)) {
		/* close stdin, stdout, stderr.
		 * close unused descriptors - don't need them. */
		bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv);
	}

	if (!(opts & OPT_d) && G.log_filename == NULL) {
		/* logging to syslog */
		openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON);
		logmode = LOGMODE_SYSLOG;
	}

	//signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */

	reopen_logfile_to_stderr();
	xchdir(G.crontab_dir_name);
	log8("crond (busybox "BB_VER") started, log level %d", G.log_level);
	rescan_crontab_dir();
	write_pidfile(CONFIG_PID_FILE_PATH "/crond.pid");

	/* Main loop */
	t2 = time(NULL);
	rescan = 60;
	sleep_time = 60;
	for (;;) {
		struct stat sbuf;
		time_t t1;
		long dt;

		/* Synchronize to 1 minute, minimum 1 second */
		t1 = t2;
		sleep(sleep_time - (time(NULL) % sleep_time));
		t2 = time(NULL);
		dt = (long)t2 - (long)t1;

		reopen_logfile_to_stderr();

		/*
		 * The file 'cron.update' is checked to determine new cron
		 * jobs.  The directory is rescanned once an hour to deal
		 * with any screwups.
		 *
		 * Check for time jump.  Disparities over an hour either way
		 * result in resynchronization.  A negative disparity
		 * less than an hour causes us to effectively sleep until we
		 * match the original time (i.e. no re-execution of jobs that
		 * have just been run).  A positive disparity less than
		 * an hour causes intermediate jobs to be run, but only once
		 * in the worst case.
		 *
		 * When running jobs, the inequality used is greater but not
		 * equal to t1, and less then or equal to t2.
		 */
		if (stat(G.crontab_dir_name, &sbuf) != 0)
			sbuf.st_mtime = 0; /* force update (once) if dir was deleted */
		if (G.crontab_dir_mtime != sbuf.st_mtime) {
			G.crontab_dir_mtime = sbuf.st_mtime;
			rescan = 1;
		}
		if (--rescan == 0) {
			rescan = 60;
			rescan_crontab_dir();
		}
		process_cron_update_file();
		log5("wakeup dt=%ld", dt);
		if (dt < -60 * 60 || dt > 60 * 60) {
			bb_error_msg("time disparity of %ld minutes detected", dt / 60);
			/* and we do not run any jobs in this case */
		} else if (dt > 0) {
			/* Usual case: time advances forward, as expected */
			flag_starting_jobs(t1, t2);
			start_jobs();
			sleep_time = 60;
			if (check_completions() > 0) {
				/* some jobs are still running */
				sleep_time = 10;
			}
		}
		/* else: time jumped back, do not run any jobs */
	} /* for (;;) */

	return 0; /* not reached */
}
Exemple #19
0
int
main(int argc, char **argv) {
    const char *config_file = "/etc/sniproxy.conf";
    int background_flag = 1;
    int max_nofiles = 65536;
    int opt;

    while ((opt = getopt(argc, argv, "fc:n:V")) != -1) {
        switch (opt) {
            case 'c':
                config_file = optarg;
                break;
            case 'f': /* foreground */
                background_flag = 0;
                break;
            case 'n':
                max_nofiles = atoi(optarg);
                break;
            case 'V':
                printf("sniproxy %s\n", sniproxy_version);
#ifdef HAVE_LIBUDNS
                printf("compiled with udns support\n");
#endif
                return EXIT_SUCCESS;
            default:
                usage();
                return EXIT_FAILURE;
        }
    }

    config = init_config(config_file, EV_DEFAULT);
    if (config == NULL) {
        fprintf(stderr, "Unable to load %s\n", config_file);
        usage();
        return EXIT_FAILURE;
    }

    /* ignore SIGPIPE, or it will kill us */
    signal(SIGPIPE, SIG_IGN);

    if (background_flag) {
        if (config->pidfile != NULL)
            remove(config->pidfile);

        daemonize();


        if (config->pidfile != NULL)
            write_pidfile(config->pidfile, getpid());
    }

    start_binder();

    set_limits(max_nofiles);

    init_listeners(&config->listeners, &config->tables, EV_DEFAULT);

    /* Drop permissions only when we can */
    drop_perms(config->user ? config->user : default_username);

    ev_signal_init(&sighup_watcher, signal_cb, SIGHUP);
    ev_signal_init(&sigusr1_watcher, signal_cb, SIGUSR1);
    ev_signal_init(&sigusr2_watcher, signal_cb, SIGUSR2);
    ev_signal_init(&sigint_watcher, signal_cb, SIGINT);
    ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM);
    ev_signal_start(EV_DEFAULT, &sighup_watcher);
    ev_signal_start(EV_DEFAULT, &sigusr1_watcher);
    ev_signal_start(EV_DEFAULT, &sigusr2_watcher);
    ev_signal_start(EV_DEFAULT, &sigint_watcher);
    ev_signal_start(EV_DEFAULT, &sigterm_watcher);

    resolv_init(EV_DEFAULT, config->resolver.nameservers,
            config->resolver.search, config->resolver.mode);

    init_connections();

    ev_run(EV_DEFAULT, 0);

    free_connections(EV_DEFAULT);
    resolv_shutdown(EV_DEFAULT);

    free_config(config, EV_DEFAULT);

    stop_binder();

    return 0;
}
Exemple #20
0
int eooqd_main(int argc, char *argv[])
{
	int r;
	char *pid_file_name, *instance_id_str;
	char *check;
	struct event *checkQueueEvent, *rePostEvent;
	struct timeval tv;
	struct rlimit limit;

	atlas_id= NULL;
	instance_id_str= NULL;
	pid_file_name= NULL;
	queue_id= "";

	(void)getopt32(argv, "A:i:P:q:", &atlas_id, &instance_id_str,
		&pid_file_name, &queue_id);

	if (argc != optind+1)
	{
		bb_show_usage();
		return 1;
	}

	instance_id= 0;
	if (instance_id_str)
	{
		instance_id= strtoul(instance_id_str, &check, 0);
		if (check[0] != '\0')
		{
			report("unable to parse instance id '%s'",
				instance_id_str);
			return 1;
		}
	}

	if(pid_file_name)
	{
		write_pidfile(pid_file_name);
	}

	state = xzalloc(sizeof(*state));

	state->atlas_id= atlas_id;
	state->queue_file= argv[optind];

	state->max_busy= 10;

	state->slots= xzalloc(sizeof(*state->slots) * state->max_busy);

	if (strlen(state->queue_file) + strlen(SUFFIX) + 1 >
		sizeof(state->curr_qfile))
	{
		report("filename too long ('%s')", state->queue_file);
		return 1;
	}

	strlcpy(state->curr_qfile, state->queue_file,
		sizeof(state->curr_qfile));
	strlcat(state->curr_qfile, SUFFIX, sizeof(state->curr_qfile));

	signal(SIGQUIT, SIG_DFL);
	limit.rlim_cur= RLIM_INFINITY;
	limit.rlim_max= RLIM_INFINITY;
	setrlimit(RLIMIT_CORE, &limit);

	/* Create libevent event base */
	EventBase= event_base_new();
	if (!EventBase)
	{
		crondlog(DIE9 "event_base_new failed"); /* exits */
	}
	DnsBase= evdns_base_new(EventBase, 1 /*initialize*/);
	if (!DnsBase)
	{
		event_base_free(EventBase);
		crondlog(DIE9 "evdns_base_new failed"); /* exits */
	}

	checkQueueEvent= event_new(EventBase, -1, EV_TIMEOUT|EV_PERSIST,
		checkQueue, NULL);
	if (!checkQueueEvent)
		crondlog(DIE9 "event_new failed"); /* exits */
	tv.tv_sec= 1;
	tv.tv_usec= 0;
	event_add(checkQueueEvent, &tv);

	rePostEvent= event_new(EventBase, -1, EV_TIMEOUT|EV_PERSIST,
		re_post, NULL);
	if (!rePostEvent)
		crondlog(DIE9 "event_new failed"); /* exits */
	tv.tv_sec= 60;
	tv.tv_usec= 0;
	event_add(rePostEvent, &tv);

	r= event_base_loop(EventBase, 0);
	if (r != 0)
		crondlog(LVL9 "event_base_loop failed");
	return 0;
}
int cr_service(bool daemon_mode)
{
	int server_fd = -1;
	int child_pid;

	struct sockaddr_un client_addr;
	socklen_t client_addr_len;

	{
		struct sockaddr_un server_addr;
		socklen_t server_addr_len;

		server_fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
		if (server_fd == -1) {
			pr_perror("Can't initialize service socket");
			goto err;
		}

		memset(&server_addr, 0, sizeof(server_addr));
		memset(&client_addr, 0, sizeof(client_addr));
		server_addr.sun_family = AF_LOCAL;

		if (opts.addr == NULL) {
			pr_warn("Binding to local dir address!\n");
			opts.addr = CR_DEFAULT_SERVICE_ADDRESS;
		}

		strcpy(server_addr.sun_path, opts.addr);

		server_addr_len = strlen(server_addr.sun_path)
				+ sizeof(server_addr.sun_family);
		client_addr_len = sizeof(client_addr);

		unlink(server_addr.sun_path);

		if (bind(server_fd, (struct sockaddr *) &server_addr,
						server_addr_len) == -1) {
			pr_perror("Can't bind");
			goto err;
		}

		pr_info("The service socket is bound to %s\n", server_addr.sun_path);

		/* change service socket permissions, so anyone can connect to it */
		if (chmod(server_addr.sun_path, 0666)) {
			pr_perror("Can't change permissions of the service socket");
			goto err;
		}

		if (listen(server_fd, 16) == -1) {
			pr_perror("Can't listen for socket connections");
			goto err;
		}
	}

	if (daemon_mode) {
		if (daemon(1, 0) == -1) {
			pr_perror("Can't run service server in the background");
			goto err;
		}
	}

	if (opts.pidfile) {
		if (write_pidfile(getpid()) == -1) {
			pr_perror("Can't write pidfile");
			goto err;
		}
	}

	if (setup_sigchld_handler())
		goto err;

	while (1) {
		int sk;

		pr_info("Waiting for connection...\n");

		sk = accept(server_fd, &client_addr, &client_addr_len);
		if (sk == -1) {
			pr_perror("Can't accept connection");
			goto err;
		}

		pr_info("Connected.\n");
		child_pid = fork();
		if (child_pid == 0) {
			int ret;

			if (restore_sigchld_handler())
				exit(1);

			close(server_fd);
			init_opts();
			ret = cr_service_work(sk);
			close(sk);
			exit(ret != 0);
		}

		if (child_pid < 0)
			pr_perror("Can't fork a child");

		close(sk);
	}

err:
	close_safe(&server_fd);

	return 1;
}
Exemple #22
0
int main(int argc, char **argv)
{
	char *dst = NULL, *src = NULL;
	struct sigaction sa;
	int mode = NONE;
	int opt;

	while ((opt=getopt_long(argc, argv, main_sopts, main_lopts, NULL)) != -1) {
		switch(opt) {
		case 'l':
			mode = SHOW;
			detach = 0;
			break;

		case 's':
			mode = LISTEN;
			break;

		case 'c':
			mode = CONNECT;
			dst  = strdup(optarg);
			break;

		case 'Q':
			mode = CONNECT;
			if (optarg)
				search_duration = atoi(optarg);
			break;

		case 'k':
			mode = KILL;
			detach = 0;
			dst  = strdup(optarg);
			break;

		case 'K':
			mode = KILL;
			detach = 0;
			break;

		case 'i':
			src = strdup(optarg);
			break;

		case 'r':
			bnep_str2svc(optarg, &role);
			break;

		case 'd':
			bnep_str2svc(optarg, &service);
			break;

		case 'D':
			use_sdp = 0;
			break;

		case 'E':
			encrypt = 1;
			break;

		case 'S':
			secure = 1;
			break;

		case 'M':
			master = 1;
			break;

		case 'e':
			strcpy(netdev, optarg);
			break;

		case 'n':
			detach = 0;
			break;

		case 'p':
			if (optarg)
				persist = atoi(optarg);
			else
				persist = 5;
			break;

		case 'C':
			if (optarg)
				use_cache = atoi(optarg);
			else
				use_cache = 2;
			break;

		case 'P':
			pidfile = strdup(optarg);
			break;

		case 'z':
			cleanup = 1;
			break;

		case 'h':
		default:
			printf(main_help);
			exit(0);
		}
	}

	argc -= optind;
	argv += optind;
	optind = 0;

	if (bnep_init())
		return -1;

	/* Check non daemon modes first */
	switch (mode) {
	case SHOW:
		do_show();
		return 0;

	case KILL:
		do_kill(dst);
		return 0;

	case NONE:
		printf(main_help);
		return 0;
	}

	/* Initialize signals */
	memset(&sa, 0, sizeof(sa));
	sa.sa_flags   = SA_NOCLDSTOP;
	sa.sa_handler = SIG_IGN;
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);

	sa.sa_handler = sig_hup;
	sigaction(SIGHUP, &sa, NULL);

	sa.sa_handler = sig_term;
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT,  &sa, NULL);

	if (detach) {
		if (fork()) exit(0);

		/* Direct stdin,stdout,stderr to '/dev/null' */
		{
			int fd = open("/dev/null", O_RDWR);
			dup2(fd, 0); dup2(fd, 1); dup2(fd, 2);
			close(fd);
		}

		setsid();
		chdir("/");
	}

	openlog("pand", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON);
	syslog(LOG_INFO, "Bluetooth PAN daemon version %s", VERSION);

	if (src) {
		src_dev = hci_devid(src);
		if (src_dev < 0 || hci_devba(src_dev, &src_addr) < 0) {
			syslog(LOG_ERR, "Invalid source. %s(%d)", strerror(errno), errno);
			return -1;
		}
	}

	if (pidfile && write_pidfile())
		return -1;

	if (dst) {
		/* Disable cache invalidation */
		use_cache = 0;

		strncpy(cache.dst, dst, sizeof(cache.dst) - 1);
		str2ba(dst, &cache.bdaddr);
		cache.valid = 1;
		free(dst);
	}

	switch (mode) {
	case CONNECT:
		do_connect();
		break;

	case LISTEN:
		do_listen();
		break;
	}

	if (pidfile)
		unlink(pidfile);

	return 0;
}
Exemple #23
0
int
main(int argc, char **argv)
{
	g_start_sec = cf_get_seconds();

	// Initialize cf_thread wrapper.
	cf_thread_init();

	// Initialize memory allocation.
	cf_alloc_init();

	// Initialize fault management framework.
	cf_fault_init();

	// Setup signal handlers.
	as_signal_setup();

	// Initialize TLS library.
	tls_check_init();

	int opt;
	int opt_i;
	const char *config_file = DEFAULT_CONFIG_FILE;
	bool run_in_foreground = false;
	bool new_style_daemon = false;
	bool cold_start_cmd = false;
	uint32_t instance = 0;

	// Parse command line options.
	while ((opt = getopt_long(argc, argv, "", CMD_OPTS, &opt_i)) != -1) {
		switch (opt) {
		case 'h':
			// printf() since we want stdout and don't want cf_fault's prefix.
			printf("%s\n", HELP);
			return 0;
		case 'v':
			// printf() since we want stdout and don't want cf_fault's prefix.
			printf("%s build %s\n", aerospike_build_type, aerospike_build_id);
			return 0;
		case 'f':
			config_file = cf_strdup(optarg);
			break;
		case 'F':
			// As a "new-style" daemon(*), asd runs in the foreground and
			// ignores the following configuration items:
			//  - user ('user')
			//	- group ('group')
			//  - PID file ('pidfile')
			//
			// If ignoring configuration items, or if the 'console' sink is not
			// specified, warnings will appear in stderr.
			//
			// (*) http://0pointer.de/public/systemd-man/daemon.html#New-Style%20Daemons
			run_in_foreground = true;
			new_style_daemon = true;
			break;
		case 'd':
			run_in_foreground = true;
			break;
		case 'c':
			cold_start_cmd = true;
			break;
		case 'n':
			instance = (uint32_t)strtol(optarg, NULL, 0);
			break;
		default:
			// fprintf() since we don't want cf_fault's prefix.
			fprintf(stderr, "%s\n", USAGE);
			return 1;
		}
	}

	// Set all fields in the global runtime configuration instance. This parses
	// the configuration file, and creates as_namespace objects. (Return value
	// is a shortcut pointer to the global runtime configuration instance.)
	as_config *c = as_config_init(config_file);

	// Detect NUMA topology and, if requested, prepare for CPU and NUMA pinning.
	cf_topo_config(c->auto_pin, (cf_topo_numa_node_index)instance,
			&c->service.bind);

	// Perform privilege separation as necessary. If configured user & group
	// don't have root privileges, all resources created or reopened past this
	// point must be set up so that they are accessible without root privileges.
	// If not, the process will self-terminate with (hopefully!) a log message
	// indicating which resource is not set up properly.
	cf_process_privsep(c->uid, c->gid);

	//
	// All resources such as files, devices, and shared memory must be created
	// or reopened below this line! (The configuration file is the only thing
	// that must be opened above, in order to parse the user & group.)
	//==========================================================================

	// A "new-style" daemon expects console logging to be configured. (If not,
	// log messages won't be seen via the standard path.)
	if (new_style_daemon) {
		if (! cf_fault_console_is_held()) {
			cf_warning(AS_AS, "in new-style daemon mode, console logging is not configured");
		}
	}

	// Activate log sinks. Up to this point, 'cf_' log output goes to stderr,
	// filtered according to NO_SINKS_LIMIT in fault.c. After this point, 'cf_'
	// log output will appear in all log file sinks specified in configuration,
	// with specified filtering. If console sink is specified in configuration,
	// 'cf_' log output will continue going to stderr, but filtering will switch
	// from NO_SINKS_LIMIT to that specified in console sink configuration.
	if (0 != cf_fault_sink_activate_all_held()) {
		// Specifics of failure are logged in cf_fault_sink_activate_all_held().
		cf_crash_nostack(AS_AS, "can't open log sink(s)");
	}

	// Daemonize asd if specified. After daemonization, output to stderr will no
	// longer appear in terminal. Instead, check /tmp/aerospike-console.<pid>
	// for console output.
	if (! run_in_foreground && c->run_as_daemon) {
		// Don't close any open files when daemonizing. At this point only log
		// sink files are open - instruct cf_process_daemonize() to ignore them.
		int open_fds[CF_FAULT_SINKS_MAX];
		int num_open_fds = cf_fault_sink_get_fd_list(open_fds);

		cf_process_daemonize(open_fds, num_open_fds);
	}

	// Log which build this is - should be the first line in the log file.
	cf_info(AS_AS, "<><><><><><><><><><>  %s build %s  <><><><><><><><><><>",
			aerospike_build_type, aerospike_build_id);

	// Includes echoing the configuration file to log.
	as_config_post_process(c, config_file);

	xdr_config_post_process();

	// If we allocated a non-default config file name, free it.
	if (config_file != DEFAULT_CONFIG_FILE) {
		cf_free((void*)config_file);
	}

	// Write the pid file, if specified.
	if (! new_style_daemon) {
		write_pidfile(c->pidfile);
	}
	else {
		if (c->pidfile) {
			cf_warning(AS_AS, "will not write PID file in new-style daemon mode");
		}
	}

	// Check that required directories are set up properly.
	validate_directory(c->work_directory, "work");
	validate_directory(c->mod_lua.user_path, "Lua user");
	validate_smd_directory();

	// Initialize subsystems. At this point we're allocating local resources,
	// starting worker threads, etc. (But no communication with other server
	// nodes or clients yet.)

	as_json_init();				// Jansson JSON API used by System Metadata
	as_index_tree_gc_init();	// thread to purge dropped index trees
	as_sindex_thr_init();		// defrag secondary index (ok during population)
	as_nsup_init();				// load previous evict-void-time(s)

	// Initialize namespaces. Each namespace decides here whether it will do a
	// warm or cold start. Index arenas, partition structures and index tree
	// structures are initialized. Secondary index system metadata is restored.
	as_namespaces_init(cold_start_cmd, instance);

	// Initialize the storage system. For warm and cool restarts, this includes
	// fully resuming persisted indexes - this may take a few minutes.
	as_storage_init();

	// Migrate memory to correct NUMA node (includes resumed index arenas).
	cf_topo_migrate_memory();

	// Drop capabilities that we kept only for initialization.
	cf_process_drop_startup_caps();

	// Activate the storage system. For cold starts and cool restarts, this
	// includes full drive scans - this may take several hours. The defrag
	// subsystem starts operating at the end of this call.
	as_storage_load();

	// Populate all secondary indexes. This may block for a long time.
	as_sindex_boot_populateall();

	cf_info(AS_AS, "initializing services...");

	cf_dns_init();				// DNS resolver
	as_netio_init();			// query responses
	as_security_init();			// security features
	as_tsvc_init();				// all transaction handling
	as_hb_init();				// inter-node heartbeat
	as_skew_monitor_init();		// clock skew monitor
	as_fabric_init();			// inter-node communications
	as_exchange_init();			// initialize the cluster exchange subsystem
	as_clustering_init();		// clustering-v5 start
	as_info_init();				// info transaction handling
	as_migrate_init();			// move data between nodes
	as_proxy_init();			// do work on behalf of others
	as_rw_init();				// read & write service
	as_query_init();			// query transaction handling
	as_udf_init();				// user-defined functions
	as_scan_init();				// scan a namespace or set
	as_batch_init();			// batch transaction handling
	as_xdr_init();				// cross data-center replication
	as_mon_init();				// monitor

	// Wait for enough available storage. We've been defragging all along, but
	// here we wait until it's enough. This may block for a long time.
	as_storage_wait_for_defrag();

	// Start subsystems. At this point we may begin communicating with other
	// cluster nodes, and ultimately with clients.

	as_smd_start();				// enables receiving cluster state change events
	as_health_start();			// starts before fabric and hb to capture them
	as_fabric_start();			// may send & receive fabric messages
	as_xdr_start();				// XDR should start before it joins other nodes
	as_hb_start();				// start inter-node heartbeat
	as_exchange_start();		// start the cluster exchange subsystem
	as_clustering_start();		// clustering-v5 start
	as_nsup_start();			// may send evict-void-time(s) to other nodes
	as_service_start();			// server will now receive client transactions
	as_info_port_start();		// server will now receive info transactions
	as_ticker_start();			// only after everything else is started

	// Relevant for enterprise edition only.
	as_storage_start_tomb_raider();

	// Log a service-ready message.
	cf_info(AS_AS, "service ready: soon there will be cake!");

	//--------------------------------------------
	// Startup is done. This thread will now wait
	// quietly for a shutdown signal.
	//

	// Stop this thread from finishing. Intentionally deadlocking on a mutex is
	// a remarkably efficient way to do this.
	pthread_mutex_lock(&g_main_deadlock);
	g_startup_complete = true;
	pthread_mutex_lock(&g_main_deadlock);

	// When the service is running, you are here (deadlocked) - the signals that
	// stop the service (yes, these signals always occur in this thread) will
	// unlock the mutex, allowing us to continue.

	g_shutdown_started = true;
	pthread_mutex_unlock(&g_main_deadlock);
	pthread_mutex_destroy(&g_main_deadlock);

	//--------------------------------------------
	// Received a shutdown signal.
	//

	as_storage_shutdown(instance);
	as_xdr_shutdown();

	cf_info(AS_AS, "finished clean shutdown - exiting");

	// If shutdown was totally clean (all threads joined) we could just return,
	// but for now we exit to make sure all threads die.
#ifdef DOPROFILE
	exit(0); // exit(0) so profile build actually dumps gmon.out
#else
	_exit(0);
#endif

	return 0;
}
Exemple #24
0
/*
 * main
 *
 */
int
main (int argc, char *argv[])
{
	GOptionContext *opt_ctx = NULL;
	gboolean become_daemon = FALSE;
	gboolean g_fatal_warnings = FALSE;
	char *pidfile = NULL, *state_file = NULL, *dhcp = NULL;
	char *config = NULL, *plugins = NULL, *conf_plugins = NULL;
	char *log_level = NULL, *log_domains = NULL;
	char **dns = NULL;
	gboolean success;
	BMPolicy *policy = NULL;
	BMDBusManager *dbus_mgr = NULL;
	GError *error = NULL;
	gboolean wrote_pidfile = FALSE;
	char *cfg_log_level = NULL, *cfg_log_domains = NULL;

	GOptionEntry options[] = {
		{ "no-daemon", 0, 0, G_OPTION_ARG_NONE, &become_daemon, "Don't become a daemon", NULL },
		{ "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, "Make all warnings fatal", NULL },
		{ "pid-file", 0, 0, G_OPTION_ARG_FILENAME, &pidfile, "Specify the location of a PID file", "filename" },
		{ "state-file", 0, 0, G_OPTION_ARG_FILENAME, &state_file, "State file location", "/path/to/state.file" },
		{ "config", 0, 0, G_OPTION_ARG_FILENAME, &config, "Config file location", "/path/to/config.file" },
		{ "plugins", 0, 0, G_OPTION_ARG_STRING, &plugins, "List of plugins separated by ','", "plugin1,plugin2" },
		{ "log-level", 0, 0, G_OPTION_ARG_STRING, &log_level, "Log level: one of [ERR, WARN, INFO, DEBUG]", "INFO" },
		{ "log-domains", 0, 0, G_OPTION_ARG_STRING, &log_domains,
		        "Log domains separated by ',': any combination of [NONE,HW,BT,USER_SET,SYS_SET,SUSPEND,CORE,DEVICE]",
		        "HW" },
		{NULL}
	};

	if (getuid () != 0) {
		fprintf (stderr, "You must be root to run BarcodeManager!\n");
		exit (1);
	}

	if (!g_module_supported ()) {
		fprintf (stderr, "GModules are not supported on your platform!\n");
		exit (1);
	}

	bindtextdomain (GETTEXT_PACKAGE, BMLOCALEDIR);
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
	textdomain (GETTEXT_PACKAGE);

	/* Parse options */
	opt_ctx = g_option_context_new ("");
	g_option_context_set_translation_domain (opt_ctx, "UTF-8");
	g_option_context_set_ignore_unknown_options (opt_ctx, FALSE);
	g_option_context_set_help_enabled (opt_ctx, TRUE);
	g_option_context_add_main_entries (opt_ctx, options, NULL);

	g_option_context_set_summary (opt_ctx,
		"BarcodeManager monitors all barcode scanners automatically.");

	success = g_option_context_parse (opt_ctx, &argc, &argv, NULL);
	g_option_context_free (opt_ctx);

	if (!success) {
		fprintf (stderr, _("Invalid option.  Please use --help to see a list of valid options.\n"));
		exit (1);
	}

	/* Make GIO ignore the remote VFS service; otherwise it tries to use the
	 * session bus to contact the remote service, and NM shouldn't ever be
	 * talking on the session bus.  See rh #588745
	 */
	setenv ("GIO_USE_VFS", "local", 1);

	pidfile = pidfile ? pidfile : g_strdup (BM_DEFAULT_PID_FILE);
	state_file = state_file ? state_file : g_strdup (BM_DEFAULT_SYSTEM_STATE_FILE);

	/* check pid file */
	if (check_pidfile (pidfile))
		exit (1);

	/* Parse the config file */
	if (config) {
		if (!parse_config_file (config, &conf_plugins, &dhcp, &dns, &cfg_log_level, &cfg_log_domains, &error)) {
			fprintf (stderr, "Config file %s invalid: (%d) %s\n",
			         config,
			         error ? error->code : -1,
			         (error && error->message) ? error->message : "unknown");
			exit (1);
		}
	} else {
		gboolean parsed = FALSE;

		/* Even though we prefer BarcodeManager.conf, we need to check the
		 * old bm-system-settings.conf first to preserve compat with older
		 * setups.  In package managed systems dropping a BarcodeManager.conf
		 * onto the system would make NM use it instead of bm-system-settings.conf,
		 * changing behavior during an upgrade.  We don't want that.
		 */

		/* Try deprecated bm-system-settings.conf first */
		if (g_file_test (BM_OLD_SYSTEM_CONF_FILE, G_FILE_TEST_EXISTS)) {
			config = g_strdup (BM_OLD_SYSTEM_CONF_FILE);
			parsed = parse_config_file (config, &conf_plugins, &dhcp, &dns, &cfg_log_level, &cfg_log_domains, &error);
			if (!parsed) {
				fprintf (stderr, "Default config file %s invalid: (%d) %s\n",
				         config,
				         error ? error->code : -1,
				         (error && error->message) ? error->message : "unknown");
				g_free (config);
				config = NULL;
				g_clear_error (&error);
			}
		}

		/* Try the preferred BarcodeManager.conf last */
		if (!parsed && g_file_test (BM_DEFAULT_SYSTEM_CONF_FILE, G_FILE_TEST_EXISTS)) {
			config = g_strdup (BM_DEFAULT_SYSTEM_CONF_FILE);
			parsed = parse_config_file (config, &conf_plugins, &dhcp, &dns, &cfg_log_level, &cfg_log_domains, &error);
			if (!parsed) {
				fprintf (stderr, "Default config file %s invalid: (%d) %s\n",
				         config,
				         error ? error->code : -1,
				         (error && error->message) ? error->message : "unknown");
				g_free (config);
				config = NULL;
				g_clear_error (&error);
			}
		}
	}
	/* Logging setup */
	if (!bm_logging_setup (log_level ? log_level : cfg_log_level,
	                       log_domains ? log_domains : cfg_log_domains,
	                       &error)) {
		fprintf (stderr,
		         _("%s.  Please use --help to see a list of valid options.\n"),
		         error->message);
		exit (1);
	}

	/* Plugins specified with '--plugins' override those of config file */
	plugins = plugins ? plugins : g_strdup (conf_plugins);
	g_free (conf_plugins);

	/* Parse the state file */
	if (!parse_state_file (state_file, &error)) {
		fprintf (stderr, "State file %s parsing failed: (%d) %s\n",
		         state_file,
		         error ? error->code : -1,
		         (error && error->message) ? error->message : "unknown");
		/* Not a hard failure */
	}
	g_clear_error (&error);

	/* Tricky: become_daemon is FALSE by default, so unless it's TRUE because
	 * of a CLI option, it'll become TRUE after this
	 */
	become_daemon = !become_daemon;
	if (become_daemon) {
		if (daemon (0, 0) < 0) {
			int saved_errno;

			saved_errno = errno;
			fprintf (stderr, "Could not daemonize: %s [error %u]\n",
			         g_strerror (saved_errno),
			         saved_errno);
			exit (1);
		}
		if (write_pidfile (pidfile))
			wrote_pidfile = TRUE;
	}

	if (g_fatal_warnings) {
		GLogLevelFlags fatal_mask;

		fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
		fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
		g_log_set_always_fatal (fatal_mask);
	}

	/*
	 * Set the umask to 0022, which results in 0666 & ~0022 = 0644.
	 * Otherwise, if root (or an su'ing user) has a wacky umask, we could
	 * write out an unreadable resolv.conf.
	 */
	umask (022);

	g_type_init ();
	if (!g_thread_supported ())
		g_thread_init (NULL);
	dbus_g_thread_init ();

#ifndef HAVE_DBUS_GLIB_DISABLE_LEGACY_PROP_ACCESS
#error HAVE_DBUS_GLIB_DISABLE_LEGACY_PROP_ACCESS not defined
#endif

#if HAVE_DBUS_GLIB_DISABLE_LEGACY_PROP_ACCESS
	/* Ensure that non-exported properties don't leak out, and that the
	 * introspection 'access' permissions are respected.
	 */
	dbus_glib_global_set_disable_legacy_property_access ();
#endif

	setup_signals ();

	bm_logging_start (become_daemon);

	bm_log_info (LOGD_CORE, "BarcodeManager (version " BM_DIST_VERSION ") is starting...");
	success = FALSE;

	if (config)
		bm_log_info (LOGD_CORE, "Read config file %s", config);

	main_loop = g_main_loop_new (NULL, FALSE);

	/* Initialize our DBus service & connection */
	dbus_mgr = bm_dbus_manager_get ();

	manager = bm_manager_get (config, plugins, state_file, &error);
	if (manager == NULL) {
		bm_log_err (LOGD_CORE, "failed to initialize the barcode manager: %s",
		          error && error->message ? error->message : "(unknown)");
		goto done;
	}

    policy = bm_policy_new (manager);
    if (policy == NULL) {
        bm_log_err (LOGD_CORE, "failed to initialize the policy.");
        goto done;
    }

	/* Start our DBus service */
	if (!bm_dbus_manager_start_service (dbus_mgr)) {
		bm_log_err (LOGD_CORE, "failed to start the dbus service.");
		goto done;
	}

	bm_manager_start (manager);

	success = TRUE;

	/* Told to quit before getting to the mainloop by the signal handler */
	if (quit_early == TRUE)
		goto done;

	g_main_loop_run (main_loop);

done:
    if (policy)
		bm_policy_destroy (policy);

	if (manager)
		g_object_unref (manager);

	bm_logging_shutdown ();

	if (pidfile && wrote_pidfile)
		unlink (pidfile);

	/* Free options */
	g_free (pidfile);
	g_free (state_file);
	g_free (config);
	g_free (plugins);
	g_free (dhcp);
	g_strfreev (dns);
	g_free (log_level);
	g_free (log_domains);
	g_free (cfg_log_level);
	g_free (cfg_log_domains);

	bm_log_info (LOGD_CORE, "exiting (%s)", success ? "success" : "error");
	exit (success ? 0 : 1);
}
int32_t main(int argc, char *argv[])
{
	int32_t opt;
	uint32_t n;
	char *cfgfile = NULL;
	struct stat sb;
	struct bitcoind *b, *sigfrom;
	struct psj *psj;
	struct sigaction act;
	struct config *cfg;

	cfg = malloc(sizeof(*cfg));
	if (cfg == NULL)
	{
		APPLOG(LOG_CRIT, "cfg malloc failed");
		exit(255);
	}

	while ((opt = getopt(argc, argv, "hs:c:")) != -1)
	{
		switch(opt)
		{
			case 'c':
				cfgfile = optarg;
				break;
			case 's':
				cfg->force_pid = atoi(optarg);
				break;

			default:
			case 'h':
				usage();
		}
	}

	APPLOG(LOG_NOTICE, "psj_sigmon v0.5 starting up");

	/* config file parsing */
	if (parse_cfg(cfgfile ? cfgfile : "config.cfg", cfg))
	{
		APPLOG(LOG_CRIT, "parse_cfg error");
		exit(255);
	}

	if (cfg->bitcoind_used == 0)
	{
		APPLOG(LOG_CRIT, "no bitcoind defined, exiting");
		exit(EXIT_SUCCESS);
	}
	if (cfg->psj_used == 0)
	{
		APPLOG(LOG_CRIT, "no psj defined, exiting");
		exit(EXIT_SUCCESS);
	}

	if (cfg->pidfile)
	{
		if (write_pidfile(cfg->pidfile) != 0)
		{
			APPLOG(LOG_CRIT, "write_pidfile failed");
			exit(255);
		}
	}

	if (cfg->daemon)
	{
		APPLOG(LOG_NOTICE, "daemonising, you will hear no more from me");
		if (daemon(false, false) == -1)
		{
			APPLOG(LOG_CRIT, "except daemonising failed..  dying");
			exit(255);
		}
		cfg->daemon_done = true;
	}

	/* install signal handlers */
	act.sa_flags = SA_SIGINFO;
	act.sa_sigaction = &sig_handler;
	sigaction(SIGUSR1, &act, NULL);
	sigaction(SIGINT, &act, NULL);
	sigaction(SIGTERM, &act, NULL);


	while(1)
	{
		select(0, NULL, NULL, NULL, NULL);

		APPLOG(LOG_INFO, "got signal %d, from pid %d", sig, pid);

		/* handle INT and TERM */
		if (sig == SIGINT || sig == SIGTERM)
			/* break out of loop and exit gracefully */
			break;

		/* ignore non-USR1 */
		if (sig != SIGUSR1)
			continue;

		if (cfg->force_pid)
		{
			pid = cfg->force_pid;
			APPLOG(LOG_DEBUG, "forcing sending-pid to %d", pid);
		}

		sigfrom = NULL;
		for(n = 0 ; n < cfg->bitcoind_used ; n++)
		{
			/* check if pid == this bitcoind's pid */
			b = cfg->bitcoind_list[n];
			
			if (stat(b->pidfile, &sb) == -1)
			{
				APPLOG(LOG_WARNING, "%s on stat of %s", strerror(errno), b->pidfile);
				continue;
			}

			if (sb.st_mtime > b->pidfile_mtime)
			{
				/* refresh what we think the pid is of this
				 * bitcoind */
				b->pid = read_pidfile(b->pidfile);
				b->pidfile_mtime = sb.st_mtime;
				APPLOG(LOG_DEBUG, "%s changed: new pid is %u", b->pidfile, b->pid);
			}

			if (b->pid == pid)
			{
				APPLOG(LOG_DEBUG, "signal matches %s (%s)", b->pidfile, b->name);
				sigfrom = b;
				break;
			}
		}

		if (sigfrom == NULL)
		{
			APPLOG(LOG_WARNING, "signal not from a recognised pid");
			continue;
		}

		/* tell each psj about b->name */
		for(n = 0 ; n < cfg->psj_used ; n++)
		{
			psj = cfg->psj_list[n];
			APPLOG(LOG_INFO, "notifying %s of signal", psj->hostport);
			poke_psj(cfg,psj, b);
		}
	}

	APPLOG(LOG_INFO, "shutting down, removing pidfile");
	unlink(cfg->pidfile);

	/* we're lazy, the kernel will clean up our memory, sorry valgrind :p */

	return EXIT_SUCCESS;
}
Exemple #26
0
int main(int argc, char *argv[])
{
  srvr_sockaddr_union_t me;
  curl_socket_t sock = CURL_SOCKET_BAD;
  curl_socket_t msgsock = CURL_SOCKET_BAD;
  int wrotepidfile = 0;
  char *pidname= (char *)".sockfilt.pid";
  bool juggle_again;
  int rc;
  int error;
  int arg=1;
  enum sockmode mode = PASSIVE_LISTEN; /* default */
  const char *addr = NULL;

  while(argc>arg) {
    if(!strcmp("--version", argv[arg])) {
      printf("sockfilt IPv4%s\n",
#ifdef ENABLE_IPV6
             "/IPv6"
#else
             ""
#endif
             );
      return 0;
    }
    else if(!strcmp("--verbose", argv[arg])) {
      verbose = TRUE;
      arg++;
    }
    else if(!strcmp("--pidfile", argv[arg])) {
      arg++;
      if(argc>arg)
        pidname = argv[arg++];
    }
    else if(!strcmp("--logfile", argv[arg])) {
      arg++;
      if(argc>arg)
        serverlogfile = argv[arg++];
    }
    else if(!strcmp("--ipv6", argv[arg])) {
#ifdef ENABLE_IPV6
      ipv_inuse = "IPv6";
      use_ipv6 = TRUE;
#endif
      arg++;
    }
    else if(!strcmp("--ipv4", argv[arg])) {
      /* for completeness, we support this option as well */
#ifdef ENABLE_IPV6
      ipv_inuse = "IPv4";
      use_ipv6 = FALSE;
#endif
      arg++;
    }
    else if(!strcmp("--bindonly", argv[arg])) {
      bind_only = TRUE;
      arg++;
    }
    else if(!strcmp("--port", argv[arg])) {
      arg++;
      if(argc>arg) {
        char *endptr;
        unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
        if((endptr != argv[arg] + strlen(argv[arg])) ||
           ((ulnum != 0UL) && ((ulnum < 1025UL) || (ulnum > 65535UL)))) {
          fprintf(stderr, "sockfilt: invalid --port argument (%s)\n",
                  argv[arg]);
          return 0;
        }
        port = curlx_ultous(ulnum);
        arg++;
      }
    }
    else if(!strcmp("--connect", argv[arg])) {
      /* Asked to actively connect to the specified local port instead of
         doing a passive server-style listening. */
      arg++;
      if(argc>arg) {
        char *endptr;
        unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
        if((endptr != argv[arg] + strlen(argv[arg])) ||
           (ulnum < 1025UL) || (ulnum > 65535UL)) {
          fprintf(stderr, "sockfilt: invalid --connect argument (%s)\n",
                  argv[arg]);
          return 0;
        }
        connectport = curlx_ultous(ulnum);
        arg++;
      }
    }
    else if(!strcmp("--addr", argv[arg])) {
      /* Set an IP address to use with --connect; otherwise use localhost */
      arg++;
      if(argc>arg) {
        addr = argv[arg];
        arg++;
      }
    }
    else {
      puts("Usage: sockfilt [option]\n"
           " --version\n"
           " --verbose\n"
           " --logfile [file]\n"
           " --pidfile [file]\n"
           " --ipv4\n"
           " --ipv6\n"
           " --bindonly\n"
           " --port [port]\n"
           " --connect [port]\n"
           " --addr [address]");
      return 0;
    }
  }

#ifdef WIN32
  win32_init();
  atexit(win32_cleanup);

  setmode(fileno(stdin), O_BINARY);
  setmode(fileno(stdout), O_BINARY);
  setmode(fileno(stderr), O_BINARY);
#endif

  install_signal_handlers();

#ifdef ENABLE_IPV6
  if(!use_ipv6)
#endif
    sock = socket(AF_INET, SOCK_STREAM, 0);
#ifdef ENABLE_IPV6
  else
    sock = socket(AF_INET6, SOCK_STREAM, 0);
#endif

  if(CURL_SOCKET_BAD == sock) {
    error = SOCKERRNO;
    logmsg("Error creating socket: (%d) %s",
           error, strerror(error));
    write_stdout("FAIL\n", 5);
    goto sockfilt_cleanup;
  }

  if(connectport) {
    /* Active mode, we should connect to the given port number */
    mode = ACTIVE;
#ifdef ENABLE_IPV6
    if(!use_ipv6) {
#endif
      memset(&me.sa4, 0, sizeof(me.sa4));
      me.sa4.sin_family = AF_INET;
      me.sa4.sin_port = htons(connectport);
      me.sa4.sin_addr.s_addr = INADDR_ANY;
      if (!addr)
        addr = "127.0.0.1";
      Curl_inet_pton(AF_INET, addr, &me.sa4.sin_addr);

      rc = connect(sock, &me.sa, sizeof(me.sa4));
#ifdef ENABLE_IPV6
    }
    else {
      memset(&me.sa6, 0, sizeof(me.sa6));
      me.sa6.sin6_family = AF_INET6;
      me.sa6.sin6_port = htons(connectport);
      if (!addr)
        addr = "::1";
      Curl_inet_pton(AF_INET6, addr, &me.sa6.sin6_addr);

      rc = connect(sock, &me.sa, sizeof(me.sa6));
    }
#endif /* ENABLE_IPV6 */
    if(rc) {
      error = SOCKERRNO;
      logmsg("Error connecting to port %hu: (%d) %s",
             connectport, error, strerror(error));
      write_stdout("FAIL\n", 5);
      goto sockfilt_cleanup;
    }
    logmsg("====> Client connect");
    msgsock = sock; /* use this as stream */
  }
  else {
    /* passive daemon style */
    sock = sockdaemon(sock, &port);
    if(CURL_SOCKET_BAD == sock) {
      write_stdout("FAIL\n", 5);
      goto sockfilt_cleanup;
    }
    msgsock = CURL_SOCKET_BAD; /* no stream socket yet */
  }

  logmsg("Running %s version", ipv_inuse);

  if(connectport)
    logmsg("Connected to port %hu", connectport);
  else if(bind_only)
    logmsg("Bound without listening on port %hu", port);
  else
    logmsg("Listening on port %hu", port);

  wrotepidfile = write_pidfile(pidname);
  if(!wrotepidfile) {
    write_stdout("FAIL\n", 5);
    goto sockfilt_cleanup;
  }

  do {
    juggle_again = juggle(&msgsock, sock, &mode);
  } while(juggle_again);

sockfilt_cleanup:

  if((msgsock != sock) && (msgsock != CURL_SOCKET_BAD))
    sclose(msgsock);

  if(sock != CURL_SOCKET_BAD)
    sclose(sock);

  if(wrotepidfile)
    unlink(pidname);

  restore_signal_handlers();

  if(got_exit_signal) {
    logmsg("============> sockfilt exits with signal (%d)", exit_signal);
    /*
     * To properly set the return status of the process we
     * must raise the same signal SIGINT or SIGTERM that we
     * caught and let the old handler take care of it.
     */
    raise(exit_signal);
  }

  logmsg("============> sockfilt quits");
  return 0;
}
Exemple #27
0
int
main(int argc, char *argv[])
{
	pid_t		pid;
	int		pm_fd;
	struct sigaction act;
	sigset_t	sigmask;
	int		c;
	char		errmsg[PATH_MAX + 64];
	int		pid_fd;

	prog = argv[0];
	if (geteuid() != 0) {
		(void) fprintf(stderr, "%s: Must be root\n", prog);
		exit(EXIT_FAILURE);
	}

	if ((pid_fd = open_pidfile(prog)) ==  -1)
		exit(EXIT_FAILURE);

	/*
	 * Process options
	 */
	broadcast = 1;
	while ((c = getopt(argc, argv, "n")) != EOF) {
		switch (c) {
		case 'n':
			broadcast = 0;
			break;
		case '?':
			(void) fprintf(stderr, "Usage: %s [-n]\n", prog);
			exit(EXIT_FAILURE);
		}
	}

	pm_fd = open(PM, O_RDWR);
	if (pm_fd == -1) {
		(void) sprintf(errmsg, "%s: %s", prog, PM);
		perror(errmsg);
		exit(EXIT_FAILURE);
	}
	(void) close(pm_fd);

	/*
	 * Initialize mutex lock used to insure only one command to
	 * run at a time.
	 */
	if (mutex_init(&poweroff_mutex, USYNC_THREAD, NULL) != 0) {
		(void) fprintf(stderr,
			"%s: Unable to initialize mutex lock\n", prog);
		exit(EXIT_FAILURE);
	}

	if ((info = (pwr_info_t *)malloc(sizeof (pwr_info_t))) == NULL) {
		(void) sprintf(errmsg, "%s: malloc", prog);
		perror(errmsg);
		exit(EXIT_FAILURE);
	}

	/*
	 * Daemon is set to go...
	 */
	if ((pid = fork()) < 0)
		exit(EXIT_FAILURE);
	else if (pid != 0)
		exit(EXIT_SUCCESS);

	pid = getpid();
	openlog(prog, 0, LOG_DAEMON);
	if (write_pidfile(pid_fd, pid) == -1)	/* logs errors on failure */
		exit(EXIT_FAILURE);
	(void) close(pid_fd);

	/*
	 * Close all the parent's file descriptors (Bug 1225843).
	 */
	closefrom(0);
	(void) setsid();
	(void) chdir("/");
	(void) umask(0);
#ifdef DEBUG
	/*
	 * Connect stdout to the console.
	 */
	if (dup2(open("/dev/console", O_WRONLY|O_NOCTTY), 1) == -1) {
		logerror("Unable to connect to the console.");
	}
#endif
	info->pd_flags = PD_AC;
	info->pd_idle_time = -1;
	info->pd_start_time = 0;
	info->pd_finish_time = 0;

	/*
	 * Allow SIGQUIT, SIGINT and SIGTERM signals to terminate us
	 * any time
	 */
	act.sa_handler = kill_handler;
	(void) sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	(void) sigaction(SIGQUIT, &act, NULL);
	(void) sigaction(SIGINT, &act, NULL);
	(void) sigaction(SIGTERM, &act, NULL);

	(void) sigfillset(&sigmask);
	(void) sigdelset(&sigmask, SIGQUIT);
	(void) sigdelset(&sigmask, SIGINT);
	(void) sigdelset(&sigmask, SIGTERM);
	(void) thr_sigsetmask(SIG_SETMASK, &sigmask, NULL);

	/*
	 * If "power_button" device node can be opened, create a new
	 * thread to monitor the power button.
	 */
	if ((pb_fd = open(PB, O_RDONLY)) != -1) {
		if (thr_create(NULL, NULL,
		    (void *(*)(void *))power_button_monitor, NULL,
		    THR_DAEMON, NULL) != 0) {
			logerror("Unable to monitor system's power button.");
		}
	}

#ifdef sparc
	do_attach();
#endif

	/*
	 * Create a new thread to monitor system activity and suspend
	 * system if idle.
	 */
	if (thr_create(NULL, NULL,
	    (void *(*)(void *))system_activity_monitor, NULL,
	    THR_DAEMON, NULL) != 0) {
		logerror("Unable to create thread to monitor system activity.");
	}

	/*
	 * Block until we receive an explicit terminate signal
	 */
	(void) sigsuspend(&sigmask);

	return (1);
}
Exemple #28
0
int zcip_main(int argc UNUSED_PARAM, char **argv)
{
	int state;
	char *r_opt;
	unsigned opts;

	// ugly trick, but I want these zeroed in one go
	struct {
		const struct in_addr null_ip;
		const struct ether_addr null_addr;
		struct in_addr ip;
		struct ifreq ifr;
		int timeout_ms; /* must be signed */
		unsigned conflicts;
		unsigned nprobes;
		unsigned nclaims;
		int ready;
	} L;
#define null_ip    (L.null_ip   )
#define null_addr  (L.null_addr )
#define ip         (L.ip        )
#define ifr        (L.ifr       )
#define timeout_ms (L.timeout_ms)
#define conflicts  (L.conflicts )
#define nprobes    (L.nprobes   )
#define nclaims    (L.nclaims   )
#define ready      (L.ready     )

	memset(&L, 0, sizeof(L));
	INIT_G();

#define FOREGROUND (opts & 1)
#define QUIT       (opts & 2)
	// parse commandline: prog [options] ifname script
	// exactly 2 args; -v accumulates and implies -f
	opt_complementary = "=2:vv:vf";
	opts = getopt32(argv, "fqr:p:v", &r_opt, &pidfile, &verbose);
#if !BB_MMU
	// on NOMMU reexec early (or else we will rerun things twice)
	if (!FOREGROUND)
		bb_daemonize_or_rexec(0 /*was: DAEMON_CHDIR_ROOT*/, argv);
#endif
	// open an ARP socket
	// (need to do it before openlog to prevent openlog from taking
	// fd 3 (sock_fd==3))
	xmove_fd(xsocket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)), sock_fd);
	if (!FOREGROUND) {
		// do it before all bb_xx_msg calls
		openlog(applet_name, 0, LOG_DAEMON);
		logmode |= LOGMODE_SYSLOG;
	}
	if (opts & 4) { // -r n.n.n.n
		if (inet_aton(r_opt, &ip) == 0
		 || (ntohl(ip.s_addr) & IN_CLASSB_NET) != LINKLOCAL_ADDR
		) {
			bb_error_msg_and_die("invalid link address");
		}
	}
	argv += optind - 1;

	/* Now: argv[0]:junk argv[1]:intf argv[2]:script argv[3]:NULL */
	/* We need to make space for script argument: */
	argv[0] = argv[1];
	argv[1] = argv[2];
	/* Now: argv[0]:intf argv[1]:script argv[2]:junk argv[3]:NULL */
#define argv_intf (argv[0])

	xsetenv("interface", argv_intf);

	// initialize the interface (modprobe, ifup, etc)
	if (run(argv, "init", NULL))
		return EXIT_FAILURE;

	// initialize saddr
	// saddr is: { u16 sa_family; u8 sa_data[14]; }
	//memset(&saddr, 0, sizeof(saddr));
	//TODO: are we leaving sa_family == 0 (AF_UNSPEC)?!
	safe_strncpy(saddr.sa_data, argv_intf, sizeof(saddr.sa_data));

	// bind to the interface's ARP socket
	xbind(sock_fd, &saddr, sizeof(saddr));

	// get the interface's ethernet address
	//memset(&ifr, 0, sizeof(ifr));
	strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf);
	xioctl(sock_fd, SIOCGIFHWADDR, &ifr);
	memcpy(&eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);

	// start with some stable ip address, either a function of
	// the hardware address or else the last address we used.
	// we are taking low-order four bytes, as top-order ones
	// aren't random enough.
	// NOTE: the sequence of addresses we try changes only
	// depending on when we detect conflicts.
	{
		uint32_t t;
		move_from_unaligned32(t, ((char *)&eth_addr + 2));
		srand(t);
	}
	if (ip.s_addr == 0)
		ip.s_addr = pick();

	// FIXME cases to handle:
	//  - zcip already running!
	//  - link already has local address... just defend/update

	// daemonize now; don't delay system startup
	if (!FOREGROUND) {
#if BB_MMU
		bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/);
#endif
		if (verbose)
			bb_info_msg("start, interface %s", argv_intf);
	}

	write_pidfile(pidfile);
	bb_signals(BB_FATAL_SIGS, cleanup);

	// run the dynamic address negotiation protocol,
	// restarting after address conflicts:
	//  - start with some address we want to try
	//  - short random delay
	//  - arp probes to see if another host uses it
	//  - arp announcements that we're claiming it
	//  - use it
	//  - defend it, within limits
	// exit if:
	// - address is successfully obtained and -q was given:
	//   run "<script> config", then exit with exitcode 0
	// - poll error (when does this happen?)
	// - read error (when does this happen?)
	// - sendto error (in arp()) (when does this happen?)
	// - revents & POLLERR (link down). run "<script> deconfig" first
	state = PROBE;
	while (1) {
		struct pollfd fds[1];
		unsigned deadline_us;
		struct arp_packet p;
		int source_ip_conflict;
		int target_ip_conflict;

		fds[0].fd = sock_fd;
		fds[0].events = POLLIN;
		fds[0].revents = 0;

		// poll, being ready to adjust current timeout
		if (!timeout_ms) {
			timeout_ms = random_delay_ms(PROBE_WAIT);
			// FIXME setsockopt(sock_fd, SO_ATTACH_FILTER, ...) to
			// make the kernel filter out all packets except
			// ones we'd care about.
		}
		// set deadline_us to the point in time when we timeout
		deadline_us = MONOTONIC_US() + timeout_ms * 1000;

		VDBG("...wait %d %s nprobes=%u, nclaims=%u\n",
				timeout_ms, argv_intf, nprobes, nclaims);

		switch (safe_poll(fds, 1, timeout_ms)) {

		default:
			//bb_perror_msg("poll"); - done in safe_poll
			cleanup(EXIT_FAILURE);

		// timeout
		case 0:
			VDBG("state = %d\n", state);
			switch (state) {
			case PROBE:
				// timeouts in the PROBE state mean no conflicting ARP packets
				// have been received, so we can progress through the states
				if (nprobes < PROBE_NUM) {
					nprobes++;
					VDBG("probe/%u %s@%s\n",
							nprobes, argv_intf, inet_ntoa(ip));
					arp(/* ARPOP_REQUEST, */
							/* &eth_addr, */ null_ip,
							&null_addr, ip);
					timeout_ms = PROBE_MIN * 1000;
					timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
				}
				else {
					// Switch to announce state.
					state = ANNOUNCE;
					nclaims = 0;
					VDBG("announce/%u %s@%s\n",
							nclaims, argv_intf, inet_ntoa(ip));
					arp(/* ARPOP_REQUEST, */
							/* &eth_addr, */ ip,
							&eth_addr, ip);
					timeout_ms = ANNOUNCE_INTERVAL * 1000;
				}
				break;
			case RATE_LIMIT_PROBE:
				// timeouts in the RATE_LIMIT_PROBE state mean no conflicting ARP packets
				// have been received, so we can move immediately to the announce state
				state = ANNOUNCE;
				nclaims = 0;
				VDBG("announce/%u %s@%s\n",
						nclaims, argv_intf, inet_ntoa(ip));
				arp(/* ARPOP_REQUEST, */
						/* &eth_addr, */ ip,
						&eth_addr, ip);
				timeout_ms = ANNOUNCE_INTERVAL * 1000;
				break;
			case ANNOUNCE:
				// timeouts in the ANNOUNCE state mean no conflicting ARP packets
				// have been received, so we can progress through the states
				if (nclaims < ANNOUNCE_NUM) {
					nclaims++;
					VDBG("announce/%u %s@%s\n",
							nclaims, argv_intf, inet_ntoa(ip));
					arp(/* ARPOP_REQUEST, */
							/* &eth_addr, */ ip,
							&eth_addr, ip);
					timeout_ms = ANNOUNCE_INTERVAL * 1000;
				}
				else {
					// Switch to monitor state.
					state = MONITOR;
					// link is ok to use earlier
					// FIXME update filters
					run(argv, "config", &ip);
					ready = 1;
					conflicts = 0;
					timeout_ms = -1; // Never timeout in the monitor state.

					// NOTE: all other exit paths
					// should deconfig ...
					if (QUIT)
						cleanup(EXIT_SUCCESS);
				}
				break;
			case DEFEND:
				// We won!  No ARP replies, so just go back to monitor.
				state = MONITOR;
				timeout_ms = -1;
				conflicts = 0;
				break;
			default:
				// Invalid, should never happen.  Restart the whole protocol.
				state = PROBE;
				ip.s_addr = pick();
				timeout_ms = 0;
				nprobes = 0;
				nclaims = 0;
				break;
			} // switch (state)
			break; // case 0 (timeout)

		// packets arriving, or link went down
		case 1:
			// We need to adjust the timeout in case we didn't receive
			// a conflicting packet.
			if (timeout_ms > 0) {
				unsigned diff = deadline_us - MONOTONIC_US();
				if ((int)(diff) < 0) {
					// Current time is greater than the expected timeout time.
					// Should never happen.
					VDBG("missed an expected timeout\n");
					timeout_ms = 0;
				} else {
					VDBG("adjusting timeout\n");
					timeout_ms = (diff / 1000) | 1; /* never 0 */
				}
			}

			if ((fds[0].revents & POLLIN) == 0) {
				if (fds[0].revents & POLLERR) {
					// FIXME: links routinely go down;
					// this shouldn't necessarily exit.
					bb_error_msg("iface %s is down", argv_intf);
					if (ready) {
						run(argv, "deconfig", &ip);
					}
					cleanup(EXIT_FAILURE);
				}
				continue;
			}

			// read ARP packet
			if (safe_read(sock_fd, &p, sizeof(p)) < 0) {
				bb_perror_msg(bb_msg_read_error);
				cleanup(EXIT_FAILURE);
			}
			if (p.eth.ether_type != htons(ETHERTYPE_ARP))
				continue;
#ifdef DEBUG
			{
				struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha;
				struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha;
				struct in_addr *spa = (struct in_addr *) p.arp.arp_spa;
				struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa;
				VDBG("%s recv arp type=%d, op=%d,\n",
					argv_intf, ntohs(p.eth.ether_type),
					ntohs(p.arp.arp_op));
				VDBG("\tsource=%s %s\n",
					ether_ntoa(sha),
					inet_ntoa(*spa));
				VDBG("\ttarget=%s %s\n",
					ether_ntoa(tha),
					inet_ntoa(*tpa));
			}
#endif
			if (p.arp.arp_op != htons(ARPOP_REQUEST)
			 && p.arp.arp_op != htons(ARPOP_REPLY))
				continue;

			source_ip_conflict = 0;
			target_ip_conflict = 0;

			if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0
			 && memcmp(&p.arp.arp_sha, &eth_addr, ETH_ALEN) != 0
			) {
				source_ip_conflict = 1;
			}
			if (p.arp.arp_op == htons(ARPOP_REQUEST)
			 && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0
			 && memcmp(&p.arp.arp_tha, &eth_addr, ETH_ALEN) != 0
			) {
				target_ip_conflict = 1;
			}

			VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n",
				state, source_ip_conflict, target_ip_conflict);
			switch (state) {
			case PROBE:
			case ANNOUNCE:
				// When probing or announcing, check for source IP conflicts
				// and other hosts doing ARP probes (target IP conflicts).
				if (source_ip_conflict || target_ip_conflict) {
					conflicts++;
					if (conflicts >= MAX_CONFLICTS) {
						VDBG("%s ratelimit\n", argv_intf);
						timeout_ms = RATE_LIMIT_INTERVAL * 1000;
						state = RATE_LIMIT_PROBE;
					}

					// restart the whole protocol
					ip.s_addr = pick();
					timeout_ms = 0;
					nprobes = 0;
					nclaims = 0;
				}
				break;
			case MONITOR:
				// If a conflict, we try to defend with a single ARP probe.
				if (source_ip_conflict) {
					VDBG("monitor conflict -- defending\n");
					state = DEFEND;
					timeout_ms = DEFEND_INTERVAL * 1000;
					arp(/* ARPOP_REQUEST, */
						/* &eth_addr, */ ip,
						&eth_addr, ip);
				}
				break;
			case DEFEND:
				// Well, we tried.  Start over (on conflict).
				if (source_ip_conflict) {
					state = PROBE;
					VDBG("defend conflict -- starting over\n");
					ready = 0;
					run(argv, "deconfig", &ip);

					// restart the whole protocol
					ip.s_addr = pick();
					timeout_ms = 0;
					nprobes = 0;
					nclaims = 0;
				}
				break;
			default:
				// Invalid, should never happen.  Restart the whole protocol.
				VDBG("invalid state -- starting over\n");
				state = PROBE;
				ip.s_addr = pick();
				timeout_ms = 0;
				nprobes = 0;
				nclaims = 0;
				break;
			} // switch state
			break; // case 1 (packets arriving)
		} // switch poll
	} // while (1)
#undef argv_intf
}
Exemple #29
0
void ns_create(int argc, char **argv)
{
	pid_t pid;
	int ret, status;
	struct ns_exec_args args;
	int flags;
	char *pidf;

	args.argc = argc;
	args.argv = argv;

	ret = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, args.status_pipe);
	if (ret) {
		fprintf(stderr, "Pipe() failed %m\n");
		exit(1);
	}

	flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUTS |
		CLONE_NEWNET | CLONE_NEWIPC | SIGCHLD;

	if (getenv("ZDTM_USERNS"))
		flags |= CLONE_NEWUSER;

	pid = clone(ns_exec, args.stack_ptr, flags, &args);
	if (pid < 0) {
		fprintf(stderr, "clone() failed: %m\n");
		exit(1);
	}

	close(args.status_pipe[1]);

	if (flags & CLONE_NEWUSER) {
		char pname[PATH_MAX];
		int fd;

		snprintf(pname, sizeof(pname), "/proc/%d/uid_map", pid);
		fd = open(pname, O_WRONLY);
		if (fd < 0) {
			fprintf(stderr, "open(%s): %m\n", pname);
			exit(1);
		}
		if (write(fd, UID_MAP, sizeof(UID_MAP)) < 0) {
			fprintf(stderr, "write(" UID_MAP "): %m\n");
			exit(1);
		}
		close(fd);

		snprintf(pname, sizeof(pname), "/proc/%d/gid_map", pid);
		fd = open(pname, O_WRONLY);
		if (fd < 0) {
			fprintf(stderr, "open(%s): %m\n", pname);
			exit(1);
		}
		if (write(fd, GID_MAP, sizeof(GID_MAP)) < 0) {
			fprintf(stderr, "write(" GID_MAP "): %m\n");
			exit(1);
		}
		close(fd);
	}
	shutdown(args.status_pipe[0], SHUT_WR);

	pidf = pidfile;
	pidfile = malloc(strlen(pidfile) + 13);
	sprintf(pidfile, "%s%s", pidf, INPROGRESS);
	if (write_pidfile(pid)) {
		fprintf(stderr, "Preparations fail\n");
		exit(1);
	}

	status = 1;
	ret = read(args.status_pipe[0], &status, sizeof(status));
	if (ret != sizeof(status) || status) {
		fprintf(stderr, "The test failed (%d, %d)\n", ret, status);
		exit(1);
	}
	ret = read(args.status_pipe[0], &status, sizeof(status));
	if (ret != 0) {
		fprintf(stderr, "Unexpected message from test\n");
		exit(1);
	}

	unlink(pidfile);
	pidfile = pidf;

	if (write_pidfile(pid))
		exit(1);

	exit(0);
}
Exemple #30
0
void Anope::Init(int ac, char **av)
{
	/* Set file creation mask and group ID. */
#if defined(DEFUMASK) && HAVE_UMASK
	umask(DEFUMASK);
#endif

	/* Parse command line arguments */
	ParseCommandLineArguments(ac, av);

	if (GetCommandLineArgument("version", 'v'))
	{
		Log(LOG_TERMINAL) << "Anope-" << Anope::Version() << " -- " << Anope::VersionBuildString();
		throw CoreException();
	}

	if (GetCommandLineArgument("help", 'h'))
	{
		Log(LOG_TERMINAL) << "Anope-" << Anope::Version() << " -- " << Anope::VersionBuildString();
		Log(LOG_TERMINAL) << "Anope IRC Services (http://www.anope.org)";
		Log(LOG_TERMINAL) << "Usage ./" << Anope::ServicesBin << " [options] ...";
		Log(LOG_TERMINAL) << "-c, --config=filename.conf";
		Log(LOG_TERMINAL) << "    --confdir=conf file direcory";
		Log(LOG_TERMINAL) << "    --dbdir=database directory";
		Log(LOG_TERMINAL) << "-d, --debug[=level]";
		Log(LOG_TERMINAL) << "-h, --help";
		Log(LOG_TERMINAL) << "    --localedir=locale directory";
		Log(LOG_TERMINAL) << "    --logdir=logs directory";
		Log(LOG_TERMINAL) << "    --modulesdir=modules directory";
		Log(LOG_TERMINAL) << "-e, --noexpire";
		Log(LOG_TERMINAL) << "-n, --nofork";
		Log(LOG_TERMINAL) << "    --nothird";
		Log(LOG_TERMINAL) << "    --protocoldebug";
		Log(LOG_TERMINAL) << "-r, --readonly";
		Log(LOG_TERMINAL) << "-s, --support";
		Log(LOG_TERMINAL) << "-v, --version";
		Log(LOG_TERMINAL) << "";
		Log(LOG_TERMINAL) << "Further support is available from http://www.anope.org";
		Log(LOG_TERMINAL) << "Or visit us on IRC at irc.anope.org #anope";
		throw CoreException();
	}

	if (GetCommandLineArgument("nofork", 'n'))
		Anope::NoFork = true;

	if (GetCommandLineArgument("support", 's'))
	{
		Anope::NoFork = Anope::NoThird = true;
		++Anope::Debug;
	}

	if (GetCommandLineArgument("readonly", 'r'))
		Anope::ReadOnly = true;

	if (GetCommandLineArgument("nothird"))
		Anope::NoThird = true;

	if (GetCommandLineArgument("noexpire", 'e'))
		Anope::NoExpire = true;

	if (GetCommandLineArgument("protocoldebug"))
		Anope::ProtocolDebug = true;

	Anope::string arg;
	if (GetCommandLineArgument("debug", 'd', arg))
	{
		if (!arg.empty())
		{
			int level = arg.is_number_only() ? convertTo<int>(arg) : -1;
			if (level > 0)
				Anope::Debug = level;
			else
				throw CoreException("Invalid option given to --debug");
		}
		else
			++Anope::Debug;
	}

	if (GetCommandLineArgument("config", 'c', arg))
	{
		if (arg.empty())
			throw CoreException("The --config option requires a file name");
		ServicesConf = Configuration::File(arg, false);
	}

	if (GetCommandLineArgument("confdir", 0, arg))
	{
		if (arg.empty())
			throw CoreException("The --confdir option requires a path");
		Anope::ConfigDir = arg;
	}

	if (GetCommandLineArgument("dbdir", 0, arg))
	{
		if (arg.empty())
			throw CoreException("The --dbdir option requires a path");
		Anope::DataDir = arg;
	}

	if (GetCommandLineArgument("localedir", 0, arg))
	{
		if (arg.empty())
			throw CoreException("The --localedir option requires a path");
		Anope::LocaleDir = arg;
	}

	if (GetCommandLineArgument("modulesdir", 0, arg))
	{
		if (arg.empty())
			throw CoreException("The --modulesdir option requires a path");
		Anope::ModuleDir = arg;
	}

	if (GetCommandLineArgument("logdir", 0, arg))
	{
		if (arg.empty())
			throw CoreException("The --logdir option requires a path");
		Anope::LogDir = arg;
	}

	/* Chdir to Services data directory. */
	if (chdir(Anope::ServicesDir.c_str()) < 0)
	{
		throw CoreException("Unable to chdir to " + Anope::ServicesDir + ": " + Anope::LastError());
	}

	Log(LOG_TERMINAL) << "Anope " << Anope::Version() << ", " << Anope::VersionBuildString();

#ifdef _WIN32
	if (!SupportedWindowsVersion())
		throw CoreException(GetWindowsVersion() + " is not a supported version of Windows");
#else
	/* If we're root, issue a warning now */
	if (!getuid() && !getgid())
	{
		/* If we are configured to setuid later, don't issue a warning */
		Configuration::Block *options = Config->GetBlock("options");
		if (options->Get<Anope::string>("user").empty())
		{
			std::cerr << "WARNING: You are currently running Anope as the root superuser. Anope does not" << std::endl;
			std::cerr << "         require root privileges to run, and it is discouraged that you run Anope" << std::endl;
			std::cerr << "         as the root superuser." << std::endl;
			sleep(3);
		}
	}
#endif

#ifdef _WIN32
	Log(LOG_TERMINAL) << "Using configuration file " << Anope::ConfigDir << "\\" << ServicesConf.GetName();
#else
	Log(LOG_TERMINAL) << "Using configuration file " << Anope::ConfigDir << "/" << ServicesConf.GetName();

	/* Fork to background */
	if (!Anope::NoFork)
	{
		/* Install these before fork() - it is possible for the child to
		 * connect and kill() the parent before it is able to install the
		 * handler.
		 */
		struct sigaction sa, old_sigusr2, old_sigchld;

		sa.sa_flags = 0;
		sigemptyset(&sa.sa_mask);
		sa.sa_handler = parent_signal_handler;

		sigaction(SIGUSR2, &sa, &old_sigusr2);
		sigaction(SIGCHLD, &sa, &old_sigchld);

		int i = fork();
		if (i > 0)
		{
			sigset_t mask;

			sigemptyset(&mask);
			sigsuspend(&mask);

			exit(Anope::ReturnValue);
		}
		else if (i == -1)
		{
			Log() << "Error, unable to fork: " << Anope::LastError();
			Anope::NoFork = true;
		}

		/* Child doesn't need these */
		sigaction(SIGUSR2, &old_sigusr2, NULL);
		sigaction(SIGCHLD, &old_sigchld, NULL);
	}

#endif

	/* Initialize the socket engine. Note that some engines can not survive a fork(), so this must be here. */
	SocketEngine::Init();

	ServiceManager::Init();
	EventManager::Init();

	new BotInfoType();
	new XLineType(nullptr);
	new OperBlockType();

	/* Read configuration file; exit if there are problems. */
	try
	{
		Config = new Configuration::Conf();
	}
	catch (const ConfigException &ex)
	{
		Log(LOG_TERMINAL) << ex.GetReason();
		Log(LOG_TERMINAL) << "*** Support resources: Read through the anope.conf self-contained";
		Log(LOG_TERMINAL) << "*** documentation. Read the documentation files found in the 'docs'";
		Log(LOG_TERMINAL) << "*** folder. Visit our portal located at http://www.anope.org/. Join";
		Log(LOG_TERMINAL) << "*** our support channel on /server irc.anope.org channel #anope.";
		throw CoreException("Configuration file failed to validate");
	}

	/* Create me */
	Configuration::Block *block = Config->GetBlock("serverinfo");
	Me = new Server(NULL, block->Get<Anope::string>("name"), 0, block->Get<Anope::string>("description"), block->Get<Anope::string>("id"));
	for (std::pair<Anope::string, User *> p : UserListByNick)
	{
		User *u = p.second;
		if (u->type != UserType::BOT)
			continue;

		ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u);
		bi->server = Me;
		++Me->users;
	}

	/* Announce ourselves to the logfile. */
	Log() << "Anope " << Anope::Version() << " starting up" << (Anope::Debug || Anope::ReadOnly ? " (options:" : "") << (Anope::Debug ? " debug" : "") << (Anope::ReadOnly ? " readonly" : "") << (Anope::Debug || Anope::ReadOnly ? ")" : "");

	InitSignals();

	/* Initialize multi-language support */
	Language::InitLanguages();

	/* Initialize random number generator */
	block = Config->GetBlock("options");
	srand(block->Get<unsigned>("seed") ^ time(NULL));

	ModeManager::Apply(nullptr);

	/* load modules */
	Log() << "Loading modules...";
	for (int i = 0; i < Config->CountBlock("module"); ++i)
		ModuleManager::LoadModule(Config->GetBlock("module", i)->Get<Anope::string>("name"), NULL);

#ifndef _WIN32
	/* We won't background later, so we should setuid now */
	if (Anope::NoFork)
		setuidgid();
#endif

	Module *protocol = ModuleManager::FindFirstOf(PROTOCOL);
	if (protocol == NULL)
		throw CoreException("You must load a protocol module!");

	/* Write our PID to the PID file. */
	write_pidfile();

	Log() << "Using IRCd protocol " << protocol->name;

	/* Auto assign sid if applicable */
	if (IRCD->RequiresID)
	{
		Anope::string sid = IRCD->SID_Retrieve();
		if (Me->GetSID() == Me->GetName())
			Me->SetSID(sid);
		for (std::pair<Anope::string, User *> p : UserListByNick)
		{
			User *u = p.second;
			if (u->type != UserType::BOT)
				continue;

			ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u);
			bi->GenerateUID();
		}
	}

	/* Load up databases */
	Log() << "Loading databases...";
	EventReturn MOD_RESULT = EventManager::Get()->Dispatch(&Event::LoadDatabase::OnLoadDatabase);;
	static_cast<void>(MOD_RESULT);
	Log() << "Databases loaded";

	for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
		it->second->Sync();
}