Ejemplo n.º 1
0
/**
 * @NOTE if #flags.protocol_version is CF_PROTOCOL_UNDEFINED, then classic
 *       protocol is used by default.
 */
AgentConnection *ServerConnection(const char *server, const char *port,
                                  unsigned int connect_timeout,
                                  ConnectionFlags flags, int *err)
{
    AgentConnection *conn = NULL;
    int ret;
    *err = 0;

    conn = NewAgentConn(server, port, flags);

#if !defined(__MINGW32__)
    signal(SIGPIPE, SIG_IGN);

    sigset_t signal_mask;
    sigemptyset(&signal_mask);
    sigaddset(&signal_mask, SIGPIPE);
    pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);

    /* FIXME: username is local */
    GetCurrentUserName(conn->username, sizeof(conn->username));
#else
    /* Always say "root" as username from windows. */
    strlcpy(conn->username, "root", sizeof(conn->username));
#endif

    if (port == NULL || *port == '\0')
    {
        port = CFENGINE_PORT_STR;
    }

    char txtaddr[CF_MAX_IP_LEN] = "";
    conn->conn_info->sd = SocketConnect(server, port, connect_timeout,
                                        flags.force_ipv4,
                                        txtaddr, sizeof(txtaddr));
    if (conn->conn_info->sd == -1)
    {
        Log(LOG_LEVEL_INFO, "No server is responding on port: %s",
            port);
        DisconnectServer(conn);
        *err = -1;
        return NULL;
    }

    assert(sizeof(conn->remoteip) >= sizeof(txtaddr));
    strcpy(conn->remoteip, txtaddr);

    switch (flags.protocol_version)
    {
    case CF_PROTOCOL_UNDEFINED:
    case CF_PROTOCOL_TLS:

        /* Set the version to request during protocol negotiation. After
         * TLSConnect() it will have the version we finally ended up with. */
        conn->conn_info->protocol = CF_PROTOCOL_LATEST;

        ret = TLSConnect(conn->conn_info, flags.trust_server,
                         conn->remoteip, conn->username);

        if (ret == -1)                                      /* Error */
        {
            DisconnectServer(conn);
            *err = -1;
            return NULL;
        }
        else if (ret == 0)                             /* Auth/ID error */
        {
            DisconnectServer(conn);
            errno = EPERM;
            *err = -2;
            return NULL;
        }
        assert(ret == 1);

        conn->conn_info->status = CONNECTIONINFO_STATUS_ESTABLISHED;
        LastSaw1(conn->remoteip, KeyPrintableHash(conn->conn_info->remote_key),
                 LAST_SEEN_ROLE_CONNECT);
        break;

    case CF_PROTOCOL_CLASSIC:

        conn->conn_info->protocol = CF_PROTOCOL_CLASSIC;
        conn->encryption_type = CfEnterpriseOptions();

        if (!IdentifyAgent(conn->conn_info))
        {
            Log(LOG_LEVEL_ERR, "Id-authentication for '%s' failed", VFQNAME);
            errno = EPERM;
            DisconnectServer(conn);
            *err = -2; // auth err
            return NULL;
        }

        if (!AuthenticateAgent(conn, flags.trust_server))
        {
            Log(LOG_LEVEL_ERR, "Authentication dialogue with '%s' failed", server);
            errno = EPERM;
            DisconnectServer(conn);
            *err = -2; // auth err
            return NULL;
        }
        conn->conn_info->status = CONNECTIONINFO_STATUS_ESTABLISHED;
        break;

    default:
        ProgrammingError("ServerConnection: ProtocolVersion %d!",
                         flags.protocol_version);
    }

    conn->authenticated = true;
    return conn;
}
Ejemplo n.º 2
0
 virtual void requestInit() {
   handlers.reset();
   // restore the old signal mask, thus unblock those that should be
   pthread_sigmask(SIG_SETMASK, &oldSet, NULL);
 }
Ejemplo n.º 3
0
static void *clamuko_scanth(void *arg)
{
	struct thrarg *tharg = (struct thrarg *) arg;
	sigset_t sigset;
	unsigned int sizelimit = 0;
	struct stat sb;
	dazukofs_handle_t scan_hndl;
	struct dazukofs_access acc;
	const char *groupname = "ClamAV";
	int skip_scan = 0;
	const char *virname;
	char filename[4096];

    /* ignore all signals */
    sigfillset(&sigset);
    /* The behavior of a process is undefined after it ignores a
     * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
    sigdelset(&sigset, SIGFPE);
    sigdelset(&sigset, SIGILL);
    sigdelset(&sigset, SIGSEGV);
#ifdef SIGBUS
    sigdelset(&sigset, SIGBUS);
#endif
    pthread_sigmask(SIG_SETMASK, &sigset, NULL);

    /* register */
    scan_hndl = dazukofs_open(groupname, DAZUKOFS_TRACK_GROUP);
    if(!scan_hndl) {
	logg("!Clamuko: Can't register with DazukoFS\n");
	return NULL;
    } else {
	logg("Clamuko: Correctly registered with DazukoFS.\n");
    }

    /* access mask (not used by DazukoFS) */
    if(optget(tharg->opts, "ClamukoScanOnOpen")->enabled)
	logg("!Clamuko: ClamukoScanOnOpen ignored when using DazukoFS.\n");
    if(optget(tharg->opts, "ClamukoScanOnClose")->enabled)
	logg("!Clamuko: ClamukoScanOnClose ignored when using DazukoFS.\n");
    if(optget(tharg->opts, "ClamukoScanOnExec")->enabled)
	logg("!Clamuko: ClamukoScanOnExec ignored when using DazukoFS.\n");
    if(optget(tharg->opts, "ClamukoIncludePath")->enabled)
	logg("!Clamuko: ClamukoIncludePath ignored when using DazukoFS.\n");
    if(optget(tharg->opts, "ClamukoExcludePath")->enabled)
	logg("!Clamuko: ClamukoExcludePath ignored when using DazukoFS.\n");

    sizelimit = optget(tharg->opts, "ClamukoMaxFileSize")->numarg;
    if(sizelimit)
	logg("Clamuko: Max file size limited to %u bytes.\n", sizelimit);
    else
	logg("Clamuko: File size limit disabled.\n");

    while(1) {
	if(dazukofs_get_access(scan_hndl, &acc)) {
	    if(!shutdown_hndl)
		break;
	    continue;
	}

	if(!fstat(acc.fd, &sb)) {
	    if(S_ISDIR(sb.st_mode)) {
		/* don't try to scan directories */
		skip_scan = 1;
	    } else if(sb.st_size > sizelimit) {
		dazukofs_get_filename(&acc, filename, sizeof(filename));
		logg("*Clamuko: %s skipped (too big)\n", filename);
		skip_scan = 1;
	    }
	}

	if(skip_scan) {
	    acc.deny = 0;
	    /* reset skip flag */
	    skip_scan = 0;
	} else if(cl_scandesc(acc.fd, &virname, NULL, tharg->engine,
			      tharg->options) == CL_VIRUS) {
	    dazukofs_get_filename(&acc, filename, sizeof(filename));
	    logg("Clamuko: %s: %s FOUND\n", filename, virname);
	    /* we can not perform any special action because it will
	     * trigger DazukoFS recursively */
	    acc.deny = 1;
	} else {
	    acc.deny = 0;
	}

	if(dazukofs_return_access(scan_hndl, &acc)) {
	    if(shutdown_hndl)
	        logg("!Clamuko: Can't return access to DazukoFS.\n");
	    break;
	}
    }

    dazukofs_close(scan_hndl, 0);

    if(shutdown_hndl)
        logg("!Clamuko: A scanner thread has unexpectedly shutdown.\n");

    return NULL;
}
Ejemplo n.º 4
0
/**
 * Main function, starts the conftest daemon.
 */
