Exemple #1
0
/* usage: ModulePath path */
MODRET set_modulepath(cmd_rec *cmd) {
  int res;
  struct stat st;

  CHECK_ARGS(cmd, 1);
  CHECK_CONF(cmd, CONF_ROOT);

  if (pr_fs_valid_path(cmd->argv[1]) < 0)
    CONF_ERROR(cmd, "must be an absolute path");

  /* Make sure that the configured path is not world-writeable. */
  res = pr_fsio_stat(cmd->argv[1], &st);
  if (res < 0)
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error checking '",
      cmd->argv[1], "': ", strerror(errno), NULL)); 

  if (!S_ISDIR(st.st_mode))
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, cmd->argv[1], " is not a directory",
      NULL));

  if (st.st_mode & S_IWOTH)
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, cmd->argv[1], " is world-writable",
      NULL));

  if (lt_dlsetsearchpath(cmd->argv[1]) < 0)
    CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error setting module path: ",
      lt_dlerror(), NULL));

  dso_module_path = pstrdup(dso_pool, cmd->argv[1]);
  return PR_HANDLED(cmd);
}
void
DynamicLoaderModule::init( SLIInterpreter* i )
{

  // bind functions to terminal names
  i->createcommand( "Install", &loadmodule_function );

  // initialize ltdl library for loading dynamic modules

  int dl_error = lt_dlinit();

  if ( !dl_error )
  {
    const char* path = getenv( "SLI_MODULE_PATH" );
    if ( path != NULL )
    {
      i->message( SLIInterpreter::M_INFO, "DynamicLoaderModule::init", "Setting module path to" );
      i->message( SLIInterpreter::M_INFO, "DynamicLoaderModule::init", path );

      dl_error = lt_dlsetsearchpath( path );
      if ( dl_error )
        i->message( SLIInterpreter::M_ERROR,
          "DynamicLoaderModule::init",
          "Could not set dynamic module path." );
    }
  }
  else
  {
    i->message( SLIInterpreter::M_ERROR,
      "DynamicLoaderModule::init",
      "Could not initialize libltdl. No dynamic modules will be avaiable." );
  }
}
Exemple #3
0
/**
 * oh_init_ltdl
 *
 * Does all the initialization needed for the ltdl process to
 * work. It takes no arguments, and returns 0 on success, < 0 on error
 *
 * Returns: 0 on Success.
 **/
static int oh_init_ltdl(void)
{
    struct oh_global_param path_param = { .type = OPENHPI_PATH };
    int err;
    static int init_done = 0;

    data_access_lock();
    if (init_done) {
        data_access_unlock();
        return 0;
    }

    err = lt_dlinit();
    if (err != 0) {
        dbg("Can not init ltdl");
        data_access_unlock();
        return -1;
    }

    oh_get_global_param(&path_param);

    err = lt_dlsetsearchpath(path_param.u.path);
    if (err != 0) {
        dbg("Can not set lt_dl search path");
        oh_exit_ltdl();
        data_access_unlock();
        return -1;
    }

    init_done = 1;
    data_access_unlock();

    return 0;
}
Exemple #4
0
int init_module_loading()
{
	int ret;
	static int initialised=0;
	
	if (initialised){
		LOG(L_CRIT, "BUG: init_module_loading: already intialised\n");
		return -1;
	}
	/* make sure preloaded modules are initialised */
	/*LTDL_SET_PRELOADED_SYMBOLS();*/
	ret=lt_dlinit();
	
	if (ret){
		LOG(L_CRIT, "ERROR: init_module_loading: lt_dlinit failed: %s\n",
				lt_dlerror());
		goto error;
	}
	
	ret=lt_dlsetsearchpath(MODULE_SEARCH_PATH);
	if (ret){
		LOG(L_CRIT, "ERROR: init_module_loading: lt_dlsetsearchpath "
					"failed: %s\n",
				lt_dlerror());
		goto error;
	}
	initialised++;
	return ret;
error:
	lt_dlexit();
	return -1;
}
Exemple #5
0
/**
 * librdf_new_world:
 *
 * Create a new Redland execution environment.
 *
 * Once this constructor is called to build a #librdf_world object
 * several functions may be called to set some parameters such as
 * librdf_world_set_error(), librdf_world_set_warning(),
 * librdf_world_set_logger(), librdf_world_set_digest(),
 * librdf_world_set_feature().
 *
 * The world object needs initializing using librdf_world_open()
 * whether or not the above functions are called.  It will be
 * automatically called by all object constructors in Redland 1.0.6
 * or later, but for earlier versions it MUST be called before using
 * any other part of Redland.
 *
 * Returns: a new #librdf_world or NULL on failure
 */
librdf_world*
librdf_new_world(void)
{
  librdf_world *world;
#ifdef HAVE_GETTIMEOFDAY
  struct timeval tv;
  struct timezone tz;
#endif

  world = (librdf_world*)LIBRDF_CALLOC(librdf_world, sizeof(*world), 1);

  if(!world)
    return NULL;

#ifdef HAVE_GETTIMEOFDAY
  if(!gettimeofday(&tv, &tz)) {
    world->genid_base = tv.tv_sec;
  } else
    world->genid_base = 1;
#else
  world->genid_base = 1;
#endif
  world->genid_counter = 1;
  
#ifdef MODULAR_LIBRDF
  world->ltdl_opened = !(lt_dlinit());
  if (world->ltdl_opened)
    lt_dlsetsearchpath(REDLAND_MODULE_PATH);
  else
    LIBRDF_DEBUG1("lt_dlinit() failed\n");
#endif

  return world;
  
}
/*
 * Read the directory and load all .so files
 */
vector<AbstractPlugin*> DlOpenPluginLoader::LoadPlugins() {
  AbstractPlugin *plugin = NULL;
  set<string>::iterator iter;
  set<string> plugin_names = FindPlugins(m_dirname);
  vector<AbstractPlugin*> plugins;

  if (!m_dl_active) {
    if (lt_dlinit()) {
      OLA_WARN << "lt_dlinit failed";
      return plugins;
    }
  }

  if (lt_dlsetsearchpath(m_dirname.c_str())) {
    OLA_WARN << "lt_setpath failed";
    lt_dlexit();
    return plugins;
  }
  m_dl_active = true;

  for (iter = plugin_names.begin(); iter != plugin_names.end(); ++iter) {
    string path = m_dirname;
    path.append("/");
    path.append(*iter);

    if ((plugin = this->LoadPlugin(path)))
      plugins.push_back(plugin);
    else
      OLA_WARN << "Failed to load plugin: " << path;
  }
  return plugins;
}
Exemple #7
0
int
radiusd_set_load_path(const char *path)
{
	if (lt_dlinit())
		return 1;
	return lt_dlsetsearchpath(path);
}
Exemple #8
0
Extension::Extension(const std::string& dir)
{
//    GNASH_REPORT_FUNCTION;
    _pluginsdir = dir;

#ifdef HAVE_LTDL
    lt_dlsetsearchpath(_pluginsdir.c_str());
#endif
}
Exemple #9
0
int module_path(const char *path)
{
#ifdef HAVE_EBCDIC
	strcpy(ebuf, path);
	__atoe(ebuf);
	path = ebuf;
#endif
	return lt_dlsetsearchpath( path );
}
Exemple #10
0
static int dso_init(void) {
#ifdef PR_USE_CTRLS
  register unsigned int i = 0;
#endif /* PR_USE_CTRLS */

  /* Allocate the pool for this module's use. */
  dso_pool = make_sub_pool(permanent_pool);
  pr_pool_tag(dso_pool, MOD_DSO_VERSION);

  lt_dlpreload_default(lt_preloaded_symbols);

  /* Initialize libltdl. */
  if (lt_dlinit() < 0) {
    pr_log_pri(PR_LOG_ERR, MOD_DSO_VERSION ": error initializing libltdl: %s",
      lt_dlerror());
    return -1;
  }

  /* Explicitly set the search path used for opening modules. */
  if (lt_dlsetsearchpath(dso_module_path) < 0) {
    pr_log_pri(PR_LOG_ERR, MOD_DSO_VERSION ": error setting module path: %s",
      lt_dlerror());
    return -1;
  }

#ifdef PR_USE_CTRLS
  /* Register ctrls handlers. */
  for (i = 0; dso_acttab[i].act_action; i++) {
    pool *sub_pool = make_sub_pool(dso_pool);

    /* Allocate and initialize the ACL for this control. */
    dso_acttab[i].act_acl = pcalloc(sub_pool, sizeof(ctrls_acl_t));
    dso_acttab[i].act_acl->acl_pool = sub_pool;
    pr_ctrls_init_acl(dso_acttab[i].act_acl);

    if (pr_ctrls_register(&dso_module, dso_acttab[i].act_action,
        dso_acttab[i].act_desc, dso_acttab[i].act_cb) < 0)
      pr_log_pri(PR_LOG_INFO, MOD_DSO_VERSION
        ": error registering '%s' control: %s", dso_acttab[i].act_action,
        strerror(errno));
  }
#endif /* PR_USE_CTRLS */

  /* Ideally, we'd call register a listener for the 'core.exit' event
   * and call lt_dlexit() there, politely freeing up any resources allocated
   * by the ltdl library.  However, it's possible that other modules, later in
   * the dispatch cycles, may need to use pointers to memory in shared modules
   * that would become invalid by such finalization.  So we skip it, for now.
   *
   * If there was a way to schedule this handler, to happen after all other
   * exit handlers, that'd be best.
   */
  pr_event_register(&dso_module, "core.restart", dso_restart_ev, NULL);

  return 0;
}
Exemple #11
0
/* This function will parse a tconfig "module" block, and attempt
 * to load the module
 */
struct tmodule *tmodule_from_tconfig(struct tconfig_block *tcfg, struct tconfig_block *global_cfg)
{
	lt_dlhandle ltmodule   = NULL;
	struct tmodule *module = NULL;
	int (*tmodule_load)(struct tconfig_block *, struct tconfig_block *);

	if (strcmp(tcfg->key, "module"))
		return NULL;

	/* Search modules directory */
	lt_dlsetsearchpath("modules");

	ltmodule = lt_dlopenext(tcfg->value);

	if (ltmodule == NULL)
	{
		troll_debug(LOG_WARN, "Could not open module \"%s\" (Reason: %s)", tcfg->value, lt_dlerror());
		return NULL;
	}

	troll_debug(LOG_DEBUG, "Loaded module \"%s\"", tcfg->value);

	if ((tmodule_load = lt_dlsym(ltmodule, "tmodule_load")) == NULL)
	{
		troll_debug(LOG_WARN, "Could not find symbol tmodule_load in  module \"%s\"", tcfg->value);
		lt_dlclose(ltmodule);
	} 
	else
	{
		/* We praise our magnificient overlords */
		if (!(*tmodule_load)(tcfg->child, global_cfg))
		{
			troll_debug(LOG_WARN, "Init function for module \"%s\" failed", tcfg->value);
			lt_dlclose(ltmodule);
			return NULL;
		}
	}

	module = tmalloc(sizeof(struct tmodule));

	module->name                    = tstrdup(tcfg->value);
	module->handle                  = ltmodule;

	/* Loading mechanism */
	module->tmodule_load            = lt_dlsym(ltmodule, "tmodule_load"); 
	module->tmodule_unload          = lt_dlsym(ltmodule, "tmodule_unload");

	/* Socket system */
	module->tmodule_get_tsockets    = lt_dlsym(ltmodule, "tmodule_get_tsockets");

	/* Messaging system */
	module->tmodule_get_messages    = lt_dlsym(ltmodule, "tmodule_get_messages");
	module->tmodule_handle_messages = lt_dlsym(ltmodule, "tmodule_handle_messages");

	return module;
}
Exemple #12
0
bool
Extension::scanAndLoad(const std::string& dir, as_object &obj)
{
//    GNASH_REPORT_FUNCTION;
    
    lt_dlsetsearchpath(_pluginsdir.c_str());
    _pluginsdir = dir;
    
    return scanAndLoad(obj);
}
Exemple #13
0
Extension::Extension(const std::string& dir)
{
//    GNASH_REPORT_FUNCTION;
#ifdef LT_DLMUTEX
//     return lt_dlmutex_register (gnash_mutex_lock, gnash_mutex_unlock,
//                                 gnash_mutex_seterror, gnash_mutex_geterror);
#endif
    _pluginsdir = dir;
    lt_dlsetsearchpath(_pluginsdir.c_str());
}
Exemple #14
0
    /**
        Initializes the dynamic module facility.
        Applications that use this library must call this function
        prior to any operation involved with the facility.
        @return true on error, false otherwise.
     */
    static bool initialize()
    {
        if ( lt_dlinit() > 0 )
            return true;

        if ( lt_dlsetsearchpath("") > 0 )
        {
            lt_dlexit();
            return true;
        }

        return false;
    }
