mirror of
https://github.com/textmate/textmate.git
synced 2026-04-28 03:00:34 -04:00
Turn private run_cmd (scm/utility.h) → io::exec
This commit is contained in:
111
Frameworks/io/src/exec.cc
Normal file
111
Frameworks/io/src/exec.cc
Normal file
@@ -0,0 +1,111 @@
|
||||
#include "exec.h"
|
||||
#include "environment.h"
|
||||
#include <text/format.h>
|
||||
#include <oak/datatypes.h>
|
||||
#include <oak/debug/OakDebugLog.h>
|
||||
|
||||
OAK_DEBUG_VAR(IO_Exec);
|
||||
|
||||
namespace io
|
||||
{
|
||||
// takes NULL-terminated list of arguments
|
||||
static std::string vexec (std::map<std::string, std::string> const& environment, std::string const& cmd, va_list args)
|
||||
{
|
||||
std::string output;
|
||||
std::string error;
|
||||
|
||||
std::vector<char*> command(1, (char*)cmd.c_str());
|
||||
char* arg = NULL;
|
||||
while((arg = va_arg(args, char*)) && *arg)
|
||||
command.push_back(arg);
|
||||
va_end(args);
|
||||
|
||||
char* argv[command.size() + 1];
|
||||
std::copy(command.begin(), command.end(), &argv[0]);
|
||||
argv[command.size()] = NULL;
|
||||
|
||||
int outputPipe[2], errorPipe[2];
|
||||
pipe(outputPipe);
|
||||
pipe(errorPipe);
|
||||
int output_fd = outputPipe[0], error_fd = errorPipe[0];
|
||||
|
||||
std::map<std::string, std::string>::const_iterator it = environment.find("PWD");
|
||||
char const* pwdDir = it != environment.end() ? it->second.c_str() : NULL;
|
||||
|
||||
oak::c_array env(environment);
|
||||
pid_t process_id = vfork();
|
||||
if(process_id == 0)
|
||||
{
|
||||
setpgid(0, getpid());
|
||||
|
||||
int const oldOutErr[] = { 0, 1, 2, output_fd };
|
||||
std::for_each(beginof(oldOutErr), endof(oldOutErr), close);
|
||||
|
||||
open("/dev/null", O_RDONLY); // stdin
|
||||
dup(outputPipe[1]);
|
||||
close(outputPipe[1]);
|
||||
dup(errorPipe[1]);
|
||||
close(errorPipe[1]);
|
||||
|
||||
if(pwdDir)
|
||||
chdir(pwdDir);
|
||||
|
||||
execve(argv[0], argv, env);
|
||||
perror("interpreter failed");
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
close(outputPipe[1]);
|
||||
close(errorPipe[1]);
|
||||
|
||||
char buf[255];
|
||||
while(ssize_t len = read(output_fd, buf, sizeof(buf)))
|
||||
{
|
||||
if(len < 0)
|
||||
break;
|
||||
output.insert(output.end(), buf, buf + len);
|
||||
}
|
||||
close(output_fd);
|
||||
|
||||
char error_buf[255];
|
||||
while(ssize_t len = read(error_fd, error_buf, sizeof(error_buf)))
|
||||
{
|
||||
if(len < 0)
|
||||
break;
|
||||
error.insert(error.end(), error_buf, error_buf + len);
|
||||
}
|
||||
close(error_fd);
|
||||
D(DBF_SCM_RunCommand, if(!error.empty()) bug("error from command: “%s”\n", error.c_str()););
|
||||
|
||||
int status = 0;
|
||||
bool didTerminate = waitpid(process_id, &status, 0) == process_id;
|
||||
if(didTerminate && WIFEXITED(status) && WEXITSTATUS(status) == 0)
|
||||
return output;
|
||||
|
||||
if(!didTerminate)
|
||||
perror("waitpid");
|
||||
else if(!WIFEXITED(status))
|
||||
fprintf(stderr, "*** abnormal exit (%d) from ‘%s’ in ‘%s’\n", status, text::join(command, " ").c_str(), pwdDir);
|
||||
else
|
||||
fprintf(stderr, "*** exit code %d from ‘%s’ in ‘%s’\n", WEXITSTATUS(status), text::join(command, " ").c_str(), pwdDir);
|
||||
|
||||
return NULL_STR;
|
||||
}
|
||||
|
||||
std::string exec (std::map<std::string, std::string> const& env, std::string const& cmd, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, cmd);
|
||||
return vexec(env, cmd, args);
|
||||
}
|
||||
|
||||
std::string exec (std::string const& cmd, ...)
|
||||
{
|
||||
std::map<std::string, std::string> env = oak::basic_environment();
|
||||
|
||||
va_list args;
|
||||
va_start(args, cmd);
|
||||
return vexec(env, cmd, args);
|
||||
}
|
||||
|
||||
} /* io */
|
||||
14
Frameworks/io/src/exec.h
Normal file
14
Frameworks/io/src/exec.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef IO_EXEC_H_4VCQB3PK
|
||||
#define IO_EXEC_H_4VCQB3PK
|
||||
|
||||
#include <oak/misc.h>
|
||||
|
||||
namespace io
|
||||
{
|
||||
// takes NULL-terminated list of arguments
|
||||
PUBLIC std::string exec (std::string const& cmd, ...);
|
||||
PUBLIC std::string exec (std::map<std::string, std::string> const& environment, std::string const& cmd, ...);
|
||||
|
||||
} /* io */
|
||||
|
||||
#endif /* end of include guard: IO_EXEC_H_4VCQB3PK */
|
||||
@@ -6,6 +6,7 @@
|
||||
#import "swap_file_data.h"
|
||||
#import "socket.h"
|
||||
#import "pipe.h"
|
||||
#import "exec.h"
|
||||
#import "environment.h"
|
||||
|
||||
#endif /* end of include guard: IO_H_VLV818VO */
|
||||
|
||||
Reference in New Issue
Block a user