Exemple #1
0
int main(int argc, const char* argv[])
{
    printf("[BEGIN] crt-vars-libSystem\n");
    bool success = true;

    if ( _NSGetArgv() != &NXArgv ) {
        printf("[FAIL] crt-libSystem: _NSGetArgv() != &NXArgv (%p!=%p) for %s", _NSGetArgv(), &NXArgv, argv[0]);
        success = false;
    }

    if ( _NSGetArgc() != &NXArgc ) {
        printf("[FAIL] crt-libSystem: _NSGetArgc() != &NXArgc (%p!=%p) for %s", _NSGetArgc(), &NXArgc, argv[0]);
        success = false;
    }

    if ( _NSGetEnviron() != &environ ) {
        printf("[FAIL] crt-libSystem: _NSGetEnviron() != &environv (%p!=%p) for %s", _NSGetEnviron(), &environ, argv[0]);
        success = false;
    }

    if ( _NSGetProgname() != &__progname ) {
        printf("[FAIL] crt-libSystem: _NSGetProgname() != &__progname (%p!=%p) for %s", _NSGetProgname(), &__progname, argv[0]);
        success = false;
    }

    if ( _NSGetMachExecuteHeader() != &_mh_execute_header ) {
        printf("[FAIL] crt-libSystem: _NSGetMachExecuteHeader() != &_mh_execute_headerv (%p!=%p) for %s", _NSGetMachExecuteHeader(), &_mh_execute_header, argv[0]);
        success = false;
    }

    if ( sVars->NXArgvPtr != &NXArgv ) {
        printf("[FAIL] crt-libSystem: sVars->NXArgvPtr != &NXArg (%p!=%p) for %s", sVars->NXArgvPtr, &NXArgv, argv[0]);
        success = false;
    }

    if ( sVars->NXArgcPtr != &NXArgc ) {
        printf("[FAIL] crt-libSystem: sVars->NXArgcPtr != &NXArgc (%p!=%p) for %s", sVars->NXArgcPtr, &NXArgc, argv[0]);
        success = false;
    }

    if ( sVars->environPtr != &environ ) {
        printf("[FAIL] crt-libSystem: sVars->environPtr != &environ (%p!=%p) for %s", sVars->environPtr, &environ, argv[0]);
        success = false;
    }

    if ( sVars->__prognamePtr != &__progname ) {
        printf("[FAIL] crt-libSystem: sVars->__prognamePtr != &__progname (%p!=%p) for %s", sVars->__prognamePtr, &__progname, argv[0]);
        success = false;
    }

    if ( sVars->mh != &_mh_execute_header ) {
        printf("[FAIL] crt-libSystem: sVars->mh != &_mh_execute_header (%p!=%p) for %s", sVars->mh, &_mh_execute_header, argv[0]);
        success = false;
    }

    if ( success )
        printf("[PASS] crt-vars-libSystem\n");

    return 0;
}
Exemple #2
0
static void on_load(void) {
#ifdef HAVE_NSGETENVIRON
    environ = *_NSGetEnviron();
#endif
    if (!initialized)
        initialized = bear_capture_env_t(&initial_env);
}
Exemple #3
0
static void sanitizeEnviron (void)
{
	char **e = NULL;
	int i;

#if HAVE_DECL___ENVIRON
	e = __environ;
#elif HAVE_DECL__NSGETENVIRON
{
	char ***ep = _NSGetEnviron();
	if (ep)
		e = *ep;
}
#endif

	if (!e)
		return;

	for (i = 0; e [i]; i++)
	{
		char *value;

		value = strchr (e [i], '=');
		if (!value)
			continue;

		value++;
		if (!strncmp (value, "() {", 4))
		{
			error (WARNING, "reset environment: %s", e [i]);
			value [0] = '\0';
		}
	}
}
Exemple #4
0
char *os_getenvname_at_index(size_t index)
{
# if defined(AMIGA) || defined(__MRC__) || defined(__SC__)
  // No environ[] on the Amiga and on the Mac (using MPW).
  return NULL;
# else
# if defined(HAVE__NSGETENVIRON)
  char **environ = *_NSGetEnviron();
# elif !defined(__WIN32__)
  // Borland C++ 5.2 has this in a header file.
  extern char         **environ;
# endif
  // check if index is inside the environ array
  for (size_t i = 0; i < index; i++) {
    if (environ[i] == NULL) {
      return NULL;
    }
  }
  char *str = environ[index];
  if (str == NULL) {
    return NULL;
  }
  int namesize = 0;
  while (str[namesize] != '=' && str[namesize] != NUL) {
    namesize++;
  }
  char *name = (char *)vim_strnsave((char_u *)str, namesize);
  return name;
# endif
}
Exemple #5
0
static int set_uncolog_osx(const char *logfn)
{
	char **env;
	size_t n;

#ifdef __linux__
	env = environ;
#elif defined(__APPLE__)
	env = *_NSGetEnviron();
#else
# error "unknown env"
#endif

	if (strlen(logfn) >= UNCO_LOG_PATH_MAX) {
		fprintf(stderr, "unco:log file name is too long:%s\n", logfn);
		return -1;
	}

	// find and replace
	for (n = 0; env[n] != NULL; ++n) {
		if (strncmp(env[n], "UNCO_LOG_PLACEHOLDER=", sizeof("UNCO_LOG_PLACEHOLDER=") - 1) == 0)
			break;
	}
	if (env[n] == NULL) {
		fprintf(stderr, "unco:env var UNCO_LOG_PLACEHOLDER not set\n");
		return -1;
	}
	snprintf(env[n], strlen(env[n]) + 1, "UNCO_LOG=%s", logfn);

	return 0;
}
Exemple #6
0
pid_t
rb_spawn_process(const char *path, const char **argv)
{
    pid_t pid;
    const void *arghack = argv;
    char **myenviron;
    int error;
    posix_spawnattr_t spattr;
    posix_spawnattr_init(&spattr);
#ifdef POSIX_SPAWN_USEVFORK
    posix_spawnattr_setflags(&spattr, POSIX_SPAWN_USEVFORK);
#endif
#ifdef __APPLE__
    myenviron = *_NSGetEnviron(); /* apple needs to go f**k themselves for this */
#else
    myenviron = environ;
#endif
    error = posix_spawn(&pid, path, NULL, &spattr, arghack, myenviron);
    posix_spawnattr_destroy(&spattr);
    if (error != 0) {
        errno = error;
        pid = -1;
    }
    return pid;
}
Exemple #7
0
/* return YAP's environment */
static YAP_Bool p_environ(void) {
#if HAVE_ENVIRON && 0
#if HAVE__NSGETENVIRON
  char **ptr = _NSGetEnviron();
#elif defined(__MINGW32__) || _MSC_VER
  extern char **_environ;
  char **ptr = _environ;
#else
  extern char **environ;
  char **ptr = environ;
#endif
  YAP_Term t1 = YAP_ARG1;
  long int i;

  i = YAP_IntOfTerm(t1);
  if (ptr[i] == NULL)
    return (FALSE);
  else {
    YAP_Term t = YAP_BufferToString(ptr[i]);
    return (YAP_Unify(t, YAP_ARG2));
  }
#else
  YAP_Error(0, 0L, "environ not available in this configuration");
  return (FALSE);
#endif
}
extern "C" CDECL int
rust_run_program(const char* argv[],
                 void* envp,
                 const char* dir,
                 int in_fd, int out_fd, int err_fd) {
    int pid = fork();
    if (pid != 0) return pid;

    sigset_t sset;
    sigemptyset(&sset);
    sigprocmask(SIG_SETMASK, &sset, NULL);

    if (in_fd) dup2(in_fd, 0);
    if (out_fd) dup2(out_fd, 1);
    if (err_fd) dup2(err_fd, 2);
    /* Close all other fds. */
    for (int fd = getdtablesize() - 1; fd >= 3; fd--) close(fd);
    if (dir) { chdir(dir); }

#ifdef __APPLE__
    if (envp) {
        *_NSGetEnviron() = (char **)envp;
    }
    execvp(argv[0], (char * const *)argv);
#else
    if (!envp) { envp = environ; }
    execvpe(argv[0], (char * const *)argv, (char * const *)envp);
#endif

    exit(1);
}
Exemple #9
0
extern "C" CDECL int
rust_run_program(const char* argv[],
                 void* envp,
                 const char* dir,
                 int in_fd, int out_fd, int err_fd) {
    int pid = fork();
    if (pid != 0) return pid;

    sigset_t sset;
    sigemptyset(&sset);
    sigprocmask(SIG_SETMASK, &sset, NULL);

    if (in_fd) dup2(in_fd, 0);
    if (out_fd) dup2(out_fd, 1);
    if (err_fd) dup2(err_fd, 2);
    /* Close all other fds. */
    for (int fd = getdtablesize() - 1; fd >= 3; fd--) close(fd);
    if (dir) {
        int result = chdir(dir);
        // FIXME: need error handling
        assert(!result && "chdir failed");
    }

    if (envp) {
#ifdef __APPLE__
        *_NSGetEnviron() = (char **)envp;
#else
        environ = (char **)envp;
#endif
    }

    execvp(argv[0], (char * const *)argv);
    exit(1);
}
Exemple #10
0
DLLEXPORT int jl_spawn(char *name, char **argv, uv_loop_t *loop,
                       uv_process_t *proc, jl_value_t *julia_struct,
                       uv_handle_type stdin_type,uv_pipe_t *stdin_pipe,
                       uv_handle_type stdout_type,uv_pipe_t *stdout_pipe,
                       uv_handle_type stderr_type,uv_pipe_t *stderr_pipe)
{
#ifdef __APPLE__
    char **environ = *_NSGetEnviron();
#endif
    uv_process_options_t opts;
    uv_stdio_container_t stdio[3];
    int error;
    opts.file = name;
#ifndef __WIN32__
    opts.env = environ;
#else
    opts.env = NULL;
#endif
    opts.cwd = NULL;
    opts.args = argv;
    opts.flags = 0;
    opts.stdio = stdio;
    opts.stdio_count = 3;
    stdio[0].type = stdin_type;
    stdio[0].data.stream = (uv_stream_t*)(stdin_pipe);
    stdio[1].type = stdout_type;
    stdio[1].data.stream = (uv_stream_t*)(stdout_pipe);
    stdio[2].type = stderr_type;
    stdio[2].data.stream = (uv_stream_t*)(stderr_pipe);
    //opts.detached = 0; #This has been removed upstream to be uncommented once it is possible again
    opts.exit_cb = &jl_return_spawn;
    error = uv_spawn(loop,proc,opts);
    proc->data = julia_struct;
    return error;
}
Exemple #11
0
jl_value_t *jl_environ(int i)
{
#ifdef __APPLE__
    char **environ = *_NSGetEnviron();
#endif
    char *env = environ[i];
    return env ? jl_pchar_to_string(env, strlen(env)) : jl_nothing;
}
static void vg_cleanup_env(void)
{
    HChar **envp = (HChar**)*_NSGetEnviron();
    env_unsetenv(envp, "VALGRIND_LAUNCHER");
    env_unsetenv(envp, "DYLD_SHARED_REGION");
    // GrP fixme should be more like mash_colon_env()
    env_unsetenv(envp, "DYLD_INSERT_LIBRARIES");
}   
Exemple #13
0
VixError
VixToolsNewEnvIterator(void *userToken,                  // IN
#ifdef __FreeBSD__
                       char **envp,                      // IN
#endif
                       VixToolsEnvIterator **envItr)     // OUT
{
   VixError err = VIX_OK;
   VixToolsEnvIterator *it = Util_SafeMalloc(sizeof *it);

   if (NULL == envItr) {
      err = VIX_E_FAIL;
      goto abort;
   }

   *envItr = NULL;

#ifdef _WIN32
   if (PROCESS_CREATOR_USER_TOKEN != userToken) {
      /*
       * The process is impersonating a user, so retrieve the user's
       * environment block instead of using the process's environment.
       */
      it->envType = VIX_TOOLS_ENV_TYPE_ENV_BLOCK;
      err = VixToolsGetEnvBlock(userToken, &it->data.eb.envBlock);
      if (VIX_FAILED(err)) {
         goto abort;
      }
      it->data.eb.currEnvVar = it->data.eb.envBlock;
   } else {
      /*
       * The action is being performed as the user running the process
       * so the process's environment is fine.
       * TODO: Is this totally equivilent to the behavior when impersonated?
       * Would fetching the environment block include changes to the user's
       * or system's environment made after the process is running?
       */
      it->envType = VIX_TOOLS_ENV_TYPE_ENVIRON;
      it->data.environ = _wenviron;
   }
#elif defined(__APPLE__)
   it->environ = *_NSGetEnviron();
#elif defined(__FreeBSD__)
   it->environ = envp;
#else
   it->environ = environ;
#endif
   *envItr = it;
abort:
   if (VIX_FAILED(err)) {
      free(it);
   }

   return err;
}
Exemple #14
0
List<String> Process::environment()
{
#ifdef OS_Darwin
    char **cur = *_NSGetEnviron();
#else
    extern char** environ;
    char** cur = environ;
#endif
    List<String> env;
    while (*cur) {
        env.push_back(*cur);
        ++cur;
    }
    return env;
}
Exemple #15
0
PR_IMPLEMENT(char **) PR_DuplicateEnvironment(void)
{
    char **the_environ, **result, **end, **src, **dst;

    _PR_LOCK_ENV();
#ifdef DARWIN
    the_environ = *(_NSGetEnviron());
#else
    the_environ = environ;
#endif

    for (end = the_environ; *end != NULL; end++)
        /* empty loop body */;

    result = (char **)PR_Malloc(sizeof(char *) * (end - the_environ + 1));
    if (result != NULL) {
        for (src = the_environ, dst = result; src != end; src++, dst++) {
            size_t len;

            len = strlen(*src) + 1;
            *dst = PR_Malloc(len);
            if (*dst == NULL) {
              /* Allocation failed.  Must clean up the half-copied env. */
              char **to_delete;

              for (to_delete = result; to_delete != dst; to_delete++) {
                PR_Free(*to_delete);
              }
              PR_Free(result);
              result = NULL;
              goto out;
            }
            memcpy(*dst, *src, len);
        }
        *dst = NULL;
    }
 out:
    _PR_UNLOCK_ENV();
    return result;
}
Exemple #16
0
void RNG_SystemInfoForRNG(void)
{
    FILE *fp;
    char buf[BUFSIZ];
    size_t bytes;
    const char * const *cp;
    char *randfile;
#ifdef DARWIN
#if TARGET_OS_IPHONE
    /* iOS does not expose a way to access environ. */
    char **environ = NULL;
#else
    char **environ = *_NSGetEnviron();
#endif
#else
    extern char **environ;
#endif
#ifdef BEOS
    static const char * const files[] = {
	"/boot/var/swap",
	"/boot/var/log/syslog",
	"/boot/var/tmp",
	"/boot/home/config/settings",
	"/boot/home",
	0
    };
#else
    static const char * const files[] = {
	"/etc/passwd",
	"/etc/utmp",
	"/tmp",
	"/var/tmp",
	"/usr/tmp",
	0
    };
#endif

#if defined(BSDI)
    static char netstat_ni_cmd[] = "netstat -nis";
#else
    static char netstat_ni_cmd[] = "netstat -ni";
#endif

    GiveSystemInfo();

    bytes = RNG_GetNoise(buf, sizeof(buf));
    RNG_RandomUpdate(buf, bytes);

    /*
     * Pass the C environment and the addresses of the pointers to the
     * hash function. This makes the random number function depend on the
     * execution environment of the user and on the platform the program
     * is running on.
     */
    if (environ != NULL) {
        cp = (const char * const *) environ;
        while (*cp) {
	    RNG_RandomUpdate(*cp, strlen(*cp));
	    cp++;
        }
        RNG_RandomUpdate(environ, (char*)cp - (char*)environ);
    }

    /* Give in system information */
    if (gethostname(buf, sizeof(buf)) == 0) {
	RNG_RandomUpdate(buf, strlen(buf));
    }
    GiveSystemInfo();

    /* grab some data from system's PRNG before any other files. */
    bytes = RNG_FileUpdate("/dev/urandom", SYSTEM_RNG_SEED_COUNT);

    /* If the user points us to a random file, pass it through the rng */
    randfile = getenv("NSRANDFILE");
    if ( ( randfile != NULL ) && ( randfile[0] != '\0') ) {
	char *randCountString = getenv("NSRANDCOUNT");
	int randCount = randCountString ? atoi(randCountString) : 0;
	if (randCount != 0) {
	    RNG_FileUpdate(randfile, randCount);
	} else {
	    RNG_FileForRNG(randfile);
	}
    }

    /* pass other files through */
    for (cp = files; *cp; cp++)
	RNG_FileForRNG(*cp);

/*
 * Bug 100447: On BSD/OS 4.2 and 4.3, we have problem calling safe_popen
 * in a pthreads environment.  Therefore, we call safe_popen last and on
 * BSD/OS we do not call safe_popen when we succeeded in getting data
 * from /dev/urandom.
 *
 * Bug 174993: On platforms providing /dev/urandom, don't fork netstat
 * either, if data has been gathered successfully.
 */

#if defined(BSDI) || defined(FREEBSD) || defined(NETBSD) \
    || defined(OPENBSD) || defined(DARWIN) || defined(LINUX) \
    || defined(HPUX)
    if (bytes)
        return;
#endif

#ifdef SOLARIS

/*
 * On Solaris, NSS may be initialized automatically from libldap in
 * applications that are unaware of the use of NSS. safe_popen forks, and
 * sometimes creates issues with some applications' pthread_atfork handlers.
 * We always have /dev/urandom on Solaris 9 and above as an entropy source,
 * and for Solaris 8 we have the libkstat interface, so we don't need to
 * fork netstat.
 */

#undef DO_NETSTAT
    if (!bytes) {
        /* On Solaris 8, /dev/urandom isn't available, so we use libkstat. */
        PRUint32 kstat_bytes = 0;
        if (SECSuccess != RNG_kstat(&kstat_bytes)) {
            PORT_Assert(0);
        }
        bytes += kstat_bytes;
        PORT_Assert(bytes);
    }
#endif

#ifdef DO_NETSTAT
    fp = safe_popen(netstat_ni_cmd);
    if (fp != NULL) {
	while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)
	    RNG_RandomUpdate(buf, bytes);
	safe_pclose(fp);
    }