Exemple #15
0
Extension::Extension() 
{
    char *env = std::getenv("GNASH_PLUGINS");
    if (!env) {
        _pluginsdir = PLUGINSDIR;
    }
    else {
        _pluginsdir = env;
    }

    log_debug("Plugins path: %s", _pluginsdir);
#ifdef HAVE_LTDL
    lt_dlsetsearchpath(_pluginsdir.c_str());
#endif
}
Exemple #16
0
void
plugins_init(const char *path)
{
    char *plugins_path;
    lt_dladvise advise;

    if (path && !strcmp(path, "none")) {
        return;
    }

    if (!(plugins_path = path ? xstrdup(path) : xstrdup(ovs_pluginsdir()))) {
        VLOG_ERR("Failed to allocate plugins path");
        return;
    }

    if (lt_dlinit() ||
        lt_dlsetsearchpath(plugins_path) ||
        lt_dladvise_init(&advise)) {
        VLOG_ERR("ltdl initializations: %s", lt_dlerror());
        goto err_init;
    }

    if (!(interface_id = lt_dlinterface_register("ovs-plugin", NULL))) {
        VLOG_ERR("lt_dlinterface_register: %s", lt_dlerror());
        goto err_interface_register;
    }

    if (lt_dladvise_global(&advise) || lt_dladvise_ext (&advise) ||
        lt_dlforeachfile(lt_dlgetsearchpath(), &plugins_open_plugin, &advise)) {
        VLOG_ERR("ltdl setting advise: %s", lt_dlerror());
        goto err_set_advise;
    }

    VLOG_INFO("Successfully initialized all plugins");
    return;

err_set_advise:
    lt_dlinterface_free(interface_id);

err_interface_register:
    if (lt_dladvise_destroy(&advise)) {
        VLOG_ERR("destroying ltdl advise%s", lt_dlerror());
        return;
    }

err_init:
    free(plugins_path);
}
Exemple #17
0
Extension::Extension() 
{
//    GNASH_REPORT_FUNCTION;
#ifdef LT_DLMUTEX
//     return lt_dlmutex_register (gnash_mutex_lock, gnash_mutex_unlock,
//                                 gnash_mutex_seterror, gnash_mutex_geterror);
#endif
    char *env = std::getenv("GNASH_PLUGINS");
    if (!env) {
        _pluginsdir = PLUGINSDIR;
    }
    else {
        _pluginsdir = env;
    }

    log_debug("Plugins path: %s", _pluginsdir);
    lt_dlsetsearchpath(_pluginsdir.c_str());
}
Exemple #18
0
int init_plugin()
{
	int err;

	err = lt_dlinit();
	if (err != 0) {
		dbg("Can not init ltdl");
		goto err1;
	}

	err = lt_dlsetsearchpath(OH_PLUGIN_PATH);
	if (err != 0) {
		dbg("Can not set lt_dl search path");
		goto err2;
	}

	return 0;
    
 err2:
	lt_dlexit();
 err1:
	return -1;
}
//Resolution of min 1/2 x^t A x + b^t x with x in [-4, +infinity]
//and x_1 in [-1.0, 0.7]
//    x_2 in [-1.3, 1.4]
//    x_3 in [-2.0, 2.1]
int main()
{
    //Definition of the quadratic function
    roboptim::Function::matrix_t A( 3,3 );
    roboptim::Function::vector_t b( 3 );

    A << 1,7,4,7,3,6,4,6,2;
    b << 1,3,4;

    roboptim::NumericQuadraticFunction f( A, b );

    //Testing f([1,1,1])
    roboptim::Function::vector_t x( 3 );
    x << 1,1,1;
    std::cout << "f(x) = " << f( x ) << std::endl;

    //Definition the constraint x_min < x < x_max
    roboptim::Function::vector_t offset( 3 );
    boost::shared_ptr< roboptim::IdentityFunction > c1(
            new roboptim::IdentityFunction( offset ) );

    //Definition of another constraint 0 < Ax +b < +infinity
    roboptim::Function::matrix_t Ac2( 3,3 );
    roboptim::Function::vector_t bc2( 3 );
    Ac2 << 2,3,1,7,1,0,3,5,2;
    bc2 << 4,3,4;
    boost::shared_ptr< roboptim::NumericLinearFunction > c2(
            new roboptim::NumericLinearFunction(Ac2, bc2) );
    
    //Test c([1,1,1])
    roboptim::IdentityFunction c1_el = *c1.get();
    std::cout << "c1(x) = [" << c1_el( x ) << "]" << std::endl;
    
    //Creation of the problem
    solver_t::problem_t pb ( f );
    std::cout << "problem input size : " << pb.function().inputSize() << std::endl;
    std::cout << "problem output size : " << pb.function().outputSize() << std::endl;

    //Set bounds for x in f(x)
    roboptim::Function::intervals_t function_arg_bounds;
    for( unsigned int i=0; i< pb.function().inputSize(); ++i ){
        roboptim::Function::interval_t x_bound = roboptim::Function::makeInterval( -4.0, roboptim::Function::infinity() );
        function_arg_bounds.push_back( x_bound );
    }

    pb.argumentBounds() = function_arg_bounds;

    //Set bounds for constraints: x_min and x_max
    roboptim::Function::intervals_t constraint_bounds;
    roboptim::Function::interval_t c1_0 = roboptim::Function::makeInterval( -1.0, 0.7 );
    roboptim::Function::interval_t c1_1 = roboptim::Function::makeInterval( -1.3, 1.4 );
    roboptim::Function::interval_t c1_2 = roboptim::Function::makeInterval( -2.0, 2.1 );
    constraint_bounds.push_back( c1_0 );
    constraint_bounds.push_back( c1_1 );
    constraint_bounds.push_back( c1_2 );

    //Set bounds for c2
    roboptim::Function::intervals_t c2_bounds;
    for( unsigned int i=0; i< pb.function().inputSize(); ++i ){
        roboptim::Function::interval_t c2_interval = roboptim::Function::makeLowerInterval( 0 );
        c2_bounds.push_back(c2_interval);
    }

    //Set scales for the problem
    solver_t::problem_t::scales_t scales(pb.function().inputSize(), 1.0);
    
    //Add constraint
    pb.addConstraint(
            boost::static_pointer_cast<
      roboptim::GenericLinearFunction<roboptim::EigenMatrixDense>  >
            (c1), constraint_bounds, scales );

    
    pb.addConstraint(
            boost::static_pointer_cast<
      roboptim::GenericLinearFunction<roboptim::EigenMatrixDense> >
            (c2), c2_bounds, scales);
      
    //Set initial guess
    roboptim::NumericQuadraticFunction::argument_t x_init( 3 );
    x_init << 0.4,0.0,0.2;

    pb.startingPoint() = x_init;

    //Set path of the roboptim-core-plugin-ipopt.so so that libltdl finds the lib.
    //The path is detected in the CMakeLists.txt which will substitute the variable PLUGIN_PATH during the compilation
    //Those two lines can be omitted if the environment variable LD_LIBRARY_PATH contains the path of the plugin
    lt_dlinit();
    lt_dlsetsearchpath (PLUGIN_PATH);

    roboptim::SolverFactory<solver_t> factory ("ipopt", pb);
    solver_t& solver = factory ();

    solver_t::result_t res = solver.minimum ();

    std::cout << solver << std::endl;

    // Check if the minimization has succeed.
    if (res.which () != solver_t::SOLVER_VALUE)
    {
        std::cout << "A solution should have been found. Failing..."
            << std::endl
            << boost::get<roboptim::SolverError> (res).what ()
            << std::endl;
        return 0;
    } 

    // Get the result.
    roboptim::Result& result = boost::get<roboptim::Result> (res);
    std::cout << "A solution has been found: " << std::endl
              << result << std::endl;
    return 1;
}
Exemple #20
0
/*
 *	Parse the module config sections, and load
 *	and call each module's init() function.
 *
 *	Libtool makes your life a LOT easier, especially with libltdl.
 *	see: http://www.gnu.org/software/libtool/
 */
int setup_modules(void)
{
	int comp;
	CONF_SECTION *cs;

	/*
	 *  FIXME: This should be pulled from somewhere else.
	 */
	const char *filename="radiusd.conf";

	/*
	 *	No current list of modules: Go initialize libltdl.
	 */
	if (!module_list) {
		/*
		 *	Set the default list of preloaded symbols.
		 *	This is used to initialize libltdl's list of
		 *	preloaded modules. 
		 *
		 *	i.e. Static modules.
		 */
		LTDL_SET_PRELOADED_SYMBOLS();

		if (lt_dlinit() != 0) {
			radlog(L_ERR|L_CONS, "Failed to initialize libraries: %s\n",
					lt_dlerror());
			exit(1); /* FIXME */
			
		}

		/*
		 *	Set the search path to ONLY our library directory.
		 *	This prevents the modules from being found from
		 *	any location on the disk.
		 */
		lt_dlsetsearchpath(radlib_dir);
		
		DEBUG2("Module: Library search path is %s",
				lt_dlgetsearchpath());

		/*
		 *	Initialize the components.
		 */
		for (comp = 0; comp < RLM_COMPONENT_COUNT; comp++) {
			components[comp] = NULL;
		}

	} else {
		detach_modules();
	}

	/*
	 *	Create any DICT_VALUE's for the types.  See
	 *	'doc/configurable_failover' for examples of 'authtype'
	 *	used to create new Auth-Type values.  In order to
	 *	let the user create new names, we've got to look for
	 *	those names, and create DICT_VALUE's for them.
	 */
	for (comp = 0; section_type_value[comp].section != NULL; comp++) {
		const char	*name2;
		DICT_ATTR	*dattr;
		DICT_VALUE	*dval;
		CONF_SECTION	*sub, *next;
		CONF_PAIR	*cp;

		/*
		 *  Big-time YUCK
		 */
		static int my_value = 32767;

		cs = cf_section_find(section_type_value[comp].section);

		if (!cs) continue;

		sub = NULL;
		do {
			/*
			 *	See if there's a sub-section by that
			 *	name.
			 */
			next = cf_subsection_find_next(cs, sub,
						      section_type_value[comp].typename);

			/*
			 *	Allow some old names, too.
			 */
			if (!next && (comp <= 4)) {
				
				next = cf_subsection_find_next(cs, sub,
							       old_section_type_value[comp].typename);
			}
			sub = next;

			/*
			 *	If so, look for it to define a new
			 *	value.
			 */
			name2 = cf_section_name2(sub);
			if (!name2) continue;


			/*
			 *	If the value already exists, don't
			 *	create it again.
			 */
			dval = dict_valbyname(section_type_value[comp].attr,
					      name2);
			if (dval) continue;

			/*
       			 *	Find the attribute for the value.
			 */
			dattr = dict_attrbyvalue(section_type_value[comp].attr);
			if (!dattr) continue;

			/*
			 *	Finally, create the new attribute.
			 */
			if (dict_addvalue(name2, dattr->name, my_value++) < 0) {
				radlog(L_ERR, "%s", librad_errstr);
				exit(1);
			}
		} while (sub != NULL);

		/*
		 *	Loop over the non-sub-sections, too.
		 */
		cp = NULL;
		do {
			/*
			 *	See if there's a conf-pair by that
			 *	name.
			 */
			cp = cf_pair_find_next(cs, cp, NULL);
			if (!cp) break;


			/*
			 *	If the value already exists, don't
			 *	create it again.
			 */
			name2 = cf_pair_attr(cp);
			dval = dict_valbyname(section_type_value[comp].attr,
					      name2);
			if (dval) continue;

			/*
       			 *	Find the attribute for the value.
			 */
			dattr = dict_attrbyvalue(section_type_value[comp].attr);
			if (!dattr) continue;

			/*
			 *	Finally, create the new attribute.
			 */
			if (dict_addvalue(name2, dattr->name, my_value++) < 0) {
				radlog(L_ERR, "%s", librad_errstr);
				exit(1);
			}
		} while (cp != NULL);
	} /* over the sections which can have redundent sub-sections */
Exemple #21
0
int main(int argc, char *argv[]) {
    pa_core *c = NULL;
    pa_strbuf *buf = NULL;
    pa_daemon_conf *conf = NULL;
    pa_mainloop *mainloop = NULL;
    char *s;
    char *configured_address;
    int r = 0, retval = 1, d = 0;
    pa_bool_t valid_pid_file = FALSE;
    pa_bool_t ltdl_init = FALSE;
    int passed_fd = -1;
    const char *e;
#ifdef HAVE_FORK
    int daemon_pipe[2] = { -1, -1 };
    int daemon_pipe2[2] = { -1, -1 };
#endif
#ifdef OS_IS_WIN32
    pa_time_event *win32_timer;
    struct timeval win32_tv;
#endif
    int autospawn_fd = -1;
    pa_bool_t autospawn_locked = FALSE;
#ifdef HAVE_DBUS
    pa_dbusobj_server_lookup *server_lookup = NULL; /* /org/pulseaudio/server_lookup */
    pa_dbus_connection *lookup_service_bus = NULL; /* Always the user bus. */
    pa_dbus_connection *server_bus = NULL; /* The bus where we reserve org.pulseaudio.Server, either the user or the system bus. */
    pa_bool_t start_server;
#endif

    pa_log_set_ident("pulseaudio");
    pa_log_set_level(PA_LOG_NOTICE);
    pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET);

#if defined(__linux__) && defined(__OPTIMIZE__)
    /*
       Disable lazy relocations to make usage of external libraries
       more deterministic for our RT threads. We abuse __OPTIMIZE__ as
       a check whether we are a debug build or not. This all is
       admittedly a bit snake-oilish.
    */

    if (!getenv("LD_BIND_NOW")) {
        char *rp;
        char *canonical_rp;

        /* We have to execute ourselves, because the libc caches the
         * value of $LD_BIND_NOW on initialization. */

        pa_set_env("LD_BIND_NOW", "1");

        if ((canonical_rp = pa_realpath(PA_BINARY))) {

            if ((rp = pa_readlink("/proc/self/exe"))) {

                if (pa_streq(rp, canonical_rp))
                    pa_assert_se(execv(rp, argv) == 0);
                else
                    pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp);

                pa_xfree(rp);

            } else
                pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?");

            pa_xfree(canonical_rp);

        } else
            pa_log_warn("Couldn't canonicalize binary path, cannot self execute.");
    }
