v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
d8-posix.cc
Go to the documentation of this file.
1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <sys/time.h>
34 #include <time.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <sys/wait.h>
38 #include <signal.h>
39 
40 
41 #include "d8.h"
42 #include "d8-debug.h"
43 #include "debug.h"
44 
45 
46 namespace v8 {
47 
48 
49 // If the buffer ends in the middle of a UTF-8 sequence then we return
50 // the length of the string up to but not including the incomplete UTF-8
51 // sequence. If the buffer ends with a valid UTF-8 sequence then we
52 // return the whole buffer.
53 static int LengthWithoutIncompleteUtf8(char* buffer, int len) {
54  int answer = len;
55  // 1-byte encoding.
56  static const int kUtf8SingleByteMask = 0x80;
57  static const int kUtf8SingleByteValue = 0x00;
58  // 2-byte encoding.
59  static const int kUtf8TwoByteMask = 0xe0;
60  static const int kUtf8TwoByteValue = 0xc0;
61  // 3-byte encoding.
62  static const int kUtf8ThreeByteMask = 0xf0;
63  static const int kUtf8ThreeByteValue = 0xe0;
64  // 4-byte encoding.
65  static const int kUtf8FourByteMask = 0xf8;
66  static const int kUtf8FourByteValue = 0xf0;
67  // Subsequent bytes of a multi-byte encoding.
68  static const int kMultiByteMask = 0xc0;
69  static const int kMultiByteValue = 0x80;
70  int multi_byte_bytes_seen = 0;
71  while (answer > 0) {
72  int c = buffer[answer - 1];
73  // Ends in valid single-byte sequence?
74  if ((c & kUtf8SingleByteMask) == kUtf8SingleByteValue) return answer;
75  // Ends in one or more subsequent bytes of a multi-byte value?
76  if ((c & kMultiByteMask) == kMultiByteValue) {
77  multi_byte_bytes_seen++;
78  answer--;
79  } else {
80  if ((c & kUtf8TwoByteMask) == kUtf8TwoByteValue) {
81  if (multi_byte_bytes_seen >= 1) {
82  return answer + 2;
83  }
84  return answer - 1;
85  } else if ((c & kUtf8ThreeByteMask) == kUtf8ThreeByteValue) {
86  if (multi_byte_bytes_seen >= 2) {
87  return answer + 3;
88  }
89  return answer - 1;
90  } else if ((c & kUtf8FourByteMask) == kUtf8FourByteValue) {
91  if (multi_byte_bytes_seen >= 3) {
92  return answer + 4;
93  }
94  return answer - 1;
95  } else {
96  return answer; // Malformed UTF-8.
97  }
98  }
99  }
100  return 0;
101 }
102 
103 
104 // Suspends the thread until there is data available from the child process.
105 // Returns false on timeout, true on data ready.
106 static bool WaitOnFD(int fd,
107  int read_timeout,
108  int total_timeout,
109  struct timeval& start_time) {
110  fd_set readfds, writefds, exceptfds;
111  struct timeval timeout;
112  int gone = 0;
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;
119  }
120  FD_ZERO(&readfds);
121  FD_ZERO(&writefds);
122  FD_ZERO(&exceptfds);
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;
128  }
129  timeout.tv_usec = (read_timeout % 1000) * 1000;
130  timeout.tv_sec = read_timeout / 1000;
131  int number_of_fds_ready = select(fd + 1,
132  &readfds,
133  &writefds,
134  &exceptfds,
135  read_timeout != -1 ? &timeout : NULL);
136  return number_of_fds_ready == 1;
137 }
138 
139 
140 // Checks whether we ran out of time on the timeout. Returns true if we ran out
141 // of time, false if we still have time.
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);
146  // Careful about overflow.
147  int seconds = time_now.tv_sec - start_time.tv_sec;
148  if (seconds > 100) {
149  if (seconds * 1000 > total_time) return true;
150  return false;
151  }
152  int useconds = time_now.tv_usec - start_time.tv_usec;
153  if (seconds * 1000000 + useconds > total_time * 1000) {
154  return true;
155  }
156  return false;
157 }
158 
159 
160 // A utility class that does a non-hanging waitpid on the child process if we
161 // bail out of the System() function early. If you don't ever do a waitpid on
162 // a subprocess then it turns into one of those annoying 'zombie processes'.
164  public:
165  explicit ZombieProtector(int pid): pid_(pid) { }
166  ~ZombieProtector() { if (pid_ != 0) waitpid(pid_, NULL, 0); }
167  void ChildIsDeadNow() { pid_ = 0; }
168  private:
169  int pid_;
170 };
171 
172 
173 // A utility class that closes a file descriptor when it goes out of scope.
175  public:
176  explicit OpenFDCloser(int fd): fd_(fd) { }
177  ~OpenFDCloser() { close(fd_); }
178  private:
179  int fd_;
180 };
181 
182 
183 // A utility class that takes the array of command arguments and puts then in an
184 // array of new[]ed UTF-8 C strings. Deallocates them again when it goes out of
185 // scope.
186 class ExecArgs {
187  public:
189  exec_args_[0] = NULL;
190  }
191  bool Init(Isolate* isolate, Handle<Value> arg0, Handle<Array> command_args) {
192  String::Utf8Value prog(arg0);
193  if (*prog == NULL) {
194  const char* message =
195  "os.system(): String conversion of program name failed";
196  isolate->ThrowException(String::NewFromUtf8(isolate, message));
197  return false;
198  }
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;
203  int i = 1;
204  for (unsigned j = 0; j < command_args->Length(); i++, j++) {
205  Handle<Value> arg(command_args->Get(Integer::New(isolate, j)));
206  String::Utf8Value utf8_arg(arg);
207  if (*utf8_arg == NULL) {
208  exec_args_[i] = NULL; // Consistent state for destructor.
209  const char* message =
210  "os.system(): String conversion of argument failed.";
211  isolate->ThrowException(String::NewFromUtf8(isolate, message));
212  return false;
213  }
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;
218  }
219  exec_args_[i] = NULL;
220  return true;
221  }
223  for (unsigned i = 0; i < kMaxArgs; i++) {
224  if (exec_args_[i] == NULL) {
225  return;
226  }
227  delete [] exec_args_[i];
228  exec_args_[i] = 0;
229  }
230  }
231  static const unsigned kMaxArgs = 1000;
232  char** arg_array() { return exec_args_; }
233  char* arg0() { return exec_args_[0]; }
234 
235  private:
236  char* exec_args_[kMaxArgs + 1];
237 };
238 
239 
240 // Gets the optional timeouts from the arguments to the system() call.
241 static bool GetTimeouts(const v8::FunctionCallbackInfo<v8::Value>& args,
242  int* read_timeout,
243  int* total_timeout) {
244  if (args.Length() > 3) {
245  if (args[3]->IsNumber()) {
246  *total_timeout = args[3]->Int32Value();
247  } else {
249  args.GetIsolate(), "system: Argument 4 must be a number"));
250  return false;
251  }
252  }
253  if (args.Length() > 2) {
254  if (args[2]->IsNumber()) {
255  *read_timeout = args[2]->Int32Value();
256  } else {
258  args.GetIsolate(), "system: Argument 3 must be a number"));
259  return false;
260  }
261  }
262  return true;
263 }
264 
265 
266 static const int kReadFD = 0;
267 static const int kWriteFD = 1;
268 
269 
270 // This is run in the child process after fork() but before exec(). It normally
271 // ends with the child process being replaced with the desired child program.
272 // It only returns if an error occurred.
273 static void ExecSubprocess(int* exec_error_fds,
274  int* stdout_fds,
275  ExecArgs& exec_args) {
276  close(exec_error_fds[kReadFD]); // Don't need this in the child.
277  close(stdout_fds[kReadFD]); // Don't need this in the child.
278  close(1); // Close stdout.
279  dup2(stdout_fds[kWriteFD], 1); // Dup pipe fd to stdout.
280  close(stdout_fds[kWriteFD]); // Don't need the original fd now.
281  fcntl(exec_error_fds[kWriteFD], F_SETFD, FD_CLOEXEC);
282  execvp(exec_args.arg0(), exec_args.arg_array());
283  // Only get here if the exec failed. Write errno to the parent to tell
284  // them it went wrong. If it went well the pipe is closed.
285  int err = errno;
286  int bytes_written;
287  do {
288  bytes_written = write(exec_error_fds[kWriteFD], &err, sizeof(err));
289  } while (bytes_written == -1 && errno == EINTR);
290  // Return (and exit child process).
291 }
292 
293 
294 // Runs in the parent process. Checks that the child was able to exec (closing
295 // the file desriptor), or reports an error if it failed.
296 static bool ChildLaunchedOK(Isolate* isolate, int* exec_error_fds) {
297  int bytes_read;
298  int err;
299  do {
300  bytes_read = read(exec_error_fds[kReadFD], &err, sizeof(err));
301  } while (bytes_read == -1 && errno == EINTR);
302  if (bytes_read != 0) {
303  isolate->ThrowException(String::NewFromUtf8(isolate, strerror(err)));
304  return false;
305  }
306  return true;
307 }
308 
309 
310 // Accumulates the output from the child in a string handle. Returns true if it
311 // succeeded or false if an exception was thrown.
312 static Handle<Value> GetStdout(Isolate* isolate,
313  int child_fd,
314  struct timeval& start_time,
315  int read_timeout,
316  int total_timeout) {
317  Handle<String> accumulator = String::Empty(isolate);
318 
319  int fullness = 0;
320  static const int kStdoutReadBufferSize = 4096;
321  char buffer[kStdoutReadBufferSize];
322 
323  if (fcntl(child_fd, F_SETFL, O_NONBLOCK) != 0) {
324  return isolate->ThrowException(
325  String::NewFromUtf8(isolate, strerror(errno)));
326  }
327 
328  int bytes_read;
329  do {
330  bytes_read = read(child_fd,
331  buffer + fullness,
332  kStdoutReadBufferSize - fullness);
333  if (bytes_read == -1) {
334  if (errno == EAGAIN) {
335  if (!WaitOnFD(child_fd,
336  read_timeout,
337  total_timeout,
338  start_time) ||
339  (TimeIsOut(start_time, total_timeout))) {
340  return isolate->ThrowException(
341  String::NewFromUtf8(isolate, "Timed out waiting for output"));
342  }
343  continue;
344  } else if (errno == EINTR) {
345  continue;
346  } else {
347  break;
348  }
349  }
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 =
355  String::NewFromUtf8(isolate, buffer, String::kNormalString, length);
356  accumulator = String::Concat(accumulator, addition);
357  fullness = bytes_read + fullness - length;
358  memcpy(buffer, buffer + length, fullness);
359  }
360  } while (bytes_read != 0);
361  return accumulator;
362 }
363 
364 
365 // Modern Linux has the waitid call, which is like waitpid, but more useful
366 // if you want a timeout. If we don't have waitid we can't limit the time
367 // waiting for the process to exit without losing the information about
368 // whether it exited normally. In the common case this doesn't matter because
369 // we don't get here before the child has closed stdout and most programs don't
370 // do that before they exit.
371 //
372 // We're disabling usage of waitid in Mac OS X because it doens't work for us:
373 // a parent process hangs on waiting while a child process is already a zombie.
374 // See http://code.google.com/p/v8/issues/detail?id=401.
375 #if defined(WNOWAIT) && !defined(ANDROID) && !defined(__APPLE__) \
376  && !defined(__NetBSD__)
377 #if !defined(__FreeBSD__)
378 #define HAS_WAITID 1
379 #endif
380 #endif
381 
382 
383 // Get exit status of child.
384 static bool WaitForChild(Isolate* isolate,
385  int pid,
386  ZombieProtector& child_waiter,
387  struct timeval& start_time,
388  int read_timeout,
389  int total_timeout) {
390 #ifdef HAS_WAITID
391 
392  siginfo_t child_info;
393  child_info.si_pid = 0;
394  int useconds = 1;
395  // Wait for child to exit.
396  while (child_info.si_pid == 0) {
397  waitid(P_PID, pid, &child_info, WEXITED | WNOHANG | WNOWAIT);
398  usleep(useconds);
399  if (useconds < 1000000) useconds <<= 1;
400  if ((read_timeout != -1 && useconds / 1000 > read_timeout) ||
401  (TimeIsOut(start_time, total_timeout))) {
402  isolate->ThrowException(String::NewFromUtf8(
403  isolate, "Timed out waiting for process to terminate"));
404  kill(pid, SIGINT);
405  return false;
406  }
407  }
408  if (child_info.si_code == CLD_KILLED) {
409  char message[999];
410  snprintf(message,
411  sizeof(message),
412  "Child killed by signal %d",
413  child_info.si_status);
414  isolate->ThrowException(String::NewFromUtf8(isolate, message));
415  return false;
416  }
417  if (child_info.si_code == CLD_EXITED && child_info.si_status != 0) {
418  char message[999];
419  snprintf(message,
420  sizeof(message),
421  "Child exited with status %d",
422  child_info.si_status);
423  isolate->ThrowException(String::NewFromUtf8(isolate, message));
424  return false;
425  }
426 
427 #else // No waitid call.
428 
429  int child_status;
430  waitpid(pid, &child_status, 0); // We hang here if the child doesn't exit.
431  child_waiter.ChildIsDeadNow();
432  if (WIFSIGNALED(child_status)) {
433  char message[999];
434  snprintf(message,
435  sizeof(message),
436  "Child killed by signal %d",
437  WTERMSIG(child_status));
438  isolate->ThrowException(String::NewFromUtf8(isolate, message));
439  return false;
440  }
441  if (WEXITSTATUS(child_status) != 0) {
442  char message[999];
443  int exit_status = WEXITSTATUS(child_status);
444  snprintf(message,
445  sizeof(message),
446  "Child exited with status %d",
447  exit_status);
448  isolate->ThrowException(String::NewFromUtf8(isolate, message));
449  return false;
450  }
451 
452 #endif // No waitid call.
453 
454  return true;
455 }
456 
457 
458 // Implementation of the system() function (see d8.h for details).
460  HandleScope scope(args.GetIsolate());
461  int read_timeout = -1;
462  int total_timeout = -1;
463  if (!GetTimeouts(args, &read_timeout, &total_timeout)) return;
464  Handle<Array> command_args;
465  if (args.Length() > 1) {
466  if (!args[1]->IsArray()) {
467  args.GetIsolate()->ThrowException(String::NewFromUtf8(
468  args.GetIsolate(), "system: Argument 2 must be an array"));
469  return;
470  }
471  command_args = Handle<Array>::Cast(args[1]);
472  } else {
473  command_args = Array::New(args.GetIsolate(), 0);
474  }
475  if (command_args->Length() > ExecArgs::kMaxArgs) {
476  args.GetIsolate()->ThrowException(String::NewFromUtf8(
477  args.GetIsolate(), "Too many arguments to system()"));
478  return;
479  }
480  if (args.Length() < 1) {
481  args.GetIsolate()->ThrowException(String::NewFromUtf8(
482  args.GetIsolate(), "Too few arguments to system()"));
483  return;
484  }
485 
486  struct timeval start_time;
487  gettimeofday(&start_time, NULL);
488 
489  ExecArgs exec_args;
490  if (!exec_args.Init(args.GetIsolate(), args[0], command_args)) {
491  return;
492  }
493  int exec_error_fds[2];
494  int stdout_fds[2];
495 
496  if (pipe(exec_error_fds) != 0) {
497  args.GetIsolate()->ThrowException(
498  String::NewFromUtf8(args.GetIsolate(), "pipe syscall failed."));
499  return;
500  }
501  if (pipe(stdout_fds) != 0) {
502  args.GetIsolate()->ThrowException(
503  String::NewFromUtf8(args.GetIsolate(), "pipe syscall failed."));
504  return;
505  }
506 
507  pid_t pid = fork();
508  if (pid == 0) { // Child process.
509  ExecSubprocess(exec_error_fds, stdout_fds, exec_args);
510  exit(1);
511  }
512 
513  // Parent process. Ensure that we clean up if we exit this function early.
514  ZombieProtector child_waiter(pid);
515  close(exec_error_fds[kWriteFD]);
516  close(stdout_fds[kWriteFD]);
517  OpenFDCloser error_read_closer(exec_error_fds[kReadFD]);
518  OpenFDCloser stdout_read_closer(stdout_fds[kReadFD]);
519 
520  if (!ChildLaunchedOK(args.GetIsolate(), exec_error_fds)) return;
521 
522  Handle<Value> accumulator = GetStdout(args.GetIsolate(),
523  stdout_fds[kReadFD],
524  start_time,
525  read_timeout,
526  total_timeout);
527  if (accumulator->IsUndefined()) {
528  kill(pid, SIGINT); // On timeout, kill the subprocess.
529  args.GetReturnValue().Set(accumulator);
530  return;
531  }
532 
533  if (!WaitForChild(args.GetIsolate(),
534  pid,
535  child_waiter,
536  start_time,
537  read_timeout,
538  total_timeout)) {
539  return;
540  }
541 
542  args.GetReturnValue().Set(accumulator);
543 }
544 
545 
547  if (args.Length() != 1) {
548  const char* message = "chdir() takes one argument";
549  args.GetIsolate()->ThrowException(
551  return;
552  }
553  String::Utf8Value directory(args[0]);
554  if (*directory == NULL) {
555  const char* message = "os.chdir(): String conversion of argument failed.";
556  args.GetIsolate()->ThrowException(
558  return;
559  }
560  if (chdir(*directory) != 0) {
561  args.GetIsolate()->ThrowException(
562  String::NewFromUtf8(args.GetIsolate(), strerror(errno)));
563  return;
564  }
565 }
566 
567 
569  if (args.Length() != 1) {
570  const char* message = "umask() takes one argument";
571  args.GetIsolate()->ThrowException(
573  return;
574  }
575  if (args[0]->IsNumber()) {
576  mode_t mask = args[0]->Int32Value();
577  int previous = umask(mask);
578  args.GetReturnValue().Set(previous);
579  return;
580  } else {
581  const char* message = "umask() argument must be numeric";
582  args.GetIsolate()->ThrowException(
584  return;
585  }
586 }
587 
588 
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) {
593  isolate->ThrowException(String::NewFromUtf8(isolate, strerror(errno)));
594  return false;
595  }
596  if ((stat_buf.st_mode & S_IFDIR) != 0) return true;
597  isolate->ThrowException(String::NewFromUtf8(isolate, strerror(EEXIST)));
598  return false;
599 }
600 
601 
602 // Returns true for success. Creates intermediate directories as needed. No
603 // error if the directory exists already.
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) { // Intermediate path element is missing.
610  char* last_slash = strrchr(directory, '/');
611  if (last_slash == NULL) {
612  isolate->ThrowException(String::NewFromUtf8(isolate, strerror(errno)));
613  return false;
614  }
615  *last_slash = 0;
616  if (!mkdirp(isolate, directory, mask)) return false;
617  *last_slash = '/';
618  result = mkdir(directory, mask);
619  if (result == 0) return true;
620  if (errno == EEXIST) {
621  return CheckItsADirectory(isolate, directory);
622  }
623  isolate->ThrowException(String::NewFromUtf8(isolate, strerror(errno)));
624  return false;
625  } else {
626  isolate->ThrowException(String::NewFromUtf8(isolate, strerror(errno)));
627  return false;
628  }
629 }
630 
631 
633  mode_t mask = 0777;
634  if (args.Length() == 2) {
635  if (args[1]->IsNumber()) {
636  mask = args[1]->Int32Value();
637  } else {
638  const char* message = "mkdirp() second argument must be numeric";
639  args.GetIsolate()->ThrowException(
641  return;
642  }
643  } else if (args.Length() != 1) {
644  const char* message = "mkdirp() takes one or two arguments";
645  args.GetIsolate()->ThrowException(
647  return;
648  }
649  String::Utf8Value directory(args[0]);
650  if (*directory == NULL) {
651  const char* message = "os.mkdirp(): String conversion of argument failed.";
652  args.GetIsolate()->ThrowException(
654  return;
655  }
656  mkdirp(args.GetIsolate(), *directory, mask);
657 }
658 
659 
661  if (args.Length() != 1) {
662  const char* message = "rmdir() takes one or two arguments";
663  args.GetIsolate()->ThrowException(
665  return;
666  }
667  String::Utf8Value directory(args[0]);
668  if (*directory == NULL) {
669  const char* message = "os.rmdir(): String conversion of argument failed.";
670  args.GetIsolate()->ThrowException(
672  return;
673  }
674  rmdir(*directory);
675 }
676 
677 
679  if (args.Length() != 2) {
680  const char* message = "setenv() takes two arguments";
681  args.GetIsolate()->ThrowException(
683  return;
684  }
685  String::Utf8Value var(args[0]);
686  String::Utf8Value value(args[1]);
687  if (*var == NULL) {
688  const char* message =
689  "os.setenv(): String conversion of variable name failed.";
690  args.GetIsolate()->ThrowException(
692  return;
693  }
694  if (*value == NULL) {
695  const char* message =
696  "os.setenv(): String conversion of variable contents failed.";
697  args.GetIsolate()->ThrowException(
699  return;
700  }
701  setenv(*var, *value, 1);
702 }
703 
704 
706  if (args.Length() != 1) {
707  const char* message = "unsetenv() takes one argument";
708  args.GetIsolate()->ThrowException(
710  return;
711  }
712  String::Utf8Value var(args[0]);
713  if (*var == NULL) {
714  const char* message =
715  "os.setenv(): String conversion of variable name failed.";
716  args.GetIsolate()->ThrowException(
718  return;
719  }
720  unsetenv(*var);
721 }
722 
723 
725  os_templ->Set(String::NewFromUtf8(isolate, "system"),
726  FunctionTemplate::New(isolate, System));
727  os_templ->Set(String::NewFromUtf8(isolate, "chdir"),
729  os_templ->Set(String::NewFromUtf8(isolate, "setenv"),
731  os_templ->Set(String::NewFromUtf8(isolate, "unsetenv"),
733  os_templ->Set(String::NewFromUtf8(isolate, "umask"),
734  FunctionTemplate::New(isolate, SetUMask));
735  os_templ->Set(String::NewFromUtf8(isolate, "mkdirp"),
737  os_templ->Set(String::NewFromUtf8(isolate, "rmdir"),
739 }
740 
741 } // namespace v8
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)
Definition: d8-posix.cc:568
ZombieProtector(int pid)
Definition: d8-posix.cc:165
V8_INLINE Isolate * GetIsolate() const
Definition: v8.h:6061
V8_INLINE ReturnValue< T > GetReturnValue() const
Definition: v8.h:6067
V8_INLINE int Length() const
Definition: v8.h:6079
static void RemoveDirectory(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:660
Local< Value > ThrowException(Local< Value > exception)
Definition: api.cc:6386
char * arg0()
Definition: d8-posix.cc:233
static Local< Integer > New(Isolate *isolate, int32_t value)
Definition: api.cc:6233
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)
Definition: d8-posix.cc:191
static void System(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:459
static void SetEnvironment(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:678
static Local< FunctionTemplate > New(Isolate *isolate, FunctionCallback callback=0, Handle< Value > data=Handle< Value >(), Handle< Signature > signature=Handle< Signature >(), int length=0)
Definition: api.cc:942
static V8_INLINE Handle< T > Cast(Handle< S > that)
Definition: v8.h:297
static void ChangeDirectory(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:546
static Local< Array > New(Isolate *isolate, int length=0)
Definition: api.cc:5786
V8_INLINE bool IsUndefined() const
Definition: v8.h:6229
int length() const
Definition: v8.h:1955
static Local< String > Concat(Handle< String > left, Handle< String > right)
Definition: api.cc:5456
static void UnsetEnvironment(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:705
OpenFDCloser(int fd)
Definition: d8-posix.cc:176
char ** arg_array()
Definition: d8-posix.cc:232
static void AddOSMethods(v8::Isolate *isolate, Handle< ObjectTemplate > os_template)
Definition: d8-posix.cc:724
static V8_INLINE v8::Local< v8::String > Empty(Isolate *isolate)
Definition: v8.h:6182
static const unsigned kMaxArgs
Definition: d8-posix.cc:231
static void MakeDirectory(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: d8-posix.cc:632
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)
Definition: api.cc:5417