int main(int argc, char *argv[])
{
	struct sigaction action;
	int status = 0;
	sigset_t set;
	int sig;
	char *suite_file = "suite.conf", *test_file = NULL, *preload, *plugins;
	file_logger_t *logger;

	if (!library_init(NULL, "conftest"))
	{
		library_deinit();
		return SS_RC_LIBSTRONGSWAN_INTEGRITY;
	}
	if (!libhydra_init())
	{
		libhydra_deinit();
		library_deinit();
		return SS_RC_INITIALIZATION_FAILED;
	}
	if (!libcharon_init())
	{
		libcharon_deinit();
		libhydra_deinit();
		library_deinit();
		return SS_RC_INITIALIZATION_FAILED;
	}

	INIT(conftest,
		.creds = mem_cred_create(),
		.config = config_create(),
		.hooks = linked_list_create(),
		.loggers = linked_list_create(),
	);
	lib->credmgr->add_set(lib->credmgr, &conftest->creds->set);

	logger = file_logger_create("stdout");
	logger->set_options(logger, NULL, FALSE);
	logger->open(logger, FALSE, FALSE);
	logger->set_level(logger, DBG_ANY, LEVEL_CTRL);
	charon->bus->add_logger(charon->bus, &logger->logger);
	conftest->loggers->insert_last(conftest->loggers, logger);

	atexit(cleanup);

	while (TRUE)
	{
		struct option long_opts[] = {
			{ "help", no_argument, NULL, 'h' },
			{ "version", no_argument, NULL, 'v' },
			{ "suite", required_argument, NULL, 's' },
			{ "test", required_argument, NULL, 't' },
			{ 0,0,0,0 }
		};
		switch (getopt_long(argc, argv, "", long_opts, NULL))
		{
			case EOF:
				break;
			case 'h':
				usage(stdout);
				return 0;
			case 'v':
				printf("strongSwan %s conftest\n", VERSION);
				return 0;
			case 's':
				suite_file = optarg;
				continue;
			case 't':
				test_file = optarg;
				continue;
			default:
				usage(stderr);
				return 1;
		}
		break;
	}

	if (!load_configs(suite_file, test_file))
	{
		return 1;
	}
	load_loggers(logger);

	preload = conftest->test->get_str(conftest->test, "preload", "");
	if (asprintf(&plugins, "%s %s", preload, PLUGINS) < 0)
	{
		return 1;
	}
	if (!charon->initialize(charon, plugins))
	{
		free(plugins);
		return 1;
	}
	lib->plugins->status(lib->plugins, LEVEL_CTRL);
	free(plugins);

	if (!load_certs(conftest->test, conftest->suite_dir))
	{
		return 1;
	}
	if (!load_keys(conftest->test, conftest->suite_dir))
	{
		return 1;
	}
	load_cdps(conftest->test);
	if (!load_hooks())
	{
		return 1;
	}
	charon->backends->add_backend(charon->backends, &conftest->config->backend);
	conftest->config->load(conftest->config, conftest->test);
	conftest->actions = actions_create();

	/* set up thread specific handlers */
	action.sa_handler = segv_handler;
	action.sa_flags = 0;
	sigemptyset(&action.sa_mask);
	sigaddset(&action.sa_mask, SIGINT);
	sigaddset(&action.sa_mask, SIGTERM);
	sigaddset(&action.sa_mask, SIGHUP);
	sigaction(SIGSEGV, &action, NULL);
	sigaction(SIGILL, &action, NULL);
	sigaction(SIGBUS, &action, NULL);
	action.sa_handler = SIG_IGN;
	sigaction(SIGPIPE, &action, NULL);
	pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);

	/* start thread pool */
	charon->start(charon);

	/* handle SIGINT/SIGTERM in main thread */
	sigemptyset(&set);
	sigaddset(&set, SIGINT);
	sigaddset(&set, SIGHUP);
	sigaddset(&set, SIGTERM);
	sigprocmask(SIG_BLOCK, &set, NULL);

	while ((sig = sigwaitinfo(&set, NULL)) != -1)
	{
		switch (sig)
		{
			case SIGINT:
			case SIGTERM:
				fprintf(stderr, "\nshutting down...\n");
				break;
			default:
				continue;
		}
		break;
	}
	return status;
}
Ejemplo n.º 5
0
void uv__io_poll(uv_loop_t* loop, int timeout) {
  struct port_event events[1024];
  struct port_event* pe;
  struct timespec spec;
  QUEUE* q;
  uv__io_t* w;
  sigset_t* pset;
  sigset_t set;
  uint64_t base;
  uint64_t diff;
  unsigned int nfds;
  unsigned int i;
  int saved_errno;
  int nevents;
  int count;
  int err;
  int fd;

  if (loop->nfds == 0) {
    assert(QUEUE_EMPTY(&loop->watcher_queue));
    return;
  }

  while (!QUEUE_EMPTY(&loop->watcher_queue)) {
    q = QUEUE_HEAD(&loop->watcher_queue);
    QUEUE_REMOVE(q);
    QUEUE_INIT(q);

    w = QUEUE_DATA(q, uv__io_t, watcher_queue);
    assert(w->pevents != 0);

    if (port_associate(loop->backend_fd, PORT_SOURCE_FD, w->fd, w->pevents, 0))
      abort();

    w->events = w->pevents;
  }

  pset = NULL;
  if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
    pset = &set;
    sigemptyset(pset);
    sigaddset(pset, SIGPROF);
  }

  assert(timeout >= -1);
  base = loop->time;
  count = 48; /* Benchmarks suggest this gives the best throughput. */

  for (;;) {
    if (timeout != -1) {
      spec.tv_sec = timeout / 1000;
      spec.tv_nsec = (timeout % 1000) * 1000000;
    }

    /* Work around a kernel bug where nfds is not updated. */
    events[0].portev_source = 0;

    nfds = 1;
    saved_errno = 0;

    if (pset != NULL)
      pthread_sigmask(SIG_BLOCK, pset, NULL);

    err = port_getn(loop->backend_fd,
                    events,
                    ARRAY_SIZE(events),
                    &nfds,
                    timeout == -1 ? NULL : &spec);

    if (pset != NULL)
      pthread_sigmask(SIG_UNBLOCK, pset, NULL);

    if (err) {
      /* Work around another kernel bug: port_getn() may return events even
       * on error.
       */
      if (errno == EINTR || errno == ETIME)
        saved_errno = errno;
      else
        abort();
    }

    /* Update loop->time unconditionally. It's tempting to skip the update when
     * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
     * operating system didn't reschedule our process while in the syscall.
     */
    SAVE_ERRNO(uv__update_time(loop));

    if (events[0].portev_source == 0) {
      if (timeout == 0) return;

      if (timeout == -1) continue;

      goto update_timeout;
    }

    if (nfds == 0) {
      assert(timeout != -1);
      return;
    }

    nevents = 0;

    assert(loop->watchers != NULL);
    loop->watchers[loop->nwatchers] = (void*)events;
    loop->watchers[loop->nwatchers + 1] = (void*)(uintptr_t)nfds;
    for (i = 0; i < nfds; i++) {
      pe = events + i;
      fd = pe->portev_object;

      /* Skip invalidated events, see uv__platform_invalidate_fd */
      if (fd == -1) continue;

      assert(fd >= 0);
      assert((unsigned)fd < loop->nwatchers);

      w = loop->watchers[fd];

      /* File descriptor that we've stopped watching, ignore. */
      if (w == NULL) continue;

      w->cb(loop, w, pe->portev_events);
      nevents++;

      /* Events Ports operates in oneshot mode, rearm timer on next run. */
      if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue))
        QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
    }
    loop->watchers[loop->nwatchers] = NULL;
    loop->watchers[loop->nwatchers + 1] = NULL;

    if (nevents != 0) {
      if (nfds == ARRAY_SIZE(events) && --count != 0) {
        /* Poll for more events but don't block this time. */
        timeout = 0;
        continue;
      }
      return;
    }

    if (saved_errno == ETIME) {
      assert(timeout != -1);
      return;
    }

    if (timeout == 0) return;

    if (timeout == -1) continue;

  update_timeout:
    assert(timeout > 0);

    diff = loop->time - base;
    if (diff >= (uint64_t)timeout) return;

    timeout -= diff;
  }
}
Ejemplo n.º 6
0
int main( int argc, char **argv )
{
    int         sig;
    sigset_t    termSig;
    pthread_t   readSerialThreadId;
    pthread_t   readStdinThreadId;
    int         rc;
    int         opt;
    const char *baudStr = NULL;
#if defined( linux )
    const char *portStr = "ttyS0";
#else
    const char *portStr = "com1";
#endif

#if USE_I2C
    PKT_TextChar        = PacketTextChar;
    PKT_SendChar        = PacketSendChar;
    PKT_PacketReceived  = PacketReceived;
#endif

//    signal( SIGINT, ControlC );
//    signal( SIGTERM, ControlC );

    LogInit( stdout );

    while (( opt = getopt_long( argc, argv, "b:dhmp:sv", gLongOption, NULL )) > 0 )
    {
        switch ( opt )
        {
            case 'b':
            {
                baudStr = optarg;
                break;
            }

            case 'd':
            {
                gDebug = true;
                break;
            }

            case 'g':
            {
                gDongle = true;
                break;
            }

            case 'm':
            {
                gMegaLoad = true;
                break;
            }

            case 'p':
            {
                portStr = optarg;
                break;
            }

            case 'r':
            {
                gUseRtsToReset = true;
                break;
            }

            case 's':
            {
                gStk500 = true;
                break;
            }

            case 'v':
            {
                gVerbose = true;
                break;
            }

#if USE_I2C
            case OPT_DEBUG_DONGLE:
            {
                gSerialDongle.m_debugDongle = true;
                break;
            }

            case OPT_DEBUG_DONGLE_DATA:
            {
                gSerialDongle.m_debugDongleData = true;
                break;
            }
#endif

            case '?':
            case 'h':
            {
                Usage();
                return 1;
            }
        }
    }

    if ( optind < argc )
    {
        if (( optind + 1 ) != argc )
        {
            fprintf( stderr, "Only one download file supported\n" );
            return 1;
        }

        gDownloadFileName = argv[ optind ];
    }

    // Open the file to download

    if ( gDownloadFileName != NULL )
    {
        // If we are asked to download a file, then read the entire file
        // into memory.

        if (( gDownloadInfo = ReadFile( gDownloadFileName )) == NULL )
        {
            return 1;
        }
    }

    if ( !gSerialPort.Open( portStr, baudStr ))
    {
        return 1;
    }
    gSerialPort.UseRTStoReset( gUseRtsToReset );
    gSerialPort.ResetTarget();

    // Put stdin in raw mode

    setbuf( stdin, NULL );
    setbuf( stdout, NULL );

#if defined( unix )
    sigemptyset( &termSig );
    sigaddset( &termSig, SIGINT );
    sigaddset( &termSig, SIGTERM );

    pthread_sigmask( SIG_BLOCK, &termSig, NULL );

    struct termios tio_new;

    if ( tcgetattr( fileno( stdin ), &gTio_org ) < 0 )
    {
        LogError( "Unable to retrieve terminal settings\n" );
        return 1;
    }
    
    tio_new = gTio_org;
    tio_new.c_lflag &= ~( ICANON | ECHO );
    tio_new.c_cc[VMIN] = 1;
    tio_new.c_cc[VTIME] = 0;

    if ( tcsetattr( fileno( stdin ), TCSANOW, &tio_new ) < 0 )
    {
        LogError( "Unable to update terminal settings\n" );
        return 1;
    }
#endif

    const char *bootLoaderType = "*** Unknown ***";

    if ( gDongle )
    {
        bootLoaderType = "Serial Dongle";
    }
    else
    if ( gMegaLoad )
    {
        bootLoaderType = "MegaLoad v2.3";
    }
    else
    if ( gStk500 )
    {
        bootLoaderType = "STK500";
    }

    gLogFs2 = fopen( "BootHost.log", "wb" );

    Log( "BootHost - BootLoader: %s\n", bootLoaderType );

    // Kick off the serial port reader thread.

    rc = pthread_create( &readSerialThreadId, NULL, ReadSerialThread, &gSerialPort );
    if ( rc != 0 )
    {
        fprintf( stderr, "Error creating ReadSerialThread: %d\n", rc );
        return 1;
    }

    // Kick off the stdin reader thread.

    rc = pthread_create( &readStdinThreadId, NULL, ReadStdinThread, NULL );
    if ( rc != 0 )
    {
        fprintf( stderr, "Error creating ReadSerialThread: %d\n", rc );
        return 1;
    }

#if defined( unix )

    // Wait for a termmination signal

    if (( rc = sigwait( &termSig, &sig )) != 0 )
    {
        fprintf( stderr, "sigwait failed\n" );
    }
    else
    {
        fprintf( stderr, "Exiting...\n" );
    }

    pthread_cancel( readSerialThreadId );
    pthread_cancel( readStdinThreadId );

    // Restore stdin back to the way it was when we started

    if ( tcsetattr( fileno( stdin ), TCSANOW, &gTio_org ) == -1 )
    {
        LogError( "Unable to restore terminal settings\n" );
    }
#endif

#if defined( __CYGWIN__ )

    // Under Windows closing the serial port and stdin will cause the reads
    // to unblock. Under linux, this isn't required, but it doesn't hurt 
    // either.

    gSerialPort.Close();
    fclose( stdin );
#endif

    // Unblock the termination signals so the user can kill us if we hang up
    // waiting for the reader threads to exit.

#if defined( unix )
    pthread_sigmask( SIG_UNBLOCK, &termSig, NULL );
#endif

    pthread_join( readSerialThreadId, NULL );
    pthread_join( readStdinThreadId, NULL );

#if !defined( __CYGWIN__ )
    gSerialPort.Close();
    fclose( stdin );
#endif

    if ( gVerbose )
    {
        printf( "Done\n" );
    }

    return 0;

} // main
Ejemplo n.º 7
0
int
main(int argc, char **argv)
{
  int i;
  sigset_t set;
#if ENABLE_MPEGTS
  uint32_t adapter_mask = 0;
#endif
  int  log_level   = LOG_INFO;
  int  log_options = TVHLOG_OPT_MILLIS | TVHLOG_OPT_STDERR | TVHLOG_OPT_SYSLOG;
  const char *log_debug = NULL, *log_trace = NULL;
  gid_t gid = -1;
  uid_t uid = -1;
  char buf[512];
  FILE *pidfile = NULL;
  extern int dvb_bouquets_parse;

  main_tid = pthread_self();

  /* Setup global mutexes */
  pthread_mutex_init(&fork_lock, NULL);
  pthread_mutex_init(&global_lock, NULL);
  pthread_mutex_init(&tasklet_lock, NULL);
  pthread_mutex_init(&atomic_lock, NULL);
  pthread_cond_init(&gtimer_cond, NULL);
  pthread_cond_init(&tasklet_cond, NULL);
  TAILQ_INIT(&tasklets);

  /* Defaults */
  tvheadend_webui_port      = 9981;
  tvheadend_webroot         = NULL;
  tvheadend_htsp_port       = 9982;
  tvheadend_htsp_port_extra = 0;
  time(&dispatch_clock);

  /* Command line options */
  int         opt_help         = 0,
              opt_version      = 0,
              opt_fork         = 0,
              opt_firstrun     = 0,
              opt_stderr       = 0,
              opt_syslog       = 0,
              opt_nosyslog     = 0,
              opt_uidebug      = 0,
              opt_abort        = 0,
              opt_noacl        = 0,
              opt_fileline     = 0,
              opt_threadid     = 0,
              opt_libav        = 0,
              opt_ipv6         = 0,
              opt_satip_rtsp   = 0,
#if ENABLE_TSFILE
              opt_tsfile_tuner = 0,
#endif
              opt_dump         = 0,
              opt_xspf         = 0,
              opt_dbus         = 0,
              opt_dbus_session = 0,
              opt_nobackup     = 0,
              opt_nobat        = 0;
  const char *opt_config       = NULL,
             *opt_user         = NULL,
             *opt_group        = NULL,
             *opt_logpath      = NULL,
             *opt_log_debug    = NULL,
             *opt_log_trace    = NULL,
             *opt_pidpath      = "/var/run/tvheadend.pid",
#if ENABLE_LINUXDVB
             *opt_dvb_adapters = NULL,
#endif
             *opt_bindaddr     = NULL,
             *opt_subscribe    = NULL,
             *opt_user_agent   = NULL;
  str_list_t  opt_satip_xml    = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) };
  str_list_t  opt_tsfile       = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) };
  cmdline_opt_t cmdline_opts[] = {
    {   0, NULL,        N_("Generic Options"),         OPT_BOOL, NULL         },
    { 'h', "help",      N_("Show this page"),          OPT_BOOL, &opt_help    },
    { 'v', "version",   N_("Show version information"),OPT_BOOL, &opt_version },

    {   0, NULL,        N_("Service Configuration"),   OPT_BOOL, NULL         },
    { 'c', "config",    N_("Alternate config path"),   OPT_STR,  &opt_config  },
    { 'B', "nobackup",  N_("Don't backup config tree at upgrade"), OPT_BOOL, &opt_nobackup },
    { 'f', "fork",      N_("Fork and run as daemon"),  OPT_BOOL, &opt_fork    },
    { 'u', "user",      N_("Run as user"),             OPT_STR,  &opt_user    },
    { 'g', "group",     N_("Run as group"),            OPT_STR,  &opt_group   },
    { 'p', "pid",       N_("Alternate pid path"),      OPT_STR,  &opt_pidpath },
    { 'C', "firstrun",  N_("If no user account exists then create one with\n"
	                   "no username and no password. Use with care as\n"
	                   "it will allow world-wide administrative access\n"
	                   "to your Tvheadend installation until you edit/create\n"
	                   "access-control from within the Tvheadend UI"),
      OPT_BOOL, &opt_firstrun },
#if ENABLE_DBUS_1
    { 'U', "dbus",      N_("Enable DBus"),
      OPT_BOOL, &opt_dbus },
    { 'e', "dbus_session", N_("DBus - use the session message bus instead system one"),
      OPT_BOOL, &opt_dbus_session },
#endif
#if ENABLE_LINUXDVB
    { 'a', "adapters",  N_("Only use specified DVB adapters (comma separated)"),
      OPT_STR, &opt_dvb_adapters },
#endif
#if ENABLE_SATIP_SERVER
    {   0, "satip_rtsp", N_("SAT>IP RTSP port number for server\n"
                            "(default: -1 = disable, 0 = webconfig, standard port is 554)"),
      OPT_INT, &opt_satip_rtsp },
#endif
#if ENABLE_SATIP_CLIENT
    {   0, "satip_xml", N_("URL with the SAT>IP server XML location"),
      OPT_STR_LIST, &opt_satip_xml },
#endif
    {   0, NULL,         N_("Server Connectivity"),    OPT_BOOL, NULL         },
    { '6', "ipv6",       N_("Listen on IPv6"),         OPT_BOOL, &opt_ipv6    },
    { 'b', "bindaddr",   N_("Specify bind address"),   OPT_STR,  &opt_bindaddr},
    {   0, "http_port",  N_("Specify alternative http port"),
      OPT_INT, &tvheadend_webui_port },
    {   0, "http_root",  N_("Specify alternative http webroot"),
      OPT_STR, &tvheadend_webroot },
    {   0, "htsp_port",  N_("Specify alternative htsp port"),
      OPT_INT, &tvheadend_htsp_port },
    {   0, "htsp_port2", N_("Specify extra htsp port"),
      OPT_INT, &tvheadend_htsp_port_extra },
    {   0, "useragent",  N_("Specify User-Agent header for the http client"),
      OPT_STR, &opt_user_agent },
    {   0, "xspf",       N_("Use XSPF playlist instead of M3U"),
      OPT_BOOL, &opt_xspf },

    {   0, NULL,        N_("Debug Options"),           OPT_BOOL, NULL         },
    { 'd', "stderr",    N_("Enable debug on stderr"),  OPT_BOOL, &opt_stderr  },
    { 's', "syslog",    N_("Enable debug to syslog"),  OPT_BOOL, &opt_syslog  },
    { 'S', "nosyslog",  N_("Disable syslog (all msgs)"), OPT_BOOL, &opt_nosyslog },
    { 'l', "logfile",   N_("Enable debug to file"),    OPT_STR,  &opt_logpath },
    {   0, "debug",     N_("Enable debug subsystems"),  OPT_STR,  &opt_log_debug },
#if ENABLE_TRACE
    {   0, "trace",     N_("Enable trace subsystems"), OPT_STR,  &opt_log_trace },
#endif
    {   0, "fileline",  N_("Add file and line numbers to debug"), OPT_BOOL, &opt_fileline },
    {   0, "threadid",  N_("Add the thread ID to debug"), OPT_BOOL, &opt_threadid },
#if ENABLE_LIBAV
    {   0, "libav",     N_("More verbose libav log"),  OPT_BOOL, &opt_libav },
#endif
    {   0, "uidebug",   N_("Enable webUI debug (non-minified JS)"), OPT_BOOL, &opt_uidebug },
    { 'A', "abort",     N_("Immediately abort"),       OPT_BOOL, &opt_abort   },
    { 'D', "dump",      N_("Enable coredumps for daemon"), OPT_BOOL, &opt_dump },
    {   0, "noacl",     N_("Disable all access control checks"),
      OPT_BOOL, &opt_noacl },
    {   0, "nobat",     N_("Disable DVB bouquets"),
      OPT_BOOL, &opt_nobat },
    { 'j', "join",      N_("Subscribe to a service permanently"),
      OPT_STR, &opt_subscribe },


#if ENABLE_TSFILE || ENABLE_TSDEBUG
    { 0, NULL, N_("Testing options"), OPT_BOOL, NULL },
    { 0, "tsfile_tuners", N_("Number of tsfile tuners"), OPT_INT, &opt_tsfile_tuner },
    { 0, "tsfile", N_("tsfile input (mux file)"), OPT_STR_LIST, &opt_tsfile },
#endif
#if ENABLE_TSDEBUG
    { 0, "tsdebug", N_("Output directory for tsdebug"), OPT_STR, &tvheadend_tsdebug },
#endif

  };

  /* Get current directory */
  tvheadend_cwd0 = dirname(tvh_strdupa(argv[0]));
  tvheadend_cwd = dirname(tvh_strdupa(tvheadend_cwd0));

  /* Set locale */
  setlocale(LC_ALL, "");
  setlocale(LC_NUMERIC, "C");
  tvh_gettext_init();

  /* make sure the timezone is set */
  tzset();

  /* Process command line */
  for (i = 1; i < argc; i++) {

    /* Find option */
    cmdline_opt_t *opt
      = cmdline_opt_find(cmdline_opts, ARRAY_SIZE(cmdline_opts), argv[i]);
    if (!opt)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts),
                 _("invalid option specified [%s]"), argv[i]);

    /* Process */
    if (opt->type == OPT_BOOL)
      *((int*)opt->param) = 1;
    else if (++i == argc)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts),
                 _("option %s requires a value"), opt->lopt);
    else if (opt->type == OPT_INT)
      *((int*)opt->param) = atoi(argv[i]);
    else if (opt->type == OPT_STR_LIST) {
      str_list_t *strl = opt->param;
      if (strl->num < strl->max)
        strl->str[strl->num++] = argv[i];
    }
    else
      *((char**)opt->param) = argv[i];

    /* Stop processing */
    if (opt_help)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), NULL);
    if (opt_version)
      show_version(argv[0]);
  }

  /* Additional cmdline processing */
  if (opt_nobat)
    dvb_bouquets_parse = 0;
#if ENABLE_LINUXDVB
  if (!opt_dvb_adapters) {
    adapter_mask = ~0;
  } else {
    char *p, *e;
    char *r = NULL;
    char *dvb_adapters = strdup(opt_dvb_adapters);
    adapter_mask = 0x0;
    p = strtok_r(dvb_adapters, ",", &r);
    while (p) {
      int a = strtol(p, &e, 10);
      if (*e != 0 || a < 0 || a > 31) {
        fprintf(stderr, _("Invalid adapter number '%s'\n"), p);
        free(dvb_adapters);
        return 1;
      }
      adapter_mask |= (1 << a);
      p = strtok_r(NULL, ",", &r);
    }
    free(dvb_adapters);
    if (!adapter_mask) {
      fprintf(stderr, "%s", _("No adapters specified!\n"));
      return 1;
    }
  }
#endif
  if (tvheadend_webroot) {
    char *tmp;
    if (*tvheadend_webroot == '/')
      tmp = strdup(tvheadend_webroot);
    else {
      tmp = malloc(strlen(tvheadend_webroot)+2);
      *tmp = '/';
      strcpy(tmp+1, tvheadend_webroot);
    }
    if (tmp[strlen(tmp)-1] == '/')
      tmp[strlen(tmp)-1] = '\0';
    tvheadend_webroot = tmp;
  }
  tvheadend_webui_debug = opt_uidebug;

  /* Setup logging */
  if (isatty(2))
    log_options |= TVHLOG_OPT_DECORATE;
  if (opt_stderr || opt_syslog || opt_logpath) {
    if (!opt_log_trace && !opt_log_debug)
      log_debug      = "all";
    log_level      = LOG_DEBUG;
    if (opt_stderr)
      log_options   |= TVHLOG_OPT_DBG_STDERR;
    if (opt_syslog)
      log_options   |= TVHLOG_OPT_DBG_SYSLOG;
    if (opt_logpath)
      log_options   |= TVHLOG_OPT_DBG_FILE;
  }
  if (opt_nosyslog)
    log_options &= ~(TVHLOG_OPT_SYSLOG|TVHLOG_OPT_DBG_SYSLOG);
  if (opt_fileline)
    log_options |= TVHLOG_OPT_FILELINE;
  if (opt_threadid)
    log_options |= TVHLOG_OPT_THREAD;
  if (opt_libav)
    log_options |= TVHLOG_OPT_LIBAV;
  if (opt_log_trace) {
    log_level  = LOG_TRACE;
    log_trace  = opt_log_trace;
  }
  if (opt_log_debug)
    log_debug  = opt_log_debug;
    
  tvhlog_init(log_level, log_options, opt_logpath);
  tvhlog_set_debug(log_debug);
  tvhlog_set_trace(log_trace);
  tvhinfo("main", "Log started");
 
  signal(SIGPIPE, handle_sigpipe); // will be redundant later
  signal(SIGILL, handle_sigill);   // see handler..

  /* Set priviledges */
  if(opt_fork || opt_group || opt_user) {
    const char *homedir;
    struct group  *grp = getgrnam(opt_group ?: "video");
    struct passwd *pw  = opt_user ? getpwnam(opt_user) : NULL;

    if(grp != NULL) {
      gid = grp->gr_gid;
    } else {
      gid = 1;
    }

    if (pw != NULL) {
      if (getuid() != pw->pw_uid) {
        gid_t glist[16];
        int gnum;
        gnum = get_user_groups(pw, glist, ARRAY_SIZE(glist));
        if (gnum > 0 && setgroups(gnum, glist)) {
          char buf[256] = "";
          int i;
          for (i = 0; i < gnum; i++)
            snprintf(buf + strlen(buf), sizeof(buf) - 1 - strlen(buf),
                     ",%d", glist[i]);
          tvhlog(LOG_ALERT, "START",
                 "setgroups(%s) failed, do you have permission?", buf+1);
          return 1;
        }
      }
      uid     = pw->pw_uid;
      homedir = pw->pw_dir;
      setenv("HOME", homedir, 1);
    } else {
      uid = 1;
    }
  }

  uuid_init();
  config_boot(opt_config, gid, uid);
  tcp_server_preinit(opt_ipv6);
  http_server_init(opt_bindaddr);    // bind to ports only
  htsp_init(opt_bindaddr);	     // bind to ports only
  satip_server_init(opt_satip_rtsp); // bind to ports only

  if (opt_fork)
    pidfile = tvh_fopen(opt_pidpath, "w+");

  if (gid != -1 && (getgid() != gid) && setgid(gid)) {
    tvhlog(LOG_ALERT, "START",
           "setgid(%d) failed, do you have permission?", gid);
    return 1;
  }
  if (uid != -1 && (getuid() != uid) && setuid(uid)) {
    tvhlog(LOG_ALERT, "START",
           "setuid(%d) failed, do you have permission?", uid);
    return 1;
  }

  /* Daemonise */
  if(opt_fork) {
    if(daemon(0, 0)) {
      exit(2);
    }
    if(pidfile != NULL) {
      fprintf(pidfile, "%d\n", getpid());
      fclose(pidfile);
    }

    /* Make dumpable */
    if (opt_dump) {
#ifdef PLATFORM_LINUX
      if (chdir("/tmp"))
        tvhwarn("START", "failed to change cwd to /tmp");
      prctl(PR_SET_DUMPABLE, 1);
#else
      tvhwarn("START", "Coredumps not implemented on your platform");
#endif
    }

    umask(0);
  }

  tvheadend_running = 1;

  /* Start log thread (must be done post fork) */
  tvhlog_start();

  /* Alter logging */
  if (opt_fork)
    tvhlog_options &= ~TVHLOG_OPT_STDERR;
  if (!isatty(2))
    tvhlog_options &= ~TVHLOG_OPT_DECORATE;
  
  /* Initialise clock */
  pthread_mutex_lock(&global_lock);
  time(&dispatch_clock);

  /* Signal handling */
  sigfillset(&set);
  sigprocmask(SIG_BLOCK, &set, NULL);
  trap_init(argv[0]);

  /* SSL library init */
  OPENSSL_config(NULL);
  SSL_load_error_strings();
  SSL_library_init();

  /* Initialise configuration */
  notify_init();
  idnode_init();
  spawn_init();
  config_init(opt_nobackup == 0);

  /**
   * Initialize subsystems
   */

  epg_in_load = 1;

  tvhthread_create(&tasklet_tid, NULL, tasklet_thread, NULL);

  dbus_server_init(opt_dbus, opt_dbus_session);

  intlconv_init();
  
  api_init();

  fsmonitor_init();

  libav_init();

  tvhtime_init();

  profile_init();

  imagecache_init();

  http_client_init(opt_user_agent);
  esfilter_init();

  bouquet_init();

  service_init();

  dvb_init();