#endif

    if ((e = getenv("PULSE_PASSED_FD"))) {
        passed_fd = atoi(e);

        if (passed_fd <= 2)
            passed_fd = -1;
    }

    /* We might be autospawned, in which case have no idea in which
     * context we have been started. Let's cleanup our execution
     * context as good as possible */

    pa_reset_personality();
    pa_drop_root();
    pa_close_all(passed_fd, -1);
    pa_reset_sigs(-1);
    pa_unblock_sigs(-1);
    pa_reset_priority();

    setlocale(LC_ALL, "");
    pa_init_i18n();

    conf = pa_daemon_conf_new();

    if (pa_daemon_conf_load(conf, NULL) < 0)
        goto finish;

    if (pa_daemon_conf_env(conf) < 0)
        goto finish;

    if (pa_cmdline_parse(conf, argc, argv, &d) < 0) {
        pa_log(_("Failed to parse command line."));
        goto finish;
    }

    pa_log_set_level(conf->log_level);
    pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target);
    if (conf->log_meta)
        pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET);
    if (conf->log_time)
        pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET);
    pa_log_set_show_backtrace(conf->log_backtrace);

#ifdef HAVE_DBUS
    /* conf->system_instance and conf->local_server_type control almost the
     * same thing; make them agree about what is requested. */
    switch (conf->local_server_type) {
        case PA_SERVER_TYPE_UNSET:
            conf->local_server_type = conf->system_instance ? PA_SERVER_TYPE_SYSTEM : PA_SERVER_TYPE_USER;
            break;
        case PA_SERVER_TYPE_USER:
        case PA_SERVER_TYPE_NONE:
            conf->system_instance = FALSE;
            break;
        case PA_SERVER_TYPE_SYSTEM:
            conf->system_instance = TRUE;
            break;
        default:
            pa_assert_not_reached();
    }

    start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (getuid() == 0 && conf->local_server_type == PA_SERVER_TYPE_SYSTEM);

    if (!start_server && conf->local_server_type == PA_SERVER_TYPE_SYSTEM) {
        pa_log_notice(_("System mode refused for non-root user. Only starting the D-Bus server lookup service."));
        conf->system_instance = FALSE;
    }
#endif

    LTDL_SET_PRELOADED_SYMBOLS();
    pa_ltdl_init();
    ltdl_init = TRUE;

    if (conf->dl_search_path)
        lt_dlsetsearchpath(conf->dl_search_path);

#ifdef OS_IS_WIN32
    {
        WSADATA data;
        WSAStartup(MAKEWORD(2, 0), &data);
    }
#endif

    pa_random_seed();

    switch (conf->cmd) {
        case PA_CMD_DUMP_MODULES:
            pa_dump_modules(conf, argc-d, argv+d);
            retval = 0;
            goto finish;

        case PA_CMD_DUMP_CONF: {

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            s = pa_daemon_conf_dump(conf);
            fputs(s, stdout);
            pa_xfree(s);
            retval = 0;
            goto finish;
        }

        case PA_CMD_DUMP_RESAMPLE_METHODS: {
            int i;

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            for (i = 0; i < PA_RESAMPLER_MAX; i++)
                if (pa_resample_method_supported(i))
                    printf("%s\n", pa_resample_method_to_string(i));

            retval = 0;
            goto finish;
        }

        case PA_CMD_HELP :
            pa_cmdline_help(argv[0]);
            retval = 0;
            goto finish;

        case PA_CMD_VERSION :

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");
            retval = 0;
            goto finish;

        case PA_CMD_CHECK: {
            pid_t pid;

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            if (pa_pid_file_check_running(&pid, "pulseaudio") < 0)
                pa_log_info(_("Daemon not running"));
            else {
                pa_log_info(_("Daemon running as PID %u"), pid);
                retval = 0;
            }

            goto finish;

        }
        case PA_CMD_KILL:

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0)
                pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno));
            else
                retval = 0;

            goto finish;

        case PA_CMD_CLEANUP_SHM:

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            if (pa_shm_cleanup() >= 0)
                retval = 0;

            goto finish;

        default:
            pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);
    }

    if (d < argc) {
        pa_log("Too many arguments.\n");
        goto finish;
    }

#ifdef HAVE_GETUID
    if (getuid() == 0 && !conf->system_instance)
        pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));
#ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */
    else if (getuid() != 0 && conf->system_instance) {
        pa_log(_("Root privileges required."));
        goto finish;
    }
#endif
#endif  /* HAVE_GETUID */

    if (conf->cmd == PA_CMD_START && conf->system_instance) {
        pa_log(_("--start not supported for system instances."));
        goto finish;
    }

    if (conf->cmd == PA_CMD_START && (configured_address = check_configured_address())) {
        /* There is an server address in our config, but where did it come from?
         * By default a standard X11 login will load module-x11-publish which will
         * inject PULSE_SERVER X11 property. If the PA daemon crashes, we will end
         * up hitting this code path. So we have to check to see if our configured_address
         * is the same as the value that would go into this property so that we can
         * recover (i.e. autospawn) from a crash.
         */
        char *ufn;
        pa_bool_t start_anyway = FALSE;

        if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) {
            char *id;

            if ((id = pa_machine_id())) {
                pa_strlist *server_list;
                char formatted_ufn[256];

                pa_snprintf(formatted_ufn, sizeof(formatted_ufn), "{%s}unix:%s", id, ufn);
                pa_xfree(id);

                if ((server_list = pa_strlist_parse(configured_address))) {
                    char *u = NULL;

                    /* We only need to check the first server */
                    server_list = pa_strlist_pop(server_list, &u);
                    pa_strlist_free(server_list);

                    start_anyway = (u && pa_streq(formatted_ufn, u));
                    pa_xfree(u);
                }
            }
            pa_xfree(ufn);
        }

        if (!start_anyway) {
            pa_log_notice(_("User-configured server at %s, refusing to start/autospawn."), configured_address);
            pa_xfree(configured_address);
            retval = 0;
            goto finish;
        }

        pa_log_notice(_("User-configured server at %s, which appears to be local. Probing deeper."), configured_address);
        pa_xfree(configured_address);
    }

    if (conf->system_instance && !conf->disallow_exit)
        pa_log_warn(_("Running in system mode, but --disallow-exit not set!"));

    if (conf->system_instance && !conf->disallow_module_loading)
        pa_log_warn(_("Running in system mode, but --disallow-module-loading not set!"));

    if (conf->system_instance && !conf->disable_shm) {
        pa_log_notice(_("Running in system mode, forcibly disabling SHM mode!"));
        conf->disable_shm = TRUE;
    }

    if (conf->system_instance && conf->exit_idle_time >= 0) {
        pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!"));
        conf->exit_idle_time = -1;
    }

    if (conf->cmd == PA_CMD_START) {
        /* If we shall start PA only when it is not running yet, we
         * first take the autospawn lock to make things
         * synchronous. */

        if ((autospawn_fd = pa_autospawn_lock_init()) < 0) {
            pa_log("Failed to initialize autospawn lock");
            goto finish;
        }

        if ((pa_autospawn_lock_acquire(TRUE) < 0)) {
            pa_log("Failed to acquire autospawn lock");
            goto finish;
        }

        autospawn_locked = TRUE;
    }

    if (conf->daemonize) {
#ifdef HAVE_FORK
        pid_t child;
#endif

        if (pa_stdio_acquire() < 0) {
            pa_log(_("Failed to acquire stdio."));
            goto finish;
        }

#ifdef HAVE_FORK
        if (pipe(daemon_pipe) < 0) {
            pa_log(_("pipe() failed: %s"), pa_cstrerror(errno));
            goto finish;
        }

        if ((child = fork()) < 0) {
            pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
            pa_close_pipe(daemon_pipe);
            goto finish;
        }

        if (child != 0) {
            ssize_t n;
            /* Father */

            pa_assert_se(pa_close(daemon_pipe[1]) == 0);
            daemon_pipe[1] = -1;

            if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {

                if (n < 0)
                    pa_log(_("read() failed: %s"), pa_cstrerror(errno));

                retval = 1;
            }

            if (retval)
                pa_log(_("Daemon startup failed."));
            else
                pa_log_info(_("Daemon startup successful."));

            goto finish;
        }

        if (autospawn_fd >= 0) {
            /* The lock file is unlocked from the parent, so we need
             * to close it in the child */

            pa_autospawn_lock_release();
            pa_autospawn_lock_done(TRUE);

            autospawn_locked = FALSE;
            autospawn_fd = -1;
        }

        pa_assert_se(pa_close(daemon_pipe[0]) == 0);
        daemon_pipe[0] = -1;
#endif

        if (conf->auto_log_target)
            pa_log_set_target(PA_LOG_SYSLOG);

#ifdef HAVE_SETSID
        if (setsid() < 0) {
            pa_log(_("setsid() failed: %s"), pa_cstrerror(errno));
            goto finish;
        }
#endif

#ifdef HAVE_FORK
        /* We now are a session and process group leader. Let's fork
         * again and let the father die, so that we'll become a
         * process that can never acquire a TTY again, in a session and
         * process group without leader */

        if (pipe(daemon_pipe2) < 0) {
            pa_log(_("pipe() failed: %s"), pa_cstrerror(errno));
            goto finish;
        }

        if ((child = fork()) < 0) {
            pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
            pa_close_pipe(daemon_pipe2);
            goto finish;
        }

        if (child != 0) {
            ssize_t n;
            /* Father */

            pa_assert_se(pa_close(daemon_pipe2[1]) == 0);
            daemon_pipe2[1] = -1;

            if ((n = pa_loop_read(daemon_pipe2[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {

                if (n < 0)
                    pa_log(_("read() failed: %s"), pa_cstrerror(errno));

                retval = 1;
            }

            /* We now have to take care of signalling the first fork with
             * the return value we've received from this fork... */
            pa_assert(daemon_pipe[1] >= 0);

            pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
            pa_close(daemon_pipe[1]);
            daemon_pipe[1] = -1;

            goto finish;
        }

        pa_assert_se(pa_close(daemon_pipe2[0]) == 0);
        daemon_pipe2[0] = -1;

        /* We no longer need the (first) daemon_pipe as it's handled in our child above */
        pa_close_pipe(daemon_pipe);
#endif

#ifdef SIGTTOU
        signal(SIGTTOU, SIG_IGN);
#endif
#ifdef SIGTTIN
        signal(SIGTTIN, SIG_IGN);
#endif
#ifdef SIGTSTP
        signal(SIGTSTP, SIG_IGN);
#endif

        pa_nullify_stdfds();
    }

    pa_set_env_and_record("PULSE_INTERNAL", "1");
    pa_assert_se(chdir("/") == 0);
    umask(0022);

#ifdef HAVE_SYS_RESOURCE_H
    set_all_rlimits(conf);
#endif
    pa_rtclock_hrtimer_enable();

    pa_raise_priority(conf->nice_level);

    if (conf->system_instance)
        if (change_user() < 0)
            goto finish;

    pa_set_env_and_record("PULSE_SYSTEM", conf->system_instance ? "1" : "0");

    pa_log_info(_("This is PulseAudio %s"), PACKAGE_VERSION);
    pa_log_debug(_("Compilation host: %s"), CANONICAL_HOST);
    pa_log_debug(_("Compilation CFLAGS: %s"), PA_CFLAGS);

    s = pa_uname_string();
    pa_log_debug(_("Running on host: %s"), s);
    pa_xfree(s);

    pa_log_debug(_("Found %u CPUs."), pa_ncpus());

    pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE);

#ifdef HAVE_VALGRIND_MEMCHECK_H
    pa_log_debug(_("Compiled with Valgrind support: yes"));
#else
    pa_log_debug(_("Compiled with Valgrind support: no"));
#endif

    pa_log_debug(_("Running in valgrind mode: %s"), pa_yes_no(pa_in_valgrind()));

    pa_log_debug(_("Running in VM: %s"), pa_yes_no(pa_running_in_vm()));

#ifdef __OPTIMIZE__
    pa_log_debug(_("Optimized build: yes"));
#else
    pa_log_debug(_("Optimized build: no"));
#endif

#ifdef NDEBUG
    pa_log_debug(_("NDEBUG defined, all asserts disabled."));
#elif defined(FASTPATH)
    pa_log_debug(_("FASTPATH defined, only fast path asserts disabled."));
#else
    pa_log_debug(_("All asserts enabled."));
#endif

    if (!(s = pa_machine_id())) {
        pa_log(_("Failed to get machine ID"));
        goto finish;
    }
    pa_log_info(_("Machine ID is %s."), s);
    pa_xfree(s);

    if ((s = pa_session_id())) {
        pa_log_info(_("Session ID is %s."), s);
        pa_xfree(s);
    }

    if (!(s = pa_get_runtime_dir()))
        goto finish;
    pa_log_info(_("Using runtime directory %s."), s);
    pa_xfree(s);

    if (!(s = pa_get_state_dir()))
        goto finish;
    pa_log_info(_("Using state directory %s."), s);
    pa_xfree(s);

    pa_log_info(_("Using modules directory %s."), conf->dl_search_path);

    pa_log_info(_("Running in system mode: %s"), pa_yes_no(pa_in_system_mode()));

    if (pa_in_system_mode())
        pa_log_warn(_("OK, so you are running PA in system mode. Please note that you most likely shouldn't be doing that.\n"
                      "If you do it nonetheless then it's your own fault if things don't work as expected.\n"
                      "Please read http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode for an explanation why system mode is usually a bad idea."));

    if (conf->use_pid_file) {
        int z;

        if ((z = pa_pid_file_create("pulseaudio")) != 0) {

            if (conf->cmd == PA_CMD_START && z > 0) {
                /* If we are already running and with are run in
                 * --start mode, then let's return this as success. */

                retval = 0;
                goto finish;
            }

            pa_log(_("pa_pid_file_create() failed."));
            goto finish;
        }

        valid_pid_file = TRUE;
    }

    pa_disable_sigpipe();

    if (pa_rtclock_hrtimer())
        pa_log_info(_("Fresh high-resolution timers available! Bon appetit!"));
    else
        pa_log_info(_("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!"));

    if (conf->lock_memory) {
#ifdef HAVE_SYS_MMAN_H
        if (mlockall(MCL_FUTURE) < 0)
            pa_log_warn("mlockall() failed: %s", pa_cstrerror(errno));
        else
            pa_log_info("Successfully locked process into memory.");
#else
        pa_log_warn("Memory locking requested but not supported on platform.");
#endif
    }

    pa_memtrap_install();

    pa_assert_se(mainloop = pa_mainloop_new());

    if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) {
        pa_log(_("pa_core_new() failed."));
        goto finish;
    }

    c->default_sample_spec = conf->default_sample_spec;
    c->alternate_sample_rate = conf->alternate_sample_rate;
    c->default_channel_map = conf->default_channel_map;
    c->default_n_fragments = conf->default_n_fragments;
    c->default_fragment_size_msec = conf->default_fragment_size_msec;
    c->deferred_volume_safety_margin_usec = conf->deferred_volume_safety_margin_usec;
    c->deferred_volume_extra_delay_usec = conf->deferred_volume_extra_delay_usec;
    c->exit_idle_time = conf->exit_idle_time;
    c->scache_idle_time = conf->scache_idle_time;
    c->resample_method = conf->resample_method;
    c->realtime_priority = conf->realtime_priority;
    c->realtime_scheduling = !!conf->realtime_scheduling;
    c->disable_remixing = !!conf->disable_remixing;
    c->disable_lfe_remixing = !!conf->disable_lfe_remixing;
    c->deferred_volume = !!conf->deferred_volume;
    c->running_as_daemon = !!conf->daemonize;
    c->disallow_exit = conf->disallow_exit;
    c->flat_volumes = conf->flat_volumes;
#ifdef HAVE_DBUS
    c->server_type = conf->local_server_type;
#endif

    c->cpu_info.cpu_type = PA_CPU_UNDEFINED;
    if (!getenv("PULSE_NO_SIMD")) {
        if (pa_cpu_init_x86(&(c->cpu_info.flags.x86)))
            c->cpu_info.cpu_type = PA_CPU_X86;
        if (pa_cpu_init_arm(&(c->cpu_info.flags.arm)))
            c->cpu_info.cpu_type = PA_CPU_ARM;
	pa_cpu_init_orc(c->cpu_info);
    }

    pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);
    pa_signal_new(SIGINT, signal_callback, c);
    pa_signal_new(SIGTERM, signal_callback, c);
#ifdef SIGUSR1
    pa_signal_new(SIGUSR1, signal_callback, c);
#endif
#ifdef SIGUSR2
    pa_signal_new(SIGUSR2, signal_callback, c);
#endif
#ifdef SIGHUP
    pa_signal_new(SIGHUP, signal_callback, c);
#endif

#ifdef OS_IS_WIN32
    win32_timer = pa_mainloop_get_api(mainloop)->time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&win32_tv), message_cb, NULL);
