12 #include <sys/types.h>
19 #include <sys/select.h>
32 static const int kUtf8SingleByteMask = 0x80;
33 static const int kUtf8SingleByteValue = 0x00;
35 static const int kUtf8TwoByteMask = 0xe0;
36 static const int kUtf8TwoByteValue = 0xc0;
38 static const int kUtf8ThreeByteMask = 0xf0;
39 static const int kUtf8ThreeByteValue = 0xe0;
41 static const int kUtf8FourByteMask = 0xf8;
42 static const int kUtf8FourByteValue = 0xf0;
44 static const int kMultiByteMask = 0xc0;
45 static const int kMultiByteValue = 0x80;
46 int multi_byte_bytes_seen = 0;
48 int c = buffer[answer - 1];
50 if ((c & kUtf8SingleByteMask) == kUtf8SingleByteValue)
return answer;
52 if ((c & kMultiByteMask) == kMultiByteValue) {
53 multi_byte_bytes_seen++;
56 if ((c & kUtf8TwoByteMask) == kUtf8TwoByteValue) {
57 if (multi_byte_bytes_seen >= 1) {
61 }
else if ((c & kUtf8ThreeByteMask) == kUtf8ThreeByteValue) {
62 if (multi_byte_bytes_seen >= 2) {
66 }
else if ((c & kUtf8FourByteMask) == kUtf8FourByteValue) {
67 if (multi_byte_bytes_seen >= 3) {
85 const struct timeval& start_time) {
86 fd_set readfds, writefds, exceptfds;
87 struct timeval timeout;
89 if (total_timeout != -1) {
90 struct timeval time_now;
91 gettimeofday(&time_now,
NULL);
92 int seconds = time_now.tv_sec - start_time.tv_sec;
93 gone = seconds * 1000 + (time_now.tv_usec - start_time.tv_usec) / 1000;
94 if (gone >= total_timeout)
return false;
100 FD_SET(fd, &exceptfds);
101 if (read_timeout == -1 ||
102 (total_timeout != -1 && total_timeout - gone < read_timeout)) {
103 read_timeout = total_timeout - gone;
105 timeout.tv_usec = (read_timeout % 1000) * 1000;
106 timeout.tv_sec = read_timeout / 1000;
109 int number_of_fds_ready = -1;
111 int number_of_fds_ready = select(fd + 1,
115 read_timeout != -1 ? &timeout :
NULL);
117 return number_of_fds_ready == 1;
123 static bool TimeIsOut(
const struct timeval& start_time,
const int& total_time) {
124 if (total_time == -1)
return false;
125 struct timeval time_now;
126 gettimeofday(&time_now,
NULL);
128 int seconds = time_now.tv_sec - start_time.tv_sec;
130 if (seconds * 1000 > total_time)
return true;
133 int useconds = time_now.tv_usec - start_time.tv_usec;
134 if (seconds * 1000000 + useconds > total_time * 1000) {
175 const char* message =
176 "os.system(): String conversion of program name failed";
180 int len = prog.
length() + 3;
181 char* c_arg =
new char[len];
182 snprintf(c_arg, len,
"%s", *prog);
185 for (
unsigned j = 0; j < command_args->Length();
i++, j++) {
188 if (*utf8_arg ==
NULL) {
190 const char* message =
191 "os.system(): String conversion of argument failed.";
195 int len = utf8_arg.
length() + 1;
196 char* c_arg =
new char[len];
197 snprintf(c_arg, len,
"%s", *utf8_arg);
224 int* total_timeout) {
226 if (args[3]->IsNumber()) {
227 *total_timeout = args[3]->Int32Value();
230 args.
GetIsolate(),
"system: Argument 4 must be a number"));
235 if (args[2]->IsNumber()) {
236 *read_timeout = args[2]->Int32Value();
239 args.
GetIsolate(),
"system: Argument 3 must be a number"));
257 close(exec_error_fds[
kReadFD]);
262 fcntl(exec_error_fds[
kWriteFD], F_SETFD, FD_CLOEXEC);
269 bytes_written = write(exec_error_fds[
kWriteFD], &err,
sizeof(err));
270 }
while (bytes_written == -1 && errno == EINTR);
281 bytes_read = read(exec_error_fds[
kReadFD], &err,
sizeof(err));
282 }
while (bytes_read == -1 && errno == EINTR);
283 if (bytes_read != 0) {
295 const struct timeval& start_time,
301 static const int kStdoutReadBufferSize = 4096;
302 char buffer[kStdoutReadBufferSize];
304 if (fcntl(child_fd, F_SETFL, O_NONBLOCK) != 0) {
311 bytes_read = read(child_fd,
313 kStdoutReadBufferSize - fullness);
314 if (bytes_read == -1) {
315 if (errno == EAGAIN) {
320 (
TimeIsOut(start_time, total_timeout))) {
325 }
else if (errno == EINTR) {
331 if (bytes_read + fullness > 0) {
332 int length = bytes_read == 0 ?
333 bytes_read + fullness :
338 fullness = bytes_read + fullness - length;
339 memcpy(buffer, buffer + length, fullness);
341 }
while (bytes_read != 0);
356 #if defined(WNOWAIT) && !defined(ANDROID) && !defined(__APPLE__) \
357 && !defined(__NetBSD__)
358 #if !defined(__FreeBSD__)
368 const struct timeval& start_time,
373 siginfo_t child_info;
374 child_info.si_pid = 0;
377 while (child_info.si_pid == 0) {
378 waitid(P_PID, pid, &child_info, WEXITED | WNOHANG | WNOWAIT);
380 if (useconds < 1000000) useconds <<= 1;
381 if ((read_timeout != -1 && useconds / 1000 > read_timeout) ||
382 (
TimeIsOut(start_time, total_timeout))) {
384 isolate,
"Timed out waiting for process to terminate"));
389 if (child_info.si_code == CLD_KILLED) {
393 "Child killed by signal %d",
394 child_info.si_status);
398 if (child_info.si_code == CLD_EXITED && child_info.si_status != 0) {
402 "Child exited with status %d",
403 child_info.si_status);
411 waitpid(pid, &child_status, 0);
413 if (WIFSIGNALED(child_status)) {
417 "Child killed by signal %d",
418 WTERMSIG(child_status));
422 if (WEXITSTATUS(child_status) != 0) {
424 int exit_status = WEXITSTATUS(child_status);
427 "Child exited with status %d",
442 int read_timeout = -1;
443 int total_timeout = -1;
444 if (!
GetTimeouts(args, &read_timeout, &total_timeout))
return;
447 if (!args[1]->IsArray()) {
449 args.
GetIsolate(),
"system: Argument 2 must be an array"));
458 args.
GetIsolate(),
"Too many arguments to system()"));
463 args.
GetIsolate(),
"Too few arguments to system()"));
467 struct timeval start_time;
468 gettimeofday(&start_time,
NULL);
474 int exec_error_fds[2];
477 if (pipe(exec_error_fds) != 0) {
482 if (pipe(stdout_fds) != 0) {
508 if (accumulator->IsUndefined()) {
529 const char* message =
"chdir() takes one argument";
535 if (*directory ==
NULL) {
536 const char* message =
"os.chdir(): String conversion of argument failed.";
541 if (chdir(*directory) != 0) {
551 const char* message =
"umask() takes one argument";
556 if (args[0]->IsNumber()) {
561 int previous = umask(args[0]->Int32Value());
566 const char* message =
"umask() argument must be numeric";
575 struct stat stat_buf;
576 int stat_result = stat(directory, &stat_buf);
577 if (stat_result != 0) {
581 if ((stat_buf.st_mode & S_IFDIR) != 0)
return true;
590 int result = mkdir(directory, mask);
591 if (result == 0)
return true;
592 if (errno == EEXIST) {
594 }
else if (errno == ENOENT) {
595 char* last_slash = strrchr(directory,
'/');
596 if (last_slash ==
NULL) {
601 if (!
mkdirp(isolate, directory, mask))
return false;
603 result = mkdir(directory, mask);
604 if (result == 0)
return true;
605 if (errno == EEXIST) {
620 if (args[1]->IsNumber()) {
621 mask = args[1]->Int32Value();
623 const char* message =
"mkdirp() second argument must be numeric";
628 }
else if (args.
Length() != 1) {
629 const char* message =
"mkdirp() takes one or two arguments";
635 if (*directory ==
NULL) {
636 const char* message =
"os.mkdirp(): String conversion of argument failed.";
647 const char* message =
"rmdir() takes one or two arguments";
653 if (*directory ==
NULL) {
654 const char* message =
"os.rmdir(): String conversion of argument failed.";
665 const char* message =
"setenv() takes two arguments";
673 const char* message =
674 "os.setenv(): String conversion of variable name failed.";
679 if (*value ==
NULL) {
680 const char* message =
681 "os.setenv(): String conversion of variable contents failed.";
686 setenv(*var, *value, 1);
692 const char* message =
"unsetenv() takes one argument";
699 const char* message =
700 "os.setenv(): String conversion of variable name failed.";
static Local< Array > New(Isolate *isolate, int length=0)
Creates a JavaScript array with the given length.
char * exec_args_[kMaxArgs+1]
static const unsigned kMaxArgs
char *const * arg_array() const
bool Init(Isolate *isolate, Handle< Value > arg0, Handle< Array > command_args)
const char * arg0() const
The argument information given to function call callbacks.
ReturnValue< T > GetReturnValue() const
Isolate * GetIsolate() const
static Local< FunctionTemplate > New(Isolate *isolate, FunctionCallback callback=0, Handle< Value > data=Handle< Value >(), Handle< Signature > signature=Handle< Signature >(), int length=0)
Creates a function template.
A stack-allocated class that governs a number of local handles.
An object reference managed by the v8 garbage collector.
static Handle< T > Cast(Handle< S > that)
static Local< Integer > New(Isolate *isolate, int32_t value)
Isolate represents an isolated instance of the V8 engine.
Local< Value > ThrowException(Local< Value > exception)
Schedules an exception to be thrown when returning to JavaScript.
static void SetEnvironment(const v8::FunctionCallbackInfo< v8::Value > &args)
static void MakeDirectory(const v8::FunctionCallbackInfo< v8::Value > &args)
static void AddOSMethods(v8::Isolate *isolate, Handle< ObjectTemplate > os_template)
static void ChangeDirectory(const v8::FunctionCallbackInfo< v8::Value > &args)
static void System(const v8::FunctionCallbackInfo< v8::Value > &args)
static void UnsetEnvironment(const v8::FunctionCallbackInfo< v8::Value > &args)
static void RemoveDirectory(const v8::FunctionCallbackInfo< v8::Value > &args)
static void SetUMask(const v8::FunctionCallbackInfo< v8::Value > &args)
Converts an object to a UTF-8-encoded character array.
static Local< String > Concat(Handle< String > left, Handle< String > right)
Creates a new string by concatenating the left and the right strings passed in as parameters.
static v8::Local< v8::String > Empty(Isolate *isolate)
A zero length string.
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)
Allocates a new string from UTF-8 data.
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
Debugger support for the V8 JavaScript engine.
static bool CheckItsADirectory(Isolate *isolate, char *directory)
static bool WaitForChild(Isolate *isolate, int pid, ZombieProtector &child_waiter, const struct timeval &start_time, int read_timeout, int total_timeout)
static bool mkdirp(Isolate *isolate, char *directory, mode_t mask)
static bool GetTimeouts(const v8::FunctionCallbackInfo< v8::Value > &args, int *read_timeout, int *total_timeout)
static bool TimeIsOut(const struct timeval &start_time, const int &total_time)
static void ExecSubprocess(int *exec_error_fds, int *stdout_fds, const ExecArgs &exec_args)
static int LengthWithoutIncompleteUtf8(char *buffer, int len)
static Handle< Value > GetStdout(Isolate *isolate, int child_fd, const struct timeval &start_time, int read_timeout, int total_timeout)
static bool WaitOnFD(int fd, int read_timeout, int total_timeout, const struct timeval &start_time)
static const int kWriteFD
static bool ChildLaunchedOK(Isolate *isolate, int *exec_error_fds)