#if ENABLE_MPEGTS
  mpegts_init(adapter_mask, &opt_satip_xml, &opt_tsfile, opt_tsfile_tuner);
#endif

  channel_init();

  bouquet_service_resolve();

  subscription_init();

  dvr_config_init();

  access_init(opt_firstrun, opt_noacl);

#if ENABLE_TIMESHIFT
  timeshift_init();
#endif

  tcp_server_init();
  webui_init(opt_xspf);
#if ENABLE_UPNP
  upnp_server_init(opt_bindaddr);
#endif

  service_mapper_init();

  descrambler_init();

  epggrab_init();
  epg_init();

  dvr_init();

  dbus_server_start();

  http_server_register();
  satip_server_register();
  htsp_register();

  if(opt_subscribe != NULL)
    subscription_dummy_join(opt_subscribe, 1);

  avahi_init();
  bonjour_init();

  epg_updated(); // cleanup now all prev ref's should have been created
  epg_in_load = 0;

  pthread_mutex_unlock(&global_lock);

  /**
   * Wait for SIGTERM / SIGINT, but only in this thread
   */

  sigemptyset(&set);
  sigaddset(&set, SIGTERM);
  sigaddset(&set, SIGINT);

  signal(SIGTERM, doexit);
  signal(SIGINT, doexit);

  pthread_sigmask(SIG_UNBLOCK, &set, NULL);

  tvhlog(LOG_NOTICE, "START", "HTS Tvheadend version %s started, "
         "running as PID:%d UID:%d GID:%d, CWD:%s CNF:%s",
         tvheadend_version,
         getpid(), getuid(), getgid(), getcwd(buf, sizeof(buf)),
         hts_settings_get_root());

  if(opt_abort)
    abort();

  mainloop();

#if ENABLE_DBUS_1
  tvhftrace("main", dbus_server_done);
#endif
#if ENABLE_UPNP
  tvhftrace("main", upnp_server_done);
#endif
  tvhftrace("main", satip_server_done);
  tvhftrace("main", htsp_done);
  tvhftrace("main", http_server_done);
  tvhftrace("main", webui_done);
  tvhftrace("main", fsmonitor_done);
  tvhftrace("main", http_client_done);
  tvhftrace("main", tcp_server_done);

  // Note: the locking is obviously a bit redundant, but without
  //       we need to disable the gtimer_arm call in epg_save()
  pthread_mutex_lock(&global_lock);
  tvhftrace("main", epg_save);

#if ENABLE_TIMESHIFT
  tvhftrace("main", timeshift_term);
#endif
  pthread_mutex_unlock(&global_lock);

  tvhftrace("main", epggrab_done);
#if ENABLE_MPEGTS
  tvhftrace("main", mpegts_done);
#endif
  tvhftrace("main", descrambler_done);
  tvhftrace("main", service_mapper_done);
  tvhftrace("main", service_done);
  tvhftrace("main", channel_done);
  tvhftrace("main", bouquet_done);
  tvhftrace("main", dvr_done);
  tvhftrace("main", subscription_done);
  tvhftrace("main", access_done);
  tvhftrace("main", epg_done);
  tvhftrace("main", avahi_done);
  tvhftrace("main", bonjour_done);
  tvhftrace("main", imagecache_done);
  tvhftrace("main", lang_code_done);
  tvhftrace("main", api_done);

  tvhtrace("main", "tasklet enter");
  pthread_cond_signal(&tasklet_cond);
  pthread_join(tasklet_tid, NULL);
  tvhtrace("main", "tasklet thread end");
  tasklet_flush();
  tvhtrace("main", "tasklet leave");

  tvhftrace("main", hts_settings_done);
  tvhftrace("main", dvb_done);
  tvhftrace("main", lang_str_done);
  tvhftrace("main", esfilter_done);
  tvhftrace("main", profile_done);
  tvhftrace("main", intlconv_done);
  tvhftrace("main", urlparse_done);
  tvhftrace("main", idnode_done);
  tvhftrace("main", notify_done);
  tvhftrace("main", spawn_done);

  tvhlog(LOG_NOTICE, "STOP", "Exiting HTS Tvheadend");
  tvhlog_end();

  tvhftrace("main", config_done);

  if(opt_fork)
    unlink(opt_pidpath);
    
#if ENABLE_TSFILE
  free(opt_tsfile.str);
#endif
  free(opt_satip_xml.str);

  /* OpenSSL - welcome to the "cleanup" hell */
  ENGINE_cleanup();
  RAND_cleanup();
  CRYPTO_cleanup_all_ex_data();
  EVP_cleanup();
  CONF_modules_free();
#ifndef OPENSSL_NO_COMP
  COMP_zlib_cleanup();
#endif
  ERR_remove_state(0);
  ERR_free_strings();
#ifndef OPENSSL_NO_COMP
  sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
#endif
  /* end of OpenSSL cleanup code */

#if ENABLE_DBUS_1
  extern void dbus_shutdown(void);
  if (opt_dbus) dbus_shutdown();
#endif
  tvh_gettext_done();
  return 0;
}

/**
 *
 */
void
tvh_str_set(char **strp, const char *src)
{
  free(*strp);
  *strp = src ? strdup(src) : NULL;
}


/**
 *
 */
int
tvh_str_update(char **strp, const char *src)
{
  if(src == NULL)
    return 0;
  free(*strp);
  *strp = strdup(src);
  return 1;
}


/**
 *
 */
void
scopedunlock(pthread_mutex_t **mtxp)
{
  pthread_mutex_unlock(*mtxp);
}
Ejemplo n.º 8
0
 void requestInit() override {
   handlers.reset();
   // restore the old signal mask, thus unblock those that should be
   pthread_sigmask(SIG_SETMASK, &oldSet, NULL);
   inited.store(true);
 }