#endif

    if (!conf->no_cpu_limit)
        pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0);

    buf = pa_strbuf_new();

#ifdef HAVE_DBUS
    pa_assert_se(dbus_threads_init_default());

    if (start_server) {
#endif
        if (conf->load_default_script_file) {
            FILE *f;

            if ((f = pa_daemon_conf_open_default_script_file(conf))) {
                r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail);
                fclose(f);
            }
        }

        if (r >= 0)
            r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail);

        pa_log_error("%s", s = pa_strbuf_tostring_free(buf));
        pa_xfree(s);

        if (r < 0 && conf->fail) {
            pa_log(_("Failed to initialize daemon."));
            goto finish;
        }

        if (!c->modules || pa_idxset_size(c->modules) == 0) {
            pa_log(_("Daemon startup without any loaded modules, refusing to work."));
            goto finish;
        }
#ifdef HAVE_DBUS
    } else {
        /* When we just provide the D-Bus server lookup service, we don't want
         * any modules to be loaded. We haven't loaded any so far, so one might
         * think there's no way to contact the server, but receiving certain
         * signals could still cause modules to load. */
        conf->disallow_module_loading = TRUE;
    }
#endif

    /* We completed the initial module loading, so let's disable it
     * from now on, if requested */
    c->disallow_module_loading = !!conf->disallow_module_loading;

#ifdef HAVE_DBUS
    if (!conf->system_instance) {
        if ((server_lookup = pa_dbusobj_server_lookup_new(c))) {
            if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.PulseAudio1")))
                goto finish;
        }
    }

    if (start_server)
        server_bus = register_dbus_name(c, conf->system_instance ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, "org.pulseaudio.Server");
#endif

#ifdef HAVE_FORK
    if (daemon_pipe2[1] >= 0) {
        int ok = 0;
        pa_loop_write(daemon_pipe2[1], &ok, sizeof(ok), NULL);
        pa_close(daemon_pipe2[1]);
        daemon_pipe2[1] = -1;
    }
#endif

    pa_log_info(_("Daemon startup complete."));

    retval = 0;
    if (pa_mainloop_run(mainloop, &retval) < 0)
        goto finish;

    pa_log_info(_("Daemon shutdown initiated."));

finish:
#ifdef HAVE_DBUS
    if (server_bus)
        pa_dbus_connection_unref(server_bus);
    if (lookup_service_bus)
        pa_dbus_connection_unref(lookup_service_bus);
    if (server_lookup)
        pa_dbusobj_server_lookup_free(server_lookup);
#endif

    if (autospawn_fd >= 0) {
        if (autospawn_locked)
            pa_autospawn_lock_release();

        pa_autospawn_lock_done(FALSE);
    }

#ifdef OS_IS_WIN32
    if (mainloop && win32_timer)
        pa_mainloop_get_api(mainloop)->time_free(win32_timer);
#endif

    if (c) {
        /* Ensure all the modules/samples are unloaded when the core is still ref'ed,
         * as unlink callback hooks in modules may need the core to be ref'ed */
        pa_module_unload_all(c);
        pa_scache_free_all(c);

        pa_core_unref(c);
        pa_log_info(_("Daemon terminated."));
    }

    if (!conf->no_cpu_limit)
        pa_cpu_limit_done();

    pa_signal_done();

#ifdef HAVE_FORK
    /* If we have daemon_pipe[1] still open, this means we've failed after
     * the first fork, but before the second. Therefore just write to it. */
    if (daemon_pipe[1] >= 0)
        pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
    else if (daemon_pipe2[1] >= 0)
        pa_loop_write(daemon_pipe2[1], &retval, sizeof(retval), NULL);

    pa_close_pipe(daemon_pipe2);
    pa_close_pipe(daemon_pipe);
#endif

    if (mainloop)
        pa_mainloop_free(mainloop);

    if (conf)
        pa_daemon_conf_free(conf);

    if (valid_pid_file)
        pa_pid_file_remove();

    /* This has no real purpose except making things valgrind-clean */
    pa_unset_env_recorded();

#ifdef OS_IS_WIN32
    WSACleanup();
#endif

    if (ltdl_init)
        pa_ltdl_done();

#ifdef HAVE_DBUS
    dbus_shutdown();
#endif

    return retval;
}
Exemple #22
0
int main(int argc, char *argv[]) {
    pa_core *c = NULL;
    pa_strbuf *buf = NULL;
    pa_daemon_conf *conf = NULL;
    pa_mainloop *mainloop = NULL;
    char *s;
    char *configured_address;
    int r = 0, retval = 1, d = 0;
    bool valid_pid_file = false;
    bool ltdl_init = false;
    int passed_fd = -1;
    const char *e;
#ifdef HAVE_FORK
    int daemon_pipe[2] = { -1, -1 };
    int daemon_pipe2[2] = { -1, -1 };
#endif
    int autospawn_fd = -1;
    bool autospawn_locked = false;
#ifdef HAVE_DBUS
    pa_dbusobj_server_lookup *server_lookup = NULL; /* /org/pulseaudio/server_lookup */
    pa_dbus_connection *lookup_service_bus = NULL; /* Always the user bus. */
    pa_dbus_connection *server_bus = NULL; /* The bus where we reserve org.pulseaudio.Server, either the user or the system bus. */
    bool start_server;
#endif

    pa_log_set_ident("pulseaudio");
    pa_log_set_level(PA_LOG_NOTICE);
    pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET);

#if defined(__linux__) && defined(__OPTIMIZE__)
    /*
       Disable lazy relocations to make usage of external libraries
       more deterministic for our RT threads. We abuse __OPTIMIZE__ as
       a check whether we are a debug build or not. This all is
       admittedly a bit snake-oilish.
    */

    if (!getenv("LD_BIND_NOW")) {
        char *rp;
        char *canonical_rp;

        /* We have to execute ourselves, because the libc caches the
         * value of $LD_BIND_NOW on initialization. */

        pa_set_env("LD_BIND_NOW", "1");

        if ((canonical_rp = pa_realpath(PA_BINARY))) {

            if ((rp = pa_readlink("/proc/self/exe"))) {

                if (pa_streq(rp, canonical_rp))
                    pa_assert_se(execv(rp, argv) == 0);
                else
                    pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp);

                pa_xfree(rp);

            } else
                pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?");

            pa_xfree(canonical_rp);

        } else
            pa_log_warn("Couldn't canonicalize binary path, cannot self execute.");
    }
#endif

    if ((e = getenv("PULSE_PASSED_FD"))) {
        passed_fd = atoi(e);

        if (passed_fd <= 2)
            passed_fd = -1;
    }

    /* We might be autospawned, in which case have no idea in which
     * context we have been started. Let's cleanup our execution
     * context as good as possible */

    pa_reset_personality();
    pa_drop_root();
    pa_close_all(passed_fd, -1);
    pa_reset_sigs(-1);
    pa_unblock_sigs(-1);
    pa_reset_priority();

    setlocale(LC_ALL, "");
    pa_init_i18n();

    conf = pa_daemon_conf_new();

    if (pa_daemon_conf_load(conf, NULL) < 0)
        goto finish;

    if (pa_daemon_conf_env(conf) < 0)
        goto finish;

    if (pa_cmdline_parse(conf, argc, argv, &d) < 0) {
        pa_log(_("Failed to parse command line."));
        goto finish;
    }

    if (conf->log_target)
        pa_log_set_target(conf->log_target);
    else {
        pa_log_target target = { .type = PA_LOG_STDERR, .file = NULL };
        pa_log_set_target(&target);
    }

    pa_log_set_level(conf->log_level);
    if (conf->log_meta)
        pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET);
    if (conf->log_time)
        pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET);
    pa_log_set_show_backtrace(conf->log_backtrace);

#ifdef HAVE_DBUS
    /* conf->system_instance and conf->local_server_type control almost the
     * same thing; make them agree about what is requested. */
    switch (conf->local_server_type) {
        case PA_SERVER_TYPE_UNSET:
            conf->local_server_type = conf->system_instance ? PA_SERVER_TYPE_SYSTEM : PA_SERVER_TYPE_USER;
            break;
        case PA_SERVER_TYPE_USER:
        case PA_SERVER_TYPE_NONE:
            conf->system_instance = false;
            break;
        case PA_SERVER_TYPE_SYSTEM:
            conf->system_instance = true;
            break;
        default:
            pa_assert_not_reached();
    }

    start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (getuid() == 0 && conf->local_server_type == PA_SERVER_TYPE_SYSTEM);

    if (!start_server && conf->local_server_type == PA_SERVER_TYPE_SYSTEM) {
        pa_log_notice(_("System mode refused for non-root user. Only starting the D-Bus server lookup service."));
        conf->system_instance = false;
    }
#endif

    LTDL_SET_PRELOADED_SYMBOLS();
    pa_ltdl_init();
    ltdl_init = true;

    if (conf->dl_search_path)
        lt_dlsetsearchpath(conf->dl_search_path);

#ifdef OS_IS_WIN32
    {
        WSADATA data;
        WSAStartup(MAKEWORD(2, 0), &data);
    }
