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;
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;
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]; }
243 int* total_timeout) {
245 if (args[3]->IsNumber()) {
246 *total_timeout = args[3]->Int32Value();
249 args.
GetIsolate(),
"system: Argument 4 must be a number"));
254 if (args[2]->IsNumber()) {
255 *read_timeout = args[2]->Int32Value();
258 args.
GetIsolate(),
"system: Argument 3 must be a number"));
266 static const int kReadFD = 0;
267 static const int kWriteFD = 1;
273 static void ExecSubprocess(
int* exec_error_fds,
275 ExecArgs& exec_args) {
276 close(exec_error_fds[kReadFD]);
277 close(stdout_fds[kReadFD]);
279 dup2(stdout_fds[kWriteFD], 1);
280 close(stdout_fds[kWriteFD]);
281 fcntl(exec_error_fds[kWriteFD], F_SETFD, FD_CLOEXEC);
282 execvp(exec_args.arg0(), exec_args.arg_array());
288 bytes_written = write(exec_error_fds[kWriteFD], &err,
sizeof(err));
289 }
while (bytes_written == -1 && errno == EINTR);
296 static bool ChildLaunchedOK(Isolate* isolate,
int* exec_error_fds) {
300 bytes_read = read(exec_error_fds[kReadFD], &err,
sizeof(err));
301 }
while (bytes_read == -1 && errno == EINTR);
302 if (bytes_read != 0) {
312 static Handle<Value> GetStdout(Isolate* isolate,
314 struct timeval& start_time,
320 static const int kStdoutReadBufferSize = 4096;
321 char buffer[kStdoutReadBufferSize];
323 if (fcntl(child_fd, F_SETFL, O_NONBLOCK) != 0) {
324 return isolate->ThrowException(
330 bytes_read = read(child_fd,
332 kStdoutReadBufferSize - fullness);
333 if (bytes_read == -1) {
334 if (errno == EAGAIN) {
335 if (!WaitOnFD(child_fd,
339 (TimeIsOut(start_time, total_timeout))) {
340 return isolate->ThrowException(
344 }
else if (errno == EINTR) {
350 if (bytes_read + fullness > 0) {
351 int length = bytes_read == 0 ?
352 bytes_read + fullness :
353 LengthWithoutIncompleteUtf8(buffer, bytes_read + fullness);
354 Handle<String> addition =
357 fullness = bytes_read + fullness - length;
358 memcpy(buffer, buffer + length, fullness);
360 }
while (bytes_read != 0);
375 #if defined(WNOWAIT) && !defined(ANDROID) && !defined(__APPLE__) \
376 && !defined(__NetBSD__)
377 #if !defined(__FreeBSD__)
384 static bool WaitForChild(Isolate* isolate,
386 ZombieProtector& child_waiter,
387 struct timeval& start_time,
392 siginfo_t child_info;
393 child_info.si_pid = 0;
396 while (child_info.si_pid == 0) {
397 waitid(P_PID, pid, &child_info, WEXITED | WNOHANG | WNOWAIT);
399 if (useconds < 1000000) useconds <<= 1;
400 if ((read_timeout != -1 && useconds / 1000 > read_timeout) ||
401 (TimeIsOut(start_time, total_timeout))) {
403 isolate,
"Timed out waiting for process to terminate"));
408 if (child_info.si_code == CLD_KILLED) {
412 "Child killed by signal %d",
413 child_info.si_status);
417 if (child_info.si_code == CLD_EXITED && child_info.si_status != 0) {
421 "Child exited with status %d",
422 child_info.si_status);
427 #else // No waitid call.
430 waitpid(pid, &child_status, 0);
431 child_waiter.ChildIsDeadNow();
432 if (WIFSIGNALED(child_status)) {
436 "Child killed by signal %d",
437 WTERMSIG(child_status));
441 if (WEXITSTATUS(child_status) != 0) {
443 int exit_status = WEXITSTATUS(child_status);
446 "Child exited with status %d",
452 #endif // No waitid call.
461 int read_timeout = -1;
462 int total_timeout = -1;
463 if (!GetTimeouts(args, &read_timeout, &total_timeout))
return;
466 if (!args[1]->IsArray()) {
468 args.
GetIsolate(),
"system: Argument 2 must be an array"));
477 args.
GetIsolate(),
"Too many arguments to system()"));
482 args.
GetIsolate(),
"Too few arguments to system()"));
486 struct timeval start_time;
487 gettimeofday(&start_time,
NULL);
493 int exec_error_fds[2];
496 if (pipe(exec_error_fds) != 0) {
501 if (pipe(stdout_fds) != 0) {
509 ExecSubprocess(exec_error_fds, stdout_fds, exec_args);
515 close(exec_error_fds[kWriteFD]);
516 close(stdout_fds[kWriteFD]);
517 OpenFDCloser error_read_closer(exec_error_fds[kReadFD]);
520 if (!ChildLaunchedOK(args.
GetIsolate(), exec_error_fds))
return;
548 const char* message =
"chdir() takes one argument";
554 if (*directory ==
NULL) {
555 const char* message =
"os.chdir(): String conversion of argument failed.";
560 if (chdir(*directory) != 0) {
570 const char* message =
"umask() takes one argument";
575 if (args[0]->IsNumber()) {
576 mode_t mask = args[0]->Int32Value();
577 int previous = umask(mask);
581 const char* message =
"umask() argument must be numeric";
589 static bool CheckItsADirectory(
Isolate* isolate,
char* directory) {
590 struct stat stat_buf;
591 int stat_result = stat(directory, &stat_buf);
592 if (stat_result != 0) {
596 if ((stat_buf.st_mode & S_IFDIR) != 0)
return true;
604 static bool mkdirp(Isolate* isolate,
char* directory, mode_t mask) {
605 int result = mkdir(directory, mask);
606 if (result == 0)
return true;
607 if (errno == EEXIST) {
608 return CheckItsADirectory(isolate, directory);
609 }
else if (errno == ENOENT) {
610 char* last_slash = strrchr(directory,
'/');
611 if (last_slash ==
NULL) {
616 if (!mkdirp(isolate, directory, mask))
return false;
618 result = mkdir(directory, mask);
619 if (result == 0)
return true;
620 if (errno == EEXIST) {
621 return CheckItsADirectory(isolate, directory);
635 if (args[1]->IsNumber()) {
636 mask = args[1]->Int32Value();
638 const char* message =
"mkdirp() second argument must be numeric";
643 }
else if (args.
Length() != 1) {
644 const char* message =
"mkdirp() takes one or two arguments";
650 if (*directory ==
NULL) {
651 const char* message =
"os.mkdirp(): String conversion of argument failed.";
662 const char* message =
"rmdir() takes one or two arguments";
668 if (*directory ==
NULL) {
669 const char* message =
"os.rmdir(): String conversion of argument failed.";
680 const char* message =
"setenv() takes two arguments";
688 const char* message =
689 "os.setenv(): String conversion of variable name failed.";
694 if (*value ==
NULL) {
695 const char* message =
696 "os.setenv(): String conversion of variable contents failed.";
701 setenv(*var, *value, 1);
707 const char* message =
"unsetenv() takes one argument";
714 const char* message =
715 "os.setenv(): String conversion of variable name failed.";
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
static void SetUMask(const v8::FunctionCallbackInfo< v8::Value > &args)
V8_INLINE Isolate * GetIsolate() const
V8_INLINE ReturnValue< T > GetReturnValue() const
V8_INLINE int Length() const
static void RemoveDirectory(const v8::FunctionCallbackInfo< v8::Value > &args)
Local< Value > ThrowException(Local< Value > exception)
static Local< Integer > New(Isolate *isolate, int32_t value)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV 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 expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage message
bool Init(Isolate *isolate, Handle< Value > arg0, Handle< Array > command_args)
static void System(const v8::FunctionCallbackInfo< v8::Value > &args)
static void SetEnvironment(const v8::FunctionCallbackInfo< v8::Value > &args)
static Local< FunctionTemplate > New(Isolate *isolate, FunctionCallback callback=0, Handle< Value > data=Handle< Value >(), Handle< Signature > signature=Handle< Signature >(), int length=0)
static V8_INLINE Handle< T > Cast(Handle< S > that)
static void ChangeDirectory(const v8::FunctionCallbackInfo< v8::Value > &args)
static Local< Array > New(Isolate *isolate, int length=0)
V8_INLINE bool IsUndefined() const
static Local< String > Concat(Handle< String > left, Handle< String > right)
static void UnsetEnvironment(const v8::FunctionCallbackInfo< v8::Value > &args)
static void AddOSMethods(v8::Isolate *isolate, Handle< ObjectTemplate > os_template)
static V8_INLINE v8::Local< v8::String > Empty(Isolate *isolate)
static const unsigned kMaxArgs
static void MakeDirectory(const v8::FunctionCallbackInfo< v8::Value > &args)
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)