Ejemplo n.º 9
0
static void
unblock_atimers (sigset_t const *oldset)
{
  pthread_sigmask (SIG_SETMASK, oldset, 0);
}
Ejemplo n.º 10
0
pid_t qemu_fork(Error **errp)
{
    sigset_t oldmask, newmask;
    struct sigaction sig_action;
    int saved_errno;
    pid_t pid;

    /*
     * Need to block signals now, so that child process can safely
     * kill off caller's signal handlers without a race.
     */
    sigfillset(&newmask);
    if (pthread_sigmask(SIG_SETMASK, &newmask, &oldmask) != 0) {
        error_setg_errno(errp, errno,
                         "cannot block signals");
        return -1;
    }

    pid = fork();
    saved_errno = errno;

    if (pid < 0) {
        /* attempt to restore signal mask, but ignore failure, to
         * avoid obscuring the fork failure */
        (void)pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
        error_setg_errno(errp, saved_errno,
                         "cannot fork child process");
        errno = saved_errno;
        return -1;
    } else if (pid) {
        /* parent process */

        /* Restore our original signal mask now that the child is
         * safely running. Only documented failures are EFAULT (not
         * possible, since we are using just-grabbed mask) or EINVAL
         * (not possible, since we are using correct arguments).  */
        (void)pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
    } else {
        /* child process */
        size_t i;

        /* Clear out all signal handlers from parent so nothing
         * unexpected can happen in our child once we unblock
         * signals */
        sig_action.sa_handler = SIG_DFL;
        sig_action.sa_flags = 0;
        sigemptyset(&sig_action.sa_mask);

        for (i = 1; i < NSIG; i++) {
            /* Only possible errors are EFAULT or EINVAL The former
             * won't happen, the latter we expect, so no need to check
             * return value */
            (void)sigaction(i, &sig_action, NULL);
        }

        /* Unmask all signals in child, since we've no idea what the
         * caller's done with their signal mask and don't want to
         * propagate that to children */
        sigemptyset(&newmask);
        if (pthread_sigmask(SIG_SETMASK, &newmask, NULL) != 0) {
            Error *local_err = NULL;
            error_setg_errno(&local_err, errno,
                             "cannot unblock signals");
            error_report_err(local_err);
            _exit(1);
        }
    }
    return pid;
}
Ejemplo n.º 11
0
LW_NTSTATUS
LwRtlMain(
    VOID
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    sigset_t waitSet;
    sigset_t intSet;
    siginfo_t info = {0};
    struct sigaction action;
    int ret = 0;
    int i = 0;

    memset(&action, 0, sizeof(action));

    LOCK_SIGNAL();

    sigfillset(&waitSet);
    sigfillset(&intSet);
    sigdelset(&intSet, SIGINT);

    for (i = 0; SignalBlacklist[i]; i++)
    {
        sigdelset(&waitSet, SignalBlacklist[i]);
        sigdelset(&intSet, SignalBlacklist[i]);
    }

    /* Set a special handler for SIGINT */
    action.sa_handler = InterruptHandler;
    action.sa_flags = 0;

    if (sigaction(SIGINT, &action, NULL) < 0)
    {
        status = LwErrnoToNtStatus(errno);
        GOTO_ERROR_ON_STATUS(status);
    }

    status = LwRtlBlockSignals();
    GOTO_ERROR_ON_STATUS(status);

    for (;;)
    {
        UNLOCK_SIGNAL();
        // sigwaitinfo on HPUX 11.11 does not fill-in info.si_signo.
#if defined(HAVE_SIGWAITINFO) && !defined(__LWI_HP_UX__)
        ret = sigwaitinfo(&waitSet, &info);
#else
        ret = sigwait(&waitSet, &info.si_signo);
#endif
        LOCK_SIGNAL();

        if (ret < 0 && errno == EINTR)
        {
            continue;
        }

        if (ret < 0)
        {
            status = LwErrnoToNtStatus(errno);
            GOTO_ERROR_ON_STATUS(status);
        }

        if (gSignal.bExit)
        {
            status = gSignal.Status;
            gSignal.bExit = FALSE;
            gSignal.Status = STATUS_SUCCESS;
            break;
        }

        if (info.si_signo == SIGINT)
        {
            /* Make hitting ^C to break into a process in gdb work.
             *
             * gdb can't trap SIGINT when we receive it with sigwaitinfo(),
             * so we reraise it against the process and then unblock it to
             * give the debugger a chance to intercept it.  If it is not
             * intercepted, InterruptHandler() will run and set gRealSigInt,
             * and we will forward the original SIGINT to all subscribed
             * tasks.  If the signal is intercepted, we pretend the original
             * SIGINT never happened, and the desired debugging behavior
             * is preserved.
             */
            gRealSigInt = FALSE;
            kill(getpid(), SIGINT);
            status = LwErrnoToNtStatus(pthread_sigmask(SIG_SETMASK, &intSet, NULL));
            GOTO_ERROR_ON_STATUS(status);
            status = LwRtlBlockSignals();
            GOTO_ERROR_ON_STATUS(status);

            if (!gRealSigInt)
            {
                continue;
            }
        }

        DispatchSignal(&info);
    }

error:

    UNLOCK_SIGNAL();

    return status;
}
Ejemplo n.º 12
0
static void s_serviceSetHBSig( void )
{

#if defined( HB_OS_UNIX ) || defined( HB_OS_OS2_GCC )
   struct sigaction act;

#if defined( HB_THREAD_SUPPORT ) && ! defined( HB_OS_OS2 )
   sigset_t blockall;
   /* set signal mask */
   sigemptyset( &blockall );
   sigaddset( &blockall, SIGHUP );
   sigaddset( &blockall, SIGQUIT );
   sigaddset( &blockall, SIGILL );
   sigaddset( &blockall, SIGABRT );
   sigaddset( &blockall, SIGFPE );
   sigaddset( &blockall, SIGSEGV );
   sigaddset( &blockall, SIGTERM );
   sigaddset( &blockall, SIGUSR1 );
   sigaddset( &blockall, SIGUSR2 );
   sigaddset( &blockall, SIGHUP );

   pthread_sigmask( SIG_SETMASK, &blockall, NULL );
#endif

   /* to avoid problems with differ sigaction structures and uninitialized
      fields */
   memset( &act, 0, sizeof( struct sigaction ) );

   #if defined( HB_OS_OS2_GCC ) || defined( __WATCOMC__ )
   act.sa_handler = s_signalHandler;
   #else
   /* using more descriptive sa_action instead of sa_handler */
   act.sa_handler   = NULL;            /* if act.sa.. is a union, we just clean this */
   act.sa_sigaction = s_signalHandler; /* this is what matters */
   /* block al signals, we don't want to be interrupted. */
   /*sigfillset( &act.sa_mask );*/
   #endif


   #ifdef HB_OS_OS2_GCC
   act.sa_flags = SA_NOCLDSTOP;
   #else
   act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
   #endif

   sigaction( SIGHUP, &act, NULL );
   sigaction( SIGQUIT, &act, NULL );
   sigaction( SIGILL, &act, NULL );
   sigaction( SIGABRT, &act, NULL );
   sigaction( SIGFPE, &act, NULL );
   sigaction( SIGSEGV, &act, NULL );
   sigaction( SIGTERM, &act, NULL );
   sigaction( SIGUSR1, &act, NULL );
   sigaction( SIGUSR2, &act, NULL );

   /* IGNORE pipe */
   signal( SIGPIPE, SIG_IGN );
#endif

#ifdef HB_OS_WIN
   /* disable all os-level error boxes */
   s_uiErrorMode = SetErrorMode(
      SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | SEM_NOGPFAULTERRORBOX |
      SEM_NOOPENFILEERRORBOX );

   SetUnhandledExceptionFilter( s_exceptionFilter );
   s_hMsgHook = SetWindowsHookEx( WH_GETMESSAGE, ( HOOKPROC ) s_MsgFilterFunc, NULL, GetCurrentThreadId() );
   SetConsoleCtrlHandler( s_ConsoleHandlerRoutine, TRUE );

#endif
}
Ejemplo n.º 13
0
static void * s_signalListener( void * my_stack )
{
   static HB_BOOL bFirst = HB_TRUE;
   sigset_t       passall;
   HB_STACK *     pStack = ( HB_STACK * ) my_stack;

#if defined( HB_OS_BSD )
   int sig;
#else
   siginfo_t sinfo;
#endif

#ifdef HB_THREAD_TLS_KEYWORD
   hb_thread_stack = my_stack;
#else
   pthread_setspecific( hb_pkCurrentStack, my_stack );
#endif

   pStack->th_id = HB_CURRENT_THREAD();
   hb_threadLinkStack( pStack );
   HB_STACK_LOCK;

   /* and now accepts all signals */
   sigemptyset( &passall );

   /* and wait for all signals */
   sigaddset( &passall, SIGHUP );
   sigaddset( &passall, SIGQUIT );
   sigaddset( &passall, SIGILL );
   sigaddset( &passall, SIGABRT );
   sigaddset( &passall, SIGFPE );
   sigaddset( &passall, SIGSEGV );
   sigaddset( &passall, SIGTERM );
   sigaddset( &passall, SIGUSR1 );
   sigaddset( &passall, SIGUSR2 );
   sigaddset( &passall, SIGHUP );

   pthread_cleanup_push( hb_threadTerminator, my_stack );
   pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, NULL );
   pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL );

   for(;; )
   {
      /* allow safe cancelation */
      HB_STACK_UNLOCK;

      /* reset signal handling; this is done here (so I don't
         mangle with pthread_ calls, and I don't hold mutexes),
         and just once (doing it twice would be useless). */
      if( bFirst )
      {
         pthread_sigmask( SIG_SETMASK, &passall, NULL );
         bFirst = HB_FALSE;
      }

      /* This is also a cancelation point. When the main thread
         is done, it will kill all the threads having a stack
         including this one.
         ATM we don't care very much about signal handling during
         termination: no handler is set for them, so the DFL
         action is taken (and that should be fine). */
#if defined( HB_OS_BSD )
      sigwait( &passall, &sig );
#else
      sigwaitinfo( &passall, &sinfo );
#endif

      /* lock stack before passing the ball to VM. */
      HB_STACK_LOCK;
#if defined( HB_OS_BSD )
      s_signalHandler( sig, NULL, NULL );
#else
      s_signalHandler( sinfo.si_signo, &sinfo, NULL );
#endif
   }

   pthread_cleanup_pop( 1 );
   return 0;
}
Ejemplo n.º 14
0
void * thread_main ( void *arg )
{
	int connfd    = -1;
	int thread_nr = -1;
	int *arg_int  = NULL;

	struct sigaction sa;

	PKI_X509_OCSP_REQ  *req = NULL;
	PKI_X509_OCSP_RESP *resp = NULL;

	if (arg)
	{
		arg_int = (int *) arg;
		thread_nr = *arg_int;

		PKI_Free(arg);
	}
	else
	{
		thread_nr = -1;
	}

	if ( ocspd_conf->verbose )
		PKI_log(PKI_LOG_INFO, "New Thread Started [%d]", thread_nr);

	// PThread specific SIGPIPE handling
	sigset_t sigpipe_mask;
	sigset_t saved_mask;

	// Let's initialize the sigpipe mask
	sigemptyset(&sigpipe_mask);

	// Let's add the SIGPIPE to the mask
	sigaddset(&sigpipe_mask, SIGPIPE);

	// Prevent the server to die in case of a write to a prematurely closed socket
	if (pthread_sigmask(SIG_BLOCK, &sigpipe_mask, &saved_mask) == -1)
	{
	  PKI_log_err("Can not block SIGPIPE signal!");
	  exit(1);
	}

	for ( ; ; )
	{
		/* Before calling the cond_wait we need to own the mutex */
		PKI_MUTEX_acquire ( &ocspd_conf->mutexes[CLIFD_MUTEX] );
		while(ocspd_conf->connfd <= 2)
		{
			PKI_COND_wait ( &ocspd_conf->condVars[CLIFD_COND],
				&ocspd_conf->mutexes[CLIFD_MUTEX] );
		}

		// Let's copy the socket descriptor
		connfd = ocspd_conf->connfd;

		// Reset the global value
		ocspd_conf->connfd = -1;

		// Let's now release the mutex to allow for the server to listen
		// for the next connection
		PKI_MUTEX_release ( &ocspd_conf->mutexes[CLIFD_MUTEX] );

		// Communicate to the main thread to listen for the next connection
		PKI_MUTEX_acquire ( &ocspd_conf->mutexes[SRVFD_MUTEX] );
		PKI_COND_signal ( &ocspd_conf->condVars[SRVFD_COND] );
		PKI_MUTEX_release ( &ocspd_conf->mutexes[SRVFD_MUTEX] );

		// Retrieves the request from the socket
		req = ocspd_req_get_socket(connfd, ocspd_conf);

		// If there is an error and we want to debug, let's print some useful info
		if (req == NULL && ocspd_conf->debug) PKI_log_debug("Can not parse REQ");

		// Now let's build the response
		resp = make_ocsp_response(req, ocspd_conf);

		// If we do not have a response, we were not able to generate one
		// from the received request, let's send a generic error.
		if (resp == NULL)
		{
			// Error info
			PKI_log_err("Can not generate the OCSP response (internal error)");

			// Generate the error response
			resp = PKI_X509_OCSP_RESP_new();
			if (resp != NULL)
			{
				PKI_X509_OCSP_RESP_set_status(resp,
					PKI_X509_OCSP_RESP_STATUS_MALFORMEDREQUEST );
			}
		}

end:

		// If we have a response, let's send it over the wire and free
		// the associated memory
		if (resp != NULL)
		{
			// Send the response over the wire
			ocspd_resp_send_socket( connfd, resp, ocspd_conf );

			// Frees the response memory
			PKI_X509_OCSP_RESP_free (resp);
		}

		// Free the memory associated with the request
		if (req != NULL) PKI_X509_OCSP_REQ_free (req);

		// Finally close the current socket
		PKI_NET_close(connfd);
	}
}
Ejemplo n.º 15
0
int main(int argc, char *argv[])
{
	char *myfile;
	int i, totalsize = 0;
	int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
	int oldsamples = 1;
	key_t key;
        union semun args;
	struct params *receiver = NULL;
	struct params *sender = NULL;
	sigset_t sigset;
	void *param = NULL;
	char f_opt[8];
	struct timespec launchdelay, maindelay;

	myfile = getenv("_");
	if (myfile == NULL)
		myfile = argv[0];

	process_options(argc, argv);

	if (check_privs())
		return 1;

	if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
		perror("mlockall");
		return 1;
	}

	get_cpu_setup();

	if (mustfork) {
		int shmem;

		/*
		 * In fork mode (-f), the shared memory contains two
		 * subsequent arrays, receiver[num_threads] and
		 * sender[num_threads].
		 */
		totalsize = num_threads * sizeof(struct params) * 2;

		shm_unlink("/sigwaittest");
  		shmem = shm_open("/sigwaittest", O_CREAT|O_EXCL|O_RDWR,
		    S_IRUSR|S_IWUSR);
		if (shmem < 0) {
			fprintf(stderr, "Could not create shared memory\n");
			return 1;
		}
		ftruncate(shmem, totalsize);
		param = mmap(0, totalsize, PROT_READ|PROT_WRITE, MAP_SHARED,
		    shmem, 0);
		if (param == MAP_FAILED) {
			fprintf(stderr, "Could not map shared memory\n");
			close(shmem);
			return 1;
		}

		receiver = (struct params *) param;
		sender = receiver + num_threads;
	} else if (wasforked) {
		struct stat buf;
		int shmem, totalsize, expect_totalsize;

		if (wasforked_threadno == -1 || wasforked_sender == -1) {
			fprintf(stderr, "Invalid fork option\n");
			return 1;
		}
		shmem = shm_open("/sigwaittest", O_RDWR, S_IRUSR|S_IWUSR);
		if (fstat(shmem, &buf)) {
			fprintf(stderr,
			    "Could not determine shared memory size\n");
			close(shmem);
			return 1;
		}
		totalsize = buf.st_size;
		param = mmap(0, totalsize, PROT_READ|PROT_WRITE, MAP_SHARED,
		    shmem, 0);
		close(shmem);
		if (param == MAP_FAILED) {
			fprintf(stderr, "Could not map shared memory\n");
			return 1;
		}

		receiver = (struct params *) param;
		expect_totalsize = receiver->num_threads *
		    sizeof(struct params) * 2;
		if (totalsize != expect_totalsize) {
			fprintf(stderr, "Memory size problem (expected %d, "
			    "found %d\n", expect_totalsize, totalsize);
			munmap(param, totalsize);
			return 1;
		}
		sender = receiver + receiver->num_threads;
		if (wasforked_sender)
			semathread(sender + wasforked_threadno);
		else
			semathread(receiver + wasforked_threadno);
		munmap(param, totalsize);
		return 0;
	}

	signal(SIGINT, sighand);
	signal(SIGTERM, sighand);

	sigemptyset(&sigset);
	pthread_sigmask(SIG_SETMASK, &sigset, NULL);

	if (!mustfork && !wasforked) {
		receiver = calloc(num_threads, sizeof(struct params));
		sender = calloc(num_threads, sizeof(struct params));
		if (receiver == NULL || sender == NULL)
			goto nomem;
	}

	launchdelay.tv_sec = 0;
	launchdelay.tv_nsec = 10000000; /* 10 ms */

	maindelay.tv_sec = 0;
	maindelay.tv_nsec = 50000000; /* 50 ms */

	for (i = 0; i < num_threads; i++) {
		struct sembuf sb = { 0, 0, 0};

		receiver[i].mindiff = UINT_MAX;
		receiver[i].maxdiff = 0;
		receiver[i].sumdiff = 0.0;

		if ((key = ftok(myfile, i)) == -1) {
			perror("ftok");
			goto nosem;
		}

		if ((receiver[i].semid = semget(key, 2, 0666 | IPC_CREAT)) == -1) {
			perror("semget");
			goto nosem;
		}

		args.val = 1;
		if (semctl(receiver[i].semid, SEM_WAIT_FOR_RECEIVER, SETVAL, args) == -1) {
			perror("semctl sema #0");
			goto nosem;
		}

		if (semctl(receiver[i].semid, SEM_WAIT_FOR_SENDER, SETVAL, args) == -1) {
			perror("semctl sema #1");
			goto nosem;
		}

		sb.sem_num = SEM_WAIT_FOR_RECEIVER;
		sb.sem_op = SEM_LOCK;
		semop(receiver[i].semid, &sb, 1);

		sb.sem_num = SEM_WAIT_FOR_SENDER;
		sb.sem_op = SEM_LOCK;
		semop(receiver[i].semid, &sb, 1);

		receiver[i].cpu = i;
		switch (setaffinity) {
		case AFFINITY_UNSPECIFIED: receiver[i].cpu = -1; break;
		case AFFINITY_SPECIFIED: receiver[i].cpu = affinity; break;
		case AFFINITY_USEALL: receiver[i].cpu = i % max_cpus; break;
		}
		receiver[i].priority = priority;
		receiver[i].tracelimit = tracelimit;
		if (priority > 1 && !sameprio)
			priority--;
		receiver[i].delay.tv_sec = interval / USEC_PER_SEC;
		receiver[i].delay.tv_nsec = (interval % USEC_PER_SEC) * 1000;
		interval += distance;
		receiver[i].max_cycles = max_cycles;
		receiver[i].sender = 0;
		receiver[i].neighbor = &sender[i];
		if (mustfork) {
			pid_t pid = fork();
			if (pid == -1) {
				fprintf(stderr, "Could not fork\n");
				return 1;
			} else if (pid == 0) {
				char *args[3];

				receiver[i].num_threads = num_threads;
				receiver[i].pid = getpid();
				sprintf(f_opt, "-fr%d", i);
				args[0] = argv[0];
				args[1] = f_opt;
				args[2] = NULL;
				execvp(args[0], args);
				fprintf(stderr,
				    "Could not execute receiver child process "
				    "#%d\n", i);
			}
		} else
			pthread_create(&receiver[i].threadid, NULL,
			    semathread, &receiver[i]);

		nanosleep(&launchdelay, NULL);

		memcpy(&sender[i], &receiver[i], sizeof(receiver[0]));
		sender[i].sender = 1;
		sender[i].neighbor = &receiver[i];
		if (mustfork) {
			pid_t pid = fork();
			if (pid == -1) {
				fprintf(stderr, "Could not fork\n");
				return 1;
			} else if (pid == 0) {
				char *args[3];

				sender[i].num_threads = num_threads;
				sender[i].pid = getpid();
				sprintf(f_opt, "-fs%d", i);
				args[0] = argv[0];
				args[1] = f_opt;
				args[2] = NULL;
				execvp(args[0], args);
				fprintf(stderr,
				    "Could not execute sender child process "
				    "#%d\n", i);
			}
		} else
			pthread_create(&sender[i].threadid, NULL, semathread,
			    &sender[i]);
	}

	while (!mustshutdown) {
		int printed;
		int errorlines = 0;

		for (i = 0; i < num_threads; i++)
			mustshutdown |= receiver[i].shutdown |
			    sender[i].shutdown;

		if (receiver[0].samples > oldsamples || mustshutdown) {
			for (i = 0; i < num_threads; i++) {
				int receiver_pid, sender_pid;

				if (mustfork) {
					receiver_pid = receiver[i].pid;
					sender_pid = sender[i].pid;
				} else {
					receiver_pid = receiver[i].tid;
					sender_pid = sender[i].tid;
				}
				printf("#%1d: ID%d, P%d, CPU%d, I%ld; #%1d: "
				    "ID%d, P%d, CPU%d, Cycles %d\n",
				    i*2, receiver_pid, receiver[i].priority,
				    receiver[i].cpu, receiver[i].delay.tv_nsec /
				    1000, i*2+1, sender_pid, sender[i].priority,
				    sender[i].cpu, sender[i].samples);
			}
			for (i = 0; i < num_threads; i++) {
				if (receiver[i].mindiff == -1)
					printf("#%d -> #%d (not yet ready)\n",
					    i*2+1, i*2);
				else
					printf("#%d -> #%d, Min %4d, Cur %4d, "
					    "Avg %4d, Max %4d\n",
					    i*2+1, i*2, receiver[i].mindiff,
					    (int) receiver[i].diff.tv_usec,
					    (int) ((receiver[i].sumdiff /
					    receiver[i].samples) + 0.5),
					    receiver[i].maxdiff);
				if (receiver[i].error[0] != '\0') {
					printf(receiver[i].error);
					receiver[i].error[0] = '\0';
					errorlines++;
				}
				if (sender[i].error[0] != '\0') {
					printf(sender[i].error);
					sender[i].error[0] = '\0';
					errorlines++;
				}
			}
			printed = 1;
		} else
			printed = 0;

		sigemptyset(&sigset);
		sigaddset(&sigset, SIGTERM);
		sigaddset(&sigset, SIGINT);
		pthread_sigmask(SIG_SETMASK, &sigset, NULL);

		nanosleep(&maindelay, NULL);

		sigemptyset(&sigset);
		pthread_sigmask(SIG_SETMASK, &sigset, NULL);

		if (printed && !mustshutdown)
			printf("\033[%dA", num_threads*2 + errorlines);
	}

	for (i = 0; i < num_threads; i++) {
		receiver[i].shutdown = 1;
		sender[i].shutdown = 1;
	}
	nanosleep(&receiver[0].delay, NULL);

	for (i = 0; i < num_threads; i++) {
		if (!receiver[i].stopped) {
			if (mustfork)
				kill(receiver[i].pid, SIGTERM);
			else
				pthread_kill(receiver[i].threadid, SIGTERM);
		}
		if (!sender[i].stopped) {
			if (mustfork)
				kill(sender[i].pid, SIGTERM);
			else
				pthread_kill(sender[i].threadid, SIGTERM);
		}
	}

	nosem:
	for (i = 0; i < num_threads; i++)
		semctl(receiver[i].semid, -1, IPC_RMID);

 	nomem:
	if (mustfork) {
		munmap(param, totalsize);
		shm_unlink("/sigwaittest");
	}

	return 0;
}
Ejemplo n.º 16
0
void netsys_not_event_signal(struct not_event *ne)
{
#ifndef HAVE_GCC_COMPARE_AND_SWAP
#ifdef HAVE_POSIX_SIGNALS
    sigset_t set, oldset;
#endif
#endif

#ifdef HAVE_POLL
    switch (ne->type) {
    case NE_PIPE:

#ifdef HAVE_GCC_COMPARE_AND_SWAP
	/* The elegant solution. See
	   http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html
	   for documentation
	*/
	if (__sync_bool_compare_and_swap(&(ne->state), 0, 1)) {
	    if (ne->fd2 >= 0) {
                int n;
		n = write(ne->fd2, "X", 1);
                if (n == -1) {
                    fprintf(stderr, "Cannot write to signaling pipe [netsys_c_event.c]\n");
                }
	    }
	}

#else
	/* We have to protect against concurrent calls of this functions
	   from signal handlers and from other threads. First, we block
	   signals for this thread. Once we did this, the only other
	   reason for running this can be another thread calling this
	   function. The second measure is to use a mutex to block the
	   other thread temporarily.

	   NB If called from a signal handler, and if we use a pipe,
	   this function is not absolutely correct. Actually, we are
	   not allowed to call pthread_mutex_lock. It's not
	   async-signal-safe. - TO BE SOLVED
	*/

#ifdef HAVE_POSIX_SIGNALS
	sigfillset(&set);
#ifdef HAVE_PTHREAD
	pthread_sigmask(SIG_BLOCK, &set, &oldset);
#else
	sigprocmask(SIG_BLOCK, &set, &oldset);
#endif /* HAVE_PTHREAD */
#endif /* HAVE_POSIX_SIGNALS */

#ifdef HAVE_PTHREAD
	pthread_mutex_lock(&(ne->mutex));
#endif /* HAVE_PTHREAD */

	if (ne->state == 0) {
	    ne->state = 1;
	    if (ne->fd2 >= 0)
		write(ne->fd2, "X", 1);
	}

#ifdef HAVE_PTHREAD
	pthread_mutex_unlock(&(ne->mutex));
#endif /* HAVE_PTHREAD */

#ifdef HAVE_POSIX_SIGNALS
#ifdef HAVE_PTHREAD
	pthread_sigmask(SIG_SETMASK, &oldset, NULL);
#else
	sigprocmask(SIG_SETMASK, &oldset, NULL);
#endif /* HAVE_PTHREAD */
#endif /* HAVE_POSIX_SIGNALS */
#endif /* HAVE_GCC_COMPARE_AND_SWAP */

	break;

    case NE_EVENTFD:
	{
	    int64_t buf;
	    buf = 1;
	    if (ne->fd1 >= 0) {
                int n;
		n = write(ne->fd1, (char *) &buf, 8);
                if (n == -1) {
                    fprintf(stderr, "Cannot write to signaling pipe [netsys_c_event.c]\n");
                }
	    };
	    break;
	}

    case NE_TIMERFD:
	/* not supported */
	break;
    }
   
#endif /* HAVE_POLL */
}
Ejemplo n.º 17
0
void *semathread(void *param)
{
	int mustgetcpu = 0;
	struct params *par = param;
	cpu_set_t mask;
	int policy = SCHED_FIFO;
	struct sched_param schedp;
	struct sembuf sb = { 0, 0, 0};
	sigset_t sigset;

	sigemptyset(&sigset);
	pthread_sigmask(SIG_SETMASK, &sigset, NULL);

	memset(&schedp, 0, sizeof(schedp));
	schedp.sched_priority = par->priority;
	sched_setscheduler(0, policy, &schedp);

	if (par->cpu != -1) {
		CPU_ZERO(&mask);
		CPU_SET(par->cpu, &mask);
		if(sched_setaffinity(0, sizeof(mask), &mask) == -1)
			snprintf(par->error, sizeof(par->error),
			    "WARNING: Could not set CPU affinity "
			    "to CPU #%d\n", par->cpu);
	} else {
        	int max_cpus = sysconf(_SC_NPROCESSORS_CONF);

        	if (max_cpus > 1)
		        mustgetcpu = 1;
	        else
			par->cpu = 0;
	}

	if (!wasforked)
		par->tid = gettid();

	while (!par->shutdown) {
		if (par->sender) {
 			sb.sem_num = SEM_WAIT_FOR_SENDER;
 			sb.sem_op = SEM_UNLOCK;
			/*
			 * Unlocking the semaphore:
			 *   Start of latency measurement ...
			 */
			gettimeofday(&par->unblocked, NULL);
			semop(par->semid, &sb, 1);
			par->samples++;
			if(par->max_cycles && par->samples >= par->max_cycles)
				par->shutdown = 1;

			if (mustgetcpu)
				par->cpu = get_cpu();

 			sb.sem_num = SEM_WAIT_FOR_RECEIVER;
 			sb.sem_op = SEM_LOCK;
			semop(par->semid, &sb, 1);

 			sb.sem_num = SEM_WAIT_FOR_SENDER;
			sb.sem_op = SEM_LOCK;
			semop(par->semid, &sb, 1);
		} else {
			/* Receiver */
			struct params *neighbor;

 			if (wasforked)
				neighbor = par + par->num_threads;
			else
				neighbor = par->neighbor;

 			sb.sem_num = SEM_WAIT_FOR_SENDER;
			sb.sem_op = SEM_LOCK;
			semop(par->semid, &sb, 1);

			/*
			 * ... We got the lock:
			 * End of latency measurement
			 */
			gettimeofday(&par->received, NULL);
			par->samples++;
			if (par->max_cycles && par->samples >= par->max_cycles)
				par->shutdown = 1;

			if (mustgetcpu)
				par->cpu = get_cpu();

			timersub(&par->received, &neighbor->unblocked,
			    &par->diff);

			if (par->diff.tv_usec < par->mindiff)
				par->mindiff = par->diff.tv_usec;
			if (par->diff.tv_usec > par->maxdiff)
				par->maxdiff = par->diff.tv_usec;
			par->sumdiff += (double) par->diff.tv_usec;
			if (par->tracelimit && par->maxdiff > par->tracelimit) {
				char tracing_enabled_file[MAX_PATH];

				strcpy(tracing_enabled_file, get_debugfileprefix());
				strcat(tracing_enabled_file, "tracing_enabled");
				int tracing_enabled =
				    open(tracing_enabled_file, O_WRONLY);
				if (tracing_enabled >= 0) {
					write(tracing_enabled, "0", 1);
					close(tracing_enabled);
				} else
					snprintf(par->error, sizeof(par->error),
					    "Could not access %s\n",
					    tracing_enabled_file);
				par->shutdown = 1;
				neighbor->shutdown = 1;
			}

 			sb.sem_num = SEM_WAIT_FOR_RECEIVER;
			sb.sem_op = SEM_UNLOCK;
			semop(par->semid, &sb, 1);

			nanosleep(&par->delay, NULL);

 			sb.sem_num = SEM_WAIT_FOR_SENDER;
			sb.sem_op = SEM_UNLOCK;
			semop(par->semid, &sb, 1);
		}
	}
	if (par->sender) {
		sb.sem_num = SEM_WAIT_FOR_SENDER;
		sb.sem_op = SEM_UNLOCK;
		semop(par->semid, &sb, 1);

		sb.sem_num = SEM_WAIT_FOR_RECEIVER;
		sb.sem_op = SEM_UNLOCK;
		semop(par->semid, &sb, 1);
	}
	par->stopped = 1;
	return NULL;
}
Ejemplo n.º 18
0
int
main(int argc, char **argv)
{
  int option;
  char *configfile;
  int background;
  int mdns_no_rsp;
  int mdns_no_daap;
  int mdns_no_mpd;
  int loglevel;
  char *logdomains;
  char *logfile;
  char *ffid;
  char *pidfile;
  const char *gcry_version;
  sigset_t sigs;
  int sigfd;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
  struct kevent ke_sigs[4];
#endif
  int ret;

  struct option option_map[] =
    {
      { "ffid",         1, NULL, 'b' },
      { "debug",        1, NULL, 'd' },
      { "logdomains",   1, NULL, 'D' },
      { "foreground",   0, NULL, 'f' },
      { "config",       1, NULL, 'c' },
      { "pidfile",      1, NULL, 'P' },
      { "version",      0, NULL, 'v' },

      { "mdns-no-rsp",  0, NULL, 512 },
      { "mdns-no-daap", 0, NULL, 513 },

      { NULL,           0, NULL, 0 }
    };

  configfile = CONFFILE;
  pidfile = PIDFILE;
  loglevel = -1;
  logdomains = NULL;
  logfile = NULL;
  background = 1;
  ffid = NULL;
  mdns_no_rsp = 0;
  mdns_no_daap = 0;
  mdns_no_mpd = 1; // only announce if mpd protocol support is activated

  while ((option = getopt_long(argc, argv, "D:d:c:P:fb:v", option_map, NULL)) != -1)
    {
      switch (option)
	{
	  case 512:
	    mdns_no_rsp = 1;
	    break;

	  case 513:
	    mdns_no_daap = 1;
	    break;

	  case 'b':
            ffid = optarg;
            break;

	  case 'd':
	    ret = safe_atoi32(optarg, &option);
	    if (ret < 0)
	      fprintf(stderr, "Error: loglevel must be an integer in '-d %s'\n", optarg);
	    else
	      loglevel = option;
            break;

	  case 'D':
	    logdomains = optarg;
            break;

          case 'f':
            background = 0;
            break;

          case 'c':
            configfile = optarg;
            break;

          case 'P':
	    pidfile = optarg;
            break;

          case 'v':
	    version();
            return EXIT_SUCCESS;
            break;

          default:
            usage(argv[0]);
            return EXIT_FAILURE;
            break;
        }
    }

  ret = logger_init(NULL, NULL, (loglevel < 0) ? E_LOG : loglevel);
  if (ret != 0)
    {
      fprintf(stderr, "Could not initialize log facility\n");

      return EXIT_FAILURE;
    }

  ret = conffile_load(configfile);
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Config file errors; please fix your config\n");

      logger_deinit();
      return EXIT_FAILURE;
    }

  logger_deinit();

  /* Reinit log facility with configfile values */
  if (loglevel < 0)
    loglevel = cfg_getint(cfg_getsec(cfg, "general"), "loglevel");

  logfile = cfg_getstr(cfg_getsec(cfg, "general"), "logfile");

  ret = logger_init(logfile, logdomains, loglevel);
  if (ret != 0)
    {
      fprintf(stderr, "Could not reinitialize log facility with config file settings\n");

      conffile_unload();
      return EXIT_FAILURE;
    }

  /* Set up libevent logging callback */
  event_set_log_callback(logger_libevent);

  DPRINTF(E_LOG, L_MAIN, "Forked Media Server Version %s taking off\n", VERSION);

  ret = av_lockmgr_register(ffmpeg_lockmgr);
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not register ffmpeg lock manager callback\n");

      ret = EXIT_FAILURE;
      goto ffmpeg_init_fail;
    }

  av_register_all();
  avfilter_register_all();
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 13)
  avformat_network_init();