#endif

    pa_random_seed();

    switch (conf->cmd) {
        case PA_CMD_DUMP_MODULES:
            pa_dump_modules(conf, argc-d, argv+d);
            retval = 0;
            goto finish;

        case PA_CMD_DUMP_CONF: {

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            s = pa_daemon_conf_dump(conf);
            fputs(s, stdout);
            pa_xfree(s);
            retval = 0;
            goto finish;
        }

        case PA_CMD_DUMP_RESAMPLE_METHODS: {
            int i;

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            for (i = 0; i < PA_RESAMPLER_MAX; i++)
                if (pa_resample_method_supported(i))
                    printf("%s\n", pa_resample_method_to_string(i));

            retval = 0;
            goto finish;
        }

        case PA_CMD_HELP :
            pa_cmdline_help(argv[0]);
            retval = 0;
            goto finish;

        case PA_CMD_VERSION :

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");
            retval = 0;
            goto finish;

        case PA_CMD_CHECK: {
            pid_t pid;

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            if (pa_pid_file_check_running(&pid, "pulseaudio") < 0)
                pa_log_info(_("Daemon not running"));
            else {
                pa_log_info(_("Daemon running as PID %u"), pid);
                retval = 0;
            }

            goto finish;

        }
        case PA_CMD_KILL:

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0)
                pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno));
            else
                retval = 0;

            goto finish;

        case PA_CMD_CLEANUP_SHM:

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            if (pa_shm_cleanup() >= 0)
                retval = 0;

            goto finish;

        default:
            pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);
    }

    if (d < argc) {
        pa_log("Too many arguments.\n");
        goto finish;
    }

#ifdef HAVE_GETUID
    if (getuid() == 0 && !conf->system_instance)
        pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));
#ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */
    else if (getuid() != 0 && conf->system_instance) {
        pa_log(_("Root privileges required."));
        goto finish;
    }