#endif

}
Exemple #17
0
rpmRC rpmjsRunFile(rpmjs js, const char * fn,
		char *const * Iargv,
		const char ** resultp)
{
    rpmRC rc = RPMRC_FAIL;

    if (js == NULL) js = rpmjsI();

    if (fn != NULL) {
#if defined(WITH_GPSEE)
	gpsee_interpreter_t * I = js->I;
	FILE * fp = rpmjsOpenFile(js, fn, resultp);

	if (fp == NULL) {
	    I->grt->exitType = et_execFailure;
	    /* XXX FIXME: strerror in *resultp */
	    goto exit;
	}

#ifdef	NOTYET	/* XXX FIXME */
	processInlineFlags(js, fp, &verbosity);
	gpsee_setVerbosity(verbosity);
#endif

	/* Just compile and exit? */
	if (F_ISSET(js->flags, NOEXEC)) {
	    JSScript *script = NULL;
	    JSObject *scrobj = NULL;

	    if (!gpsee_compileScript(I->cx, fn,
			fp, NULL, &script, I->realm->globalObject, &scrobj))
	    {
		I->grt->exitType = et_exception;
		/* XXX FIXME: isatty(3) */
		gpsee_reportUncaughtException(I->cx, JSVAL_NULL,
			(gpsee_verbosity(0) >= GSR_FORCE_STACK_DUMP_VERBOSITY)
			||
			((gpsee_verbosity(0) >= GPSEE_ERROR_OUTPUT_VERBOSITY)
				&& isatty(STDERR_FILENO)));
	    } else {
		I->grt->exitType = et_finished;
		rc = RPMRC_OK;
	    }
	} else {
	    char *const * Ienviron = NULL;

	    if (F_ISSET(js->flags, ALLOW)) {
#if defined(__APPLE__)
		Ienviron = (char *const *) _NSGetEnviron();
#else
		Ienviron = environ;
#endif
	    }

	    I->grt->exitType = et_execFailure;
	    if (gpsee_runProgramModule(I->cx, fn,
			NULL, fp, Iargv, Ienviron) == JS_FALSE)
	    {
		int code = gpsee_getExceptionExitCode(I->cx);
		if (code >= 0) {
		    I->grt->exitType = et_requested;
		    I->grt->exitCode = code;
		    /* XXX FIXME: format and return code in *resultp. */
		    /* XXX hack tp get code into rc -> ec by negating */
		    rc = -code;
		} else
		if (JS_IsExceptionPending(I->cx)) {
		    /* XXX FIXME: isatty(3) */
		    gpsee_reportUncaughtException(I->cx, JSVAL_NULL,
			(gpsee_verbosity(0) >= GSR_FORCE_STACK_DUMP_VERBOSITY)
			||
			((gpsee_verbosity(0) >= GPSEE_ERROR_OUTPUT_VERBOSITY)
				&& isatty(STDERR_FILENO)));
		}
	    } else {
		I->grt->exitType = et_finished;
		rc = RPMRC_OK;
	    }
	}
	fclose(fp);
	fp = NULL;
#endif	/* WITH_GPSEE */
    }

#if defined(WITH_GPSEE)
exit:
#endif	/* WITH_GPSEE */

RPMJSDBG(0, (stderr, "<== %s(%p,%s) rc %d |%s|\n", __FUNCTION__, js, fn, rc, (resultp ? *resultp :"")));

    return rc;
}
int main(int argc, const char **argv)
#endif
{
	bContext *C = CTX_create();
	SYS_SystemHandle syshandle;

#ifndef WITH_PYTHON_MODULE
	bArgs *ba;
#endif

#ifdef WIN32
	wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
	int argci = 0;
	char **argv = MEM_mallocN(argc * sizeof(char *), "argv array");
	for (argci = 0; argci < argc; argci++) {
		argv[argci] = alloc_utf_8_from_16(argv_16[argci], 0);
	}
	LocalFree(argv_16);
#endif

#ifdef WITH_PYTHON_MODULE
#ifdef __APPLE__
	environ = *_NSGetEnviron();
#endif

#undef main
	evil_C = C;
#endif



#ifdef WITH_BINRELOC
	br_init(NULL);
#endif

#ifdef WITH_LIBMV
	libmv_initLogging(argv[0]);
#endif

	setCallbacks();
#if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE)
	/* patch to ignore argument finder gives us (pid?) */
	if (argc == 2 && strncmp(argv[1], "-psn_", 5) == 0) {
		extern int GHOST_HACK_getFirstFile(char buf[]);
		static char firstfilebuf[512];

		argc = 1;

		if (GHOST_HACK_getFirstFile(firstfilebuf)) {
			argc = 2;
			argv[1] = firstfilebuf;
		}
	}

#endif

#ifdef __FreeBSD__
	fpsetmask(0);
#endif

	/* initialize path to executable */
	BLI_init_program_path(argv[0]);

	BLI_threadapi_init();

	initglobals();  /* blender.c */

	IMB_init();
	BKE_images_init();

	BKE_brush_system_init();

	BLI_callback_global_init();

#ifdef WITH_GAMEENGINE
	syshandle = SYS_GetSystem();
#else
	syshandle = 0;
#endif

	/* first test for background */
#ifndef WITH_PYTHON_MODULE
	ba = BLI_argsInit(argc, (const char **)argv); /* skip binary path */
	setupArguments(C, ba, &syshandle);

	BLI_argsParse(ba, 1, NULL, NULL);

	if (use_crash_handler) {
		/* after parsing args */
		signal(SIGSEGV, blender_crash_handler);
	}
#else
	G.factory_startup = true;  /* using preferences or user startup makes no sense for py-as-module */
	(void)syshandle;
#endif

#ifdef WITH_FFMPEG
	IMB_ffmpeg_init();
#endif

	/* after level 1 args, this is so playanim skips RNA init */
	RNA_init();

	RE_engines_init();
	init_nodesystem();
	/* end second init */


#if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
	G.background = true; /* python module mode ALWAYS runs in background mode (for now) */
#else
	/* for all platforms, even windos has it! */
	if (G.background) {
		signal(SIGINT, blender_esc);  /* ctrl c out bg render */
	}
#endif

	/* background render uses this font too */
	BKE_vfont_builtin_register(datatoc_bfont_pfb, datatoc_bfont_pfb_size);

	/* Initialize ffmpeg if built in, also needed for bg mode if videos are
	 * rendered via ffmpeg */
	sound_init_once();
	
	init_def_material();

	if (G.background == 0) {
#ifndef WITH_PYTHON_MODULE
		BLI_argsParse(ba, 2, NULL, NULL);
		BLI_argsParse(ba, 3, NULL, NULL);
#endif
		WM_init(C, argc, (const char **)argv);

		/* this is properly initialized with user defs, but this is default */
		/* call after loading the startup.blend so we can read U.tempdir */
		BLI_init_temporary_dir(U.tempdir);

#ifdef WITH_SDL
		BLI_setenv("SDL_VIDEODRIVER", "dummy");
#endif
	}
	else {
#ifndef WITH_PYTHON_MODULE
		BLI_argsParse(ba, 3, NULL, NULL);
#endif

		WM_init(C, argc, (const char **)argv);

		/* don't use user preferences temp dir */
		BLI_init_temporary_dir(NULL);
	}
#ifdef WITH_PYTHON
	/**
	 * NOTE: the U.pythondir string is NULL until WM_init() is executed,
	 * so we provide the BPY_ function below to append the user defined
	 * python-dir to Python's sys.path at this point.  Simply putting
	 * WM_init() before #BPY_python_start() crashes Blender at startup.
	 */

	/* TODO - U.pythondir */
#else
	printf("\n* WARNING * - Blender compiled without Python!\nthis is not intended for typical usage\n\n");
#endif
	
	CTX_py_init_set(C, 1);
	WM_keymap_init(C);

#ifdef WITH_FREESTYLE
	/* initialize Freestyle */
	FRS_initialize();
	FRS_set_context(C);
#endif

	/* OK we are ready for it */
#ifndef WITH_PYTHON_MODULE
	BLI_argsParse(ba, 4, load_file, C);
	
	if (G.background == 0) {
		if (!G.file_loaded)
			if (U.uiflag2 & USER_KEEP_SESSION)
				WM_recover_last_session(C, NULL);
	}

#endif

#ifndef WITH_PYTHON_MODULE
	BLI_argsFree(ba);
#endif

#ifdef WIN32
	while (argci) {
		free(argv[--argci]);
	}
	MEM_freeN(argv);
	argv = NULL;
#endif

#ifdef WITH_PYTHON_MODULE
	return 0; /* keep blender in background mode running */
#endif

	if (G.background) {
		/* actually incorrect, but works for now (ton) */
		WM_exit(C);
	}
	else {
		if (G.fileflags & G_FILE_AUTOPLAY) {
			if (G.f & G_SCRIPT_AUTOEXEC) {
				if (WM_init_game(C)) {
					return 0;
				}
			}
			else {
				if (!(G.f & G_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
					G.f |= G_SCRIPT_AUTOEXEC_FAIL;
					BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Game AutoStart");
				}
			}
		}

		if (!G.file_loaded) {
			WM_init_splash(C);
		}
	}

	WM_main(C);

	return 0;
} /* end of int main(argc, argv)	*/
int NaClMainForChromium(int handle_count, const NaClHandle *handles,
                        int debug) {
  char *av[1];
  int ac = 1;
  const char **envp;
  struct NaClApp state;
  int main_thread_only = 1;
  int export_addr_to = kSrpcFd; /* Used to be set by -X. */
  struct NaClApp *nap;
  NaClErrorCode errcode;
  int ret_code = 1;
  struct NaClEnvCleanser env_cleanser;

#if NACL_OSX
  /* Mac dynamic libraries cannot access the environ variable directly. */
  envp = (const char **) *_NSGetEnviron();
#else
  /* Overzealous code style check is overzealous. */
  /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */
  extern char **environ;
  envp = (const char **) environ;
#endif

  NaClAllModulesInit();

  /* Add a handler to catch untrusted errors only */
  NaClSignalHandlerAdd(NaClSignalHandleUntrusted);

  /* to be passed to NaClMain, eventually... */
  av[0] = "NaClMain";

  if (!NaClAppCtor(&state)) {
    fprintf(stderr, "Error while constructing app state\n");
    goto done;
  }

  state.restrict_to_main_thread = main_thread_only;

  nap = &state;
  errcode = LOAD_OK;

  /* import IMC handle - used to be "-i" */
  CHECK(handle_count == 3);
  NaClAddImcHandle(nap, handles[0], export_addr_to);
  NaClAddImcHandle(nap, handles[1], 6); /* async_receive_desc */
  NaClAddImcHandle(nap, handles[2], 7); /* async_send_desc */

  /*
   * in order to report load error to the browser plugin through the
   * secure command channel, we do not immediate jump to cleanup code
   * on error.  rather, we continue processing (assuming earlier
   * errors do not make it inappropriate) until the secure command
   * channel is set up, and then bail out.
   */

  /*
   * Ensure this operating system platform is supported.
   */
  errcode = NaClRunSelQualificationTests();
  if (LOAD_OK != errcode) {
    nap->module_load_status = errcode;
    fprintf(stderr, "Error while loading in SelMain: %s\n",
            NaClErrorString(errcode));
  }

  /* Give debuggers a well known point at which xlate_base is known.  */
  NaClGdbHook(&state);

  /*
   * If export_addr_to is set to a non-negative integer, we create a
   * bound socket and socket address pair and bind the former to
   * descriptor 3 and the latter to descriptor 4.  The socket address
   * is written out to the export_addr_to descriptor.
   *
   * The service runtime also accepts a connection on the bound socket
   * and spawns a secure command channel thread to service it.
   *
   * If export_addr_to is -1, we only create the bound socket and
   * socket address pair, and we do not export to an IMC socket.  This
   * use case is typically only used in testing, where we only "dump"
   * the socket address to stdout or similar channel.
   */
  if (-2 < export_addr_to) {
    NaClCreateServiceSocket(nap);
    if (0 <= export_addr_to) {
      NaClSendServiceAddressTo(nap, export_addr_to);
      /*
       * NB: spawns a thread that uses the command channel.  we do
       * this after NaClAppLoadFile so that NaClApp object is more
       * fully populated.  Hereafter any changes to nap should be done
       * while holding locks.
       */
      NaClSecureCommandChannel(nap);
    }
  }

  if (NULL != nap->secure_channel && LOAD_OK == errcode) {
    /*
     * wait for start_module RPC call on secure channel thread.
     */
    errcode = NaClWaitForStartModuleCommand(nap);
  }

  /*
   * error reporting done; can quit now if there was an error earlier.
   */
  if (LOAD_OK != errcode) {
    goto done;
  }


  /*
   * Enable debugging if requested.
   */
  if (debug) NaClDebugSetAllow(1);

  NaClEnvCleanserCtor(&env_cleanser);
  if (!NaClEnvCleanserInit(&env_cleanser, envp)) {
    NaClLog(LOG_FATAL, "Failed to initialise env cleanser\n");
  }

  /*
   * only nap->ehdrs.e_entry is usable, no symbol table is
   * available.
   */
  if (!NaClCreateMainThread(nap, ac, av,
                            NaClEnvCleanserEnvironment(&env_cleanser))) {
    fprintf(stderr, "creating main thread failed\n");
    goto done;
  }

  NaClEnvCleanserDtor(&env_cleanser);

  ret_code = NaClWaitForMainThreadToExit(nap);

  /*
   * exit_group or equiv kills any still running threads while module
   * addr space is still valid.  otherwise we'd have to kill threads
   * before we clean up the address space.
   */
  return ret_code;

 done:
  fflush(stdout);

  NaClAllModulesFini();

  return ret_code;
}
Exemple #20
0
extern "C" CDECL rust_str *
rust_getcwd() {
    rust_task *task = rust_get_current_task();
    LOG(task, task, "rust_getcwd()");

    char cbuf[BUF_BYTES];

#if defined(__WIN32__)
    if (!_getcwd(cbuf, sizeof(cbuf))) {
#else
        if (!getcwd(cbuf, sizeof(cbuf))) {
#endif
        task->fail();
        return NULL;
    }

    return make_str(task->kernel, cbuf, strlen(cbuf), "rust_str(getcwd)");
}

#if defined(__WIN32__)
extern "C" CDECL rust_vec_box *
rust_env_pairs() {
    rust_task *task = rust_get_current_task();
    size_t envc = 0;
    LPTCH ch = GetEnvironmentStringsA();
    LPTCH c;
    for (c = ch; *c; c += strlen(c) + 1) {
        ++envc;
    }
    c = ch;
    rust_vec_box *v = (rust_vec_box *)
        task->kernel->malloc(vec_size<rust_vec_box*>(envc),
                       "str vec interior");
    v->body.fill = v->body.alloc = sizeof(rust_vec*) * envc;
    for (size_t i = 0; i < envc; ++i) {
        size_t n = strlen(c);
        rust_str *str = make_str(task->kernel, c, n, "str");
        ((rust_str**)&v->body.data)[i] = str;
        c += n + 1;
    }
    if (ch) {
        FreeEnvironmentStrings(ch);
    }
    return v;
}
#else
extern "C" CDECL rust_vec_box *
rust_env_pairs() {
    rust_task *task = rust_get_current_task();
#ifdef __APPLE__
    char **environ = *_NSGetEnviron();
#endif
    char **e = environ;
    size_t envc = 0;
    while (*e) {
        ++envc; ++e;
    }
    return make_str_vec(task->kernel, envc, environ);
}
#endif

extern "C" CDECL void
unsupervise() {
    rust_task *task = rust_get_current_task();
    task->unsupervise();
}
static int reexec(cpu_type_t cputype, const char *guardenv)
{
	posix_spawnattr_t  attr;
	int                ret, envcount;
	size_t             copied = 0;
	char			   **argv, **oldenvp, **newenvp;
	char			   execpath[MAXPATHLEN+1];
	uint32_t		   execsize;
	char               guardstr[32];

	argv = *_NSGetArgv();
	oldenvp = *_NSGetEnviron();
	for (envcount = 0; oldenvp[envcount]; envcount++);
	// if there are 4 elements and a NULL, envcount will be 4

	newenvp = calloc(envcount+2, sizeof(newenvp[0]));
	for (envcount = 0; oldenvp[envcount]; envcount++) {
		newenvp[envcount] = oldenvp[envcount];
	}

	snprintf(guardstr, sizeof(guardstr), "%s=1", guardenv);
	newenvp[envcount++] = guardstr;
	newenvp[envcount] = NULL;

	execsize = (uint32_t)sizeof(execpath);
	ret = _NSGetExecutablePath(execpath, &execsize);
	if (ret != 0) {
		return -1;
	}

	ret = posix_spawnattr_init(&attr);
	if (ret != 0) {
		return -1;
	}
	ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETEXEC);
	if (ret != 0) {
		return -1;
	}
	ret = posix_spawnattr_setbinpref_np(&attr, 1, &cputype, &copied);
	if (ret != 0 || copied != 1) {
		return -1;
	}

#if 0
	fprintf(stderr, "reexec: %s (arch=%d)\n", execpath, cputype);
	for (envcount=0; newenvp[envcount]; envcount++) {
		fprintf(stderr, "env[%d] = %s\n", envcount, newenvp[envcount]);
	}
	for (envcount=0; argv[envcount]; envcount++) {
		fprintf(stderr, "argv[%d] = %s\n", envcount, argv[envcount]);
	}
#endif

	ret = posix_spawn(NULL, execpath, NULL, &attr, argv, newenvp);
	if (ret != 0) {
		errno = ret;
		return -1;
	}

	/* should not be reached */
	return 0;
}
int NaClMainForChromium(int handle_count, const NaClHandle *handles,
                        int debug) {
  char *av[1];
  int ac = 1;
  const char **envp;
  struct NaClApp state;
  int main_thread_only = 1;
  char                          *nacl_file = "test_nexe/hello_ppapi.nexe";
  struct NaClApp *nap;
  enum NaClAbiCheckOption       check_abi = NACL_ABI_CHECK_OPTION_CHECK;
  struct GioFile                gout;
  struct GioMemoryFileSnapshot  gf;
  NaClErrorCode errcode;
  int ret_code = 1;
  struct NaClEnvCleanser env_cleanser;

#if NACL_OSX
  /* Mac dynamic libraries cannot access the environ variable directly. */
  envp = (const char **) *_NSGetEnviron();
#else
  /* Overzealous code style check is overzealous. */
  /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */
  extern char **environ;
  envp = (const char **) environ;
#endif

  NaClAllModulesInit();

  /* Add a handler to catch untrusted errors only */
  NaClSignalHandlerAdd(NaClSignalHandleUntrusted);

  /* to be passed to NaClMain, eventually... */
  av[0] = "NaClMain";

  if (!NaClAppCtor(&state)) {
    fprintf(stderr, "Error while constructing app state\n");
    goto done;
  }

  state.restrict_to_main_thread = main_thread_only;

  nap = &state;
  errcode = LOAD_OK;
  /*
   * in order to report load error to the browser plugin through the
   * secure command channel, we do not immediate jump to cleanup code
   * on error.  rather, we continue processing (assuming earlier
   * errors do not make it inappropriate) until the secure command
   * channel is set up, and then bail out.
   */

  /*
   * Ensure this operating system platform is supported.
   */
  errcode = NaClRunSelQualificationTests();
  if (LOAD_OK != errcode) {
    nap->module_load_status = errcode;
    fprintf(stderr, "Error while loading in SelMain: %s\n",
            NaClErrorString(errcode));
  }

  /* Give debuggers a well known point at which xlate_base is known.  */
  NaClGdbHook(&state);

  if (0 == GioMemoryFileSnapshotCtor(&gf, nacl_file)) {
    perror("sel_main");
    fprintf(stderr, "Cannot open \"%s\".\n", nacl_file);
    errcode = LOAD_OPEN_ERROR;
  }

  if (LOAD_OK == errcode) {
    errcode = NaClAppLoadFile((struct Gio *) &gf, nap, check_abi);
    if (LOAD_OK != errcode) {
      fprintf(stderr, "Error while loading \"%s\": %s\n",
              nacl_file,
              NaClErrorString(errcode));
      fprintf(stderr,
              ("Using the wrong type of nexe (nacl-x86-32"
               " on an x86-64 or vice versa)\n"
               "or a corrupt nexe file may be"
               " responsible for this error.\n"));
    }

    NaClXMutexLock(&nap->mu);
    nap->module_load_status = errcode;
    NaClXCondVarBroadcast(&nap->cv);
    NaClXMutexUnlock(&nap->mu);
  }

   if (LOAD_OK == errcode) {
     if (verbosity) {
       gprintf((struct Gio *) &gout, "printing NaClApp details\n");
       NaClAppPrintDetails(nap, (struct Gio *) &gout);
     }

     /*
      * Finish setting up the NaCl App.  This includes dup'ing
      * descriptors 0-2 and making them available to the NaCl App.
      */
     errcode = NaClAppPrepareToLaunch(nap,
                                      0,
                                      1,
                                      2);
     if (LOAD_OK != errcode) {
       nap->module_load_status = errcode;
       fprintf(stderr, "NaClAppPrepareToLaunch returned %d", errcode);
     }
   }

   if (-1 == (*((struct Gio *) &gf)->vtbl->Close)((struct Gio *) &gf)) {
     fprintf(stderr, "Error while closing \"%s\".\n", nacl_file);
   }
   (*((struct Gio *) &gf)->vtbl->Dtor)((struct Gio *) &gf);

 /*
  * Print out a marker for scripts to use to mark the start of app
  * output.
  */
 NaClLog(1, "NACL: Application output follows\n");

 /*
  * Make sure all the file buffers are flushed before entering
  * the application code.
  */
 fflush((FILE *) NULL);

  /*
   * Enable debugging if requested.
   */
  if (debug) NaClDebugSetAllow(1);

  NaClEnvCleanserCtor(&env_cleanser);
  if (!NaClEnvCleanserInit(&env_cleanser, envp)) {
    NaClLog(LOG_FATAL, "Failed to initialise env cleanser\n");
  }

  /*
   * only nap->ehdrs.e_entry is usable, no symbol table is
   * available.
   */
  if (!NaClCreateMainThread(nap, ac, av,
                            NaClEnvCleanserEnvironment(&env_cleanser))) {
    fprintf(stderr, "creating main thread failed\n");
    goto done;
  }

  NaClEnvCleanserDtor(&env_cleanser);

  ret_code = NaClWaitForMainThreadToExit(nap);

  /*
   * exit_group or equiv kills any still running threads while module
   * addr space is still valid.  otherwise we'd have to kill threads
   * before we clean up the address space.
   */
  return ret_code;

 done:
  fflush(stdout);

  NaClAllModulesFini();

  return ret_code;
}
int main (int argc, char *const *argv, char *const *envp, const char **apple)
{
#if defined (DEBUG_LLDB_LAUNCHER)
    const char *program_name = strrchr(apple[0], '/');
    
    if (program_name)
        program_name++; // Skip the last slash..
    else
        program_name = apple[0];
    
    printf("%s called with:\n", program_name);
    for (int i=0; i<argc; ++i)
        printf("argv[%u] = '%s'\n", i, argv[i]);
#endif

    cpu_type_t cpu_type = 0;
    bool show_usage = false;
    int ch;
    int disable_aslr = 0; // By default we disable ASLR
    bool pass_env = true;
    std::string unix_socket_name;
    std::string working_dir;
    
#if __GLIBC__
    optind = 0;
#else
    optreset = 1;
    optind = 1;
#endif

	while ((ch = getopt_long_only(argc, argv, "a:deE:hsu:?", g_long_options, NULL)) != -1)
	{
		switch (ch) 
		{
        case 0:
            break;

		case 'a':	// "-a i386" or "--arch=i386"
			if (optarg)
			{
				if (streq (optarg, "i386"))
                    cpu_type = CPU_TYPE_I386;
				else if (streq (optarg, "x86_64"))
                    cpu_type = CPU_TYPE_X86_64;
                else if (streq (optarg, "x86_64h"))
                    cpu_type = 0; // Don't set CPU type when we have x86_64h
                else if (strstr (optarg, "arm") == optarg)
                    cpu_type = CPU_TYPE_ARM;
                else
                {
                    ::fprintf (stderr, "error: unsupported cpu type '%s'\n", optarg);
                    ::exit (1);
                }
			} 
			break;

        case 'd':
            disable_aslr = 1;
            break;            

        case 'e':
            pass_env = false;
            break;
            
        case 'E':
            {
                // Since we will exec this program into our new program, we can just set environment
                // variables in this process and they will make it into the child process.
                std::string name;
                std::string value;
                const char *equal_pos = strchr (optarg, '=');
                if (equal_pos)
                {
                    name.assign (optarg, equal_pos - optarg);
                    value.assign (equal_pos + 1);
                }
                else
                {
                    name = optarg;
                }
                ::setenv (name.c_str(), value.c_str(), 1);
            }
            break;
            
        case 's':
            // Create a new session to avoid having control-C presses kill our current
            // terminal session when this program is launched from a .command file
            ::setsid();
            break;

        case 'u':
            unix_socket_name.assign (optarg);
            break;

        case 'w':
            {
                struct stat working_dir_stat;
                if (stat (optarg, &working_dir_stat) == 0)
                    working_dir.assign (optarg);
                else
                    ::fprintf(stderr, "warning: working directory doesn't exist: '%s'\n", optarg);
            }
            break;

		case 'h':
		case '?':
		default:
			show_usage = true;
			break;
		}
	}
	argc -= optind;
	argv += optind;

    if (show_usage || argc <= 0 || unix_socket_name.empty())
        usage();

#if defined (DEBUG_LLDB_LAUNCHER)
    printf ("\n%s post options:\n", program_name);
    for (int i=0; i<argc; ++i)
        printf ("argv[%u] = '%s'\n", i, argv[i]);
#endif

    // Open the socket that was passed in as an option
    struct sockaddr_un saddr_un;
    int s = ::socket (AF_UNIX, SOCK_STREAM, 0);
    if (s < 0)
    {
        perror("error: socket (AF_UNIX, SOCK_STREAM, 0)");
        exit(1);
    }

    saddr_un.sun_family = AF_UNIX;
    ::strncpy(saddr_un.sun_path, unix_socket_name.c_str(), sizeof(saddr_un.sun_path) - 1);
    saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
    saddr_un.sun_len = SUN_LEN (&saddr_un);

    if (::connect (s, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0) 
    {
        perror("error: connect (socket, &saddr_un, saddr_un_len)");
        exit(1);
    }
    
    // We were able to connect to the socket, now write our PID so whomever
    // launched us will know this process's ID
    char pid_str[64];
    const int pid_str_len = ::snprintf (pid_str, sizeof(pid_str), "%i", ::getpid());
    const int bytes_sent = ::send (s, pid_str, pid_str_len, 0);
    
    if (pid_str_len != bytes_sent)
    {
        perror("error: send (s, pid_str, pid_str_len, 0)");
        exit (1);
    }

    // We are done with the socket
    close (s);

    system("clear");
    printf ("Launching: '%s'\n", argv[0]);
    if (working_dir.empty())
    {
        char cwd[PATH_MAX];
        const char *cwd_ptr = getcwd(cwd, sizeof(cwd));
        printf ("Working directory: '%s'\n", cwd_ptr);
    }
    else
    {
        printf ("Working directory: '%s'\n", working_dir.c_str());
    }
    printf ("%i arguments:\n", argc);

    for (int i=0; i<argc; ++i)
        printf ("argv[%u] = '%s'\n", i, argv[i]);

    // Now we posix spawn to exec this process into the inferior that we want
    // to debug.
    posix_spawn_for_debug (argv,
                           pass_env ? *_NSGetEnviron() : NULL, // Pass current environment as we may have modified it if "--env" options was used, do NOT pass "envp" here
                           working_dir.empty() ? NULL : working_dir.c_str(),
                           cpu_type, 
                           disable_aslr);
    
	return 0;
}
Exemple #24
0
bool wxGetEnvMap(wxEnvVariableHashMap *map)
{
    wxCHECK_MSG( map, false, wxS("output pointer can't be NULL") );

#if defined(__VISUALC__)
    // This variable only exists to force the CRT to fill the wide char array,
    // it might only have it in narrow char version until now as we use main()
    // (and not _wmain()) as our entry point.
    static wxChar* s_dummyEnvVar = _tgetenv(wxT("TEMP"));

    wxChar **env = _tenviron;
#elif defined(__VMS)
   // Now this routine wil give false for OpenVMS
   // TODO : should we do something with logicals?
    char **env=NULL;
#elif defined(__DARWIN__)
#if wxOSX_USE_COCOA_OR_CARBON
    // Under Mac shared libraries don't have access to the global environ
    // variable so use this Mac-specific function instead as advised by
    // environ(7) under Darwin
    char ***penv = _NSGetEnviron();
    if ( !penv )
        return false;
    char **env = *penv;
#else
    char **env=NULL;
    // todo translate NSProcessInfo environment into map
#endif
#else // non-MSVC non-Mac
    // Not sure if other compilers have _tenviron so use the (more standard)
    // ANSI version only for them.

    // Both POSIX and Single UNIX Specification say that this variable must
    // exist but not that it must be declared anywhere and, indeed, it's not
    // declared in several common systems (some BSDs, Solaris with native CC)
    // so we (re)declare it ourselves to deal with these cases. However we do
    // not do this under MSW where there can be DLL-related complications, i.e.
    // the variable might be DLL-imported or not. Luckily we don't have to
    // worry about this as all MSW compilers do seem to define it in their
    // standard headers anyhow so we can just rely on already having the
    // correct declaration. And if this turns out to be wrong, we can always
    // add a configure test checking whether it is declared later.
#ifndef __WINDOWS__
    extern char **environ;
#endif // !__WINDOWS__

    char **env = environ;
#endif

    if ( env )
    {
        wxString name,
                 value;
        while ( *env )
        {
            const wxString var(*env);

            name = var.BeforeFirst(wxS('='), &value);

            (*map)[name] = value;

            env++;
        }

        return true;
    }

    return false;
}
Exemple #25
0
static PRProcess *
ForkAndExec(
    const char *path,
    char *const *argv,
    char *const *envp,
    const PRProcessAttr *attr)
{
    PRProcess *process;
    int nEnv, idx;
    char *const *childEnvp;
    char **newEnvp = NULL;
    int flags;

    process = PR_NEW(PRProcess);
    if (!process) {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return NULL;
    }

    childEnvp = envp;
    if (attr && attr->fdInheritBuffer) {
        PRBool found = PR_FALSE;

        if (NULL == childEnvp) {
#ifdef DARWIN
            childEnvp = *(_NSGetEnviron());
#else
            childEnvp = environ;
#endif
        }
        for (nEnv = 0; childEnvp[nEnv]; nEnv++) {
        }
        newEnvp = (char **) PR_MALLOC((nEnv + 2) * sizeof(char *));
        if (NULL == newEnvp) {
            PR_DELETE(process);
            PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
            return NULL;
        }
        for (idx = 0; idx < nEnv; idx++) {
            newEnvp[idx] = childEnvp[idx];
            if (!found && !strncmp(newEnvp[idx], "NSPR_INHERIT_FDS=", 17)) {
                newEnvp[idx] = attr->fdInheritBuffer;
                found = PR_TRUE;
            }
        }
        if (!found) {
            newEnvp[idx++] = attr->fdInheritBuffer;
        }
        newEnvp[idx] = NULL;
        childEnvp = newEnvp;
    }

#ifdef AIX
    process->md.pid = (*pr_wp.forkptr)();
#elif defined(NTO) || defined(SYMBIAN)
    /*
     * fork() & exec() does not work in a multithreaded process.
     * Use spawn() instead.
     */
    {
        int fd_map[3] = { 0, 1, 2 };

        if (attr) {
            if (attr->stdinFd && attr->stdinFd->secret->md.osfd != 0) {
                fd_map[0] = dup(attr->stdinFd->secret->md.osfd);
                flags = fcntl(fd_map[0], F_GETFL, 0);
                if (flags & O_NONBLOCK)
                    fcntl(fd_map[0], F_SETFL, flags & ~O_NONBLOCK);
            }
            if (attr->stdoutFd && attr->stdoutFd->secret->md.osfd != 1) {
                fd_map[1] = dup(attr->stdoutFd->secret->md.osfd);
                flags = fcntl(fd_map[1], F_GETFL, 0);
                if (flags & O_NONBLOCK)
                    fcntl(fd_map[1], F_SETFL, flags & ~O_NONBLOCK);
            }
            if (attr->stderrFd && attr->stderrFd->secret->md.osfd != 2) {
                fd_map[2] = dup(attr->stderrFd->secret->md.osfd);
                flags = fcntl(fd_map[2], F_GETFL, 0);
                if (flags & O_NONBLOCK)
                    fcntl(fd_map[2], F_SETFL, flags & ~O_NONBLOCK);
            }

            PR_ASSERT(attr->currentDirectory == NULL);  /* not implemented */
        }

#ifdef SYMBIAN
        /* In Symbian OS, we use posix_spawn instead of fork() and exec() */
        posix_spawn(&(process->md.pid), path, NULL, NULL, argv, childEnvp);
#else
        process->md.pid = spawn(path, 3, fd_map, NULL, argv, childEnvp);
#endif

        if (fd_map[0] != 0)
            close(fd_map[0]);
        if (fd_map[1] != 1)
            close(fd_map[1]);
        if (fd_map[2] != 2)
            close(fd_map[2]);
    }
#else
    process->md.pid = fork();
#endif
    if ((pid_t) -1 == process->md.pid) {
        PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, errno);
        PR_DELETE(process);
        if (newEnvp) {
            PR_DELETE(newEnvp);
        }
        return NULL;
    } else if (0 == process->md.pid) {  /* the child process */
        /*
         * If the child process needs to exit, it must call _exit().
         * Do not call exit(), because exit() will flush and close
         * the standard I/O file descriptors, and hence corrupt
         * the parent process's standard I/O data structures.
         */

#if !defined(NTO) && !defined(SYMBIAN)
        if (attr) {
            /* the osfd's to redirect stdin, stdout, and stderr to */
            int in_osfd = -1, out_osfd = -1, err_osfd = -1;

            if (attr->stdinFd
                    && attr->stdinFd->secret->md.osfd != 0) {
                in_osfd = attr->stdinFd->secret->md.osfd;
                if (dup2(in_osfd, 0) != 0) {
                    _exit(1);  /* failed */
                }
                flags = fcntl(0, F_GETFL, 0);
                if (flags & O_NONBLOCK) {
                    fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
                }
            }
            if (attr->stdoutFd
                    && attr->stdoutFd->secret->md.osfd != 1) {
                out_osfd = attr->stdoutFd->secret->md.osfd;
                if (dup2(out_osfd, 1) != 1) {
                    _exit(1);  /* failed */
                }
                flags = fcntl(1, F_GETFL, 0);
                if (flags & O_NONBLOCK) {
                    fcntl(1, F_SETFL, flags & ~O_NONBLOCK);
                }
            }
            if (attr->stderrFd
                    && attr->stderrFd->secret->md.osfd != 2) {
                err_osfd = attr->stderrFd->secret->md.osfd;
                if (dup2(err_osfd, 2) != 2) {
                    _exit(1);  /* failed */
                }
                flags = fcntl(2, F_GETFL, 0);
                if (flags & O_NONBLOCK) {
                    fcntl(2, F_SETFL, flags & ~O_NONBLOCK);
                }
            }
            if (in_osfd != -1) {
                close(in_osfd);
            }
            if (out_osfd != -1 && out_osfd != in_osfd) {
                close(out_osfd);
            }
            if (err_osfd != -1 && err_osfd != in_osfd
                    && err_osfd != out_osfd) {
                close(err_osfd);
            }
            if (attr->currentDirectory) {
                if (chdir(attr->currentDirectory) < 0) {
                    _exit(1);  /* failed */
                }
            }
        }

        if (childEnvp) {
            (void)execve(path, argv, childEnvp);
        } else {
            /* Inherit the environment of the parent. */
            (void)execv(path, argv);
        }
        /* Whoops! It returned. That's a bad sign. */
        _exit(1);
#endif /* !NTO */
    }

    if (newEnvp) {
        PR_DELETE(newEnvp);
    }

#if defined(_PR_NATIVE_THREADS)
    PR_Lock(pr_wp.ml);
    if (0 == pr_wp.numProcs++) {
        PR_NotifyCondVar(pr_wp.cv);
    }
    PR_Unlock(pr_wp.ml);
#endif
    return process;
}
int NaClSelLdrMain(int argc, char **argv) {
  int                           opt;
  char                          *rest;
  struct redir                  *entry;
  struct redir                  *redir_queue;
  struct redir                  **redir_qend;


  struct NaClApp                state;
  char                          *nacl_file = NULL;
  char                          *blob_library_file = NULL;
  int                           rpc_supplies_nexe = 0;
  int                           export_addr_to = -1;

  struct NaClApp                *nap = &state;

  struct GioFile                gout;
  NaClErrorCode                 errcode = LOAD_INTERNAL;
  struct GioMemoryFileSnapshot  blob_file;

  int                           ret_code;
  struct DynArray               env_vars;

  char                          *log_file = NULL;
  int                           verbosity = 0;
  int                           fuzzing_quit_after_load = 0;
  int                           debug_mode_bypass_acl_checks = 0;
  int                           debug_mode_ignore_validator = 0;
  int                           skip_qualification = 0;
  int                           handle_signals = 0;
  int                           enable_debug_stub = 0;
  struct NaClPerfCounter        time_all_main;
  const char                    **envp;
  struct NaClEnvCleanser        env_cleanser;

#if NACL_OSX
  /* Mac dynamic libraries cannot access the environ variable directly. */
  envp = (const char **) *_NSGetEnviron();
#else
  /* Overzealous code style check is overzealous. */
  /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */
  extern char **environ;
  envp = (const char **) environ;
#endif

  ret_code = 1;
  redir_queue = NULL;
  redir_qend = &redir_queue;

  memset(&state, 0, sizeof state);
  NaClAllModulesInit();
  NaClBootstrapChannelErrorReporterInit();
  NaClErrorLogHookInit(NaClBootstrapChannelErrorReporter, &state);

  verbosity = NaClLogGetVerbosity();

  NaClPerfCounterCtor(&time_all_main, "SelMain");

  fflush((FILE *) NULL);

  NaClDebugExceptionHandlerStandaloneHandleArgs(argc, argv);

  if (!GioFileRefCtor(&gout, stdout)) {
    fprintf(stderr, "Could not create general standard output channel\n");
    exit(1);
  }
  if (!NaClAppCtor(&state)) {
    NaClLog(LOG_FATAL, "NaClAppCtor() failed\n");
  }
  if (!DynArrayCtor(&env_vars, 0)) {
    NaClLog(LOG_FATAL, "Failed to allocate env var array\n");
  }
  /*
   * On platforms with glibc getopt, require POSIXLY_CORRECT behavior,
   * viz, no reordering of the arglist -- stop argument processing as
   * soon as an unrecognized argument is encountered, so that, for
   * example, in the invocation
   *
   *   sel_ldr foo.nexe -vvv
   *
   * the -vvv flags are made available to the nexe, rather than being
   * consumed by getopt.  This makes the behavior of the Linux build
   * of sel_ldr consistent with the Windows and OSX builds.
   */
  while ((opt = my_getopt(argc, argv,
#if NACL_LINUX
                       "+D:z:"
#endif
                       "aB:ceE:f:Fgh:i:l:Qr:RsSvw:X:Z")) != -1) {
    switch (opt) {
      case 'a':
        fprintf(stderr, "DEBUG MODE ENABLED (bypass acl)\n");
        debug_mode_bypass_acl_checks = 1;
        break;
      case 'B':
        blob_library_file = optarg;
        break;
      case 'c':
        ++debug_mode_ignore_validator;
        break;
#if NACL_LINUX
      case 'D':
        NaClHandleRDebug(optarg, argv[0]);
        break;
#endif
      case 'e':
        nap->enable_exception_handling = 1;
        break;
      case 'E':
        /*
         * For simplicity, we treat the environment variables as a
         * list of strings rather than a key/value mapping.  We do not
         * try to prevent duplicate keys or require the strings to be
         * of the form "KEY=VALUE".  This is in line with how execve()
         * works in Unix.
         *
         * We expect that most callers passing "-E" will either pass
         * in a fixed list or will construct the list using a
         * high-level language, in which case de-duplicating keys
         * outside of sel_ldr is easier.  However, we could do
         * de-duplication here if it proves to be worthwhile.
         */
        if (!DynArraySet(&env_vars, env_vars.num_entries, optarg)) {
          NaClLog(LOG_FATAL, "Adding item to env_vars failed\n");
        }
        break;
      case 'f':
        nacl_file = optarg;
        break;
      case 'F':
        fuzzing_quit_after_load = 1;
        break;

      case 'g':
        enable_debug_stub = 1;
        break;

      case 'h':
      case 'r':
      case 'w':
        /* import host descriptor */
        entry = malloc(sizeof *entry);
        if (NULL == entry) {
          fprintf(stderr, "No memory for redirection queue\n");
          exit(1);
        }
        entry->next = NULL;
        entry->nacl_desc = strtol(optarg, &rest, 0);
        entry->tag = HOST_DESC;
        entry->u.host.d = strtol(rest+1, (char **) 0, 0);
        entry->u.host.mode = ImportModeMap(opt);
        *redir_qend = entry;
        redir_qend = &entry->next;
        break;
      case 'i':
        /* import IMC handle */
        entry = malloc(sizeof *entry);
        if (NULL == entry) {
          fprintf(stderr, "No memory for redirection queue\n");
          exit(1);
        }
        entry->next = NULL;
        entry->nacl_desc = strtol(optarg, &rest, 0);
        entry->tag = IMC_DESC;
        entry->u.handle = (NaClHandle) strtol(rest+1, (char **) 0, 0);
        *redir_qend = entry;
        redir_qend = &entry->next;
        break;
      case 'l':
        log_file = optarg;
        break;
      case 'Q':
        fprintf(stderr, "PLATFORM QUALIFICATION DISABLED BY -Q - "
                "Native Client's sandbox will be unreliable!\n");
        skip_qualification = 1;
        break;
      case 'R':
        rpc_supplies_nexe = 1;
        break;
      /* case 'r':  with 'h' and 'w' above */
      case 's':
        nap->validator_stub_out_mode = 1;
        break;
      case 'S':
        handle_signals = 1;
        break;
      case 'v':
        ++verbosity;
        NaClLogIncrVerbosity();
        break;
      /* case 'w':  with 'h' and 'r' above */
      case 'X':
        export_addr_to = strtol(optarg, (char **) 0, 0);
        break;
#if NACL_LINUX
      case 'z':
        NaClHandleReservedAtZero(optarg);
        break;
#endif
      case 'Z':
        NaClLog(LOG_WARNING, "Enabling Fixed-Feature CPU Mode\n");
        nap->fixed_feature_cpu_mode = 1;
        if (!nap->validator->FixCPUFeatures(nap->cpu_features)) {
          NaClLog(LOG_ERROR,
                  "This CPU lacks features required by "
                  "fixed-function CPU mode.\n");
          exit(1);
        }
        break;
      default:
        fprintf(stderr, "ERROR: unknown option: [%c]\n\n", opt);
        PrintUsage();
        exit(-1);
    }
  }

  if (debug_mode_ignore_validator == 1)
    fprintf(stderr, "DEBUG MODE ENABLED (ignore validator)\n");
  else if (debug_mode_ignore_validator > 1)
    fprintf(stderr, "DEBUG MODE ENABLED (skip validator)\n");

  if (verbosity) {
    int         ix;
    char const  *separator = "";

    fprintf(stderr, "sel_ldr argument list:\n");
    for (ix = 0; ix < argc; ++ix) {
      fprintf(stderr, "%s%s", separator, argv[ix]);
      separator = " ";
    }
    putc('\n', stderr);
  }

  if (debug_mode_bypass_acl_checks) {
    NaClInsecurelyBypassAllAclChecks();
  }

  /*
   * change stdout/stderr to log file now, so that subsequent error
   * messages will go there.  unfortunately, error messages that
   * result from getopt processing -- usually out-of-memory, which
   * shouldn't happen -- won't show up.
   */
  if (NULL != log_file) {
    NaClLogSetFile(log_file);
  }

  if (rpc_supplies_nexe) {
    if (NULL != nacl_file) {
      fprintf(stderr,
              "sel_ldr: mutually exclusive flags -f and -R both used\n");
      exit(1);
    }
    /* post: NULL == nacl_file */
    if (export_addr_to < 0) {
      fprintf(stderr,
              "sel_ldr: -R requires -X to set up secure command channel\n");
      exit(1);
    }
  } else {
    if (NULL == nacl_file && optind < argc) {
      nacl_file = argv[optind];
      ++optind;
    }
    if (NULL == nacl_file) {
      fprintf(stderr, "No nacl file specified\n");
      exit(1);
    }
    /* post: NULL != nacl_file */
  }
  /*
   * post condition established by the above code (in Hoare logic
   * terminology):
   *
   * NULL == nacl_file iff rpc_supplies_nexe
   *
   * so hence forth, testing !rpc_supplies_nexe suffices for
   * establishing NULL != nacl_file.
   */
  CHECK((NULL == nacl_file) == rpc_supplies_nexe);

  /* to be passed to NaClMain, eventually... */
  argv[--optind] = (char *) "NaClMain";

  state.ignore_validator_result = (debug_mode_ignore_validator > 0);
  state.skip_validator = (debug_mode_ignore_validator > 1);

  if (getenv("NACL_UNTRUSTED_EXCEPTION_HANDLING") != NULL) {
    state.enable_exception_handling = 1;
  }
  if (state.enable_exception_handling || enable_debug_stub) {
#if NACL_WINDOWS
    state.attach_debug_exception_handler_func =
        NaClDebugExceptionHandlerStandaloneAttach;
#elif NACL_LINUX
    /* NaCl's signal handler is always enabled on Linux. */
#elif NACL_OSX
    if (!NaClInterceptMachExceptions()) {
      fprintf(stderr, "ERROR setting up Mach exception interception.\n");
      return -1;
    }
#else
# error Unknown host OS
#endif
  }
  if (NACL_LINUX) {
    handle_signals = 1;
  }

  errcode = LOAD_OK;

  /*
   * in order to report load error to the browser plugin through the
   * secure command channel, we do not immediate jump to cleanup code
   * on error.  rather, we continue processing (assuming earlier
   * errors do not make it inappropriate) until the secure command
   * channel is set up, and then bail out.
   */

  /*
   * Ensure the platform qualification checks pass.
   *
   * NACL_DANGEROUS_SKIP_QUALIFICATION_TEST is used by tsan / memcheck
   * (see src/third_party/valgrind/).
   */
  if (!skip_qualification &&
      getenv("NACL_DANGEROUS_SKIP_QUALIFICATION_TEST") != NULL) {
    fprintf(stderr, "PLATFORM QUALIFICATION DISABLED BY ENVIRONMENT - "
            "Native Client's sandbox will be unreliable!\n");
    skip_qualification = 1;
  }

  if (!skip_qualification) {
    NaClErrorCode pq_error = NACL_FI_VAL("pq", NaClErrorCode,
                                         NaClRunSelQualificationTests());
    if (LOAD_OK != pq_error) {
      errcode = pq_error;
      nap->module_load_status = pq_error;
      fprintf(stderr, "Error while loading \"%s\": %s\n",
              NULL != nacl_file ? nacl_file
                                : "(no file, to-be-supplied-via-RPC)",
              NaClErrorString(errcode));
    }
  }

  if (handle_signals) {
    NaClSignalHandlerInit();
  } else {
    /*
     * Patch the Windows exception dispatcher to be safe in the case
     * of faults inside x86-64 sandboxed code.  The sandbox is not
     * secure on 64-bit Windows without this.
     */
#if (NACL_WINDOWS && NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && \
     NACL_BUILD_SUBARCH == 64)
    NaClPatchWindowsExceptionDispatcher();
#endif
  }
  NaClSignalTestCrashOnStartup();

  /*
   * Open both files first because (on Mac OS X at least)
   * NaClAppLoadFile() enables an outer sandbox.
   */
  if (NULL != blob_library_file) {
    NaClFileNameForValgrind(blob_library_file);
    if (0 == GioMemoryFileSnapshotCtor(&blob_file, blob_library_file)) {
      perror("sel_main");
      fprintf(stderr, "Cannot open \"%s\".\n", blob_library_file);
      exit(1);
    }
    NaClPerfCounterMark(&time_all_main, "SnapshotBlob");
    NaClPerfCounterIntervalLast(&time_all_main);
  }

  NaClAppInitialDescriptorHookup(nap);

  if (!rpc_supplies_nexe) {
    struct GioMemoryFileSnapshot main_file;

    NaClFileNameForValgrind(nacl_file);
    if (0 == GioMemoryFileSnapshotCtor(&main_file, nacl_file)) {
      perror("sel_main");
      fprintf(stderr, "Cannot open \"%s\".\n", nacl_file);
      exit(1);
    }
    NaClPerfCounterMark(&time_all_main, "SnapshotNaclFile");
    NaClPerfCounterIntervalLast(&time_all_main);

    if (LOAD_OK == errcode) {
      NaClLog(2, "Loading nacl file %s (non-RPC)\n", nacl_file);
      errcode = NaClAppLoadFile((struct Gio *) &main_file, nap);
      if (LOAD_OK != errcode) {
        fprintf(stderr, "Error while loading \"%s\": %s\n",
                nacl_file,
                NaClErrorString(errcode));
        fprintf(stderr,
                ("Using the wrong type of nexe (nacl-x86-32"
                 " on an x86-64 or vice versa)\n"
                 "or a corrupt nexe file may be"
                 " responsible for this error.\n"));
      }
      NaClPerfCounterMark(&time_all_main, "AppLoadEnd");
      NaClPerfCounterIntervalLast(&time_all_main);

      NaClXMutexLock(&nap->mu);
      nap->module_load_status = errcode;
      NaClXCondVarBroadcast(&nap->cv);
      NaClXMutexUnlock(&nap->mu);
    }

    if (-1 == (*((struct Gio *) &main_file)->vtbl->Close)((struct Gio *)
                                                          &main_file)) {
      fprintf(stderr, "Error while closing \"%s\".\n", nacl_file);
    }
    (*((struct Gio *) &main_file)->vtbl->Dtor)((struct Gio *) &main_file);

    if (fuzzing_quit_after_load) {
      exit(0);
    }
  }

  /*
   * Execute additional I/O redirections.  NB: since the NaClApp
   * takes ownership of host / IMC socket descriptors, all but
   * the first run will not get access if the NaClApp closes
   * them.  Currently a normal NaClApp process exit does not
   * close descriptors, since the underlying host OS will do so
   * as part of service runtime exit.
   */
  NaClLog(4, "Processing I/O redirection/inheritance from command line\n");
  for (entry = redir_queue; NULL != entry; entry = entry->next) {
    switch (entry->tag) {
      case HOST_DESC:
        NaClAddHostDescriptor(nap, entry->u.host.d,
                              entry->u.host.mode, entry->nacl_desc);
        break;
      case IMC_DESC:
        NaClAddImcHandle(nap, entry->u.handle, entry->nacl_desc);
        break;
    }
  }

  /*
   * If export_addr_to is set to a non-negative integer, we create a
   * bound socket and socket address pair and bind the former to
   * descriptor NACL_SERVICE_PORT_DESCRIPTOR (3 [see sel_ldr.h]) and
   * the latter to descriptor NACL_SERVICE_ADDRESS_DESCRIPTOR (4).
   * The socket address is sent to the export_addr_to descriptor.
   *
   * The service runtime also accepts a connection on the bound socket
   * and spawns a secure command channel thread to service it.
   */
  if (0 <= export_addr_to) {
    NaClCreateServiceSocket(nap);
    /*
     * LOG_FATAL errors that occur before NaClSetUpBootstrapChannel will
     * not be reported via the crash log mechanism (for Chromium
     * embedding of NaCl, shown in the JavaScript console).
     *
     * Some errors, such as due to NaClRunSelQualificationTests, do not
     * trigger a LOG_FATAL but instead set module_load_status to be sent
     * in the start_module RPC reply.  Log messages associated with such
     * errors would be seen, since NaClSetUpBootstrapChannel will get
     * called.
     */
    NaClSetUpBootstrapChannel(nap, (NaClHandle) export_addr_to);
    /*
     * NB: spawns a thread that uses the command channel.  we do
     * this after NaClAppLoadFile so that NaClApp object is more
     * fully populated.  Hereafter any changes to nap should be done
     * while holding locks.
     */
    NaClSecureCommandChannel(nap);
  }

  /*
   * May have created a thread, so need to synchronize uses of nap
   * contents henceforth.
   */

  if (rpc_supplies_nexe) {
    errcode = NaClWaitForLoadModuleStatus(nap);
    NaClPerfCounterMark(&time_all_main, "WaitForLoad");
    NaClPerfCounterIntervalLast(&time_all_main);
  } else {
    /**************************************************************************
     * TODO(bsy): This else block should be made unconditional and
     * invoked after the LoadModule RPC completes, eliminating the
     * essentially dulicated code in latter part of NaClLoadModuleRpc.
     * This cannot be done until we have full saucer separation
     * technology, since Chrome currently uses sel_main_chrome.c and
     * relies on the functionality of the duplicated code.
     *************************************************************************/
    if (LOAD_OK == errcode) {
      if (verbosity) {
        gprintf((struct Gio *) &gout, "printing NaClApp details\n");
        NaClAppPrintDetails(nap, (struct Gio *) &gout);
      }

      /*
       * Finish setting up the NaCl App.  On x86-32, this means
       * allocating segment selectors.  On x86-64 and ARM, this is
       * (currently) a no-op.
       */
      errcode = NaClAppPrepareToLaunch(nap);
      if (LOAD_OK != errcode) {
        nap->module_load_status = errcode;
        fprintf(stderr, "NaClAppPrepareToLaunch returned %d", errcode);
      }
      NaClPerfCounterMark(&time_all_main, "AppPrepLaunch");
      NaClPerfCounterIntervalLast(&time_all_main);
    }

    /* Give debuggers a well known point at which xlate_base is known.  */
    NaClGdbHook(&state);
  }

  /*
   * Tell the debug stub to bind a TCP port before enabling the outer
   * sandbox.  This is only needed on Mac OS X since that is the only
   * platform where we have an outer sandbox in standalone sel_ldr.
   * In principle this call should work on all platforms, but Windows
   * XP seems to have some problems when we do bind()/listen() on a
   * separate thread from accept().
   */
  if (enable_debug_stub && NACL_OSX) {
    if (!NaClDebugBindSocket()) {
      exit(1);
    }
  }

  /*
   * Enable the outer sandbox, if one is defined.  Do this as soon as
   * possible.
   *
   * This must come after NaClWaitForLoadModuleStatus(), which waits
   * for another thread to have called NaClAppLoadFile().
   * NaClAppLoadFile() does not work inside the Mac outer sandbox in
   * standalone sel_ldr when using a dynamic code area because it uses
   * NaClCreateMemoryObject() which opens a file in /tmp.
   *
   * We cannot enable the sandbox if file access is enabled.
   */
  if (!NaClAclBypassChecks && g_enable_outer_sandbox_func != NULL) {
    g_enable_outer_sandbox_func();
  }

  if (NULL != blob_library_file) {
    if (LOAD_OK == errcode) {
      NaClLog(2, "Loading blob file %s\n", blob_library_file);
      errcode = NaClAppLoadFileDynamically(nap, (struct Gio *) &blob_file);
      if (LOAD_OK != errcode) {
        fprintf(stderr, "Error while loading \"%s\": %s\n",
                blob_library_file,
                NaClErrorString(errcode));
      }
      NaClPerfCounterMark(&time_all_main, "BlobLoaded");
      NaClPerfCounterIntervalLast(&time_all_main);
    }

    if (-1 == (*((struct Gio *) &blob_file)->vtbl->Close)((struct Gio *)
                                                          &blob_file)) {
      fprintf(stderr, "Error while closing \"%s\".\n", blob_library_file);
    }
    (*((struct Gio *) &blob_file)->vtbl->Dtor)((struct Gio *) &blob_file);
    if (verbosity) {
      gprintf((struct Gio *) &gout, "printing post-IRT NaClApp details\n");
      NaClAppPrintDetails(nap, (struct Gio *) &gout);
    }
  }

  /*
   * Print out a marker for scripts to use to mark the start of app
   * output.
   */
  NaClLog(1, "NACL: Application output follows\n");

  /*
   * Make sure all the file buffers are flushed before entering
   * the application code.
   */
  fflush((FILE *) NULL);

  if (NULL != nap->secure_service) {
    NaClErrorCode start_result;
    /*
     * wait for start_module RPC call on secure channel thread.
     */
    start_result = NaClWaitForStartModuleCommand(nap);
    NaClPerfCounterMark(&time_all_main, "WaitedForStartModuleCommand");
    NaClPerfCounterIntervalLast(&time_all_main);
    if (LOAD_OK == errcode) {
      errcode = start_result;
    }
  }

  /*
   * error reporting done; can quit now if there was an error earlier.
   */
  if (LOAD_OK != errcode) {
    NaClLog(4,
            "Not running app code since errcode is %s (%d)\n",
            NaClErrorString(errcode),
            errcode);
    goto done;
  }

  if (!DynArraySet(&env_vars, env_vars.num_entries, NULL)) {
    NaClLog(LOG_FATAL, "Adding env_vars NULL terminator failed\n");
  }

  NaClEnvCleanserCtor(&env_cleanser, 0);
  if (!NaClEnvCleanserInit(&env_cleanser, envp,
          (char const *const *)env_vars.ptr_array)) {
    NaClLog(LOG_FATAL, "Failed to initialise env cleanser\n");
  }

  if (!NaClAppLaunchServiceThreads(nap)) {
    fprintf(stderr, "Launch service threads failed\n");
    goto done;
  }
  if (enable_debug_stub) {
    if (!NaClDebugInit(nap)) {
      goto done;
    }
  }
  NACL_TEST_INJECTION(BeforeMainThreadLaunches, ());
  if (!NaClCreateMainThread(nap,
                            argc - optind,
                            argv + optind,
                            NaClEnvCleanserEnvironment(&env_cleanser))) {
    fprintf(stderr, "creating main thread failed\n");
    goto done;
  }

  NaClEnvCleanserDtor(&env_cleanser);

  NaClPerfCounterMark(&time_all_main, "CreateMainThread");
  NaClPerfCounterIntervalLast(&time_all_main);
  DynArrayDtor(&env_vars);

  ret_code = NaClWaitForMainThreadToExit(nap);
  NaClPerfCounterMark(&time_all_main, "WaitForMainThread");
  NaClPerfCounterIntervalLast(&time_all_main);

  NaClPerfCounterMark(&time_all_main, "SelMainEnd");
  NaClPerfCounterIntervalTotal(&time_all_main);

  /*
   * exit_group or equiv kills any still running threads while module
   * addr space is still valid.  otherwise we'd have to kill threads
   * before we clean up the address space.
   */
  NaClExit(ret_code);

 done:
  fflush(stdout);

  if (verbosity) {
    gprintf((struct Gio *) &gout, "exiting -- printing NaClApp details\n");
    NaClAppPrintDetails(nap, (struct Gio *) &gout);

    printf("Dumping vmmap.\n"); fflush(stdout);
    PrintVmmap(nap);
    fflush(stdout);
  }
  /*
   * If there is a secure command channel, we sent an RPC reply with
   * the reason that the nexe was rejected.  If we exit now, that
   * reply may still be in-flight and the various channel closure (esp
   * reverse channel) may be detected first.  This would result in a
   * crash being reported, rather than the error in the RPC reply.
   * Instead, we wait for the hard-shutdown on the command channel.
   */
  if (LOAD_OK != errcode) {
    NaClBlockIfCommandChannelExists(nap);
  }

  if (verbosity > 0) {
    printf("Done.\n");
  }
  fflush(stdout);

  if (handle_signals) NaClSignalHandlerFini();
  NaClAllModulesFini();

  NaClExit(ret_code);

  /* Unreachable, but having the return prevents a compiler error. */
  return ret_code;
}
Exemple #27
0
/*******************************************************************************
* Fork a process after a specified delay, and either wait on it to exit or
* leave it to run in the background.
*
* Returns -2 on spawn() failure, -1 on other failure, and depending on wait:
* wait: true - exit status of forked program
* wait: false - pid of background process
*******************************************************************************/
int fork_program(const char * argv0, char * const argv[], Boolean wait)
{
    int            result;
    int            spawn_result;
    pid_t          child_pid;
    int            child_status;
    int            normal_iopolicy = getiopolicy_np(IOPOL_TYPE_DISK,
                                                    IOPOL_SCOPE_PROCESS);
    char ** environ = *(_NSGetEnviron());

    if (!wait) {
        setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_THROTTLE);
    }

    spawn_result = posix_spawn(&child_pid, argv0, /* file_actions */ NULL,
        /* spawnattrs */ NULL, argv, environ);

    // If we couldn't spawn the process, return -2 with errno for detail
    if (spawn_result != 0) {
        OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel,
            "posix_spawn failed for %s.", argv0);
        errno = spawn_result;
        result = -2;
        goto finish;
    }

    OSKextLog(/* kext */ NULL, kOSKextLogDetailLevel,
              "started child process %s[%d] (%ssynchronous).",
              argv0, child_pid, wait ? "" : "a");

    if (wait) {
        OSKextLogSpec logSpec = kOSKextLogDetailLevel;
        if (waitpid(child_pid, &child_status, 0) == -1) {
            result = -1;
            goto finish;
        }
        if (WIFEXITED(child_status)) {
            result = WEXITSTATUS(child_status);
            if (result) {
                logSpec = kOSKextLogErrorLevel;
            }
            OSKextLog(/* kext */ NULL, logSpec,
                "Child process %s[%d] exited with status %d.",
                argv0, child_pid, result);
        } else if (WIFSIGNALED(child_status)) {
            result = WTERMSIG(child_status);
            logSpec = kOSKextLogErrorLevel;
            OSKextLog(/* kext */ NULL, logSpec,
                "Child process %s[%d] exited due to signal %d.",
                argv0, child_pid, result);
        } else {
            // shouldn't be any other types of exit
            result = -1;
        }
    } else {
        result = child_pid;
    }

