コード例 #1
0
ファイル: test_util.c プロジェクト: KyleSanderson/serf
const char * get_srcdir_file(apr_pool_t *pool, const char * file)
{
    char *srcdir = "";

    if (apr_env_get(&srcdir, "srcdir", pool) == APR_SUCCESS) {
        return apr_pstrcat(pool, srcdir, "/", file, NULL);
    }
    else {
        return file;
    }
}
コード例 #2
0
ファイル: libpath.c プロジェクト: dekellum/hashdot
apr_status_t exec_self( int argc,
                        const char *argv[] )
{
    apr_status_t rv = APR_SUCCESS;
    apr_array_header_t *dpaths =
        get_property_array( "hashdot.vm.libpath" );

    if( dpaths == NULL ) return rv;

    char * ldpenv = NULL;
    apr_env_get( &ldpenv, LIB_PATH_VAR, _mp );

    apr_array_header_t *newpaths =
        apr_array_make( _mp, 8, sizeof( const char* ) );
    int i;
    for( i = 0; i < dpaths->nelts; i++ ) {
        const char *path = ((const char **) dpaths->elts )[i];
        if( !ldpenv || !strstr( ldpenv, path ) ) {
            *( (const char **) apr_array_push( newpaths ) ) = path;
            DEBUG( "New path to add: %s", path );
        }
    }

    // Need to set LD_LIBRARY_PATH, new paths found.
    if( newpaths->nelts > 0 ) {
        if( ldpenv ) {
            *( (const char **) apr_array_push( newpaths ) ) = ldpenv;
        }
        ldpenv = apr_array_pstrcat( _mp, newpaths, ':' );
        DEBUG( "New %s = [%s]", LIB_PATH_VAR, ldpenv );
        rv = apr_env_set( LIB_PATH_VAR, ldpenv, _mp );

        const char *exe_name = NULL;
        if( rv == APR_SUCCESS ) {
            rv = find_self_exe( &exe_name );
        }

        // Exec using linux(-only?) /proc/self/exe link to self,
        // instead of argv[0], since the later will not specify a path
        // when initial call is made via PATH, and since execve won't
        // itself look at PATH.
        // Note: Can't use apr_proc_create for this, since it always
        // forks first.

        if( rv == APR_SUCCESS ) {
            DEBUG( "Exec'ing self as %s", argv[0] );
            execv( exe_name, (char * const *) argv );
            rv = APR_FROM_OS_ERROR( errno ); //shouldn't return from execv call
        }
    }

    return rv;
}
コード例 #3
0
ファイル: testenv.c プロジェクト: kheradmand/Break
static void test_getenv(CuTest *tc)
{
    char *value;
    apr_status_t rv;

    if (!have_env_set) {
        CuNotImpl(tc, "apr_env_set (skip test for apr_env_get)");
        return;
    }

    rv = apr_env_get(&value, TEST_ENVVAR_NAME, p);
    have_env_get = (rv != APR_ENOTIMPL);
    if (!have_env_get) {
        CuNotImpl(tc, "apr_env_get");
        return;
    }
    apr_assert_success(tc, "get environment variable", rv);
    CuAssertStrEquals(tc, TEST_ENVVAR_VALUE, value);
}
コード例 #4
0
ファイル: testenv.c プロジェクト: AAthresh/quantlib
static void test_getenv(abts_case *tc, void *data)
{
    char *value;
    apr_status_t rv;

    if (!have_env_set) {
        ABTS_NOT_IMPL(tc, "apr_env_set (skip test for apr_env_get)");
        return;
    }

    rv = apr_env_get(&value, TEST_ENVVAR_NAME, p);
    have_env_get = (rv != APR_ENOTIMPL);
    if (!have_env_get) {
        ABTS_NOT_IMPL(tc, "apr_env_get");
        return;
    }
    APR_ASSERT_SUCCESS(tc, "get environment variable", rv);
    ABTS_STR_EQUAL(tc, TEST_ENVVAR_VALUE, value);
}
コード例 #5
0
ファイル: env.c プロジェクト: LuaDist/lua-apr
int lua_apr_env_get(lua_State *L)
{
  apr_pool_t *memory_pool;
  apr_status_t status;
  const char *name;
  char *value;

  memory_pool = to_pool(L);
  name = luaL_checkstring(L, 1);
  status = apr_env_get(&value, name, memory_pool);
  if (APR_STATUS_IS_ENOENT(status)) {
    return 0;
  } else if (status != APR_SUCCESS) {
    return push_error_status(L, status);
  } else {
    lua_pushstring(L, value);
    return 1;
  }
}
コード例 #6
0
ファイル: thread_pool_config.c プロジェクト: accre/lstore
void thread_pool_stats_init()
{
    int i;
    char *eval;

    //** Check if we are enabling stat collection
    eval = NULL;
    apr_env_get(&eval, "GOP_TP_STATS", _tp_pool);
    if (eval != NULL) {
        i = atol(eval);
        if (i > 0) {
            _tp_stats = i;

            if (thread_local_stats_key == NULL) {
                apr_threadkey_private_create(&thread_local_stats_key,_thread_pool_destructor, _tp_pool);
                thread_pool_stats_make();
            }
        }
    }
}
コード例 #7
0
ファイル: iconv_module.c プロジェクト: Ga-vin/apache
static apr_status_t
iconv_getpath(char *buf, const char *name, apr_pool_t *ctx)
{
	char buffer[APR_PATH_MAX];
        apr_array_header_t *pathelts;
        apr_pool_t *subpool;
        apr_status_t status;
	char *ptr;

        status = apr_pool_create(&subpool, ctx);
        if (status)
            return status;

	if (apr_tolower(name[0]) == 'x' && name[1] == '-')
		name += 2;
        ptr = buffer;
        while (0 != (*ptr++ = apr_tolower(*name++)))
            ;

        if (!apr_env_get(&ptr, "APR_ICONV_PATH", subpool)
            && !apr_filepath_list_split(&pathelts, ptr, subpool))
        {
            int i;
            char **elts = (char **)pathelts->elts;
            for (i = 0; i < pathelts->nelts; ++i)
            {
                if (iconv_getpathname(buf, elts[i], buffer, subpool) == 0)
                {
                    apr_pool_destroy(subpool);
                    return APR_SUCCESS;
                }
            }
        }

        status = iconv_getpathname(buf, ICONV_DEFAULT_PATH, buffer, subpool);
        apr_pool_destroy(subpool);
        return status;
}
コード例 #8
0
ファイル: apu_dso.c プロジェクト: cmjonze/apr
apr_status_t apu_dso_load(apr_dso_handle_t **dlhandleptr,
                          apr_dso_handle_sym_t *dsoptr,
                          const char *module,
                          const char *modsym,
                          apr_pool_t *pool)
{
    apr_dso_handle_t *dlhandle = NULL;
    char *pathlist;
    char path[APR_PATH_MAX + 1];
    apr_array_header_t *paths;
    apr_pool_t *global;
    apr_status_t rv = APR_EDSOOPEN;
    char *eos = NULL;
    int i;

    *dsoptr = apr_hash_get(dsos, module, APR_HASH_KEY_STRING);
    if (*dsoptr) {
        return APR_EINIT;
    }

    /* The driver DSO must have exactly the same lifetime as the
     * drivers hash table; ignore the passed-in pool */
    global = apr_hash_pool_get(dsos);

    /* Retrieve our path search list or prepare for a single search */
    if ((apr_env_get(&pathlist, APR_DSOPATH, pool) != APR_SUCCESS)
          || (apr_filepath_list_split(&paths, pathlist, pool) != APR_SUCCESS))
        paths = apr_array_make(pool, 1, sizeof(char*));

#if defined(APR_DSO_LIBDIR)
    /* Always search our prefix path, but on some platforms such as
     * win32 this may be left undefined
     */
    (*((char **)apr_array_push(paths))) = APR_DSO_LIBDIR;
#endif

    for (i = 0; i < paths->nelts; ++i)
    {
#if defined(WIN32)
        /* Use win32 dso search semantics and attempt to
         * load the relative lib on the first pass.
         */
        if (!eos) {
            eos = path;
            --i;
        }
        else
#endif
        {
            eos = apr_cpystrn(path, ((char**)paths->elts)[i], sizeof(path));
            if ((eos > path) && (eos - path < sizeof(path) - 1))
                *(eos++) = '/';
        }
        apr_cpystrn(eos, module, sizeof(path) - (eos - path));

        rv = apr_dso_load(&dlhandle, path, global);
        if (dlhandleptr) {
            *dlhandleptr = dlhandle;
        }
        if (rv == APR_SUCCESS) { /* APR_EDSOOPEN */
            break;
        }
#if defined(APR_DSO_LIBDIR)
        else if (i < paths->nelts - 1) {
#else
        else {   /* No APR_DSO_LIBDIR to skip */
#endif
             /* try with apr-APR_MAJOR_VERSION appended */
            eos = apr_cpystrn(eos,
                              "apr-" APR_STRINGIFY(APR_MAJOR_VERSION) "/",
                              sizeof(path) - (eos - path));

            apr_cpystrn(eos, module, sizeof(path) - (eos - path));

            rv = apr_dso_load(&dlhandle, path, global);
            if (dlhandleptr) {
                *dlhandleptr = dlhandle;
            }
            if (rv == APR_SUCCESS) { /* APR_EDSOOPEN */
                break;
            }
        }
    }

    if (rv != APR_SUCCESS) /* APR_ESYMNOTFOUND */
        return rv;

    rv = apr_dso_sym(dsoptr, dlhandle, modsym);
    if (rv != APR_SUCCESS) { /* APR_ESYMNOTFOUND */
        apr_dso_unload(dlhandle);
    }
    else {
        module = apr_pstrdup(global, module);
        apr_hash_set(dsos, module, APR_HASH_KEY_STRING, *dsoptr);
    }
    return rv;
}
コード例 #9
0
ファイル: gpsmon.c プロジェクト: phan-pivotal/gpdb
void gx_main(int port, apr_int64_t signature)
{
	/* set up our log files */
	if (opt.log_dir)
	{
		mkdir(opt.log_dir, S_IRWXU | S_IRWXG);

		if (0 != chdir(opt.log_dir))
		{
			/* Invalid dir for log file, try home dir */
			char *home_dir = NULL;
			if (0 == apr_env_get(&home_dir, "HOME", gx.pool))
			{
				if (home_dir)
					chdir(home_dir);
			}
		}
	}

	update_log_filename();
	freopen(log_filename, "w", stdout);
	setlinebuf(stdout);

	if (!get_and_allocate_hostname())
		gpsmon_fatalx(FLINE, 0, "failed to allocate memory for hostname");
	TR0(("HOSTNAME = '%s'\n", gx.hostname));



	// first chace to write to log file
	TR2(("signature = %" FMT64 "\n", signature));
	TR1(("detected %d cpu cores\n", number_cpu_cores));

	setup_gx(port, signature);
	setup_sigar();
	setup_udp();
	setup_tcp();

	gx.tick = 0;
	for (;;)
	{
		struct timeval tv;
		apr_hash_index_t* hi;

		/* serve events every 2 second */
		gx.tick++;
		gx.now = time(NULL);
		tv.tv_sec = 2;
		tv.tv_usec = 0;

		/* event dispatch blocks for a certain time based on the seconds given
		 * to event_loopexit */
		if (-1 == event_loopexit(&tv))
		{
			gpmon_warningx(FLINE, APR_FROM_OS_ERROR(errno),
					"event_loopexit failed");
		}

		if (-1 == event_dispatch())
		{
			gpsmon_fatalx(FLINE, APR_FROM_OS_ERROR(errno), "event_dispatch failed");
		}

		/* get pid metrics */
		for (hi = apr_hash_first(0, gx.qexectab); hi; hi = apr_hash_next(hi))
		{
            void* vptr;
            gpmon_qexec_t* rec;
            apr_hash_this(hi, 0, 0, &vptr);
            rec = vptr;
            get_pid_metrics(rec->key.hash_key.pid,
                    rec->key.tmid,
                    rec->key.ssid,
                    rec->key.ccnt);
		}

		/* check log size */
		if (gx.tick % 60 == 0)
		{
			apr_finfo_t finfo;
			if (0 == apr_stat(&finfo, log_filename, APR_FINFO_SIZE, gx.pool))
			{
				if (opt.max_log_size != 0 && finfo.size > opt.max_log_size)
				{
					update_log_filename();
					freopen(log_filename, "w", stdout);
					setlinebuf(stdout);
				}
			}
		}
	}
}
コード例 #10
0
ファイル: util.c プロジェクト: 2asoft/freebsd
svn_error_t *
svn_cl__merge_file_externally(const char *base_path,
                              const char *their_path,
                              const char *my_path,
                              const char *merged_path,
                              const char *wc_path,
                              apr_hash_t *config,
                              svn_boolean_t *remains_in_conflict,
                              apr_pool_t *pool)
{
  char *merge_tool;
  /* Error if there is no editor specified */
  if (apr_env_get(&merge_tool, "SVN_MERGE", pool) != APR_SUCCESS)
    {
      struct svn_config_t *cfg;
      merge_tool = NULL;
      cfg = config ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG) : NULL;
      /* apr_env_get wants char **, this wants const char ** */
      svn_config_get(cfg, (const char **)&merge_tool,
                     SVN_CONFIG_SECTION_HELPERS,
                     SVN_CONFIG_OPTION_MERGE_TOOL_CMD, NULL);
    }

  if (merge_tool)
    {
      const char *c;

      for (c = merge_tool; *c; c++)
        if (!svn_ctype_isspace(*c))
          break;

      if (! *c)
        return svn_error_create
          (SVN_ERR_CL_NO_EXTERNAL_MERGE_TOOL, NULL,
           _("The SVN_MERGE environment variable is empty or "
             "consists solely of whitespace. Expected a shell command.\n"));
    }
  else
      return svn_error_create
        (SVN_ERR_CL_NO_EXTERNAL_MERGE_TOOL, NULL,
         _("The environment variable SVN_MERGE and the merge-tool-cmd run-time "
           "configuration option were not set.\n"));

  {
    const char *arguments[7] = { 0 };
    char *cwd;
    int exitcode;

    apr_status_t status = apr_filepath_get(&cwd, APR_FILEPATH_NATIVE, pool);
    if (status != 0)
      return svn_error_wrap_apr(status, NULL);

    arguments[0] = merge_tool;
    arguments[1] = base_path;
    arguments[2] = their_path;
    arguments[3] = my_path;
    arguments[4] = merged_path;
    arguments[5] = wc_path;
    arguments[6] = NULL;

    SVN_ERR(svn_io_run_cmd(svn_dirent_internal_style(cwd, pool), merge_tool,
                           arguments, &exitcode, NULL, TRUE, NULL, NULL, NULL,
                           pool));
    /* Exit code 0 means the merge was successful.
     * Exit code 1 means the file was left in conflict but it
     * is OK to continue with the merge.
     * Any other exit code means there was a real problem. */
    if (exitcode != 0 && exitcode != 1)
      return svn_error_createf(SVN_ERR_EXTERNAL_PROGRAM, NULL,
        _("The external merge tool '%s' exited with exit code %d."),
        merge_tool, exitcode);
    else if (remains_in_conflict)
      *remains_in_conflict = exitcode == 1;
  }
  return SVN_NO_ERROR;
}
コード例 #11
0
ファイル: tempdir.c プロジェクト: kheradmand/Break
APR_DECLARE(apr_status_t) apr_temp_dir_get(const char **temp_dir, 
                                           apr_pool_t *p)
{
    apr_status_t apr_err;
    const char *try_dirs[] = { "/tmp", "/usr/tmp", "/var/tmp" };
    const char *try_envs[] = { "TMP", "TEMP", "TMPDIR" };
    char *cwd;
    int i;

    /* Our goal is to find a temporary directory suitable for writing
       into.  We'll only pay the price once if we're successful -- we
       cache our successful find.  Here's the order in which we'll try
       various paths:

          $TMP
          $TEMP
          $TMPDIR
          "C:\TEMP"     (windows only)
          "SYS:\TMP"    (netware only)
          "/tmp"
          "/var/tmp"
          "/usr/tmp"
          P_tmpdir      (POSIX define)
          `pwd` 

       NOTE: This algorithm is basically the same one used by Python
       2.2's tempfile.py module.  */

    /* Try the environment first. */
    for (i = 0; i < (sizeof(try_envs) / sizeof(const char *)); i++) {
        char *value;
        apr_err = apr_env_get(&value, try_envs[i], p);
        if ((apr_err == APR_SUCCESS) && value) {
            apr_size_t len = strlen(value);
            if (len && (len < APR_PATH_MAX) && test_tempdir(value, p)) {
                memcpy(global_temp_dir, value, len + 1);
                goto end;
            }
        }
    }

#ifdef WIN32
    /* Next, on Win32, try the C:\TEMP directory. */
    if (test_tempdir("C:\\TEMP", p)) {
        memcpy(global_temp_dir, "C:\\TEMP", 7 + 1);
        goto end;
    }
#endif
#ifdef NETWARE
    /* Next, on NetWare, try the SYS:/TMP directory. */
    if (test_tempdir("SYS:/TMP", p)) {
        memcpy(global_temp_dir, "SYS:/TMP", 8 + 1);
        goto end;
    }
#endif

    /* Next, try a set of hard-coded paths. */
    for (i = 0; i < (sizeof(try_dirs) / sizeof(const char *)); i++) {
        if (test_tempdir(try_dirs[i], p)) {
            memcpy(global_temp_dir, try_dirs[i], strlen(try_dirs[i]) + 1);
            goto end;
        }
    }

#ifdef P_tmpdir
    /* 
     * If we have it, use the POSIX definition of where 
     * the tmpdir should be 
     */
    if (test_tempdir(P_tmpdir, p)) {
        memcpy(global_temp_dir, P_tmpdir, strlen(P_tmpdir) +1);
        goto end;
    }
#endif
    
    /* Finally, try the current working directory. */
    if (APR_SUCCESS == apr_filepath_get(&cwd, APR_FILEPATH_NATIVE, p)) {
        if (test_tempdir(cwd, p)) {
            memcpy(global_temp_dir, cwd, strlen(cwd) + 1);
            goto end;
        }
    }

end:
    if (global_temp_dir[0]) {
        *temp_dir = apr_pstrdup(p, global_temp_dir);
        return APR_SUCCESS;
    }
    return APR_EGENERAL;
}
コード例 #12
0
ファイル: icl_mem.c プロジェクト: cookrn/openamq
void
    icl_mem_initialise (
void)
{
apr_status_t
    status;
char
    *value;

    //  Test for already active before applying any locks; avoids deadlock in
    //  some classes
    if (!s_icl_mem_active) {

#if (defined (BASE_THREADSAFE))
        //  First make sure the object mutex has been created
        if (!icl_global_mutex) {
            icl_system_panic ("icl_init", "iCL not initialised - call icl_system_initialise()\n");
            abort ();
        }
        apr_thread_mutex_lock (icl_global_mutex);
        if (!s_icl_mem_mutex)
            s_icl_mem_mutex = icl_mutex_new ();
        apr_thread_mutex_unlock (icl_global_mutex);

        //  Now lock the object mutex
        icl_mutex_lock   (s_icl_mem_mutex);

        //  Test again for already active now that we hold the lock
        if (!s_icl_mem_active) {
#endif
            //  Register the class termination call-back functions
            icl_system_register (NULL, self_terminate);
    //
    status = apr_env_get (&value, "ALLOCATOR", icl_global_pool);
    if (status == APR_SUCCESS) {
        if (streq (value, "thin"))
            icl_mem_allocator = ICL_MEM_THIN;
        else if (streq (value, "fat"))
            icl_mem_allocator = ICL_MEM_FAT;
        else if (streq (value, "direct"))
            icl_mem_allocator = ICL_MEM_DIRECT;
        else {
            icl_system_panic ("icl_mem", "Unknown allocator: %s, legal values are 'fat', 'thin', 'direct'", value);
            abort ();
        }
    }
    else
        //  If no value was provided choose a default based on value of DEBUG
#if defined (DEBUG)
        icl_mem_allocator = ICL_MEM_FAT;
#else
        icl_mem_allocator = ICL_MEM_DIRECT;
#endif
            s_icl_mem_active = TRUE;
#if (defined (BASE_THREADSAFE))
        }
        icl_mutex_unlock (s_icl_mem_mutex);
#endif

    }
}
コード例 #13
0
APR_DECLARE(apr_status_t) port_dso_search_path(char** path,
										apr_pool_t* pool) {
	return apr_env_get(path, "PATH", pool);
}
コード例 #14
0
ファイル: mod_trell_ops.c プロジェクト: KjeFre/tinia
/** Try to start a process running the master job. */
static int
trell_start_master( trell_sconf_t* svr_conf,  request_rec* r )
{
    apr_status_t rv;
    
    // Open file into which master job stdout is piped.
    apr_file_t* master_stdout = NULL;
    rv = apr_file_open( &master_stdout,
                        apr_psprintf( r->pool, "/tmp/%s.stdout", svr_conf->m_master_id ),
                        APR_FOPEN_CREATE | APR_WRITE | APR_TRUNCATE | APR_XTHREAD,
                        APR_OS_DEFAULT, r->pool );
    if( rv != APR_SUCCESS ) {
        ap_log_rerror( APLOG_MARK, APLOG_CRIT, rv, r, "mod_trell: Failed to open master job stdout" );
        return rv;
    }
        
    // Open file into which master job stderr is piped.
    apr_file_t* master_stderr = NULL;
    rv = apr_file_open( &master_stderr,
                        apr_psprintf( r->pool, "/tmp/%s.stderr", svr_conf->m_master_id ),
                        APR_FOPEN_CREATE | APR_WRITE | APR_TRUNCATE | APR_XTHREAD,
                        APR_OS_DEFAULT, r->pool );
    if( rv != APR_SUCCESS ) {
        ap_log_rerror( APLOG_MARK, APLOG_CRIT, rv, r, "mod_trell: Failed to open master job stderr" );
        return rv;
    }

    // Create process attribute and set file handles for pipes
    apr_procattr_t* procattr;
    
    rv = apr_procattr_create( &procattr, r->pool );
    if( rv != APR_SUCCESS ) {
        ap_log_rerror( APLOG_MARK, APLOG_CRIT, rv, r, "mod_trell: apr_procattr_create failed" );
        return rv;
    }
    
    rv = apr_procattr_child_out_set( procattr, master_stdout, NULL );
    if( rv != APR_SUCCESS ) {
        ap_log_rerror( APLOG_MARK, APLOG_CRIT, rv, r, "mod_trell: apr_procattr_child_out_set failed" );
        return rv;
    }
    
    rv = apr_procattr_child_err_set( procattr, master_stderr, NULL );
    if( rv != APR_SUCCESS ) {
        ap_log_rerror( APLOG_MARK, APLOG_CRIT, rv, r, "mod_trell: apr_procattr_child_err_set failed" );
        return rv;
    }
    
    rv = apr_procattr_cmdtype_set( procattr, APR_PROGRAM );
    if( rv != APR_SUCCESS ) {
        ap_log_rerror( APLOG_MARK, APLOG_CRIT, rv, r, "mod_trell: apr_procattr_cmdtype_set failed" );
        return rv;
    }


    const char* env[7] = {
        apr_psprintf( r->pool, "TINIA_JOB_ID=%s",    svr_conf->m_master_id ),
        apr_psprintf( r->pool, "TINIA_MASTER_ID=%s", svr_conf->m_master_id ),
        apr_psprintf( r->pool, "TINIA_APP_ROOT=%s",  svr_conf->m_app_root_dir ),
        NULL,   // PATH
        NULL,   // LD_LIBRARY_PATH
        NULL,   // DISPLAY
        NULL
    };

    // Copy PATH and LD_LIBRARY_PATH from the current environement, if set. It
    // might be an idea to pass these variables through the apache-config,
    // allowing more detailded control on jobs.
    int p = 3;
    char* PATH = NULL;
    if( (apr_env_get( &PATH, "PATH", r->pool ) == APR_SUCCESS ) &&
            (PATH != NULL) )
    {
        env[p++] = apr_psprintf( r->pool, "PATH=%s", PATH );
    } 
    char* LD_LIBRARY_PATH = NULL;
    if( (apr_env_get( &LD_LIBRARY_PATH, "LD_LIBRARY_PATH", r->pool ) == APR_SUCCESS ) &&
            (LD_LIBRARY_PATH != NULL) )
    {
        env[p++] = apr_psprintf( r->pool, "LD_LIBRARY_PATH=%s", LD_LIBRARY_PATH );
    }
    char* DISPLAY = NULL;
    if( (apr_env_get( &DISPLAY, "DISPLAY", r->pool ) == APR_SUCCESS ) &&
            (DISPLAY != NULL) )
    {
        env[p++] = apr_psprintf( r->pool, "DISPLAY=%s", DISPLAY );
    }
    
    // Set up arguments            
    const char* args[2] = {
        svr_conf->m_master_exe,
        NULL
    };

    
    apr_proc_t newproc;
    rv = apr_proc_create( &newproc,
                          svr_conf->m_master_exe,
                          args,
                          env,
                          procattr,
                          r->pool );
    if( rv != APR_SUCCESS ) {
        ap_log_rerror( APLOG_MARK, APLOG_CRIT, rv, r, "mod_trell: Failed to execute '%s'", svr_conf->m_master_exe );
        return rv;
    }
    
    rv = trell_set_master_pid( svr_conf, r, newproc.pid );
    if( rv != APR_SUCCESS ) {
        return rv;
    }
    
    ap_log_rerror( APLOG_MARK, APLOG_NOTICE, OK, r, "mod_trell: Master running at pid %d", newproc.pid );
    return APR_SUCCESS;    
}