#endif
#endif  /* HAVE_GETUID */

    if (conf->cmd == PA_CMD_START && conf->system_instance) {
        pa_log(_("--start not supported for system instances."));
        goto finish;
    }

    if (conf->cmd == PA_CMD_START && (configured_address = check_configured_address())) {
        /* There is an server address in our config, but where did it come from?
         * By default a standard X11 login will load module-x11-publish which will
         * inject PULSE_SERVER X11 property. If the PA daemon crashes, we will end
         * up hitting this code path. So we have to check to see if our configured_address
         * is the same as the value that would go into this property so that we can
         * recover (i.e. autospawn) from a crash.
         */
        char *ufn;
        bool start_anyway = false;

        if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) {
            char *id;

            if ((id = pa_machine_id())) {
                pa_strlist *server_list;
                char formatted_ufn[256];

                pa_snprintf(formatted_ufn, sizeof(formatted_ufn), "{%s}unix:%s", id, ufn);
                pa_xfree(id);

                if ((server_list = pa_strlist_parse(configured_address))) {
                    char *u = NULL;

                    /* We only need to check the first server */
                    server_list = pa_strlist_pop(server_list, &u);
                    pa_strlist_free(server_list);

                    start_anyway = (u && pa_streq(formatted_ufn, u));
                    pa_xfree(u);
                }
            }
            pa_xfree(ufn);
        }

        if (!start_anyway) {
            pa_log_notice(_("User-configured server at %s, refusing to start/autospawn."), configured_address);
            pa_xfree(configured_address);
            retval = 0;
            goto finish;
        }

        pa_log_notice(_("User-configured server at %s, which appears to be local. Probing deeper."), configured_address);
        pa_xfree(configured_address);
    }

    if (conf->system_instance && !conf->disallow_exit)
        pa_log_warn(_("Running in system mode, but --disallow-exit not set!"));

    if (conf->system_instance && !conf->disallow_module_loading)
        pa_log_warn(_("Running in system mode, but --disallow-module-loading not set!"));

    if (conf->system_instance && !conf->disable_shm) {
        pa_log_notice(_("Running in system mode, forcibly disabling SHM mode!"));
        conf->disable_shm = true;
    }

    if (conf->system_instance && conf->exit_idle_time >= 0) {
        pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!"));
        conf->exit_idle_time = -1;
    }

    if (conf->cmd == PA_CMD_START) {
        /* If we shall start PA only when it is not running yet, we
         * first take the autospawn lock to make things
         * synchronous. */

        if ((autospawn_fd = pa_autospawn_lock_init()) < 0) {
            pa_log("Failed to initialize autospawn lock");
            goto finish;
        }

        if ((pa_autospawn_lock_acquire(true) < 0)) {
            pa_log("Failed to acquire autospawn lock");
            goto finish;
        }

        autospawn_locked = true;
    }

    if (conf->daemonize) {
#ifdef HAVE_FORK
        pid_t child;
#endif

        if (pa_stdio_acquire() < 0) {
            pa_log(_("Failed to acquire stdio."));
            goto finish;
        }

#ifdef HAVE_FORK
        if (pipe(daemon_pipe) < 0) {
            pa_log(_("pipe() failed: %s"), pa_cstrerror(errno));
            goto finish;
        }

        if ((child = fork()) < 0) {
            pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
            pa_close_pipe(daemon_pipe);
            goto finish;
        }

        if (child != 0) {
            ssize_t n;
            /* Father */

            pa_assert_se(pa_close(daemon_pipe[1]) == 0);
            daemon_pipe[1] = -1;

            if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {

                if (n < 0)
                    pa_log(_("read() failed: %s"), pa_cstrerror(errno));

                retval = 1;
            }

            if (retval)
                pa_log(_("Daemon startup failed."));
            else
                pa_log_info(_("Daemon startup successful."));

            goto finish;
        }

        if (autospawn_fd >= 0) {
            /* The lock file is unlocked from the parent, so we need
             * to close it in the child */

            pa_autospawn_lock_release();
            pa_autospawn_lock_done(true);

            autospawn_locked = false;
            autospawn_fd = -1;
        }

        pa_assert_se(pa_close(daemon_pipe[0]) == 0);
        daemon_pipe[0] = -1;
#endif

        if (!conf->log_target) {
#ifdef HAVE_JOURNAL
            pa_log_target target = { .type = PA_LOG_JOURNAL, .file = NULL };
#else
            pa_log_target target = { .type = PA_LOG_SYSLOG, .file = NULL };
#endif
            pa_log_set_target(&target);
        }
int pa__init(pa_module*m) {
    struct userdata *u;
    pa_sample_spec ss;
    pa_channel_map map;
    pa_modargs *ma;
    char *t;
    pa_sink *master;
    pa_sink_input_new_data sink_input_data;
    pa_sink_new_data sink_data;
    const char *plugin, *label, *input_ladspaport_map, *output_ladspaport_map;
    LADSPA_Descriptor_Function descriptor_func;
    unsigned long input_ladspaport[PA_CHANNELS_MAX], output_ladspaport[PA_CHANNELS_MAX];
    const char *e, *cdata;
    const LADSPA_Descriptor *d;
    unsigned long p, h, j, n_control, c;
    pa_bool_t *use_default = NULL;

    pa_assert(m);

    pa_assert_cc(sizeof(LADSPA_Data) == sizeof(float));

    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
        pa_log("Failed to parse module arguments.");
        goto fail;
    }

    if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) {
        pa_log("Master sink not found");
        goto fail;
    }

    ss = master->sample_spec;
    ss.format = PA_SAMPLE_FLOAT32;
    map = master->channel_map;
    if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
        pa_log("Invalid sample format specification or channel map");
        goto fail;
    }

    if (!(plugin = pa_modargs_get_value(ma, "plugin", NULL))) {
        pa_log("Missing LADSPA plugin name");
        goto fail;
    }

    if (!(label = pa_modargs_get_value(ma, "label", NULL))) {
        pa_log("Missing LADSPA plugin label");
        goto fail;
    }

    if (!(input_ladspaport_map = pa_modargs_get_value(ma, "input_ladspaport_map", NULL)))
        pa_log_debug("Using default input ladspa port mapping");

    if (!(output_ladspaport_map = pa_modargs_get_value(ma, "output_ladspaport_map", NULL)))
        pa_log_debug("Using default output ladspa port mapping");

    cdata = pa_modargs_get_value(ma, "control", NULL);

    u = pa_xnew0(struct userdata, 1);
    u->module = m;
    m->userdata = u;
    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, NULL);
    u->max_ladspaport_count = 1; /*to avoid division by zero etc. in pa__done when failing before this value has been set*/
    u->channels = 0;
    u->input = NULL;
    u->output = NULL;

    if (!(e = getenv("LADSPA_PATH")))
        e = LADSPA_PATH;

    /* FIXME: This is not exactly thread safe */
    t = pa_xstrdup(lt_dlgetsearchpath());
    lt_dlsetsearchpath(e);
    m->dl = lt_dlopenext(plugin);
    lt_dlsetsearchpath(t);
    pa_xfree(t);

    if (!m->dl) {
        pa_log("Failed to load LADSPA plugin: %s", lt_dlerror());
        goto fail;
    }

    if (!(descriptor_func = (LADSPA_Descriptor_Function) pa_load_sym(m->dl, NULL, "ladspa_descriptor"))) {
        pa_log("LADSPA module lacks ladspa_descriptor() symbol.");
        goto fail;
    }

    for (j = 0;; j++) {

        if (!(d = descriptor_func(j))) {
            pa_log("Failed to find plugin label '%s' in plugin '%s'.", label, plugin);
            goto fail;
        }

        if (strcmp(d->Label, label) == 0)
            break;
    }

    u->descriptor = d;

    pa_log_debug("Module: %s", plugin);
    pa_log_debug("Label: %s", d->Label);
    pa_log_debug("Unique ID: %lu", d->UniqueID);
    pa_log_debug("Name: %s", d->Name);
    pa_log_debug("Maker: %s", d->Maker);
    pa_log_debug("Copyright: %s", d->Copyright);

    n_control = 0;
    u->channels = ss.channels;

    /*
    * Enumerate ladspa ports
    * Default mapping is in order given by the plugin
    */
    for (p = 0; p < d->PortCount; p++) {
        if (LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) {
            if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p])) {
                pa_log_debug("Port %lu is input: %s", p, d->PortNames[p]);
                input_ladspaport[u->input_count] = p;
                u->input_count++;
            } else if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p])) {
                pa_log_debug("Port %lu is output: %s", p, d->PortNames[p]);
                output_ladspaport[u->output_count] = p;
                u->output_count++;
            }
        } else if (LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]) && LADSPA_IS_PORT_INPUT(d->PortDescriptors[p])) {
            pa_log_debug("Port %lu is control: %s", p, d->PortNames[p]);
            n_control++;
        } else
            pa_log_debug("Ignored port %s", d->PortNames[p]);
        /* XXX: Has anyone ever seen an in-place plugin with non-equal number of input and output ports? */
        /* Could be if the plugin is for up-mixing stereo to 5.1 channels */
        /* Or if the plugin is down-mixing 5.1 to two channel stereo or binaural encoded signal */
        if (u->input_count > u->max_ladspaport_count)
            u->max_ladspaport_count = u->input_count;
        else
            u->max_ladspaport_count = u->output_count;
    }

    if (u->channels % u->max_ladspaport_count) {
        pa_log("Cannot handle non-integral number of plugins required for given number of channels");
        goto fail;
    }

    pa_log_debug("Will run %lu plugin instances", u->channels / u->max_ladspaport_count);

    /* Parse data for input ladspa port map */
    if (input_ladspaport_map) {
        const char *state = NULL;
        char *pname;
        c = 0;
        while ((pname = pa_split(input_ladspaport_map, ",", &state))) {
            if (c == u->input_count) {
                pa_log("Too many ports in input ladspa port map");
                goto fail;
            }


            for (p = 0; p < d->PortCount; p++) {
                if (strcmp(d->PortNames[p], pname) == 0) {
                    if (LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p]) && LADSPA_IS_PORT_INPUT(d->PortDescriptors[p])) {
                        input_ladspaport[c] = p;
                    } else {
                        pa_log("Port %s is not an audio input ladspa port", pname);
                        pa_xfree(pname);
                        goto fail;
                    }
                }
            }
            c++;
            pa_xfree(pname);
        }
    }

    /* Parse data for output port map */
    if (output_ladspaport_map) {
        const char *state = NULL;
        char *pname;
        c = 0;
        while ((pname = pa_split(output_ladspaport_map, ",", &state))) {
            if (c == u->output_count) {
                pa_log("Too many ports in output ladspa port map");
                goto fail;
            }
            for (p = 0; p < d->PortCount; p++) {
                if (strcmp(d->PortNames[p], pname) == 0) {
                    if (LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p]) && LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p])) {
                        output_ladspaport[c] = p;
                    } else {
                        pa_log("Port %s is not an output ladspa port", pname);
                        pa_xfree(pname);
                        goto fail;
                    }
                }
            }
            c++;
            pa_xfree(pname);
        }
    }


    u->block_size = pa_frame_align(pa_mempool_block_size_max(m->core->mempool), &ss);

    /* Create buffers */
    if (LADSPA_IS_INPLACE_BROKEN(d->Properties)) {
        u->input = (LADSPA_Data**) pa_xnew(LADSPA_Data*, (unsigned) u->input_count);
        for (c = 0; c < u->input_count; c++)
            u->input[c] = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size);
        u->output = (LADSPA_Data**) pa_xnew(LADSPA_Data*, (unsigned) u->output_count);
        for (c = 0; c < u->output_count; c++)
            u->output[c] = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size);
    } else {
Exemple #24
0
boost::shared_ptr<Handler::cygnal_init_t>
Handler::initModule(const std::string& str)
{
    // GNASH_REPORT_FUNCTION;

    if (str.empty()) {
	return _plugin;
    }

    string module = str;
    if (module[0] == '/') {
	module.erase(0,1);
    }
    
    SharedLib *sl;
    string symbol(module);

    _pluginsdir = PLUGINSDIR;
    log_security(_("Initializing module: \"%s\" from %s"), symbol, _pluginsdir);
    
    // Update the list of loaded plugins so we only load them once.
    if (_plugins[module] == 0) {
        sl = new SharedLib(module, "CYGNAL_PLUGINS");
	lt_dlsetsearchpath(_pluginsdir.c_str());
        sl->openLib();
        _plugins[module] = sl;
    } else {
        sl = _plugins[module];
    }

    _plugin.reset(new Handler::cygnal_init_t);

    symbol = module;
    symbol.append("_init_func");
    Handler::cygnal_io_init_t init_symptr = reinterpret_cast<Handler::cygnal_io_init_t>
	(sl->getInitEntry(symbol));
    if (!init_symptr) {
	log_network(_("No %s symbol in plugin"), symbol);
    } else {
	boost::shared_ptr<cygnal_init_t> info = init_symptr(_netconnect);
	log_network("Initialized Plugin: \"%s\": %s", info->version,
		    info->description);
    }
    
    // Look for the "module"_read_init function we'll use to get data
    // from the cgi-bin as a dynamically loadable plugin.
    symbol = module;
    symbol.append("_read_func");
    
    Handler::cygnal_io_read_t read_symptr = reinterpret_cast<Handler::cygnal_io_read_t>
	(sl->getInitEntry(symbol));

     if (!read_symptr) {    
         log_error(_("Couldn't get %s symbol"), symbol);
	 _plugin.reset();
 	 return _plugin;
     }

     _plugin->read_func = read_symptr;

     // Look for the "module"_write_init function we'll use to send data
     // to the cgi-bin as a dynamically loadable plugin.
     symbol = module;
     symbol.append("_write_func");
     Handler::cygnal_io_write_t write_symptr = reinterpret_cast<Handler::cygnal_io_write_t>
	(sl->getInitEntry(symbol));

     if (!write_symptr) {    
         log_error(_("Couldn't get %s symbol"), symbol);
	 _plugin.reset();
	 return _plugin;
     }

     _plugin->write_func = write_symptr;

    return _plugin;
}
static
globus_result_t
globus_l_extension_dlopen(
    const char *                        name,
    lt_dlhandle *                       handle)
{
    char                                library[1024];
    lt_dlhandle                         dlhandle;
    char *                              path;
    char *                              basename;
    char *                              search_path = NULL;
    char *                              save_path = NULL;
    globus_result_t                     result = GLOBUS_SUCCESS;
    GlobusFuncName(globus_l_extension_dlopen);
    
    path = globus_libc_strdup(name);
    if(path && (basename = strrchr(path, '/')))
    {
        *basename = 0;
        if(basename == path)
        {
            /* ignore root dir */
            name = path + 1;
        }
        else if(*(basename + 1) == 0)
        {
            /* ignore trailing slashes */
            name = path;
        }
        else
        {
            name = basename + 1;
            if(globus_l_globus_location)
            {
                /* if globus_location is not set, then it's likely I won't
                 * find the library
                 */
                search_path = globus_common_create_string(
                    "%s/%s", globus_l_globus_location, path);
            }
        }
    }
    
    globus_l_libtool_mutex_lock();
    
    if(search_path || globus_l_globus_location)
    {
        if((save_path = (char *) lt_dlgetsearchpath()))
        {
            /* libtool frees this pointer before setting the next one */
            save_path = globus_libc_strdup(save_path);
        }
    
        lt_dlsetsearchpath(
            search_path ? search_path : globus_l_globus_location);
    }
    
    snprintf(library, 1024, "lib%s", name);
    library[1023] = 0;
    dlhandle = lt_dlopenext(library);
    if(!dlhandle)
    {
        /* older libtools dont search the extensions correctly */
        snprintf(library, 1024, "lib%s" MY_LIB_EXT, name);
        library[1023] = 0;
        dlhandle = lt_dlopenext(library);
    }

#if USE_SYMBOL_LABELS
    if (!dlhandle)
    {
        snprintf(library, 1024, "lib%s_%s",
            name,
            (sizeof(long) == 8) ? "gcc64pthr" : "gcc32pthr");
        library[1023] = 0;
        dlhandle = lt_dlopenext(library);

        if(!dlhandle)
        {
            /* older libtools dont search the extensions correctly */
            snprintf(library, 1024, "lib%s_%s" MY_LIB_EXT, name,
                (sizeof(long) == 8) ? "gcc64pthr" : "gcc32pthr");
            library[1023] = 0;
            dlhandle = lt_dlopenext(library);
        }
    }
#endif

    if(!dlhandle)
    {
        const char *                error;
        
        error = lt_dlerror();
        
        GlobusExtensionDebugPrintf(
            GLOBUS_L_EXTENSION_DEBUG_DLL,
            (_GCSL("[%s] Couldn't dlopen %s in %s (or LD_LIBRARY_PATH): %s\n"),
             _globus_func_name, library,
             search_path ? search_path : globus_l_globus_location 
                ? globus_l_globus_location : "(default)",
             error ? error : "(null)"));
        result = globus_error_put(
            globus_error_construct_error(
                GLOBUS_EXTENSION_MODULE,
                NULL,
                GLOBUS_EXTENSION_ERROR_OPEN_FAILED,
                __FILE__,
                _globus_func_name,
                __LINE__,
                "Couldn't dlopen %s in %s (or LD_LIBRARY_PATH): %s\n",
                library,
                (search_path ? search_path : 
                               (globus_l_globus_location ? 
                                    globus_l_globus_location : 
                                "(default)")),
                error ? error : "(null)"));
    }
    
    if(search_path || globus_l_globus_location)
    {
        lt_dlsetsearchpath(save_path);
        if(save_path)
        {
            globus_free(save_path);
        }
    }
    globus_l_libtool_mutex_unlock();
    
    if(search_path)
    {
        globus_free(search_path);
    }
    
    if(path)
    {
        globus_free(path);
    }
    
    *handle = dlhandle;
    return result;
}
int pa__init(pa_module*m) {
    struct userdata *u;
    pa_sample_spec ss;
    pa_channel_map map;
    pa_modargs *ma;
    char *t;
    pa_sink *master;
    pa_sink_input_new_data sink_input_data;
    pa_sink_new_data sink_data;
    const char *plugin, *label;
    LADSPA_Descriptor_Function descriptor_func;
    const char *e, *cdata;
    const LADSPA_Descriptor *d;
    unsigned long input_port, output_port, p, j, n_control;
    unsigned c;
    pa_bool_t *use_default = NULL;

    pa_assert(m);

    pa_assert_cc(sizeof(LADSPA_Data) == sizeof(float));

    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
        pa_log("Failed to parse module arguments.");
        goto fail;
    }

    if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) {
        pa_log("Master sink not found");
        goto fail;
    }

    ss = master->sample_spec;
    ss.format = PA_SAMPLE_FLOAT32;
    map = master->channel_map;
    if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
        pa_log("Invalid sample format specification or channel map");
        goto fail;
    }

    if (!(plugin = pa_modargs_get_value(ma, "plugin", NULL))) {
        pa_log("Missing LADSPA plugin name");
        goto fail;
    }

    if (!(label = pa_modargs_get_value(ma, "label", NULL))) {
        pa_log("Missing LADSPA plugin label");
        goto fail;
    }

    cdata = pa_modargs_get_value(ma, "control", NULL);

    u = pa_xnew0(struct userdata, 1);
    u->module = m;
    m->userdata = u;
    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, NULL);

    if (!(e = getenv("LADSPA_PATH")))
        e = LADSPA_PATH;

    /* FIXME: This is not exactly thread safe */
    t = pa_xstrdup(lt_dlgetsearchpath());
    lt_dlsetsearchpath(e);
    m->dl = lt_dlopenext(plugin);
    lt_dlsetsearchpath(t);
    pa_xfree(t);

    if (!m->dl) {
        pa_log("Failed to load LADSPA plugin: %s", lt_dlerror());
        goto fail;
    }

    if (!(descriptor_func = (LADSPA_Descriptor_Function) pa_load_sym(m->dl, NULL, "ladspa_descriptor"))) {
        pa_log("LADSPA module lacks ladspa_descriptor() symbol.");
        goto fail;
    }

    for (j = 0;; j++) {

        if (!(d = descriptor_func(j))) {
            pa_log("Failed to find plugin label '%s' in plugin '%s'.", label, plugin);
            goto fail;
        }

        if (strcmp(d->Label, label) == 0)
            break;
    }

    u->descriptor = d;

    pa_log_debug("Module: %s", plugin);
    pa_log_debug("Label: %s", d->Label);
    pa_log_debug("Unique ID: %lu", d->UniqueID);
    pa_log_debug("Name: %s", d->Name);
    pa_log_debug("Maker: %s", d->Maker);
    pa_log_debug("Copyright: %s", d->Copyright);

    input_port = output_port = (unsigned long) -1;
    n_control = 0;

    for (p = 0; p < d->PortCount; p++) {

        if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) {

            if (strcmp(d->PortNames[p], "Input") == 0) {
                pa_assert(input_port == (unsigned long) -1);
                input_port = p;
            } else {
                pa_log("Found audio input port on plugin we cannot handle: %s", d->PortNames[p]);
                goto fail;
            }

        } else if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) {

            if (strcmp(d->PortNames[p], "Output") == 0) {
                pa_assert(output_port == (unsigned long) -1);
                output_port = p;
            } else {
                pa_log("Found audio output port on plugin we cannot handle: %s", d->PortNames[p]);
                goto fail;
            }

        } else if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
            n_control++;
        else {
            pa_assert(LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]));
            pa_log_debug("Ignored control output port \"%s\".", d->PortNames[p]);
        }
    }

    if ((input_port == (unsigned long) -1) || (output_port == (unsigned long) -1)) {
        pa_log("Failed to identify input and output ports. "
               "Right now this module can only deal with plugins which provide an 'Input' and an 'Output' audio port. "
               "Patches welcome!");
        goto fail;
    }

    u->block_size = pa_frame_align(pa_mempool_block_size_max(m->core->mempool), &ss);

    u->input = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size);
    if (LADSPA_IS_INPLACE_BROKEN(d->Properties))
        u->output = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size);
    else
        u->output = u->input;

    u->channels = ss.channels;

    for (c = 0; c < ss.channels; c++) {
        if (!(u->handle[c] = d->instantiate(d, ss.rate))) {
            pa_log("Failed to instantiate plugin %s with label %s for channel %i", plugin, d->Label, c);
            goto fail;
        }

        d->connect_port(u->handle[c], input_port, u->input);
        d->connect_port(u->handle[c], output_port, u->output);
    }

    if (!cdata && n_control > 0) {
        pa_log("This plugin requires specification of %lu control parameters.", n_control);
        goto fail;
    }

    if (n_control > 0) {
        const char *state = NULL;
        char *k;
        unsigned long h;

        u->control = pa_xnew(LADSPA_Data, (unsigned) n_control);
        use_default = pa_xnew(pa_bool_t, (unsigned) n_control);
        p = 0;

        while ((k = pa_split(cdata, ",", &state)) && p < n_control) {
            double f;

            if (*k == 0) {
                use_default[p++] = TRUE;
                pa_xfree(k);
                continue;
            }

            if (pa_atod(k, &f) < 0) {
                pa_log("Failed to parse control value '%s'", k);
                pa_xfree(k);
                goto fail;
            }

            pa_xfree(k);

            use_default[p] = FALSE;
            u->control[p++] = (LADSPA_Data) f;
        }

        /* The previous loop doesn't take the last control value into account
           if it is left empty, so we do it here. */
        if (*cdata == 0 || cdata[strlen(cdata) - 1] == ',') {
            if (p < n_control)
                use_default[p] = TRUE;
            p++;
        }

        if (p > n_control || k) {
            pa_log("Too many control values passed, %lu expected.", n_control);
            pa_xfree(k);
            goto fail;
        }

        if (p < n_control) {
            pa_log("Not enough control values passed, %lu expected, %lu passed.", n_control, p);
            goto fail;
        }

        h = 0;
        for (p = 0; p < d->PortCount; p++) {
            LADSPA_PortRangeHintDescriptor hint = d->PortRangeHints[p].HintDescriptor;

            if (!LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
                continue;

            if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p])) {
                for (c = 0; c < ss.channels; c++)
                    d->connect_port(u->handle[c], p, &u->control_out);
                continue;
            }

            pa_assert(h < n_control);

            if (use_default[h]) {
                LADSPA_Data lower, upper;

                if (!LADSPA_IS_HINT_HAS_DEFAULT(hint)) {
                    pa_log("Control port value left empty but plugin defines no default.");
                    goto fail;
                }

                lower = d->PortRangeHints[p].LowerBound;
                upper = d->PortRangeHints[p].UpperBound;

                if (LADSPA_IS_HINT_SAMPLE_RATE(hint)) {
                    lower *= (LADSPA_Data) ss.rate;
                    upper *= (LADSPA_Data) ss.rate;
                }

                switch (hint & LADSPA_HINT_DEFAULT_MASK) {

                    case LADSPA_HINT_DEFAULT_MINIMUM:
                        u->control[h] = lower;
                        break;

                    case LADSPA_HINT_DEFAULT_MAXIMUM:
                        u->control[h] = upper;
                        break;

                    case LADSPA_HINT_DEFAULT_LOW:
                        if (LADSPA_IS_HINT_LOGARITHMIC(hint))
                            u->control[h] = (LADSPA_Data) exp(log(lower) * 0.75 + log(upper) * 0.25);
                        else
                            u->control[h] = (LADSPA_Data) (lower * 0.75 + upper * 0.25);
                        break;

                    case LADSPA_HINT_DEFAULT_MIDDLE:
                        if (LADSPA_IS_HINT_LOGARITHMIC(hint))
                            u->control[h] = (LADSPA_Data) exp(log(lower) * 0.5 + log(upper) * 0.5);
                        else
                            u->control[h] = (LADSPA_Data) (lower * 0.5 + upper * 0.5);
                        break;

                    case LADSPA_HINT_DEFAULT_HIGH:
                        if (LADSPA_IS_HINT_LOGARITHMIC(hint))
                            u->control[h] = (LADSPA_Data) exp(log(lower) * 0.25 + log(upper) * 0.75);
                        else
                            u->control[h] = (LADSPA_Data) (lower * 0.25 + upper * 0.75);
                        break;

                    case LADSPA_HINT_DEFAULT_0:
                        u->control[h] = 0;
                        break;

                    case LADSPA_HINT_DEFAULT_1:
                        u->control[h] = 1;
                        break;

                    case LADSPA_HINT_DEFAULT_100:
                        u->control[h] = 100;
                        break;

                    case LADSPA_HINT_DEFAULT_440:
                        u->control[h] = 440;
                        break;

                    default:
                        pa_assert_not_reached();
                }
            }

            if (LADSPA_IS_HINT_INTEGER(hint))
                u->control[h] = roundf(u->control[h]);

            pa_log_debug("Binding %f to port %s", u->control[h], d->PortNames[p]);

            for (c = 0; c < ss.channels; c++)
                d->connect_port(u->handle[c], p, &u->control[h]);

            h++;
        }

        pa_assert(h == n_control);
    }

    if (d->activate)
        for (c = 0; c < u->channels; c++)
            d->activate(u->handle[c]);

    /* Create sink */
    pa_sink_new_data_init(&sink_data);
    sink_data.driver = __FILE__;
    sink_data.module = m;
    if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
        sink_data.name = pa_sprintf_malloc("%s.ladspa", master->name);
    pa_sink_new_data_set_sample_spec(&sink_data, &ss);
    pa_sink_new_data_set_channel_map(&sink_data, &map);
    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
    pa_proplist_sets(sink_data.proplist, "device.ladspa.module", plugin);
    pa_proplist_sets(sink_data.proplist, "device.ladspa.label", d->Label);
    pa_proplist_sets(sink_data.proplist, "device.ladspa.name", d->Name);
    pa_proplist_sets(sink_data.proplist, "device.ladspa.maker", d->Maker);
    pa_proplist_sets(sink_data.proplist, "device.ladspa.copyright", d->Copyright);
    pa_proplist_setf(sink_data.proplist, "device.ladspa.unique_id", "%lu", (unsigned long) d->UniqueID);

    if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
        pa_log("Invalid properties");
        pa_sink_new_data_done(&sink_data);
        goto fail;
    }

    if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
        const char *z;

        z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
        pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s", d->Name, z ? z : master->name);
    }

    u->sink = pa_sink_new(m->core, &sink_data,
                          PA_SINK_HW_MUTE_CTRL|PA_SINK_HW_VOLUME_CTRL|PA_SINK_DECIBEL_VOLUME|
                          (master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
    pa_sink_new_data_done(&sink_data);

    if (!u->sink) {
        pa_log("Failed to create sink.");
        goto fail;
    }

    u->sink->parent.process_msg = sink_process_msg_cb;
    u->sink->set_state = sink_set_state_cb;
    u->sink->update_requested_latency = sink_update_requested_latency_cb;
    u->sink->request_rewind = sink_request_rewind_cb;
    u->sink->set_volume = sink_set_volume_cb;
    u->sink->set_mute = sink_set_mute_cb;
    u->sink->userdata = u;

    pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);

    /* Create sink input */
    pa_sink_input_new_data_init(&sink_input_data);
    sink_input_data.driver = __FILE__;
    sink_input_data.module = m;
    sink_input_data.sink = master;
    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "LADSPA Stream");
    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
    pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
    pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);

    pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
    pa_sink_input_new_data_done(&sink_input_data);

    if (!u->sink_input)
        goto fail;

    u->sink_input->pop = sink_input_pop_cb;
    u->sink_input->process_rewind = sink_input_process_rewind_cb;
    u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
    u->sink_input->update_max_request = sink_input_update_max_request_cb;
    u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
    u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb;
    u->sink_input->kill = sink_input_kill_cb;
    u->sink_input->attach = sink_input_attach_cb;
    u->sink_input->detach = sink_input_detach_cb;
    u->sink_input->state_change = sink_input_state_change_cb;
    u->sink_input->may_move_to = sink_input_may_move_to_cb;
    u->sink_input->moving = sink_input_moving_cb;
    u->sink_input->volume_changed = sink_input_volume_changed_cb;
    u->sink_input->mute_changed = sink_input_mute_changed_cb;
    u->sink_input->userdata = u;

    pa_sink_put(u->sink);
    pa_sink_input_put(u->sink_input);

    pa_modargs_free(ma);

    pa_xfree(use_default);

    return 0;