#endif
  av_log_set_callback(logger_ffmpeg);

#ifdef LASTFM
  /* Initialize libcurl */
  curl_global_init(CURL_GLOBAL_DEFAULT);
#endif

  /* Initialize libgcrypt */
  gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);

  gcry_version = gcry_check_version(GCRYPT_VERSION);
  if (!gcry_version)
    {
      DPRINTF(E_FATAL, L_MAIN, "libgcrypt version mismatch\n");

      ret = EXIT_FAILURE;
      goto gcrypt_init_fail;
    }

  /* We aren't handling anything sensitive, so give up on secure
   * memory, which is a scarce system resource.
   */
  gcry_control(GCRYCTL_DISABLE_SECMEM, 0);

  gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);

  DPRINTF(E_DBG, L_MAIN, "Initialized with gcrypt %s\n", gcry_version);

  /* Block signals for all threads except the main one */
  sigemptyset(&sigs);
  sigaddset(&sigs, SIGINT);
  sigaddset(&sigs, SIGHUP);
  sigaddset(&sigs, SIGCHLD);
  sigaddset(&sigs, SIGTERM);
  sigaddset(&sigs, SIGPIPE);
  ret = pthread_sigmask(SIG_BLOCK, &sigs, NULL);
  if (ret != 0)
    {
      DPRINTF(E_LOG, L_MAIN, "Error setting signal set\n");

      ret = EXIT_FAILURE;
      goto signal_block_fail;
    }

  /* Daemonize and drop privileges */
  ret = daemonize(background, pidfile);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_MAIN, "Could not initialize server\n");

      ret = EXIT_FAILURE;
      goto daemon_fail;
    }

  /* Initialize event base (after forking) */
  evbase_main = event_base_new();

  DPRINTF(E_LOG, L_MAIN, "mDNS init\n");
  ret = mdns_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "mDNS init failed\n");

      ret = EXIT_FAILURE;
      goto mdns_fail;
    }

  /* Initialize the database before starting */
  DPRINTF(E_INFO, L_MAIN, "Initializing database\n");
  ret = db_init();
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Database init failed\n");

      ret = EXIT_FAILURE;
      goto db_fail;
    }

  /* Open a DB connection for the main thread */
  ret = db_perthread_init();
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not perform perthread DB init for main\n");

      ret = EXIT_FAILURE;
      goto db_fail;
    }

  /* Spawn worker thread */
  ret = worker_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Worker thread failed to start\n");

      ret = EXIT_FAILURE;
      goto worker_fail;
    }

  /* Spawn cache thread */
  ret = cache_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Cache thread failed to start\n");

      ret = EXIT_FAILURE;
      goto cache_fail;
    }

  /* Spawn file scanner thread */
  ret = filescanner_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "File scanner thread failed to start\n");

      ret = EXIT_FAILURE;
      goto filescanner_fail;
    }

#ifdef HAVE_SPOTIFY_H
  /* Spawn Spotify thread */
  ret = spotify_init();
  if (ret < 0)
    {
      DPRINTF(E_INFO, L_MAIN, "Spotify thread not started\n");;
    }
#endif

  /* Spawn player thread */
  ret = player_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Player thread failed to start\n");

      ret = EXIT_FAILURE;
      goto player_fail;
    }

  /* Spawn HTTPd thread */
  ret = httpd_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "HTTPd thread failed to start\n");

      ret = EXIT_FAILURE;
      goto httpd_fail;
    }

#ifdef MPD
  /* Spawn MPD thread */
  ret = mpd_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "MPD thread failed to start\n");

      ret = EXIT_FAILURE;
      goto mpd_fail;
    }
  mdns_no_mpd = 0;
#endif

  /* Start Remote pairing service */
  ret = remote_pairing_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Remote pairing service failed to start\n");

      ret = EXIT_FAILURE;
      goto remote_fail;
    }

  /* Register mDNS services */
  ret = register_services(ffid, mdns_no_rsp, mdns_no_daap, mdns_no_mpd);
  if (ret < 0)
    {
      ret = EXIT_FAILURE;
      goto mdns_reg_fail;
    }

#if defined(__linux__)
  /* Set up signal fd */
  sigfd = signalfd(-1, &sigs, SFD_NONBLOCK | SFD_CLOEXEC);
  if (sigfd < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not setup signalfd: %s\n", strerror(errno));

      ret = EXIT_FAILURE;
      goto signalfd_fail;
    }

  sig_event = event_new(evbase_main, sigfd, EV_READ, signal_signalfd_cb, NULL);
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
  sigfd = kqueue();
  if (sigfd < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not setup kqueue: %s\n", strerror(errno));

      ret = EXIT_FAILURE;
      goto signalfd_fail;
    }

  EV_SET(&ke_sigs[0], SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
  EV_SET(&ke_sigs[1], SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
  EV_SET(&ke_sigs[2], SIGHUP, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
  EV_SET(&ke_sigs[3], SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);

  ret = kevent(sigfd, ke_sigs, 4, NULL, 0, NULL);
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not register signal events: %s\n", strerror(errno));

      ret = EXIT_FAILURE;
      goto signalfd_fail;
    }

  sig_event = event_new(evbase_main, sigfd, EV_READ, signal_kqueue_cb, NULL);
#endif
  if (!sig_event)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not create signal event\n");

      ret = EXIT_FAILURE;
      goto sig_event_fail;
    }

  event_add(sig_event, NULL);

  /* Run the loop */
  event_base_dispatch(evbase_main);

  DPRINTF(E_LOG, L_MAIN, "Stopping gracefully\n");
  ret = EXIT_SUCCESS;

  /*
   * On a clean shutdown, bring mDNS down first to give a chance
   * to the clients to perform a clean shutdown on their end
   */
  DPRINTF(E_LOG, L_MAIN, "mDNS deinit\n");
  mdns_deinit();

 sig_event_fail:
 signalfd_fail:
 mdns_reg_fail:
  DPRINTF(E_LOG, L_MAIN, "Remote pairing deinit\n");
  remote_pairing_deinit();

 remote_fail:
#ifdef MPD
  DPRINTF(E_LOG, L_MAIN, "MPD deinit\n");
  mpd_deinit();

 mpd_fail:
#endif
  DPRINTF(E_LOG, L_MAIN, "HTTPd deinit\n");
  httpd_deinit();

 httpd_fail:
  DPRINTF(E_LOG, L_MAIN, "Player deinit\n");
  player_deinit();

 player_fail:
#ifdef HAVE_SPOTIFY_H
  DPRINTF(E_LOG, L_MAIN, "Spotify deinit\n");
  spotify_deinit();
#endif
  DPRINTF(E_LOG, L_MAIN, "File scanner deinit\n");
  filescanner_deinit();

 filescanner_fail:
  DPRINTF(E_LOG, L_MAIN, "Cache deinit\n");
  cache_deinit();

 cache_fail:
  DPRINTF(E_LOG, L_MAIN, "Worker deinit\n");
  worker_deinit();

 worker_fail:
  DPRINTF(E_LOG, L_MAIN, "Database deinit\n");
  db_perthread_deinit();
  db_deinit();

 db_fail:
  if (ret == EXIT_FAILURE)
    {
      DPRINTF(E_LOG, L_MAIN, "mDNS deinit\n");
      mdns_deinit();
    }

 mdns_fail:
 daemon_fail:
  if (background)
    {
      ret = seteuid(0);
      if (ret < 0)
	DPRINTF(E_LOG, L_MAIN, "seteuid() failed: %s\n", strerror(errno));
      else
	{
	  ret = unlink(pidfile);
	  if (ret < 0)
	    DPRINTF(E_LOG, L_MAIN, "Could not unlink PID file %s: %s\n", pidfile, strerror(errno));
	}
    }

 signal_block_fail:
 gcrypt_init_fail:
#ifdef LASTFM
  curl_global_cleanup();
#endif
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 13)
  avformat_network_deinit();
#endif
  av_lockmgr_register(NULL);

 ffmpeg_init_fail:
  DPRINTF(E_LOG, L_MAIN, "Exiting.\n");
  conffile_unload();
  logger_deinit();

  return ret;
}
Ejemplo n.º 19
0
/**
 * Manually process the flags for the registered secondary handler to call it as if it had been evoked by the OS
 * in response to a signal, without re-raising it.
 */
