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]; }
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 use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting 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 more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage message
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)
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 use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if NULL
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