fail:
    if (ma)
        pa_modargs_free(ma);

    pa_xfree(use_default);

    pa__done(m);

    return -1;
}
Exemple #27
0
int main(int argc, char *argv[]) {
    pa_core *c = NULL;
    pa_strbuf *buf = NULL;
    pa_daemon_conf *conf = NULL;
    pa_mainloop *mainloop = NULL;
    char *s;
    int r = 0, retval = 1, d = 0;
    pa_bool_t valid_pid_file = FALSE;
    pa_bool_t ltdl_init = FALSE;
    int passed_fd = -1;
    const char *e;
#ifdef HAVE_FORK
    int daemon_pipe[2] = { -1, -1 };
#endif
#ifdef OS_IS_WIN32
    pa_time_event *win32_timer;
    struct timeval win32_tv;
#endif
    int autospawn_fd = -1;
    pa_bool_t autospawn_locked = FALSE;
#ifdef HAVE_DBUS
    pa_dbus_connection *dbus = NULL;
#endif

    pa_log_set_ident("pulseaudio");
    pa_log_set_level(PA_LOG_NOTICE);
    pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET);

#if defined(__linux__) && defined(__OPTIMIZE__)
    /*
       Disable lazy relocations to make usage of external libraries
       more deterministic for our RT threads. We abuse __OPTIMIZE__ as
       a check whether we are a debug build or not. This all is
       admittedly a bit snake-oilish.
    */

    if (!getenv("LD_BIND_NOW")) {
        char *rp;
        char *canonical_rp;

        /* We have to execute ourselves, because the libc caches the
         * value of $LD_BIND_NOW on initialization. */

        pa_set_env("LD_BIND_NOW", "1");

        if ((canonical_rp = pa_realpath(PA_BINARY))) {

            if ((rp = pa_readlink("/proc/self/exe"))) {

                if (pa_streq(rp, canonical_rp))
                    pa_assert_se(execv(rp, argv) == 0);
                else
                    pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp);

                pa_xfree(rp);

            } else
                pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?");

            pa_xfree(canonical_rp);

        } else
            pa_log_warn("Couldn't canonicalize binary path, cannot self execute.");
    }
#endif

    if ((e = getenv("PULSE_PASSED_FD"))) {
        passed_fd = atoi(e);

        if (passed_fd <= 2)
            passed_fd = -1;
    }

    /* We might be autospawned, in which case have no idea in which
     * context we have been started. Let's cleanup our execution
     * context as good as possible */

    pa_reset_personality();
    pa_drop_root();
    pa_close_all(passed_fd, -1);
    pa_reset_sigs(-1);
    pa_unblock_sigs(-1);
    pa_reset_priority();

    setlocale(LC_ALL, "");
    pa_init_i18n();

    conf = pa_daemon_conf_new();

    if (pa_daemon_conf_load(conf, NULL) < 0)
        goto finish;

    if (pa_daemon_conf_env(conf) < 0)
        goto finish;

    if (pa_cmdline_parse(conf, argc, argv, &d) < 0) {
        pa_log(_("Failed to parse command line."));
        goto finish;
    }

    pa_log_set_level(conf->log_level);
    pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target);
    if (conf->log_meta)
        pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET);
    if (conf->log_time)
        pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET);
    pa_log_set_show_backtrace(conf->log_backtrace);

    LTDL_SET_PRELOADED_SYMBOLS();
    pa_ltdl_init();
    ltdl_init = TRUE;

    if (conf->dl_search_path)
        lt_dlsetsearchpath(conf->dl_search_path);

#ifdef OS_IS_WIN32
    {
        WSADATA data;
        WSAStartup(MAKEWORD(2, 0), &data);
    }
#endif

    pa_random_seed();

    switch (conf->cmd) {
        case PA_CMD_DUMP_MODULES:
            pa_dump_modules(conf, argc-d, argv+d);
            retval = 0;
            goto finish;

        case PA_CMD_DUMP_CONF: {

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            s = pa_daemon_conf_dump(conf);
            fputs(s, stdout);
            pa_xfree(s);
            retval = 0;
            goto finish;
        }

        case PA_CMD_DUMP_RESAMPLE_METHODS: {
            int i;

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            for (i = 0; i < PA_RESAMPLER_MAX; i++)
                if (pa_resample_method_supported(i))
                    printf("%s\n", pa_resample_method_to_string(i));

            retval = 0;
            goto finish;
        }

        case PA_CMD_HELP :
            pa_cmdline_help(argv[0]);
            retval = 0;
            goto finish;

        case PA_CMD_VERSION :

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");
            retval = 0;
            goto finish;

        case PA_CMD_CHECK: {
            pid_t pid;

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            if (pa_pid_file_check_running(&pid, "pulseaudio") < 0)
                pa_log_info(_("Daemon not running"));
            else {
                pa_log_info(_("Daemon running as PID %u"), pid);
                retval = 0;
            }

            goto finish;

        }
        case PA_CMD_KILL:

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0)
                pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno));
            else
                retval = 0;

            goto finish;

        case PA_CMD_CLEANUP_SHM:

            if (d < argc) {
                pa_log("Too many arguments.\n");
                goto finish;
            }

            if (pa_shm_cleanup() >= 0)
                retval = 0;

            goto finish;

        default:
            pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);
    }

    if (d < argc) {
        pa_log("Too many arguments.\n");
        goto finish;
    }

    if (getuid() == 0 && !conf->system_instance)
        pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));
    else if (getuid() != 0 && conf->system_instance) {
        pa_log(_("Root privileges required."));
        goto finish;
    }

    if (conf->cmd == PA_CMD_START && conf->system_instance) {
        pa_log(_("--start not supported for system instances."));
        goto finish;
    }

    if (conf->system_instance && !conf->disallow_exit)
        pa_log_warn(_("Running in system mode, but --disallow-exit not set!"));

    if (conf->system_instance && !conf->disallow_module_loading)
        pa_log_warn(_("Running in system mode, but --disallow-module-loading not set!"));

    if (conf->system_instance && !conf->disable_shm) {
        pa_log_notice(_("Running in system mode, forcibly disabling SHM mode!"));
        conf->disable_shm = TRUE;
    }

    if (conf->system_instance && conf->exit_idle_time >= 0) {
        pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!"));
        conf->exit_idle_time = -1;
    }

    if (conf->cmd == PA_CMD_START) {
        /* If we shall start PA only when it is not running yet, we
         * first take the autospawn lock to make things
         * synchronous. */

        if ((autospawn_fd = pa_autospawn_lock_init()) < 0) {
            pa_log("Failed to initialize autospawn lock");
            goto finish;
        }

        if ((pa_autospawn_lock_acquire(TRUE) < 0)) {
            pa_log("Failed to acquire autospawn lock");
            goto finish;
        }

        autospawn_locked = TRUE;
    }

    if (conf->daemonize) {
        pid_t child;
        int tty_fd;

        if (pa_stdio_acquire() < 0) {
            pa_log(_("Failed to acquire stdio."));
            goto finish;
        }

#ifdef HAVE_FORK
        if (pipe(daemon_pipe) < 0) {
            pa_log(_("pipe failed: %s"), pa_cstrerror(errno));
            goto finish;
        }

        if ((child = fork()) < 0) {
            pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
            goto finish;
        }

        if (child != 0) {
            ssize_t n;
            /* Father */

            pa_assert_se(pa_close(daemon_pipe[1]) == 0);
            daemon_pipe[1] = -1;

            if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {

                if (n < 0)
                    pa_log(_("read() failed: %s"), pa_cstrerror(errno));

                retval = 1;
            }

            if (retval)
                pa_log(_("Daemon startup failed."));
            else
                pa_log_info(_("Daemon startup successful."));

            goto finish;
        }

        if (autospawn_fd >= 0) {
            /* The lock file is unlocked from the parent, so we need
             * to close it in the child */

            pa_autospawn_lock_release();
            pa_autospawn_lock_done(TRUE);

            autospawn_locked = FALSE;
            autospawn_fd = -1;
        }

        pa_assert_se(pa_close(daemon_pipe[0]) == 0);
        daemon_pipe[0] = -1;
#endif

        if (conf->auto_log_target)
            pa_log_set_target(PA_LOG_SYSLOG);

#ifdef HAVE_SETSID
        setsid();
#endif
#ifdef HAVE_SETPGID
        setpgid(0,0);
#endif

#ifndef OS_IS_WIN32
        pa_close(0);
        pa_close(1);
        pa_close(2);

        pa_assert_se(open("/dev/null", O_RDONLY) == 0);
        pa_assert_se(open("/dev/null", O_WRONLY) == 1);
        pa_assert_se(open("/dev/null", O_WRONLY) == 2);
#else
        FreeConsole();
#endif

#ifdef SIGTTOU
        signal(SIGTTOU, SIG_IGN);
#endif
#ifdef SIGTTIN
        signal(SIGTTIN, SIG_IGN);
#endif
#ifdef SIGTSTP
        signal(SIGTSTP, SIG_IGN);
#endif

#ifdef TIOCNOTTY
        if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
            ioctl(tty_fd, TIOCNOTTY, (char*) 0);
            pa_assert_se(pa_close(tty_fd) == 0);
        }