finish:
    setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, normal_iopolicy);
    
    return result;
}
Exemple #28
0
static PRProcess *
ForkAndExec(
    const char *path,
    char *const *argv,
    char *const *envp,
    const PRProcessAttr *attr)
{
    PRProcess *process;
    int nEnv, idx;
    char *const *childEnvp;
    char **newEnvp = NULL;
    int flags;
#ifdef VMS
    char VMScurdir[FILENAME_MAX+1] = { '\0' } ;
#endif	

    process = PR_NEW(PRProcess);
    if (!process) {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return NULL;
    }

    childEnvp = envp;
    if (attr && attr->fdInheritBuffer) {
        PRBool found = PR_FALSE;

        if (NULL == childEnvp) {
#ifdef DARWIN
            childEnvp = *(_NSGetEnviron());
#else
            childEnvp = environ;
#endif
        }
        for (nEnv = 0; childEnvp[nEnv]; nEnv++) {
        }
        newEnvp = (char **) PR_MALLOC((nEnv + 2) * sizeof(char *));
        if (NULL == newEnvp) {
            PR_DELETE(process);
            PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
            return NULL;
        }
        for (idx = 0; idx < nEnv; idx++) {
            newEnvp[idx] = childEnvp[idx];
            if (!found && !strncmp(newEnvp[idx], "NSPR_INHERIT_FDS=", 17)) {
                newEnvp[idx] = attr->fdInheritBuffer;
                found = PR_TRUE;
            }
        }
        if (!found) {
            newEnvp[idx++] = attr->fdInheritBuffer;
        }
        newEnvp[idx] = NULL;
        childEnvp = newEnvp;
    }

#ifdef VMS
/*
** Since vfork/exec is implemented VERY differently on OpenVMS, we have to
** handle the setting up of the standard streams very differently. And since
** none of this code can ever execute in the context of the child, we have
** to perform the chdir in the parent so the child is born into the correct
** directory (and then switch the parent back again).
*/
{
    int decc$set_child_standard_streams(int,int,int);
    int n, fd_stdin=0, fd_stdout=1, fd_stderr=2;

    /* Set up any standard streams we are given, assuming defaults */
    if (attr) {
       if (attr->stdinFd)
           fd_stdin = attr->stdinFd->secret->md.osfd;
       if (attr->stdoutFd)
           fd_stdout = attr->stdoutFd->secret->md.osfd;
       if (attr->stderrFd)
           fd_stderr = attr->stderrFd->secret->md.osfd;
    }

    /*
    ** Put a lock around anything that isn't going to be thread-safe.
    */
    PR_Lock(_pr_vms_fork_lock);

    /*
    ** Prepare the child's streams. We always do this in case a previous fork
    ** has left the stream assignments in some non-standard way.
    */
    n = decc$set_child_standard_streams(fd_stdin,fd_stdout,fd_stderr);
    if (n == -1) {
       PR_SetError(PR_BAD_DESCRIPTOR_ERROR, errno);
       PR_DELETE(process);
       if (newEnvp) {
           PR_DELETE(newEnvp);
       }
       PR_Unlock(_pr_vms_fork_lock);
       return NULL;
    }

    /* Switch directory if we have to */
    if (attr) {
       if (attr->currentDirectory) {
           if ( (getcwd(VMScurdir,sizeof(VMScurdir)) == NULL) ||
                (chdir(attr->currentDirectory) < 0) ) {
               PR_SetError(PR_DIRECTORY_OPEN_ERROR, errno);
               PR_DELETE(process);
               if (newEnvp) {
                   PR_DELETE(newEnvp);
               }
               PR_Unlock(_pr_vms_fork_lock);
               return NULL;
           }
       }
    }
}
#endif /* VMS */

#ifdef AIX
    process->md.pid = (*pr_wp.forkptr)();
#elif defined(NTO) || defined(SYMBIAN)
    /*
     * fork() & exec() does not work in a multithreaded process.
     * Use spawn() instead.
     */
    {
        int fd_map[3] = { 0, 1, 2 };

        if (attr) {
            if (attr->stdinFd && attr->stdinFd->secret->md.osfd != 0) {
                fd_map[0] = dup(attr->stdinFd->secret->md.osfd);
                flags = fcntl(fd_map[0], F_GETFL, 0);
                if (flags & O_NONBLOCK)
                    fcntl(fd_map[0], F_SETFL, flags & ~O_NONBLOCK);
            }
            if (attr->stdoutFd && attr->stdoutFd->secret->md.osfd != 1) {
                fd_map[1] = dup(attr->stdoutFd->secret->md.osfd);
                flags = fcntl(fd_map[1], F_GETFL, 0);
                if (flags & O_NONBLOCK)
                    fcntl(fd_map[1], F_SETFL, flags & ~O_NONBLOCK);
            }
            if (attr->stderrFd && attr->stderrFd->secret->md.osfd != 2) {
                fd_map[2] = dup(attr->stderrFd->secret->md.osfd);
                flags = fcntl(fd_map[2], F_GETFL, 0);
                if (flags & O_NONBLOCK)
                    fcntl(fd_map[2], F_SETFL, flags & ~O_NONBLOCK);
            }

            PR_ASSERT(attr->currentDirectory == NULL);  /* not implemented */
        }

#ifdef SYMBIAN
        /* In Symbian OS, we use posix_spawn instead of fork() and exec() */
        posix_spawn(&(process->md.pid), path, NULL, NULL, argv, childEnvp);
#else
        process->md.pid = spawn(path, 3, fd_map, NULL, argv, childEnvp);
#endif

        if (fd_map[0] != 0)
            close(fd_map[0]);
        if (fd_map[1] != 1)
            close(fd_map[1]);
        if (fd_map[2] != 2)
            close(fd_map[2]);
    }
#else
    process->md.pid = fork();
#endif
    if ((pid_t) -1 == process->md.pid) {
        PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, errno);
        PR_DELETE(process);
        if (newEnvp) {
            PR_DELETE(newEnvp);
        }
        return NULL;
    } else if (0 == process->md.pid) {  /* the child process */
        /*
         * If the child process needs to exit, it must call _exit().
         * Do not call exit(), because exit() will flush and close
         * the standard I/O file descriptors, and hence corrupt
         * the parent process's standard I/O data structures.
         */

#if !defined(NTO) && !defined(SYMBIAN)
#ifdef VMS
       /* OpenVMS has already handled all this above */
#else
        if (attr) {
            /* the osfd's to redirect stdin, stdout, and stderr to */
            int in_osfd = -1, out_osfd = -1, err_osfd = -1;

            if (attr->stdinFd
                    && attr->stdinFd->secret->md.osfd != 0) {
                in_osfd = attr->stdinFd->secret->md.osfd;
                if (dup2(in_osfd, 0) != 0) {
                    _exit(1);  /* failed */
                }
                flags = fcntl(0, F_GETFL, 0);
                if (flags & O_NONBLOCK) {
                    fcntl(0, F_SETFL, flags & ~O_NONBLOCK);
                }
            }
            if (attr->stdoutFd
                    && attr->stdoutFd->secret->md.osfd != 1) {
                out_osfd = attr->stdoutFd->secret->md.osfd;
                if (dup2(out_osfd, 1) != 1) {
                    _exit(1);  /* failed */
                }
                flags = fcntl(1, F_GETFL, 0);
                if (flags & O_NONBLOCK) {
                    fcntl(1, F_SETFL, flags & ~O_NONBLOCK);
                }
            }
            if (attr->stderrFd
                    && attr->stderrFd->secret->md.osfd != 2) {
                err_osfd = attr->stderrFd->secret->md.osfd;
                if (dup2(err_osfd, 2) != 2) {
                    _exit(1);  /* failed */
                }
                flags = fcntl(2, F_GETFL, 0);
                if (flags & O_NONBLOCK) {
                    fcntl(2, F_SETFL, flags & ~O_NONBLOCK);
                }
            }
            if (in_osfd != -1) {
                close(in_osfd);
            }
            if (out_osfd != -1 && out_osfd != in_osfd) {
                close(out_osfd);
            }
            if (err_osfd != -1 && err_osfd != in_osfd
                    && err_osfd != out_osfd) {
                close(err_osfd);
            }
            if (attr->currentDirectory) {
                if (chdir(attr->currentDirectory) < 0) {
                    _exit(1);  /* failed */
                }
            }
        }
#endif /* !VMS */

        if (childEnvp) {
            (void)execve(path, argv, childEnvp);
        } else {
            /* Inherit the environment of the parent. */
            (void)execv(path, argv);
        }
        /* Whoops! It returned. That's a bad sign. */
#ifdef VMS
       /*
       ** On OpenVMS we are still in the context of the parent, and so we
       ** can (and should!) perform normal error handling.
       */
       PR_SetError(PR_UNKNOWN_ERROR, errno);
       PR_DELETE(process);
       if (newEnvp) {
           PR_DELETE(newEnvp);
       }
       if (VMScurdir[0] != '\0')
           chdir(VMScurdir);
       PR_Unlock(_pr_vms_fork_lock);
       return NULL;
#else
        _exit(1);
#endif /* VMS */
#endif /* !NTO */
    }

    if (newEnvp) {
        PR_DELETE(newEnvp);
    }