int
omrsig_handler(int sig, void *siginfo, void *uc)
{
	int rc = OMRSIG_RC_ERROR;
	if (validSignalNum(sig, false)) {
		/* Only mask signals and lock while getting the handler slot. */
		SIGLOCK(sigMutex);
		OMR_SigData handlerSlot = sigData[sig];
		SIGUNLOCK(sigMutex);

		if (handlerIsFunction(&handlerSlot.secondaryAction)) {
#if defined(POSIX_SIGNAL)
#if defined(OSX)
			sigset_t oldMask = {0};
#else /* defined(OSX) */
			sigset_t oldMask = {{0}};
#endif /* defined(OSX) */
			sigset_t usedMask = handlerSlot.secondaryAction.sa_mask;
			sigaddset(&usedMask, sig);
			int ec = pthread_sigmask(SIG_BLOCK, &usedMask, &oldMask);

			/* SA_NODEFER - If set, sig will not be added to the process' signal mask on entry to the signal handler
			 * unless it is included in sa_mask. Otherwise, sig will always be added to the process' signal mask on
			 * entry to the signal handler.
			 */
			if ((0 == ec) && ((handlerSlot.secondaryAction.sa_flags & SA_NODEFER)
#if (defined(AIXPPC) || defined(J9ZOS390))
				/* Only AIX and zos respects that SA_RESETHAND behaves like SA_NODEFER by POSIX spec. */
				|| (handlerSlot.secondaryAction.sa_flags & SA_RESETHAND)
#endif /* (defined(AIXPPC) || defined(J9ZOS390)) */
				)) {
#if defined(OSX)
				sigset_t mask = {0};
#else /* defined(OSX) */
				sigset_t mask = {{0}};
#endif /* defined(OSX) */
				sigemptyset(&mask);
				sigaddset(&mask, sig);
				ec = pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
			}


			/* SA_RESETHAND - If set, the disposition of the signal will be reset to SIG_DFL and the SA_SIGINFO flag
			 * will be cleared on entry to the signal handler. Does not work for SIGILL or SIGTRAP, silently. Also
			 * behaves like SA_NODEFER according to POSIX standard, but AIX is the supported OS found to do this.
			 */
			if (0 == ec) {
				sighandler_t handler = SIG_DFL;
				sigaction_t action = (sigaction_t)SIG_DFL;
				int flags = handlerSlot.secondaryAction.sa_flags;
				if (flags & SA_SIGINFO) {
					action = handlerSlot.secondaryAction.sa_sigaction;
				} else {
					handler = handlerSlot.secondaryAction.sa_handler;
				}
				if (handlerSlot.secondaryAction.sa_flags & SA_RESETHAND) {
					handlerSlot.secondaryAction.sa_flags &= ~SA_SIGINFO;
					handlerSlot.secondaryAction.sa_handler = SIG_DFL;
					omrsig_sigaction_internal(sig, &handlerSlot.secondaryAction, NULL, false);
				}

				/* SA_SIGINFO - The signal handler takes three arguments, not one. In this case, sa_sigaction should be
				 * used instead of sa_handler.
				 * NOTE FOR NOW: null, DFL, and IGN check the sa_handler when registering it, not here
				 */
				if (flags & SA_SIGINFO) {
					action(sig, (siginfo_t *)siginfo, uc);
				} else {
					handler(sig);
				}
				ec = pthread_sigmask(SIG_SETMASK, &oldMask, NULL);
			}
			if (0 == ec) {
				rc = OMRSIG_RC_SIGNAL_HANDLED;
			}
#else /* defined(POSIX_SIGNAL) */
			handlerSlot.secondaryAction.sa_handler(sig);
			rc = OMRSIG_RC_SIGNAL_HANDLED;
#endif /* defined(POSIX_SIGNAL) */
		} else if (SIG_DFL == handlerSlot.secondaryAction.sa_handler){
			rc = OMRSIG_RC_DEFAULT_ACTION_REQUIRED;
		}
	}
	return rc;
}
Ejemplo n.º 20
0
int main(int ac, char **av)
{
    fd_set              rfds;
    void                *ipc;
    struct sigaction	sv;
    sigset_t            sigs;
    int                 ret;

    /* Parse argv args and initialize default options */
    afp_options_parse_cmdline(&obj, ac, av);

    if (!(obj.cmdlineflags & OPTION_DEBUG) && (daemonize(0, 0) != 0))
        exit(EXITERR_SYS);

    /* Log SIGBUS/SIGSEGV SBT */
    fault_setup(NULL);

    if (afp_config_parse(&obj, "afpd") != 0)
        afp_exit(EXITERR_CONF);

    /* Save the user's current umask */
    obj.options.save_mask = umask(obj.options.umask);

    /* install child handler for asp and dsi. we do this before afp_goaway
     * as afp_goaway references stuff from here. 
     * XXX: this should really be setup after the initial connections. */
    if (!(server_children = server_child_alloc(obj.options.connections, CHILD_NFORKS))) {
        LOG(log_error, logtype_afpd, "main: server_child alloc: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }
    
    sigemptyset(&sigs);
    pthread_sigmask(SIG_SETMASK, &sigs, NULL);

    memset(&sv, 0, sizeof(sv));    
    /* linux at least up to 2.4.22 send a SIGXFZ for vfat fs,
       even if the file is open with O_LARGEFILE ! */
#ifdef SIGXFSZ
    sv.sa_handler = SIG_IGN;
    sigemptyset( &sv.sa_mask );
    if (sigaction(SIGXFSZ, &sv, NULL ) < 0 ) {
        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }
#endif
    
    sv.sa_handler = afp_goaway; /* handler for all sigs */

    sigemptyset( &sv.sa_mask );
    sigaddset(&sv.sa_mask, SIGALRM);
    sigaddset(&sv.sa_mask, SIGHUP);
    sigaddset(&sv.sa_mask, SIGTERM);
    sigaddset(&sv.sa_mask, SIGUSR1);
    sigaddset(&sv.sa_mask, SIGQUIT);    
    sv.sa_flags = SA_RESTART;
    if ( sigaction( SIGCHLD, &sv, NULL ) < 0 ) {
        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }

    sigemptyset( &sv.sa_mask );
    sigaddset(&sv.sa_mask, SIGALRM);
    sigaddset(&sv.sa_mask, SIGTERM);
    sigaddset(&sv.sa_mask, SIGHUP);
    sigaddset(&sv.sa_mask, SIGCHLD);
    sigaddset(&sv.sa_mask, SIGQUIT);
    sv.sa_flags = SA_RESTART;
    if ( sigaction( SIGUSR1, &sv, NULL ) < 0 ) {
        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }

    sigemptyset( &sv.sa_mask );
    sigaddset(&sv.sa_mask, SIGALRM);
    sigaddset(&sv.sa_mask, SIGTERM);
    sigaddset(&sv.sa_mask, SIGUSR1);
    sigaddset(&sv.sa_mask, SIGCHLD);
    sigaddset(&sv.sa_mask, SIGQUIT);
    sv.sa_flags = SA_RESTART;
    if ( sigaction( SIGHUP, &sv, NULL ) < 0 ) {
        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }

    sigemptyset( &sv.sa_mask );
    sigaddset(&sv.sa_mask, SIGALRM);
    sigaddset(&sv.sa_mask, SIGHUP);
    sigaddset(&sv.sa_mask, SIGUSR1);
    sigaddset(&sv.sa_mask, SIGCHLD);
    sigaddset(&sv.sa_mask, SIGQUIT);
    sv.sa_flags = SA_RESTART;
    if ( sigaction( SIGTERM, &sv, NULL ) < 0 ) {
        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }

    sigemptyset( &sv.sa_mask );
    sigaddset(&sv.sa_mask, SIGALRM);
    sigaddset(&sv.sa_mask, SIGHUP);
    sigaddset(&sv.sa_mask, SIGUSR1);
    sigaddset(&sv.sa_mask, SIGCHLD);
    sigaddset(&sv.sa_mask, SIGTERM);
    sv.sa_flags = SA_RESTART;
    if (sigaction(SIGQUIT, &sv, NULL ) < 0 ) {
        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
        afp_exit(EXITERR_SYS);
    }

    /* afp.conf:  not in config file: lockfile, configfile
     *            preference: command-line provides defaults.
     *                        config file over-writes defaults.
     *
     * we also need to make sure that killing afpd during startup
     * won't leave any lingering registered names around.
     */

    sigemptyset(&sigs);
    sigaddset(&sigs, SIGALRM);
    sigaddset(&sigs, SIGHUP);
    sigaddset(&sigs, SIGUSR1);
#if 0
    /* don't block SIGTERM */
    sigaddset(&sigs, SIGTERM);
#endif
    sigaddset(&sigs, SIGCHLD);

    pthread_sigmask(SIG_BLOCK, &sigs, NULL);
    if (configinit(&obj) != 0) {
        LOG(log_error, logtype_afpd, "main: no servers configured");
        afp_exit(EXITERR_CONF);
    }
    pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);

    /* Initialize */
    cnid_init();
    
    /* watch atp, dsi sockets and ipc parent/child file descriptor. */

    if (obj.options.flags & OPTION_KEEPSESSIONS) {
        LOG(log_note, logtype_afpd, "Activating continous service");
        disasociated_ipc_fd = ipc_server_uds(_PATH_AFP_IPC);
    }

    fd_set_listening_sockets(&obj);

    /* set limits */
    (void)setlimits();

    afp_child_t *child;
    int recon_ipc_fd;
    pid_t pid;
    int saveerrno;

    /* wait for an appleshare connection. parent remains in the loop
     * while the children get handled by afp_over_{asp,dsi}.  this is
     * currently vulnerable to a denial-of-service attack if a
     * connection is made without an actual login attempt being made
     * afterwards. establishing timeouts for logins is a possible 
     * solution. */
    while (1) {
        LOG(log_maxdebug, logtype_afpd, "main: polling %i fds", fdset_used);
        pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
        ret = poll(fdset, fdset_used, -1);
        pthread_sigmask(SIG_BLOCK, &sigs, NULL);
        saveerrno = errno;

        if (gotsigchld) {
            gotsigchld = 0;
            child_handler();
            continue;
        }

        if (reloadconfig) {
            nologin++;
            auth_unload();
            fd_reset_listening_sockets(&obj);

            LOG(log_info, logtype_afpd, "re-reading configuration file");

            configfree(&obj, NULL);
            if (configinit(&obj) != 0) {
                LOG(log_error, logtype_afpd, "config re-read: no servers configured");
                afp_exit(EXITERR_CONF);
            }

            fd_set_listening_sockets(&obj);

            nologin = 0;
            reloadconfig = 0;
            errno = saveerrno;
            continue;
        }

        if (ret == 0)
            continue;
        
        if (ret < 0) {
            if (errno == EINTR)
                continue;
            LOG(log_error, logtype_afpd, "main: can't wait for input: %s", strerror(errno));
            break;
        }

        for (int i = 0; i < fdset_used; i++) {
            if (fdset[i].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)) {
                switch (polldata[i].fdtype) {

                case LISTEN_FD:
                    if (child = dsi_start(&obj, (DSI *)polldata[i].data, server_children)) {
                        /* Add IPC fd to select fd set */
                        fdset_add_fd(obj.options.connections + AFP_LISTENERS + FDSET_SAFETY,
                                     &fdset,
                                     &polldata,
                                     &fdset_used,
                                     &fdset_size,
                                     child->ipc_fd,
                                     IPC_FD,
                                     child);
                    }
                    break;

                case IPC_FD:
                    child = (afp_child_t *)polldata[i].data;
                    LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->pid);

                    if (ipc_server_read(server_children, child->ipc_fd) != 0) {
                        fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fd);
                        close(child->ipc_fd);
                        child->ipc_fd = -1;
                        if ((obj.options.flags & OPTION_KEEPSESSIONS) && child->disasociated) {
                            LOG(log_note, logtype_afpd, "main: removing reattached child[%u]", child->pid);
                            server_child_remove(server_children, CHILD_DSIFORK, child->pid);
                        }
                    }
                    break;

                case DISASOCIATED_IPC_FD:
                    LOG(log_debug, logtype_afpd, "main: IPC reconnect request");
                    if ((recon_ipc_fd = accept(disasociated_ipc_fd, NULL, NULL)) == -1) {
                        LOG(log_error, logtype_afpd, "main: accept: %s", strerror(errno));
                        break;
                    }
                    if (readt(recon_ipc_fd, &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) {
                        LOG(log_error, logtype_afpd, "main: readt: %s", strerror(errno));
                        close(recon_ipc_fd);
                        break;
                    }
                    LOG(log_note, logtype_afpd, "main: IPC reconnect from pid [%u]", pid);

                    if ((child = server_child_add(server_children, CHILD_DSIFORK, pid, recon_ipc_fd)) == NULL) {
                        LOG(log_error, logtype_afpd, "main: server_child_add");
                        close(recon_ipc_fd);
                        break;
                    }
                    child->disasociated = 1;
                    fdset_add_fd(obj.options.connections + AFP_LISTENERS + FDSET_SAFETY,
                                 &fdset,
                                 &polldata,
                                 &fdset_used,
                                 &fdset_size,
                                 recon_ipc_fd,
                                 IPC_FD,
                                 child);
                    break;

                default:
                    LOG(log_debug, logtype_afpd, "main: IPC request for unknown type");
                    break;
                } /* switch */
            }  /* if */
        } /* for (i)*/
    } /* while (1) */

    return 0;
}
Ejemplo n.º 21
0
int main(int argc, char **argv)
{
	extern char *optarg;
	extern int optopt;
	int i, c, signal;
	size_t opt_subbuf_size = 0;
	size_t opt_n_subbufs = 0;
	sigset_t signals;

	pthread_mutex_init(&processing_mutex, NULL);

	sigemptyset(&signals);
	sigaddset(&signals, SIGINT);
	sigaddset(&signals, SIGTERM);
	pthread_sigmask(SIG_BLOCK, &signals, NULL);

	while ((c = getopt(argc, argv, "b:n:")) != -1) {
		switch (c) {
		case 'b':
			opt_subbuf_size = (unsigned)atoi(optarg);
			if (!opt_subbuf_size)
				usage();
			break;
		case 'n':
			opt_n_subbufs = (unsigned)atoi(optarg);
			if (!opt_n_subbufs)
				usage();
			break;
		case '?':
			printf("Unknown option -%c\n", optopt);
			usage();
			break;
		default:
			break;
		}
	}

	if ((opt_n_subbufs && !opt_subbuf_size) ||
	    (!opt_n_subbufs && opt_subbuf_size))
		usage();

	if (opt_n_subbufs && opt_n_subbufs) {
		subbuf_size = opt_subbuf_size;
		n_subbufs = opt_n_subbufs;
	}

	ncpus = sysconf(_SC_NPROCESSORS_ONLN);

	control_write(app_dirname, "subbuf_size", subbuf_size);
	control_write(app_dirname, "n_subbufs", n_subbufs);
	/* disable logging in case we exited badly in a previous run */
	control_write(app_dirname, "enabled", 0);
	fprintf(stderr, "control_write: create\n");

	control_write(app_dirname, "create", 1);

	if (open_app_files())
		return -1;

	if (open_control_files(app_dirname, percpu_basename)) {
		close_app_files();
		return -1;
	}

	if (create_percpu_threads()) {
		close_control_files();
		close_app_files();
		return -1;
	}

	control_write(app_dirname, "enabled", 1);

	printf("Creating channel with %lu sub-buffers of size %lu.\n",
	       n_subbufs, subbuf_size);
	printf("Logging... Press Control-C to stop.\n");

	sigemptyset(&signals);
	sigaddset(&signals, SIGINT);
	sigaddset(&signals, SIGTERM);

	while (sigwait(&signals, &signal) == 0) {
		switch(signal) {
		case SIGINT:
		case SIGTERM:
			control_write(app_dirname, "enabled", 0);
			kill_percpu_threads(ncpus);
			while(1) {
				pthread_mutex_lock(&processing_mutex);
				if (!processing) {
					pthread_mutex_unlock(&processing_mutex);
					break;
				}
				pthread_mutex_unlock(&processing_mutex);
			}
			for (i = 0; i < ncpus; i++)
				check_buffer(i);
			summarize();
			close_control_files();
			close_app_files();
			control_write(app_dirname, "create", 0);
			exit(0);
		}
	}
}
Ejemplo n.º 22
0
isc_result_t
isc__app_ctxstart(isc_appctx_t *ctx0) {
	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
	isc_result_t result;
	int presult;
	sigset_t sset;
	char strbuf[ISC_STRERRORSIZE];

	REQUIRE(VALID_APPCTX(ctx));

	/*
	 * Start an ISC library application.
	 */

#ifdef NEED_PTHREAD_INIT
	/*
	 * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this.
	 */
	presult = pthread_init();
	if (presult != 0) {
		isc__strerror(presult, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_app_start() pthread_init: %s", strbuf);
		return (ISC_R_UNEXPECTED);
	}
#endif

#ifdef ISC_PLATFORM_USETHREADS
#ifdef HAVE_LINUXTHREADS
	main_thread = pthread_self();
#endif /* HAVE_LINUXTHREADS */

	result = isc_mutex_init(&ctx->readylock);
	if (result != ISC_R_SUCCESS)
		return (result);

	result = isc_condition_init(&ctx->ready);
	if (result != ISC_R_SUCCESS)
		goto cleanup_rlock;

	result = isc_mutex_init(&ctx->lock);
	if (result != ISC_R_SUCCESS)
		goto cleanup_rcond;
#else /* ISC_PLATFORM_USETHREADS */
	result = isc_mutex_init(&ctx->lock);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
#endif /* ISC_PLATFORM_USETHREADS */

	ISC_LIST_INIT(ctx->on_run);

	ctx->shutdown_requested = ISC_FALSE;
	ctx->running = ISC_FALSE;
	ctx->want_shutdown = ISC_FALSE;
	ctx->want_reload = ISC_FALSE;
	ctx->blocked = ISC_FALSE;

#ifndef HAVE_SIGWAIT
	/*
	 * Install do-nothing handlers for SIGINT and SIGTERM.
	 *
	 * We install them now because BSDI 3.1 won't block
	 * the default actions, regardless of what we do with
	 * pthread_sigmask().
	 */
	result = handle_signal(SIGINT, exit_action);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	result = handle_signal(SIGTERM, exit_action);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
#endif

	/*
	 * Always ignore SIGPIPE.
	 */
	result = handle_signal(SIGPIPE, SIG_IGN);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	/*
	 * On Solaris 2, delivery of a signal whose action is SIG_IGN
	 * will not cause sigwait() to return. We may have inherited
	 * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent
	 * process (e.g, Solaris cron).  Set an action of SIG_DFL to make
	 * sure sigwait() works as expected.  Only do this for SIGTERM and
	 * SIGINT if we don't have sigwait(), since a different handler is
	 * installed above.
	 */
	result = handle_signal(SIGHUP, SIG_DFL);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

#ifdef HAVE_SIGWAIT
	result = handle_signal(SIGTERM, SIG_DFL);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	result = handle_signal(SIGINT, SIG_DFL);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
#endif

#ifdef ISC_PLATFORM_USETHREADS
	/*
	 * Block SIGHUP, SIGINT, SIGTERM.
	 *
	 * If isc_app_start() is called from the main thread before any other
	 * threads have been created, then the pthread_sigmask() call below
	 * will result in all threads having SIGHUP, SIGINT and SIGTERM
	 * blocked by default, ensuring that only the thread that calls
	 * sigwait() for them will get those signals.
	 */
	if (sigemptyset(&sset) != 0 ||
	    sigaddset(&sset, SIGHUP) != 0 ||
	    sigaddset(&sset, SIGINT) != 0 ||
	    sigaddset(&sset, SIGTERM) != 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_app_start() sigsetops: %s", strbuf);
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}
	presult = pthread_sigmask(SIG_BLOCK, &sset, NULL);
	if (presult != 0) {
		isc__strerror(presult, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_app_start() pthread_sigmask: %s",
				 strbuf);
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}
#else /* ISC_PLATFORM_USETHREADS */
	/*
	 * Unblock SIGHUP, SIGINT, SIGTERM.
	 *
	 * If we're not using threads, we need to make sure that SIGHUP,
	 * SIGINT and SIGTERM are not inherited as blocked from the parent
	 * process.
	 */
	if (sigemptyset(&sset) != 0 ||
	    sigaddset(&sset, SIGHUP) != 0 ||
	    sigaddset(&sset, SIGINT) != 0 ||
	    sigaddset(&sset, SIGTERM) != 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_app_start() sigsetops: %s", strbuf);
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}
	presult = sigprocmask(SIG_UNBLOCK, &sset, NULL);
	if (presult != 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_app_start() sigprocmask: %s", strbuf);
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}
#endif /* ISC_PLATFORM_USETHREADS */

	return (ISC_R_SUCCESS);

 cleanup:
#ifdef ISC_PLATFORM_USETHREADS
 cleanup_rcond:
	(void)isc_condition_destroy(&ctx->ready);

 cleanup_rlock:
	(void)isc_mutex_destroy(&ctx->readylock);
#endif /* ISC_PLATFORM_USETHREADS */
	return (result);
}
Ejemplo n.º 23
0
void HttpServer::timeout_action()
{
	string json_str = "{\"OK\":1}";
	if (!m_server_checked) {	// start widget again in case it dead. browser not need to restart
		g_error_code = 1;
	} else if (!m_test_cases) {
		json_str = "{\"Error\":\"no case\"}";
	} else if (m_exeType != "auto") {	// skip to next set if widget crash when run manual cases
		if (g_run_wiget == true) {	// check whether widget is running
			DBG_ONLY("----do widget live checking");
			//-------------------------------------------------------------------------------------------------------------------------------------------
#if defined(__WIN32__) || defined(__WIN64__)
			string cmd =
				"tasklist | findstr xwalk.exe";
			if (!run_cmd_new(cmd, "xwalk.exe", NULL)) {
							m_set_finished = true;
							m_block_finished = true;
#else
			string cmd =
			    "ps ax | grep " + m_suite_id +
			    " | grep -v grep | awk '{print $NF}'";

			if (!run_cmd_new(cmd, m_suite_id, NULL)) {
				DBG_ONLY
				    ("----widget is not online, finish the set");
				m_set_finished = true;
				m_block_finished = true;
#endif
			} else {
				set_timer(60);	// continue to set timer for manual cases
			}
		}
	} else if (m_block_case_index < m_block_case_count) {
		g_error_code = 3;
		checkResult(&m_test_cases[m_block_case_index]);
		json_str = "{\"OK\":\"send timeout\"}";
	} else {
		json_str = "{\"Error\":\"case out of index\"}";
	}
	if (g_show_log)
		DBG_ONLY(json_str);
}

void HttpServer::print_info_string(int case_index)
{
	if (g_show_log) {
		DBG_ONLY(endl << "execute case: ");
		DBG_ONLY(m_suite_name << " # " <<
			 m_test_cases[case_index].case_id << " ..(" <<
			 m_test_cases[case_index].result << ")");

		if (m_test_cases[case_index].result != "PASS")	// print error message if case not pass
			DBG_ONLY(m_test_cases[case_index].std_out);
	}

	pthread_mutex_lock(&result_mutex);
	m_result.append(m_test_cases[case_index].result_to_json());
	if (m_exeType == "auto") {
		if (m_block_case_index < m_block_case_count) {
			m_block_case_index++;
			m_total_case_index++;
		}
	}
	pthread_mutex_unlock(&result_mutex);
}

// prepare to run current auto case by set the start time, etc.
bool HttpServer::get_auto_case(string content, string * type)
{
	if (!m_killing_widget) {
		if (content != "") {
			string value = content.substr(content.find("=") + 1);
			if (value.length() > 0) {
				if (m_running_session == value) {
					if (m_block_case_index <
					    m_block_case_count) {
						set_timer(m_test_cases[m_block_case_index].timeout_value + 10);	// +10 is to avoid dup result from suite if case timeout
						set_cl_timeout(m_test_cases
							       [m_block_case_index].
							       timeout_value +
							       10);
						m_test_cases
						    [m_block_case_index].
						    set_start_at();
						if (g_show_log)
							DBG_ONLY(endl <<
								 "start time: "
								 <<
								 m_test_cases
								 [m_block_case_index].
								 start_at);
						return true;
					} else {
						if (g_show_log)
							DBG_ONLY(endl <<
								 "[ no auto case is available any more ]");
						*type = "none";
						m_block_finished = true;
						if (m_current_block_index ==
						    m_totalBlocks)
							m_set_finished = true;	// the set is finished if current block is the last block
					}
				} else {
					if (g_show_log)
						DBG_ONLY
						    ("[ Error: invalid session ID ]");
					*type = "invalid";
				}
			}
		}
	} else {
		if (g_show_log)
			DBG_ONLY(endl <<
				 "[ restart client process is activated, exit current client ]");
		*type = "stop";
	}
	return false;
}

void *socket_thread(void *para)
{
#if defined(__WIN32__) || defined(__WIN64__)
#else
	sigset_t set;
	int s;

	/* Block SIGALRM; other threads created by main() will inherit
	   a copy of the signal mask. */

	sigemptyset(&set);
	sigaddset(&set, SIGALRM);
	s = pthread_sigmask(SIG_BLOCK, &set, NULL);
	if ((s != 0) && (g_show_log))
		DBG_ONLY("fail to pthread_sigmask !!!");
#endif

	struct sockaddr_in clientAddr;
	int addr_len = sizeof(clientAddr);

	while (httpserver.gIsRun) {
#if defined(__WIN32__) || defined(__WIN64__)
		int clientsocket =
		    accept(serversocket, (struct sockaddr *)&clientAddr,
			   (int *)&addr_len);
#else
		int clientsocket =
		    accept(serversocket, (struct sockaddr *)&clientAddr,
			   (socklen_t *) & addr_len);
#endif
		if (clientsocket < 0) {
			if (g_show_log)
				DBG_ONLY("fail to accept client socket !!!");
		} else {
			thread_info tinfo;
			tinfo.server = &httpserver;
			tinfo.clientsocket = clientsocket;
			if (g_show_log)
				DBG_ONLY("open " << clientsocket);
			pthread_create(&tinfo.thread_id, NULL, processthread,
				       &tinfo);
			//if (tinfo.thread_id != 0) pthread_detach(tinfo.thread_id);// this will release resource after threat exit. otherwise it may not execute the thread after run for a while. but still cause some strange issue
#if defined(__WIN32__) || defined(__WIN64__)
			if (tinfo.thread_id.p)
				pthread_join(tinfo.thread_id, NULL);
			else if (g_show_log)
				DBG_ONLY("fail to create thread !!!");
#else
			if (tinfo.thread_id != 0)
				pthread_join(tinfo.thread_id, NULL);
			else if (g_show_log)
				DBG_ONLY("fail to create thread !!!");
#endif
		}
	}
	close(serversocket);
	pthread_exit(NULL);
	return 0;
}
Ejemplo n.º 24
0
/**
 * Execute the given command. If the execution fails, the wait_start()
 * thread in control.c should notice this and send an alert message.
 * @param S A Service object
 * @param C A Command object
 * @param E An optional event object. May be NULL.
 */
void spawn(Service_T S, command_t C, Event_T E) {
        pid_t pid;
        sigset_t mask;
        sigset_t save;
        int stat_loc = 0;
        int exit_status;
        char date[42];

        ASSERT(S);
        ASSERT(C);

        if (access(C->arg[0], X_OK) != 0) {
                LogError("Error: Could not execute %s\n", C->arg[0]);
                return;
        }

        /*
         * Block SIGCHLD
         */
        sigemptyset(&mask);
        sigaddset(&mask, SIGCHLD);
        pthread_sigmask(SIG_BLOCK, &mask, &save);

        Time_string(Time_now(), date);
        pid = fork();
        if (pid < 0) {
                LogError("Cannot fork a new process -- %s\n", STRERROR);
                pthread_sigmask(SIG_SETMASK, &save, NULL);
                return;
        }

        if (pid == 0) {
                if (C->has_gid) {
                        if (setgid(C->gid) != 0) {
                                stat_loc |= setgid_ERROR;
                        }
                }
                if (C->has_uid) {
                        struct passwd *user = getpwuid(C->uid);
                        if (user) {
                                if (initgroups(user->pw_name, getgid()) == 0) {
                                        if (setuid(C->uid) != 0) {
                                                stat_loc |= setuid_ERROR;
                                        }
                                } else {
                                        stat_loc |= initgroups_ERROR;
                                }
                        } else {
                                stat_loc |= getpwuid_ERROR;
                        }
                }

                set_monit_environment(S, C, E, date);

                if (! (Run.flags & Run_Daemon)) {
                        for (int i = 0; i < 3; i++)
                                if (close(i) == -1 || open("/dev/null", O_RDWR) != i)
                                        stat_loc |= redirect_ERROR;
                }

                Util_closeFds();

                setsid();

                pid = fork();
                if (pid < 0) {
                        stat_loc |= fork_ERROR;
                        _exit(stat_loc);
                }

                if (pid == 0) {
                        /*
                         * Reset all signals, so the spawned process is *not* created
                         * with any inherited SIG_BLOCKs
                         */
                        sigemptyset(&mask);
                        pthread_sigmask(SIG_SETMASK, &mask, NULL);
                        signal(SIGINT, SIG_DFL);
                        signal(SIGHUP, SIG_DFL);
                        signal(SIGTERM, SIG_DFL);
                        signal(SIGUSR1, SIG_DFL);
                        signal(SIGPIPE, SIG_DFL);

                        (void) execv(C->arg[0], C->arg);
                        _exit(errno);
                }

                /* Exit first child and return errors to parent */
                _exit(stat_loc);
        }

        /* Wait for first child - aka second parent, to exit */
        if (waitpid(pid, &stat_loc, 0) != pid) {
                LogError("Waitpid error\n");
        }

        exit_status = WEXITSTATUS(stat_loc);
        if (exit_status & setgid_ERROR)
                LogError("Failed to change gid to '%d' for '%s'\n", C->gid, C->arg[0]);
        if (exit_status & setuid_ERROR)
                LogError("Failed to change uid to '%d' for '%s'\n", C->uid, C->arg[0]);
        if (exit_status & initgroups_ERROR)
                LogError("initgroups for UID %d failed when executing '%s'\n", C->uid, C->arg[0]);
        if (exit_status & fork_ERROR)
                LogError("Cannot fork a new process for '%s'\n", C->arg[0]);
        if (exit_status & redirect_ERROR)
                LogError("Cannot redirect IO to /dev/null for '%s'\n", C->arg[0]);
        if (exit_status & getpwuid_ERROR)
                LogError("UID %d not found on the system when executing '%s'\n", C->uid, C->arg[0]);

        /*
         * Restore the signal mask
         */
        pthread_sigmask(SIG_SETMASK, &save, NULL);

        /*
         * We do not need to wait for the second child since we forked twice,
         * the init system-process will wait for it. So we just return
         */

}
Ejemplo n.º 25
0
 SignalHandlers() {
   memset(signaled, 0, sizeof(signaled));
   pthread_sigmask(SIG_SETMASK, NULL, &oldSet);
 }
Ejemplo n.º 26
0
void * token_depositing_thread_function(void *args){
    pthread_sigmask(SIG_BLOCK, &set, 0);
    long local_token_created_count = 0;
    long local_token_dropped_count = 0;
    float local_total_packet_time_in_Q1 = 0.0;
    int stop_flag = 0;
    struct timeval current_time;
    
    while(1){
        
        
        /* Sleep for needed time */
        usleep(token_arrival_time * 1000000.0);
        
        /* Lock the mutex */
        pthread_mutex_lock(&mutex);
        
        if(cntrl_c_signal){
            stop_flag = 1;
        }
        else{
            local_token_created_count++;
            
            /* Increment token count */
            if(number_of_tokens_in_bucket < bucket_capacity){
                
                number_of_tokens_in_bucket++;
                
                gettimeofday(&current_time, NULL);
                printf("%012.3fms: token t%ld arrives, token bucket now has %ld tokens\n",calculate_time_difference(current_time,emulation_start_time),local_token_created_count,number_of_tokens_in_bucket);
            }
            else {
                
                local_token_dropped_count++;
                
                gettimeofday(&current_time, NULL);
                printf("%012.3fms: token t%ld arrives, dropped\n",calculate_time_difference(current_time,emulation_start_time),local_token_created_count);
            }
            
            if(!My402ListEmpty(&Q1)){
                My402ListElem * temp_arrival_thread_element = My402ListLast(&Q1);
                struct packet * temp_arrival_thread_packet = (struct packet *)(temp_arrival_thread_element->obj);
                
                /* Move the first packet to q2 if there are enough tokens */
                if(number_of_tokens_in_bucket >= temp_arrival_thread_packet->tokens_needed){
                    
                    int is_empty = My402ListEmpty(&Q2);
                    
                    number_of_tokens_in_bucket = number_of_tokens_in_bucket - temp_arrival_thread_packet->tokens_needed;
                    
                    My402ListUnlink(&Q1,temp_arrival_thread_element);
                    
                    gettimeofday(&current_time, NULL);
                    printf("%012.3fms: p%ld leaves Q1, time in Q1 = %.3fms, token bucket now has %ld token\n",calculate_time_difference(current_time,emulation_start_time),temp_arrival_thread_packet->id,calculate_time_difference(current_time, temp_arrival_thread_packet->updation_time),number_of_tokens_in_bucket);
                    
                    local_total_packet_time_in_Q1 = local_total_packet_time_in_Q1 + calculate_time_difference(current_time, temp_arrival_thread_packet->updation_time);
                    
                    gettimeofday(&temp_arrival_thread_packet->updation_time, NULL);
                    My402ListPrepend(&Q2, temp_arrival_thread_packet);
                    
                    gettimeofday(&current_time, NULL);
                    printf("%012.3fms: p%ld enters Q2\n",calculate_time_difference(current_time,emulation_start_time),temp_arrival_thread_packet->id);
                    
                    if(is_empty){
                        pthread_cond_broadcast(&condition_variable);
                    }
                    
                }
                temp_arrival_thread_element = NULL;
                temp_arrival_thread_packet = NULL;
            }
            else {
                if(packet_arrival_thread_stop){
                    stop_flag = 1;
                }
            }
            if(server_thread_stop){
                stop_flag = 1;
            }
        }
        /* Unloack the mutex */
        pthread_mutex_unlock(&mutex);
        if(stop_flag){
            pthread_mutex_lock(&mutex);
            
            if(local_total_packet_time_in_Q1 != 0.0){
                if(average_number_of_packets_in_Q1 == -1.0){
                    average_number_of_packets_in_Q1 = 0.0;
                }
                average_number_of_packets_in_Q1 = average_number_of_packets_in_Q1 + local_total_packet_time_in_Q1;
            }
            average_number_of_packets_in_Q1 = average_number_of_packets_in_Q1 + local_total_packet_time_in_Q1;
            if(local_token_created_count !=0){
                token_drop_probability = (float)local_token_dropped_count / (float)local_token_created_count;
            }
            if(packet_arrival_thread_stop && !server_thread_stop){
                pthread_cond_broadcast(&condition_variable);
            }
            pthread_mutex_unlock(&mutex);
            break;
        }
    }
    pthread_exit(0);
    return NULL;
}
Ejemplo n.º 27
0
void *clamukofsth(void *arg)
{
	struct thrarg *tharg = (struct thrarg *) arg;
	sigset_t sigset;
        struct sigaction act;
	pthread_t *clamuko_pids = NULL;
	const char *groupname = "ClamAV";
	int count;
	int started;

    /* is another server thread already working? */
    if(pthread_mutex_trylock(&running_mutex))
	return NULL;

    /* ignore all signals except SIGUSR1 */
    sigfillset(&sigset);
    sigdelset(&sigset, SIGUSR1);
    /* The behavior of a process is undefined after it ignores a
     * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
    sigdelset(&sigset, SIGFPE);
    sigdelset(&sigset, SIGILL);
    sigdelset(&sigset, SIGSEGV);
#ifdef SIGBUS
    sigdelset(&sigset, SIGBUS);
#endif
    pthread_sigmask(SIG_SETMASK, &sigset, NULL);

    count = optget(tharg->opts, "ClamukoScannerCount")->numarg;
    if(count < 1) goto out;

    clamuko_pids = calloc(count, sizeof(pthread_t));
    if(!clamuko_pids) goto out;

    if(setup_shutdown_handle(groupname)) goto out;

    act.sa_handler = clamuko_exit;
    sigfillset(&(act.sa_mask));
    sigaction(SIGUSR1, &act, NULL);
    sigaction(SIGSEGV, &act, NULL);

    for(started = 0; started < count; started++) {
	pthread_attr_t clamuko_attr;

	if(pthread_attr_init(&clamuko_attr)) break;
	pthread_attr_setdetachstate(&clamuko_attr, PTHREAD_CREATE_JOINABLE);
	if(pthread_create(&clamuko_pids[started], &clamuko_attr,
			  clamuko_scanth, tharg)) break;
	logg("Clamuko: Started scanner thread %d.\n", started);
    }

    pthread_cond_wait(&shutdown_cond, &running_mutex);
    logg("Clamuko: Stop signal received.\n");

    shutdown_clamuko();

    for(started-- ; started >= 0; started--) {
	logg("Clamuko: Waiting for scanner thread %d to finish.\n", started);
	pthread_join(clamuko_pids[started], NULL);
    }

    logg("Clamuko: Stopped.\n");
out:
    if(clamuko_pids) free(clamuko_pids);
    pthread_mutex_unlock(&running_mutex);
    return NULL;
}
Ejemplo n.º 28
0
}

DirectResult
direct_socketpair( int __domain, int __type, int __protocol, int __fds[2] )
{
     if (socketpair( __domain, __type, __protocol, __fds ))
          return errno2result( errno );

     return DR_OK;
}

DirectResult
direct_sigprocmask( int __how, __const sigset_t *__restrict __set,
                    sigset_t *__restrict __oset )
{
     int ret = pthread_sigmask( __how, __set, __oset );

     return errno2result( ret );
}

uid_t
direct_getuid()
{
     return getuid();
}

uid_t
direct_geteuid()
{
     return geteuid();
}
Ejemplo n.º 29
0
int main (int argc, char **argv)
{
	starter_config_t *cfg = NULL;
	starter_config_t *new_cfg;
	starter_conn_t *conn, *conn2;
	starter_ca_t *ca, *ca2;

	struct sigaction action;
	struct stat stb;

	int i;
	int id = 1;
	struct timespec ts;
	unsigned long auto_update = 0;
	time_t last_reload;
	bool no_fork = FALSE;
	bool attach_gdb = FALSE;
	bool load_warning = FALSE;

	library_init(NULL);
	atexit(library_deinit);

	libhydra_init("starter");
	atexit(libhydra_deinit);

	/* parse command line */
	for (i = 1; i < argc; i++)
	{
		if (streq(argv[i], "--debug"))
		{
			current_loglevel = 2;
		}
		else if (streq(argv[i], "--debug-more"))
		{
			current_loglevel = 3;
		}
		else if (streq(argv[i], "--debug-all"))
		{
			current_loglevel = 4;
		}
		else if (streq(argv[i], "--nolog"))
		{
			current_loglevel = 0;
		}
		else if (streq(argv[i], "--nofork"))
		{
			no_fork = TRUE;
		}
		else if (streq(argv[i], "--attach-gdb"))
		{
			no_fork = TRUE;
			attach_gdb = TRUE;
		}
		else if (streq(argv[i], "--auto-update") && i+1 < argc)
		{
			auto_update = atoi(argv[++i]);
			if (!auto_update)
				usage(argv[0]);
		}
		else if (streq(argv[i], "--daemon") && i+1 < argc)
		{
			daemon_name = argv[++i];
		}
		else
		{
			usage(argv[0]);
		}
	}

	if (!set_daemon_name())
	{
		DBG1(DBG_APP, "unable to set daemon name");
		exit(LSB_RC_FAILURE);
	}

	init_log("ipsec_starter");

	DBG1(DBG_APP, "Starting %sSwan "VERSION" IPsec [starter]...",
		lib->settings->get_bool(lib->settings,
			"charon.i_dont_care_about_security_and_use_aggressive_mode_psk",
				FALSE) ? "weak" : "strong");

#ifdef LOAD_WARNING
	load_warning = TRUE;
#endif

	if (lib->settings->get_bool(lib->settings, "starter.load_warning", load_warning))
	{
		if (lib->settings->get_str(lib->settings, "charon.load", NULL))
		{
			DBG1(DBG_APP, "!! Your strongswan.conf contains manual plugin load options for charon.");
			DBG1(DBG_APP, "!! This is recommended for experts only, see");
			DBG1(DBG_APP, "!! http://wiki.strongswan.org/projects/strongswan/wiki/PluginLoad");
		}
	}

	/* verify that we can start */
	if (getuid() != 0)
	{
		DBG1(DBG_APP, "permission denied (must be superuser)");
		cleanup();
		exit(LSB_RC_NOT_ALLOWED);
	}

	if (check_pid(pid_file))
	{
		DBG1(DBG_APP, "%s is already running (%s exists) -- skipping daemon start",
			 daemon_name, pid_file);
	}
	else
	{
		_action_ |= FLAG_ACTION_START_CHARON;
	}
	if (stat(DEV_RANDOM, &stb) != 0)
	{
		DBG1(DBG_APP, "unable to start strongSwan IPsec -- no %s!", DEV_RANDOM);
		cleanup();
		exit(LSB_RC_FAILURE);
	}

	if (stat(DEV_URANDOM, &stb)!= 0)
	{
		DBG1(DBG_APP, "unable to start strongSwan IPsec -- no %s!", DEV_URANDOM);
		cleanup();
		exit(LSB_RC_FAILURE);
	}

	cfg = confread_load(CONFIG_FILE);
	if (cfg == NULL || cfg->err > 0)
	{
		DBG1(DBG_APP, "unable to start strongSwan -- fatal errors in config");
		if (cfg)
		{
			confread_free(cfg);
		}
		cleanup();
		exit(LSB_RC_INVALID_ARGUMENT);
	}

	/* determine if we have a native netkey IPsec stack */
	if (!starter_netkey_init())
	{
		DBG1(DBG_APP, "no netkey IPsec stack detected");
		if (!starter_klips_init())
		{
			DBG1(DBG_APP, "no KLIPS IPsec stack detected");
			DBG1(DBG_APP, "no known IPsec stack detected, ignoring!");
		}
	}

	last_reload = time_monotonic(NULL);

	if (check_pid(starter_pid_file))
	{
		DBG1(DBG_APP, "starter is already running (%s exists) -- no fork done",
			 starter_pid_file);
		confread_free(cfg);
		cleanup();
		exit(LSB_RC_SUCCESS);
	}

#ifdef GENERATE_SELFCERT
	generate_selfcert();
#endif

	/* fork if we're not debugging stuff */
	if (!no_fork)
	{
		log_to_stderr = FALSE;

		switch (fork())
		{
			case 0:
			{
				int fnull;

				close_log();
				closefrom(3);

				fnull = open("/dev/null", O_RDWR);
				if (fnull >= 0)
				{
					dup2(fnull, STDIN_FILENO);
					dup2(fnull, STDOUT_FILENO);
					dup2(fnull, STDERR_FILENO);
					close(fnull);
				}

				setsid();
				init_log("ipsec_starter");
			}
			break;
			case -1:
				DBG1(DBG_APP, "can't fork: %s", strerror(errno));
				break;
			default:
				confread_free(cfg);
				cleanup();
				exit(LSB_RC_SUCCESS);
		}
	}

	/* save pid file in /var/run/starter[.daemon_name].pid */
	{
		FILE *fd = fopen(starter_pid_file, "w");

		if (fd)
		{
			fprintf(fd, "%u\n", getpid());
			fclose(fd);
		}
	}

	/* we handle these signals only in pselect() */
	memset(&action, 0, sizeof(action));
	sigemptyset(&action.sa_mask);
	sigaddset(&action.sa_mask, SIGHUP);
	sigaddset(&action.sa_mask, SIGINT);
	sigaddset(&action.sa_mask, SIGTERM);
	sigaddset(&action.sa_mask, SIGQUIT);
	sigaddset(&action.sa_mask, SIGALRM);
	sigaddset(&action.sa_mask, SIGUSR1);
	pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);

	/* install a handler for fatal signals */
	action.sa_handler = fatal_signal_handler;
	sigaction(SIGSEGV, &action, NULL);
	sigaction(SIGILL, &action, NULL);
	sigaction(SIGBUS, &action, NULL);
	action.sa_handler = SIG_IGN;
	sigaction(SIGPIPE, &action, NULL);

	/* install main signal handler */
	action.sa_handler = signal_handler;
	sigaction(SIGHUP, &action, NULL);
	sigaction(SIGINT, &action, NULL);
	sigaction(SIGTERM, &action, NULL);
	sigaction(SIGQUIT, &action, NULL);
	sigaction(SIGALRM, &action, NULL);
	sigaction(SIGUSR1, &action, NULL);
	/* this is not blocked above as we want to receive it asynchronously */
	sigaction(SIGCHLD, &action, NULL);

	/* empty mask for pselect() call below */
	sigemptyset(&action.sa_mask);

	for (;;)
	{
		/*
		 * Stop charon (if started) and exit
		 */
		if (_action_ & FLAG_ACTION_QUIT)
		{
			if (starter_charon_pid())
			{
				starter_stop_charon();
			}
			starter_netkey_cleanup();
			confread_free(cfg);
			unlink(starter_pid_file);
			cleanup();
			DBG1(DBG_APP, "ipsec starter stopped");
			close_log();
			exit(LSB_RC_SUCCESS);
		}

		/*
		 * Delete all connections. Will be added below
		 */
		if (_action_ & FLAG_ACTION_RELOAD)
		{
			if (starter_charon_pid())
			{
				for (conn = cfg->conn_first; conn; conn = conn->next)
				{
					if (conn->state == STATE_ADDED)
					{
						if (starter_charon_pid())
						{
							if (conn->startup == STARTUP_ROUTE)
							{
								starter_stroke_unroute_conn(conn);
							}
							starter_stroke_del_conn(conn);
						}
						conn->state = STATE_TO_ADD;
					}
				}
				for (ca = cfg->ca_first; ca; ca = ca->next)
				{
					if (ca->state == STATE_ADDED)
					{
						if (starter_charon_pid())
						{
							starter_stroke_del_ca(ca);
						}
						ca->state = STATE_TO_ADD;
					}
				}
			}
			_action_ &= ~FLAG_ACTION_RELOAD;
		}

		/*
		 * Update configuration
		 */
		if (_action_ & FLAG_ACTION_UPDATE)
		{
			DBG2(DBG_APP, "Reloading config...");
			new_cfg = confread_load(CONFIG_FILE);

			if (new_cfg && (new_cfg->err == 0))
			{
				/* Switch to new config. New conn will be loaded below */

				/* Look for new connections that are already loaded */
				for (conn = cfg->conn_first; conn; conn = conn->next)
				{
					if (conn->state == STATE_ADDED)
					{
						for (conn2 = new_cfg->conn_first; conn2; conn2 = conn2->next)
						{
							if (conn2->state == STATE_TO_ADD && starter_cmp_conn(conn, conn2))
							{
								conn->state = STATE_REPLACED;
								conn2->state = STATE_ADDED;
								conn2->id = conn->id;
								break;
							}
						}
					}
				}

				/* Remove conn sections that have become unused */
				for (conn = cfg->conn_first; conn; conn = conn->next)
				{
					if (conn->state == STATE_ADDED)
					{
						if (starter_charon_pid())
						{
							if (conn->startup == STARTUP_ROUTE)
							{
								starter_stroke_unroute_conn(conn);
							}
							starter_stroke_del_conn(conn);
						}
					}
				}

				/* Look for new ca sections that are already loaded */
				for (ca = cfg->ca_first; ca; ca = ca->next)
				{
					if (ca->state == STATE_ADDED)
					{
						for (ca2 = new_cfg->ca_first; ca2; ca2 = ca2->next)
						{
							if (ca2->state == STATE_TO_ADD && starter_cmp_ca(ca, ca2))
							{
								ca->state = STATE_REPLACED;
								ca2->state = STATE_ADDED;
								break;
							}
						}
					}
				}

				/* Remove ca sections that have become unused */
				for (ca = cfg->ca_first; ca; ca = ca->next)
				{
					if (ca->state == STATE_ADDED)
					{
						if (starter_charon_pid())
						{
							starter_stroke_del_ca(ca);
						}
					}
				}
				confread_free(cfg);
				cfg = new_cfg;
			}
			else
			{
				DBG1(DBG_APP, "can't reload config file due to errors -- keeping old one");
				if (new_cfg)
				{
					confread_free(new_cfg);
				}
			}
			_action_ &= ~FLAG_ACTION_UPDATE;
			last_reload = time_monotonic(NULL);
		}

		/*
		 * Start daemon
		 */
		if (_action_ & FLAG_ACTION_START_CHARON)
		{
			if (cfg->setup.charonstart && !starter_charon_pid())
			{
				DBG2(DBG_APP, "Attempting to start %s...", daemon_name);
				if (starter_start_charon(cfg, no_fork, attach_gdb))
				{
					/* schedule next try */
					alarm(CHARON_RESTART_DELAY);
				}
				starter_stroke_configure(cfg);
			}
			_action_ &= ~FLAG_ACTION_START_CHARON;

			for (ca = cfg->ca_first; ca; ca = ca->next)
			{
				if (ca->state == STATE_ADDED)
				{
					ca->state = STATE_TO_ADD;
				}
			}

			for (conn = cfg->conn_first; conn; conn = conn->next)
			{
				if (conn->state == STATE_ADDED)
				{
					conn->state = STATE_TO_ADD;
				}
			}
		}

		/*
		 * Add stale conn and ca sections
		 */
		if (starter_charon_pid())
		{
			for (ca = cfg->ca_first; ca; ca = ca->next)
			{
				if (ca->state == STATE_TO_ADD)
				{
					if (starter_charon_pid())
					{
						starter_stroke_add_ca(ca);
					}
					ca->state = STATE_ADDED;
				}
			}

			for (conn = cfg->conn_first; conn; conn = conn->next)
			{
				if (conn->state == STATE_TO_ADD)
				{
					if (conn->id == 0)
					{
						/* affect new unique id */
						conn->id = id++;
					}
					if (starter_charon_pid())
					{
						starter_stroke_add_conn(cfg, conn);
					}
					conn->state = STATE_ADDED;

					if (conn->startup == STARTUP_START)
					{
						if (starter_charon_pid())
						{
							starter_stroke_initiate_conn(conn);
						}
					}
					else if (conn->startup == STARTUP_ROUTE)
					{
						if (starter_charon_pid())
						{
							starter_stroke_route_conn(conn);
						}
					}
				}
			}
		}

		/*
		 * If auto_update activated, when to stop select
		 */
		if (auto_update)
		{
			time_t now = time_monotonic(NULL);

			ts.tv_sec = (now < last_reload + auto_update) ?
						(last_reload + auto_update - now) : 0;
			ts.tv_nsec = 0;
		}

		/*
		 * Wait for something to happen
		 */
		if (!_action_ &&
			pselect(0, NULL, NULL, NULL, auto_update ? &ts : NULL,
					&action.sa_mask) == 0)
		{
			/* timeout -> auto_update */
			_action_ |= FLAG_ACTION_UPDATE;
		}
	}
	exit(LSB_RC_SUCCESS);
}
Ejemplo n.º 30
0
BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
		LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
		LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment,
		LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
{
	pid_t pid;
	int flags;
	int numArgs;
	LPSTR* pArgs = NULL;
	char** envp = NULL;
	char* filename = NULL;
	HANDLE thread;
	HANDLE process;
	WINPR_ACCESS_TOKEN* token;
	LPTCH lpszEnvironmentBlock;
	BOOL ret = FALSE;
	sigset_t oldSigMask;
	sigset_t newSigMask;
	BOOL restoreSigMask = FALSE;

	pid = 0;
	numArgs = 0;
	lpszEnvironmentBlock = NULL;

	pArgs = CommandLineToArgvA(lpCommandLine, &numArgs);
	if (!pArgs)
		return FALSE;

	flags = 0;

	token = (WINPR_ACCESS_TOKEN*) hToken;

	if (lpEnvironment)
	{
		envp = EnvironmentBlockToEnvpA(lpEnvironment);
	}
	else
	{
		lpszEnvironmentBlock = GetEnvironmentStrings();
		if (!lpszEnvironmentBlock)
			goto finish;
		envp = EnvironmentBlockToEnvpA(lpszEnvironmentBlock);
	}
	if (!envp)
		goto finish;

	filename = FindApplicationPath(pArgs[0]);
	if (NULL == filename)
		goto finish;

	/* block all signals so that the child can safely reset the caller's handlers */
	sigfillset(&newSigMask);
	restoreSigMask = !pthread_sigmask(SIG_SETMASK, &newSigMask, &oldSigMask);

	/* fork and exec */

	pid = fork();

	if (pid < 0)
	{
		/* fork failure */
		goto finish;
	}

	if (pid == 0)
	{
		/* child process */
#ifndef __sun
		int maxfd;
#endif
		int fd;
		int sig;
		sigset_t set;
		struct sigaction act;

		/* set default signal handlers */
		memset(&act, 0, sizeof(act));
		act.sa_handler = SIG_DFL;
		act.sa_flags = 0;
		sigemptyset(&act.sa_mask);
		for (sig = 1; sig < NSIG; sig++)
			sigaction(sig, &act, NULL);
		/* unblock all signals */
		sigfillset(&set);
		pthread_sigmask(SIG_UNBLOCK, &set, NULL);

		if (lpStartupInfo)
		{
			int handle_fd;

			handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdOutput);
			if (handle_fd != -1)
				dup2(handle_fd, STDOUT_FILENO);

			handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdError);
			if (handle_fd != -1)
				dup2(handle_fd, STDERR_FILENO);

			handle_fd = winpr_Handle_getFd(lpStartupInfo->hStdInput);
			if (handle_fd != -1)
				dup2(handle_fd, STDIN_FILENO);
		}


#ifdef __sun
		closefrom(3);
#else
#ifdef F_MAXFD // on some BSD derivates
		maxfd = fcntl(0, F_MAXFD);
#else
		maxfd = sysconf(_SC_OPEN_MAX);
#endif
		for(fd=3; fd<maxfd; fd++)
			close(fd);
#endif // __sun

		if (token)
		{
			if (token->GroupId)
			{
				int rc = setgid((gid_t) token->GroupId);
				if (rc < 0)
				{
				}
				else
				{
					initgroups(token->Username, (gid_t) token->GroupId);
				}
			}

			if (token->UserId)
				setuid((uid_t) token->UserId);

		}

		/* TODO: add better cwd handling and error checking */
		if (lpCurrentDirectory && strlen(lpCurrentDirectory) > 0)
			chdir(lpCurrentDirectory);

		if (execve(filename, pArgs, envp) < 0)
		{
			/* execve failed - end the process */
			_exit(1);
		}
	}
	else
	{
		/* parent process */
	}

	process = CreateProcessHandle(pid);

	if (!process)
	{
		goto finish;
	}

	thread = CreateNoneHandle();

	if (!thread)
	{
		ProcessHandleCloseHandle(process);
		goto finish;
	}

	lpProcessInformation->hProcess = process;
	lpProcessInformation->hThread = thread;
	lpProcessInformation->dwProcessId = (DWORD) pid;
	lpProcessInformation->dwThreadId = (DWORD) pid;

	ret = TRUE;

finish:

	/* restore caller's original signal mask */
	if (restoreSigMask)
		pthread_sigmask(SIG_SETMASK, &oldSigMask, NULL);


	free(filename);

	if (pArgs)
	{
		HeapFree(GetProcessHeap(), 0, pArgs);
	}

	if (lpszEnvironmentBlock)
		FreeEnvironmentStrings(lpszEnvironmentBlock);

	if (envp)
	{
		int i = 0;

		while (envp[i])
		{
			free(envp[i]);
			i++;
		}

		free(envp);
	}

	return ret;
}