#endif
    }

    pa_set_env_and_record("PULSE_INTERNAL", "1");
    pa_assert_se(chdir("/") == 0);
    umask(0022);

#ifdef HAVE_SYS_RESOURCE_H
    set_all_rlimits(conf);
#endif
    pa_rtclock_hrtimer_enable();

    pa_raise_priority(conf->nice_level);

    if (conf->system_instance)
        if (change_user() < 0)
            goto finish;

    pa_set_env_and_record("PULSE_SYSTEM", conf->system_instance ? "1" : "0");

    pa_log_info(_("This is PulseAudio %s"), PACKAGE_VERSION);
    pa_log_debug(_("Compilation host: %s"), CANONICAL_HOST);
    pa_log_debug(_("Compilation CFLAGS: %s"), PA_CFLAGS);

    s = pa_uname_string();
    pa_log_debug(_("Running on host: %s"), s);
    pa_xfree(s);

    pa_log_debug(_("Found %u CPUs."), pa_ncpus());

    pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE);

#ifdef HAVE_VALGRIND_MEMCHECK_H
    pa_log_debug(_("Compiled with Valgrind support: yes"));
#else
    pa_log_debug(_("Compiled with Valgrind support: no"));
#endif

    pa_log_debug(_("Running in valgrind mode: %s"), pa_yes_no(pa_in_valgrind()));

    pa_log_debug(_("Running in VM: %s"), pa_yes_no(pa_running_in_vm()));

#ifdef __OPTIMIZE__
    pa_log_debug(_("Optimized build: yes"));
#else
    pa_log_debug(_("Optimized build: no"));
#endif

#ifdef NDEBUG
    pa_log_debug(_("NDEBUG defined, all asserts disabled."));
#elif defined(FASTPATH)
    pa_log_debug(_("FASTPATH defined, only fast path asserts disabled."));
#else
    pa_log_debug(_("All asserts enabled."));
#endif

    if (!(s = pa_machine_id())) {
        pa_log(_("Failed to get machine ID"));
        goto finish;
    }
    pa_log_info(_("Machine ID is %s."), s);
    pa_xfree(s);

    if ((s = pa_session_id())) {
        pa_log_info(_("Session ID is %s."), s);
        pa_xfree(s);
    }

    if (!(s = pa_get_runtime_dir()))
        goto finish;
    pa_log_info(_("Using runtime directory %s."), s);
    pa_xfree(s);

    if (!(s = pa_get_state_dir()))
        goto finish;
    pa_log_info(_("Using state directory %s."), s);
    pa_xfree(s);

    pa_log_info(_("Using modules directory %s."), conf->dl_search_path);

    pa_log_info(_("Running in system mode: %s"), pa_yes_no(pa_in_system_mode()));

    if (pa_in_system_mode())
        pa_log_warn(_("OK, so you are running PA in system mode. Please note that you most likely shouldn't be doing that.\n"
                      "If you do it nonetheless then it's your own fault if things don't work as expected.\n"
                      "Please read http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode for an explanation why system mode is usually a bad idea."));

    if (conf->use_pid_file) {
        int z;

        if ((z = pa_pid_file_create("pulseaudio")) != 0) {

            if (conf->cmd == PA_CMD_START && z > 0) {
                /* If we are already running and with are run in
                 * --start mode, then let's return this as success. */

                retval = 0;
                goto finish;
            }

            pa_log(_("pa_pid_file_create() failed."));
            goto finish;
        }

        valid_pid_file = TRUE;
    }

    pa_disable_sigpipe();

    if (pa_rtclock_hrtimer())
        pa_log_info(_("Fresh high-resolution timers available! Bon appetit!"));
    else
        pa_log_info(_("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!"));

    if (conf->lock_memory) {
#ifdef HAVE_SYS_MMAN_H
        if (mlockall(MCL_FUTURE) < 0)
            pa_log_warn("mlockall() failed: %s", pa_cstrerror(errno));
        else
            pa_log_info("Sucessfully locked process into memory.");
#else
        pa_log_warn("Memory locking requested but not supported on platform.");
#endif
    }

    pa_memtrap_install();

    if (!getenv("PULSE_NO_SIMD")) {
        pa_cpu_init_x86();
        pa_cpu_init_arm();
    }

    pa_assert_se(mainloop = pa_mainloop_new());

    if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) {
        pa_log(_("pa_core_new() failed."));
        goto finish;
    }

    c->default_sample_spec = conf->default_sample_spec;
    c->default_channel_map = conf->default_channel_map;
    c->default_n_fragments = conf->default_n_fragments;
    c->default_fragment_size_msec = conf->default_fragment_size_msec;
    c->exit_idle_time = conf->exit_idle_time;
    c->scache_idle_time = conf->scache_idle_time;
    c->resample_method = conf->resample_method;
    c->realtime_priority = conf->realtime_priority;
    c->realtime_scheduling = !!conf->realtime_scheduling;
    c->disable_remixing = !!conf->disable_remixing;
    c->disable_lfe_remixing = !!conf->disable_lfe_remixing;
    c->running_as_daemon = !!conf->daemonize;
    c->disallow_exit = conf->disallow_exit;
    c->flat_volumes = conf->flat_volumes;

    pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);
    pa_signal_new(SIGINT, signal_callback, c);
    pa_signal_new(SIGTERM, signal_callback, c);
#ifdef SIGUSR1
    pa_signal_new(SIGUSR1, signal_callback, c);
#endif
#ifdef SIGUSR2
    pa_signal_new(SIGUSR2, signal_callback, c);
#endif
#ifdef SIGHUP
    pa_signal_new(SIGHUP, signal_callback, c);
#endif

#ifdef OS_IS_WIN32
    win32_timer = pa_mainloop_get_api(mainloop)->rtclock_time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&win32_tv), message_cb, NULL);
#endif

    if (!conf->no_cpu_limit)
        pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0);

    buf = pa_strbuf_new();
    if (conf->load_default_script_file) {
        FILE *f;

        if ((f = pa_daemon_conf_open_default_script_file(conf))) {
            r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail);
            fclose(f);
        }
    }

    if (r >= 0)
        r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail);

    pa_log_error("%s", s = pa_strbuf_tostring_free(buf));
    pa_xfree(s);

    /* We completed the initial module loading, so let's disable it
     * from now on, if requested */
    c->disallow_module_loading = !!conf->disallow_module_loading;

    if (r < 0 && conf->fail) {
        pa_log(_("Failed to initialize daemon."));
        goto finish;
    }

    if (!c->modules || pa_idxset_size(c->modules) == 0) {
        pa_log(_("Daemon startup without any loaded modules, refusing to work."));
        goto finish;
    }

#ifdef HAVE_FORK
    if (daemon_pipe[1] >= 0) {
        int ok = 0;
        pa_loop_write(daemon_pipe[1], &ok, sizeof(ok), NULL);
        pa_close(daemon_pipe[1]);
        daemon_pipe[1] = -1;
    }
#endif

#ifdef HAVE_DBUS
    dbus = register_dbus(c);
#endif

    pa_log_info(_("Daemon startup complete."));

    retval = 0;
    if (pa_mainloop_run(mainloop, &retval) < 0)
        goto finish;

    pa_log_info(_("Daemon shutdown initiated."));

finish:
#ifdef HAVE_DBUS
    if (dbus)
        pa_dbus_connection_unref(dbus);
#endif

    if (autospawn_fd >= 0) {
        if (autospawn_locked)
            pa_autospawn_lock_release();

        pa_autospawn_lock_done(FALSE);
    }

#ifdef OS_IS_WIN32
    if (win32_timer)
        pa_mainloop_get_api(mainloop)->time_free(win32_timer);
#endif

    if (c) {
        pa_core_unref(c);
        pa_log_info(_("Daemon terminated."));
    }

    if (!conf->no_cpu_limit)
        pa_cpu_limit_done();

    pa_signal_done();

#ifdef HAVE_FORK
    if (daemon_pipe[1] >= 0)
        pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);

    pa_close_pipe(daemon_pipe);
#endif

    if (mainloop)
        pa_mainloop_free(mainloop);

    if (conf)
        pa_daemon_conf_free(conf);

    if (valid_pid_file)
        pa_pid_file_remove();

    /* This has no real purpose except making things valgrind-clean */
    pa_unset_env_recorded();

#ifdef OS_IS_WIN32
    WSACleanup();
#endif

    if (ltdl_init)
        pa_ltdl_done();

#ifdef HAVE_DBUS
    dbus_shutdown();
#endif

    return retval;
}
void
DynamicLoaderModule::LoadModuleFunction::execute( SLIInterpreter* i ) const
{
  i->assert_stack_load( 1 );

  sDynModule new_module;

  new_module.name = getValue< std::string >( i->OStack.top() );
  if ( new_module.name.empty() )
    throw DynamicModuleManagementError( "Module name must not be empty." );

  // check if module already loaded
  // this check can happen here, since we are comparing dynamically loaded modules
  // based on the name given to the Install command
  if ( std::find( dyn_modules_.begin(), dyn_modules_.end(), new_module ) != dyn_modules_.end() )
    throw DynamicModuleManagementError( "Module '" + new_module.name + "' is loaded already." );

  // call lt_dlerror() to reset any error messages hanging around
  lt_dlerror();
  int searchpath_result = lt_dlsetsearchpath( SLI_PREFIX "/lib/nest" );
  if ( searchpath_result != 0 )
  {
    char* errstr = ( char* ) lt_dlerror();
    std::string msg = "Could not set user search path: " SLI_PREFIX "/lib/nest";
    if ( errstr )
      msg += "\nThe dynamic loader returned the following error: '" + std::string( errstr ) + "'.";
    throw DynamicModuleManagementError( msg );
  }

  // try to open the module
  const lt_dlhandle hModule = lt_dlopenext( new_module.name.c_str() );

  if ( !hModule )
  {
    char* errstr = ( char* ) lt_dlerror();
    std::string msg = "Module '" + new_module.name + "' could not be opened.";
    if ( errstr )
      msg += "\nThe dynamic loader returned the following error: '" + std::string( errstr ) + "'.";
    msg += "\n\nPlease check LD_LIBRARY_PATH (OSX: DYLD_LIBRARY_PATH)!";
    throw DynamicModuleManagementError( msg );
  }

  // see if we can find the mod symbol in the module
  SLIModule* pModule = ( SLIModule* ) lt_dlsym( hModule, "mod" );
  char* errstr = ( char* ) lt_dlerror();
  if ( errstr )
  {
    lt_dlclose( hModule ); // close module again
    lt_dlerror();          // remove any error caused by lt_dlclose()
    throw DynamicModuleManagementError(
            "Module '" + new_module.name + "' could not be loaded.\n"
            "The dynamic loader returned the following error: '" 
            + std::string(errstr) + "'.");
  }

  // check if module is linked in. This test is based on the module name
  // returned by DynModule::name(), since we have no file names for linked modules.
  // We can only perform it after we have loaded the module.
  if ( std::find_if( DynamicLoaderModule::getLinkedModules().begin(),
         DynamicLoaderModule::getLinkedModules().end(),
         std::bind2nd( std::ptr_fun( has_name ), pModule->name() ) )
    != DynamicLoaderModule::getLinkedModules().end() )
  {
    lt_dlclose( hModule ); // close module again
    lt_dlerror();          // remove any error caused by lt_dlclose()
    throw DynamicModuleManagementError(
            "Module '" + new_module.name + "' is linked into NEST.\n"
            "You neither need nor may load it dynamically in addition.");
  }

  // all is well an we can register the module with the interpreter
  try
  {
    pModule->install( std::cerr, i );
  }
  catch ( std::exception& e )
  {
    // We should uninstall the partially installed module here, but
    // this must wait for #152.
    // For now, we just close the module file and rethrow the exception.

    lt_dlclose( hModule );
    lt_dlerror(); // remove any error caused by lt_dlclose()
    throw;        // no arg re-throws entire exception, see Stroustrup 14.3.1
  }

  // add the handle to list of loaded modules
  new_module.handle = hModule;
  new_module.pModule = pModule;
  dyn_modules_.push_back( new_module );

  LOG( M_INFO, "Install", ( "loaded module " + pModule->name() ).c_str() );

  // remove operand and operator from stack
  i->OStack.pop();
  i->EStack.pop();

  // put handle to module onto stack
  int moduleid = dyn_modules_.size() - 1;
  i->OStack.push( moduleid );
  ( *moduledict_ )[ new_module.name ] = moduleid;

  // now we can run the module initializer, after we have cleared the EStack
  if ( !pModule->commandstring().empty() )
  {
    Token t = new StringDatum( pModule->commandstring() );
    i->OStack.push_move( t );
    Token c = new NameDatum( "initialize_module" );
    i->EStack.push_move( c );
  }
}