#ifdef VMS
    /* If we switched directories, then remember to switch back */
    if (VMScurdir[0] != '\0') {
       chdir(VMScurdir); /* can't do much if it fails */
    }
    PR_Unlock(_pr_vms_fork_lock);
#endif /* VMS */

#if defined(_PR_NATIVE_THREADS)
    PR_Lock(pr_wp.ml);
    if (0 == pr_wp.numProcs++) {
        PR_NotifyCondVar(pr_wp.cv);
    }
    PR_Unlock(pr_wp.ml);
#endif
    return process;
}
Exemple #29
0
void Options::initialize()
{
    static std::once_flag initializeOptionsOnceFlag;
    
    std::call_once(
        initializeOptionsOnceFlag,
        [] {
            // Initialize each of the options with their default values:
#define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
            name_() = defaultValue_;                                    \
            name_##Default() = defaultValue_;
            JSC_OPTIONS(FOR_EACH_OPTION)
#undef FOR_EACH_OPTION

            overrideDefaults();
                
            // Allow environment vars to override options if applicable.
            // The evn var should be the name of the option prefixed with
            // "JSC_".
#if PLATFORM(COCOA)
            bool hasBadOptions = false;
            for (char** envp = *_NSGetEnviron(); *envp; envp++) {
                const char* env = *envp;
                if (!strncmp("JSC_", env, 4)) {
                    if (!Options::setOption(&env[4])) {
                        dataLog("ERROR: invalid option: ", *envp, "\n");
                        hasBadOptions = true;
                    }
                }
            }
            if (hasBadOptions && Options::validateOptions())
                CRASH();
#else // PLATFORM(COCOA)
#define FOR_EACH_OPTION(type_, name_, defaultValue_, availability_, description_) \
            overrideOptionWithHeuristic(name_(), name_##ID, "JSC_" #name_, Availability::availability_);
            JSC_OPTIONS(FOR_EACH_OPTION)
#undef FOR_EACH_OPTION
#endif // PLATFORM(COCOA)

#define FOR_EACH_OPTION(aliasedName_, unaliasedName_, equivalence_) \
            overrideAliasedOptionWithHeuristic("JSC_" #aliasedName_);
            JSC_ALIASED_OPTIONS(FOR_EACH_OPTION)
#undef FOR_EACH_OPTION

#if 0
                ; // Deconfuse editors that do auto indentation
#endif
    
#if USE(OPTIONS_FILE)
            {
                const char* filename = OPTIONS_FILENAME;
                FILE* optionsFile = fopen(filename, "r");
                if (!optionsFile) {
                    dataLogF("Failed to open file %s. Did you add the file-read-data entitlement to WebProcess.sb?\n", filename);
                    return;
                }
                
                StringBuilder builder;
                char* line;
                char buffer[BUFSIZ];
                while ((line = fgets(buffer, sizeof(buffer), optionsFile)))
                    builder.append(buffer);
                
                const char* optionsStr = builder.toString().utf8().data();
                dataLogF("Setting options: %s\n", optionsStr);
                setOptions(optionsStr);
                
                int result = fclose(optionsFile);
                if (result)
                    dataLogF("Failed to close file %s: %s\n", filename, strerror(errno));
            }
#endif

            recomputeDependentOptions();

            // Do range checks where needed and make corrections to the options:
            ASSERT(Options::thresholdForOptimizeAfterLongWarmUp() >= Options::thresholdForOptimizeAfterWarmUp());
            ASSERT(Options::thresholdForOptimizeAfterWarmUp() >= Options::thresholdForOptimizeSoon());
            ASSERT(Options::thresholdForOptimizeAfterWarmUp() >= 0);

            dumpOptionsIfNeeded();
            ensureOptionsAreCoherent();
        });
}
Exemple #30
0
#include <vle/utils/Spawn.hpp>
#include <vle/utils/i18n.hpp>
#include <sys/wait.h>
#include <unistd.h>
#include <cerrno>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>

#ifdef __APPLE__
 #include <crt_externs.h>
 extern "C" char ** environ = *_NSGetEnviron();
#endif

namespace vle { namespace utils {

const unsigned long int Spawn::default_buffer_size = BUFSIZ;

struct strdup_functor
    : std::unary_function < std::string, char* >
{
    char * operator()(const std::string& str) const
    {
        return strdup(str.c_str());
    }
};