コード例 #1
0
ファイル: string_commands.cpp プロジェクト: timn/fawkes
/** Copy an environment and extend certain paths.
 * This will create a vector which comprises the environment in @p environ.
 * The path_ext are assumed to be pairwise entries of environment variable
 * name followed by an entry for the path extensions. Paths are here
 * colon-separated strings of paths, e.g. like the PATH environment variable.
 * If the variable had already been set, the given paths are appended to
 * the variable (a closing colon will be maintained if it exists). If they
 * were not set before, the entry is added.
 * @param environ environment to copy
 * @param path_ext path extension, an array of an odd number of elements,
 * always pairwise an entry for the variable name followed by the path extension.
 * The last element must always be NULL.
 * @return vector of strings with copied and extended environment
 */
std::vector<std::string>
envp_copy_expand(char *environ[], const char *path_ext[])
{
  std::list<std::tuple<std::string, std::string, bool>> path_ext_m;
  for (size_t i = 0; path_ext[i] && path_ext[i+1]; i += 2) {
    std::string match = std::string(path_ext[i]) + "=";
    path_ext_m.push_back(std::make_tuple(match, std::string(path_ext[i+1]), false));
  }

  unsigned int extra_ent = 0;

  size_t environ_length = 0;
  for (size_t i = 0; environ[i]; ++i) {
    ++environ_length;
    std::string ev = environ[i];
    for (auto &m : path_ext_m) {
      if (ev.find(std::get<0>(m)) == 0) {
	std::get<2>(m) = true;
	++extra_ent;
	break;
      }
    }
  }

  size_t envp_length = environ_length + extra_ent;
  std::vector<std::string> envp(envp_length);
  for (size_t i = 0; environ[i]; ++i) {
    std::string ev(environ[i]);
    for (auto m : path_ext_m) {
      if (ev.find(std::get<0>(m)) == 0) {
	// modify
	if (ev[ev.length()-1] == ':') {
	  ev += std::get<1>(m) + ":";
	} else {
	  ev += ":" + std::get<1>(m);
	}
      }
    }
    envp[i] = ev;
  }

  unsigned int extra_ind = 0;
  for (auto m : path_ext_m) {
    if (! std::get<2>(m)) {
      std::string ev = std::get<0>(m) + std::get<1>(m) + ":";
      envp[envp_length - extra_ent + extra_ind++] = ev;
    }
  }

  return envp;
}
コード例 #2
0
ファイル: exec_win32.c プロジェクト: sysman9/Liberty
EIF_BOOLEAN basic_exec_win32_execute(se_exec_data_t*data, char*args, EIF_BOOLEAN keep_env, char*add_env, HANDLE*in_h, HANDLE*out_h, HANDLE*err_h) {
    STARTUPINFO start_info;
    EIF_BOOLEAN result = 0;

    ZeroMemory( &start_info, sizeof(STARTUPINFO) );

    start_info.cb = sizeof(STARTUPINFO);
    if(in_h) {
        start_info.hStdInput = in_h[0];
        SetHandleInformation(in_h[1], HANDLE_FLAG_INHERIT, 0);
    } else {
        start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    }
    if(INVALID_HANDLE_VALUE == start_info.hStdInput) goto leave;
    if(out_h) {
        start_info.hStdOutput = out_h[1];
        SetHandleInformation(out_h[0], HANDLE_FLAG_INHERIT, 0);
    } else {
        start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    }
    if(INVALID_HANDLE_VALUE == start_info.hStdOutput) goto leave;
    if(err_h) {
        start_info.hStdError = err_h[1];
        SetHandleInformation(err_h[0], HANDLE_FLAG_INHERIT, 0);
    } else {
        start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
    }
    if(INVALID_HANDLE_VALUE == start_info.hStdError) goto leave;
    start_info.dwFlags |= STARTF_USESTDHANDLES;

    if(CreateProcess(NULL, args,
                     NULL,                                /* process security attributes          */
                     NULL,                                /* primary thread security attributes   */
                     TRUE,                                /* handles are inherited                */
                     0,                                   /* creation flags                       */
                     keep_env?NULL:envp(),
                     NULL,                                /* use parent's current directory       */
                     &start_info,                         /* STARTUPINFO pointer                  */
                     &data->process_information)) {       /* receives PROCESS_INFORMATION         */
        CloseHandle(data->process_information.hThread);
        data->running = 1;
        result = 1;
    }
leave:
    if(in_h) CloseHandle(in_h[0]);
    if(out_h) CloseHandle(out_h[1]);
    if(err_h) CloseHandle(err_h[1]);
    return result;
}
コード例 #3
0
ファイル: SC_Process.cpp プロジェクト: 0179cool/rpcs3
void sys_game_process_exitspawn2(
			u32 path_addr,
			u32 argv_addr,
			u32 envp_addr,
			u32 data_addr,
			u32 data_size,
			u32 prio,
			u64 flags)
{
	sc_p.Error("sys_game_process_exitspawn2 UNIMPLEMENTED");
	sc_p.Warning("path: %s", Memory.ReadString(path_addr).c_str());
	sc_p.Warning("argv: 0x%x", argv_addr);
	sc_p.Warning("envp: 0x%x", envp_addr);
	sc_p.Warning("data: 0x%x", data_addr);
	sc_p.Warning("data_size: 0x%x", data_size);
	sc_p.Warning("prio: %d", prio);
	sc_p.Warning("flags: %d", flags);

	std::string path = Memory.ReadString(path_addr);
	std::vector<std::string> argv;
	std::vector<std::string> env;

	mem_ptr_t<u32> argvp(argv_addr);
	while (argvp.GetAddr() && argvp.IsGood() && *argvp)
	{
		argv.push_back(Memory.ReadString(Memory.Read32(argvp.GetAddr())));
		argvp++;
	}
	mem_ptr_t<u32> envp(envp_addr);
	while (envp.GetAddr() && envp.IsGood() && *envp)
	{
		env.push_back(Memory.ReadString(Memory.Read32(envp.GetAddr())));
		envp++;
	}

	for (auto &arg : argv){
		sc_p.Log("argument: %s", arg.c_str());
	}
	for (auto &en : env){
		sc_p.Log("env_argument: %s", en.c_str());
	}
	//TODO: execute the file in <path> with the args in argv
	//and the environment parameters in envp and copy the data
	//from data_addr into the adress space of the new process
	//then kill the current process
	return;
}
コード例 #4
0
ファイル: exec_posix.c プロジェクト: tioui/Liberty
EIF_BOOLEAN basic_exec_posix_execute(se_exec_data_t*data, char*prog, char**args, EIF_BOOLEAN keep_env, char**add_env, int* in_fd, int* out_fd, int* err_fd) {
  int id = fork();
  if (id == 0) {
    /* child */

    if(in_fd) {
      dup2(in_fd[0], 0);
      close(in_fd[1]);
    }

    if(out_fd) {
      dup2(out_fd[1], 1);
      close(out_fd[0]);
    }

    if(err_fd) {
      dup2(err_fd[1], 2);
      close(err_fd[0]);
    }

    if (prog == NULL && args == NULL) {
      data->running = 1;
      data->child = 1;
#ifdef SE_SEDB
      sedb_duplicate();
#endif
      return 1;
    } else {
      if (add_env == NULL && keep_env) {
        execvp(prog, args); /* NO RETURN in child */
        se_print_run_time_stack();
        exit(1);
      }else{
        char** new_env;
        char** old_env;
        int old_size, add_size;
        int src, dest = 0;
        if(keep_env){
          old_env = environ;
        }else{
          old_env = envp();
        }
        old_size = arr_size(old_env);
        add_size = arr_size(add_env);
        new_env = malloc(sizeof(void*) * (old_size + add_size));

        /* we first copy the pointers from the old env */
        for(src = 0; src < old_size; src++){
          new_env[dest++] = old_env[src];
        }

        /* now the ones from add_env */
        for(src = 0; src < add_size; src++){
          int override = find_variable(old_env, add_env[src]);
          if (override >= 0){
            new_env[override] = add_env[src];
          }else{
            new_env[dest++] = add_env[src];
          }
        }

        execve(prog, args, new_env); /* NO RETURN in child */
        se_print_run_time_stack();
        exit(1);
      }
    }
  }
コード例 #5
0
ファイル: VM_0005fProcess.C プロジェクト: vilay/check
/*
 * Class:     VM_0005fProcess
 * Method:    exec4
 * Signature: (Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL 
Java_com_ibm_JikesRVM_VM_1Process_exec4
  (JNIEnv *env, 
   jobject self, 
   jstring programName,
   jobjectArray argvArguments,
   jobjectArray environment,
   jstring dirPathStr) 
{

  // Get the program name
  StringPtr programString(convertString(env, programName));
#ifdef DEBUG
  fprintf(stderr, "program name is %s\n", programString.get());
#endif

  // Build argv array
  jsize argvLen = env->GetArrayLength((jarray) argvArguments);
  StringArray argv(argvLen);
  for (int i = 0; i < argvLen; ++i) {
    jstring arg = (jstring) env->GetObjectArrayElement(argvArguments, i);
    assert(arg);
    char *str = convertString(env, arg);
#ifdef DEBUG
    fprintf(stderr, "arg %d is %s\n", i, str);
#endif
    argv.setAndAdoptString(i, str);
  }

  // Build environment array (if any)
  jsize envpLen = (environment != 0)
    ? env->GetArrayLength((jarray) environment)
    : 0;
  StringArray envp(envpLen);
  for (int i = 0; i < envpLen; ++i) {
    jstring arg = (jstring) env->GetObjectArrayElement(environment, i);
    assert(arg);
    char *str = convertString(env, arg);
#ifdef DEBUG
    fprintf(stderr, "env %d is %s\n", i, str);
#endif
    envp.setAndAdoptString(i, str);
  }

  // Get the directory path (if any)
  StringPtr dirPath(
    (dirPathStr != 0)
      ? convertString(env, dirPathStr)
      : 0
  );
#ifdef DEBUG
  fprintf(stderr, "working directory is %s\n",
    (dirPath.get() != 0) ? dirPath.get() : "unspecified, will use current");
#endif

  // Create pipes to communicate with child process.

  jclass ProcessClassID = env->FindClass( "com/ibm/JikesRVM/VM_Process" );
  assert(ProcessClassID);
  int inputPipe[2], outputPipe[2], errorPipe[2]; 
  pid_t fid = -1;
  int ret = createPipe(inputPipe, env, ProcessClassID, self, 
                       "inputDescriptor", OUTPUT);
  if (ret)
    goto fail;
  ret = createPipe(outputPipe, env, ProcessClassID, self, 
                   "outputDescriptor", INPUT);
  if (ret)
    goto close_inputPipe_and_fail;
  ret = createPipe(errorPipe, env, ProcessClassID, self, 
                   "errorDescriptor", INPUT);
  if (ret)
    goto close_outputPipe_and_fail;
    
  // do the exec
  fid = fork();
  if (fid == 0) {
    // child

    // If a working directory was specified, try to
    // make it the current directory.
    if (dirPath.get() != 0) {
      if (chdir(dirPath.get()) != 0) {
#ifdef DEBUG
        fprintf(stderr, "chdir() failed: %s\n", strerror(errno));
#endif
        // FIXME:
        // Presumably we should throw some sort of I/O error
        // (from Runtime.exec()) if we can't change into the
        // working directory the caller specified.
        // Instead, we just return this value as the exit code.
        exit(EXIT_STATUS_BAD_WORKING_DIR);
      }
    }

#define SHOULD_NEVER_FAIL(cmd) do                       \
{                                                       \
  if ((cmd) < 0) {                                      \
    perror(#cmd " failed, but should never; aborting"); \
    abort();                                            \
  }                                                     \
} while(0)

    /* Attach pipes to stdin, stdout, stderr
       These absolutely should never fail. */
    SHOULD_NEVER_FAIL(dup2(inputPipe[INPUT], 0));
    SHOULD_NEVER_FAIL(dup2(outputPipe[OUTPUT], 1));       
    SHOULD_NEVER_FAIL(dup2(errorPipe[OUTPUT], 2));

    /* Close the original file descriptors returned by pipe().  Since they're
       already open, they should never fail either. */
    SHOULD_NEVER_FAIL(closePipe(inputPipe));
    SHOULD_NEVER_FAIL(closePipe(outputPipe));
    SHOULD_NEVER_FAIL(closePipe(errorPipe));

    // Set environment for child process.
    if (environment != 0) {
      environ = envp.get();
    }
#if 0
    else {
      fprintf(stderr, "Current environment:\n");
      char **p = environ;
      while (*p != 0 ) {
        fprintf(stderr, "\t%s\n", *p);
        ++p;
      }
    }
#endif

    // Execute the program.
    // XXX See comment below on error handling.
    // int err = execvp(programString.get(), argv.get());
    (void) execvp(programString.get(), argv.get());
    // We get here only if an error occurred.
    
#ifdef DEBUG
    fprintf(stderr, "execvp() failed: %s\n", strerror(errno));
#endif

    programString.release();
    argv.release();
    envp.release();
    dirPath.release();

    // FIXME:
    // Unfortunately, it's difficult to convey an error code
    // back to the parent process to let it know that we couldn't
    // actually execute the program.  We could use shared memory
    // or a special pipe to send the error information.
    // For now, just exit with a non-zero status.
    /* However, traditionally the shell and xargs use status 127 to mean that
     * they were unable to find something to execute.
     * To quote the bash manpage, "If a command is found
     *  but is not executable, the return status is 126.¨
     * We shall adopt those customs here. --Steve Augart*/
    if (errno == ENOENT || errno == ENOTDIR)
        exit(EXIT_STATUS_EXECUTABLE_NOT_FOUND);
    exit(EXIT_STATUS_COULD_NOT_EXECUTE); // couldn't be executed for some
                                         // other reason. 
  } else if (fid > 0) {
    // parent

    // Store child's pid
    jfieldID pidFieldID = env->GetFieldID(ProcessClassID, "pid", "I");
    assert(pidFieldID);
    env->SetIntField(self, pidFieldID, fid);
#ifdef DEBUG
    fprintf(stderr, "child process id is %d\n", fid);
#endif

    // Close unused ends of pipes

    // input side of child's stdin:
    SHOULD_NEVER_FAIL(close(inputPipe[INPUT]));
    // output side of child's stdout:
    SHOULD_NEVER_FAIL(close(outputPipe[OUTPUT])); 
    // output side of child's stderr
    SHOULD_NEVER_FAIL(close(errorPipe[OUTPUT]));

    // Note: memory for programName, argv, and envp will be cleaned
    // up automatically

#ifdef DEBUG
    fprintf(stderr, "done exec\n");
#endif

    return fid;
  }
  else {
    // An error occurred in fork()
#ifdef DEBUG
    fprintf(stderr, "fork() failed: %s\n", strerror(errno));
#endif

    // Close pipes
    closePipe(errorPipe);
  close_outputPipe_and_fail:
    closePipe(outputPipe);
  close_inputPipe_and_fail:
    closePipe(inputPipe);
  fail:
    return -1;
  }
}
コード例 #6
0
ファイル: subprocess.cpp プロジェクト: lazycrazyowl/mesos
// Runs the provided command in a subprocess.
Try<Subprocess> subprocess(
    const string& command,
    const Option<map<string, string> >& environment,
    const Option<lambda::function<int()> >& setup)
{
  // Create pipes for stdin, stdout, stderr.
  // Index 0 is for reading, and index 1 is for writing.
  int stdinPipe[2];
  int stdoutPipe[2];
  int stderrPipe[2];

  if (pipe(stdinPipe) == -1) {
    return ErrnoError("Failed to create pipe");
  } else if (pipe(stdoutPipe) == -1) {
    os::close(stdinPipe[0]);
    os::close(stdinPipe[1]);
    return ErrnoError("Failed to create pipe");
  } else if (pipe(stderrPipe) == -1) {
    os::close(stdinPipe[0]);
    os::close(stdinPipe[1]);
    os::close(stdoutPipe[0]);
    os::close(stdoutPipe[1]);
    return ErrnoError("Failed to create pipe");
  }

  // We need to do this construction before doing the fork as it
  // might not be async-safe.
  // TODO(tillt): Consider optimizing this to not pass an empty map
  // into the constructor or even further to use execl instead of
  // execle once we have no user supplied environment.
  os::ExecEnv envp(environment.get(map<string, string>()));

  pid_t pid;
  if ((pid = fork()) == -1) {
    os::close(stdinPipe[0]);
    os::close(stdinPipe[1]);
    os::close(stdoutPipe[0]);
    os::close(stdoutPipe[1]);
    os::close(stderrPipe[0]);
    os::close(stderrPipe[1]);
    return ErrnoError("Failed to fork");
  }

  Subprocess process;
  process.data->pid = pid;

  if (process.data->pid == 0) {
    // Child.
    // Close parent's end of the pipes.
    os::close(stdinPipe[1]);
    os::close(stdoutPipe[0]);
    os::close(stderrPipe[0]);

    // Make our pipes look like stdin, stderr, stdout before we exec.
    while (dup2(stdinPipe[0], STDIN_FILENO)   == -1 && errno == EINTR);
    while (dup2(stdoutPipe[1], STDOUT_FILENO) == -1 && errno == EINTR);
    while (dup2(stderrPipe[1], STDERR_FILENO) == -1 && errno == EINTR);

    // Close the copies.
    os::close(stdinPipe[0]);
    os::close(stdoutPipe[1]);
    os::close(stderrPipe[1]);

    if (setup.isSome()) {
      int status = setup.get()();
      if (status != 0) {
        _exit(status);
      }
    }

    execle("/bin/sh", "sh", "-c", command.c_str(), (char*) NULL, envp());

    ABORT("Failed to execle '/bin sh -c ", command.c_str(), "'\n");
  }

  // Parent.

  // Close the child's end of the pipes.
  os::close(stdinPipe[0]);
  os::close(stdoutPipe[1]);
  os::close(stderrPipe[1]);

  process.data->in = stdinPipe[1];
  process.data->out = stdoutPipe[0];
  process.data->err = stderrPipe[0];

  // Rather than directly exposing the future from process::reap, we
  // must use an explicit promise so that we can ensure we can receive
  // the termination signal. Otherwise, the caller can discard the
  // reap future, and we will not know when it is safe to close the
  // file descriptors.
  Promise<Option<int> >* promise = new Promise<Option<int> >();
  process.data->status = promise->future();

  // We need to bind a copy of this Subprocess into the onAny callback
  // below to ensure that we don't close the file descriptors before
  // the subprocess has terminated (i.e., because the caller doesn't
  // keep a copy of this Subprocess around themselves).
  process::reap(process.data->pid)
    .onAny(lambda::bind(internal::cleanup, lambda::_1, promise, process));

  return process;
}