31 #include <sys/types.h> 
   53 static int LengthWithoutIncompleteUtf8(
char* buffer, 
int len) {
 
   56   static const int kUtf8SingleByteMask = 0x80;
 
   57   static const int kUtf8SingleByteValue = 0x00;
 
   59   static const int kUtf8TwoByteMask = 0xe0;
 
   60   static const int kUtf8TwoByteValue = 0xc0;
 
   62   static const int kUtf8ThreeByteMask = 0xf0;
 
   63   static const int kUtf8ThreeByteValue = 0xe0;
 
   65   static const int kUtf8FourByteMask = 0xf8;
 
   66   static const int kUtf8FourByteValue = 0xf0;
 
   68   static const int kMultiByteMask = 0xc0;
 
   69   static const int kMultiByteValue = 0x80;
 
   70   int multi_byte_bytes_seen = 0;
 
   72     int c = buffer[answer - 1];
 
   74     if ((c & kUtf8SingleByteMask) == kUtf8SingleByteValue) 
return answer;
 
   76     if ((c & kMultiByteMask) == kMultiByteValue) {
 
   77       multi_byte_bytes_seen++;
 
   80       if ((c & kUtf8TwoByteMask) == kUtf8TwoByteValue) {
 
   81         if (multi_byte_bytes_seen >= 1) {
 
   85       } 
else if ((c & kUtf8ThreeByteMask) == kUtf8ThreeByteValue) {
 
   86         if (multi_byte_bytes_seen >= 2) {
 
   90       } 
else if ((c & kUtf8FourByteMask) == kUtf8FourByteValue) {
 
   91         if (multi_byte_bytes_seen >= 3) {
 
  106 static bool WaitOnFD(
int fd,
 
  109                      struct timeval& start_time) {
 
  110   fd_set readfds, writefds, exceptfds;
 
  111   struct timeval timeout;
 
  113   if (total_timeout != -1) {
 
  114     struct timeval time_now;
 
  115     gettimeofday(&time_now, 
NULL);
 
  116     int seconds = time_now.tv_sec - start_time.tv_sec;
 
  117     gone = seconds * 1000 + (time_now.tv_usec - start_time.tv_usec) / 1000;
 
  118     if (gone >= total_timeout) 
return false;
 
  123   FD_SET(fd, &readfds);
 
  124   FD_SET(fd, &exceptfds);
 
  125   if (read_timeout == -1 ||
 
  126       (total_timeout != -1 && total_timeout - gone < read_timeout)) {
 
  127     read_timeout = total_timeout - gone;
 
  129   timeout.tv_usec = (read_timeout % 1000) * 1000;
 
  130   timeout.tv_sec = read_timeout / 1000;
 
  131   int number_of_fds_ready = select(fd + 1,
 
  135                                    read_timeout != -1 ? &timeout : 
NULL);
 
  136   return number_of_fds_ready == 1;
 
  142 static bool TimeIsOut(
const struct timeval& start_time, 
const int& total_time) {
 
  143   if (total_time == -1) 
return false;
 
  144   struct timeval time_now;
 
  145   gettimeofday(&time_now, 
NULL);
 
  147   int seconds = time_now.tv_sec - start_time.tv_sec;
 
  149     if (seconds * 1000 > total_time) 
return true;
 
  152   int useconds = time_now.tv_usec - start_time.tv_usec;
 
  153   if (seconds * 1000000 + useconds > total_time * 1000) {
 
  189     exec_args_[0] = 
NULL;
 
  194       const char* message =
 
  195           "os.system(): String conversion of program name failed";
 
  199     int len = prog.
length() + 3;
 
  200     char* c_arg = 
new char[len];
 
  201     snprintf(c_arg, len, 
"%s", *prog);
 
  202     exec_args_[0] = c_arg;
 
  204     for (
unsigned j = 0; j < command_args->Length(); i++, j++) {
 
  207       if (*utf8_arg == 
NULL) {
 
  208         exec_args_[i] = 
NULL;  
 
  209         const char* message =
 
  210             "os.system(): String conversion of argument failed.";
 
  214       int len = utf8_arg.length() + 1;
 
  215       char* c_arg = 
new char[len];
 
  216       snprintf(c_arg, len, 
"%s", *utf8_arg);
 
  217       exec_args_[i] = c_arg;
 
  219     exec_args_[i] = 
NULL;
 
  223     for (
unsigned i = 0; i < 
kMaxArgs; i++) {
 
  224       if (exec_args_[i] == 
NULL) {
 
  227       delete [] exec_args_[i];
 
  233   char* 
arg0() { 
return exec_args_[0]; }
 
  241 static bool GetTimeouts(
const Arguments& args,
 
  243                         int* total_timeout) {
 
  244   if (args.Length() > 3) {
 
  245     if (args[3]->IsNumber()) {
 
  246       *total_timeout = args[3]->Int32Value();
 
  252   if (args.Length() > 2) {
 
  253     if (args[2]->IsNumber()) {
 
  254       *read_timeout = args[2]->Int32Value();
 
  264 static const int kReadFD = 0;
 
  265 static const int kWriteFD = 1;
 
  271 static void ExecSubprocess(
int* exec_error_fds,
 
  273                            ExecArgs& exec_args) {
 
  274   close(exec_error_fds[kReadFD]);  
 
  275   close(stdout_fds[kReadFD]);      
 
  277   dup2(stdout_fds[kWriteFD], 1);   
 
  278   close(stdout_fds[kWriteFD]);     
 
  279   fcntl(exec_error_fds[kWriteFD], F_SETFD, FD_CLOEXEC);
 
  280   execvp(exec_args.arg0(), exec_args.arg_array());
 
  286     bytes_written = write(exec_error_fds[kWriteFD], &err, 
sizeof(err));
 
  287   } 
while (bytes_written == -1 && errno == EINTR);
 
  294 static bool ChildLaunchedOK(
int* exec_error_fds) {
 
  298     bytes_read = read(exec_error_fds[kReadFD], &err, 
sizeof(err));
 
  299   } 
while (bytes_read == -1 && errno == EINTR);
 
  300   if (bytes_read != 0) {
 
  310 static Handle<Value> GetStdout(
int child_fd,
 
  311                                struct timeval& start_time,
 
  317   static const int kStdoutReadBufferSize = 4096;
 
  318   char buffer[kStdoutReadBufferSize];
 
  320   if (fcntl(child_fd, F_SETFL, O_NONBLOCK) != 0) {
 
  326     bytes_read = read(child_fd,
 
  328                       kStdoutReadBufferSize - fullness);
 
  329     if (bytes_read == -1) {
 
  330       if (errno == EAGAIN) {
 
  331         if (!WaitOnFD(child_fd,
 
  335             (TimeIsOut(start_time, total_timeout))) {
 
  339       } 
else if (errno == EINTR) {
 
  345     if (bytes_read + fullness > 0) {
 
  346       int length = bytes_read == 0 ?
 
  347                    bytes_read + fullness :
 
  348                    LengthWithoutIncompleteUtf8(buffer, bytes_read + fullness);
 
  349       Handle<String> addition = 
String::New(buffer, length);
 
  351       fullness = bytes_read + fullness - length;
 
  352       memcpy(buffer, buffer + length, fullness);
 
  354   } 
while (bytes_read != 0);
 
  369 #if defined(WNOWAIT) && !defined(ANDROID) && !defined(__APPLE__) \ 
  370     && !defined(__NetBSD__) 
  371 #if !defined(__FreeBSD__) 
  378 static bool WaitForChild(
int pid,
 
  379                          ZombieProtector& child_waiter,
 
  380                          struct timeval& start_time,
 
  385   siginfo_t child_info;
 
  386   child_info.si_pid = 0;
 
  389   while (child_info.si_pid == 0) {
 
  390     waitid(P_PID, pid, &child_info, WEXITED | WNOHANG | WNOWAIT);
 
  392     if (useconds < 1000000) useconds <<= 1;
 
  393     if ((read_timeout != -1 && useconds / 1000 > read_timeout) ||
 
  394         (TimeIsOut(start_time, total_timeout))) {
 
  400   if (child_info.si_code == CLD_KILLED) {
 
  404              "Child killed by signal %d",
 
  405              child_info.si_status);
 
  409   if (child_info.si_code == CLD_EXITED && child_info.si_status != 0) {
 
  413              "Child exited with status %d",
 
  414              child_info.si_status);
 
  419 #else  // No waitid call. 
  422   waitpid(pid, &child_status, 0);  
 
  423   child_waiter.ChildIsDeadNow();
 
  424   if (WIFSIGNALED(child_status)) {
 
  428              "Child killed by signal %d",
 
  429              WTERMSIG(child_status));
 
  433   if (WEXITSTATUS(child_status) != 0) {
 
  435     int exit_status = WEXITSTATUS(child_status);
 
  438              "Child exited with status %d",
 
  444 #endif  // No waitid call. 
  453   int read_timeout = -1;
 
  454   int total_timeout = -1;
 
  455   if (!GetTimeouts(args, &read_timeout, &total_timeout)) 
return v8::Undefined();
 
  458     if (!args[1]->IsArray()) {
 
  472   struct timeval start_time;
 
  473   gettimeofday(&start_time, 
NULL);
 
  476   if (!exec_args.
Init(args[0], command_args)) {
 
  479   int exec_error_fds[2];
 
  482   if (pipe(exec_error_fds) != 0) {
 
  485   if (pipe(stdout_fds) != 0) {
 
  491     ExecSubprocess(exec_error_fds, stdout_fds, exec_args);
 
  497   close(exec_error_fds[kWriteFD]);
 
  498   close(stdout_fds[kWriteFD]);
 
  499   OpenFDCloser error_read_closer(exec_error_fds[kReadFD]);
 
  502   if (!ChildLaunchedOK(exec_error_fds)) 
return v8::Undefined();
 
  513   if (!WaitForChild(pid,
 
  521   return scope.
Close(accumulator);
 
  527     const char* message = 
"chdir() takes one argument";
 
  531   if (*directory == 
NULL) {
 
  532     const char* message = 
"os.chdir(): String conversion of argument failed.";
 
  535   if (chdir(*directory) != 0) {
 
  544     const char* message = 
"umask() takes one argument";
 
  547   if (args[0]->IsNumber()) {
 
  548     mode_t mask = args[0]->Int32Value();
 
  549     int previous = umask(mask);
 
  552     const char* message = 
"umask() argument must be numeric";
 
  558 static bool CheckItsADirectory(
char* directory) {
 
  559   struct stat stat_buf;
 
  560   int stat_result = stat(directory, &stat_buf);
 
  561   if (stat_result != 0) {
 
  565   if ((stat_buf.st_mode & S_IFDIR) != 0) 
return true;
 
  573 static bool mkdirp(
char* directory, mode_t mask) {
 
  574   int result = mkdir(directory, mask);
 
  575   if (result == 0) 
return true;
 
  576   if (errno == EEXIST) {
 
  577     return CheckItsADirectory(directory);
 
  578   } 
else if (errno == ENOENT) {  
 
  579     char* last_slash = strrchr(directory, 
'/');
 
  580     if (last_slash == 
NULL) {
 
  585     if (!mkdirp(directory, mask)) 
return false;
 
  587     result = mkdir(directory, mask);
 
  588     if (result == 0) 
return true;
 
  589     if (errno == EEXIST) {
 
  590       return CheckItsADirectory(directory);
 
  604     if (args[1]->IsNumber()) {
 
  605       mask = args[1]->Int32Value();
 
  607       const char* message = 
"mkdirp() second argument must be numeric";
 
  610   } 
else if (args.
Length() != 1) {
 
  611     const char* message = 
"mkdirp() takes one or two arguments";
 
  615   if (*directory == 
NULL) {
 
  616     const char* message = 
"os.mkdirp(): String conversion of argument failed.";
 
  619   mkdirp(*directory, mask);
 
  626     const char* message = 
"rmdir() takes one or two arguments";
 
  630   if (*directory == 
NULL) {
 
  631     const char* message = 
"os.rmdir(): String conversion of argument failed.";
 
  641     const char* message = 
"setenv() takes two arguments";
 
  647     const char* message =
 
  648         "os.setenv(): String conversion of variable name failed.";
 
  651   if (*value == 
NULL) {
 
  652     const char* message =
 
  653         "os.setenv(): String conversion of variable contents failed.";
 
  656   setenv(*var, *value, 1);
 
  663     const char* message = 
"unsetenv() takes one argument";
 
  668     const char* message =
 
  669         "os.setenv(): String conversion of variable name failed.";
 
static Local< FunctionTemplate > New(InvocationCallback callback=0, Handle< Value > data=Handle< Value >(), Handle< Signature > signature=Handle< Signature >())
bool Init(Handle< Value > arg0, Handle< Array > command_args)
static V8EXPORT Local< String > New(const char *data, int length=-1)
static Handle< Value > SetUMask(const Arguments &args)
static void AddOSMethods(Handle< ObjectTemplate > os_template)
static Handle< T > Cast(Handle< S > that)
void Set(Handle< String > name, Handle< Data > value, PropertyAttribute attributes=None)
static Handle< Value > SetEnvironment(const Arguments &args)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
static Handle< Value > RemoveDirectory(const Arguments &args)
static V8EXPORT v8::Local< v8::String > Empty()
static Handle< Value > UnsetEnvironment(const Arguments &args)
static V8EXPORT Local< Integer > New(int32_t value)
Local< T > Close(Handle< T > value)
Handle< Primitive > V8EXPORT Undefined()
static V8EXPORT Local< Number > New(double value)
static V8EXPORT Local< String > Concat(Handle< String > left, Handle< String > right)
static Handle< Value > MakeDirectory(const Arguments &args)
Handle< Value > V8EXPORT ThrowException(Handle< Value > exception)
static Handle< Value > System(const Arguments &args)
static Handle< Value > ChangeDirectory(const Arguments &args)
static V8EXPORT Local< Object > New()
static const unsigned kMaxArgs