process: Add exitCode property
[platform/upstream/nodejs.git] / src / node.cc
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 #include "node.h"
23 #include "node_buffer.h"
24 #include "node_constants.h"
25 #include "node_file.h"
26 #include "node_http_parser.h"
27 #include "node_javascript.h"
28 #include "node_version.h"
29
30 #if defined HAVE_PERFCTR
31 #include "node_counters.h"
32 #endif
33
34 #if HAVE_OPENSSL
35 #include "node_crypto.h"
36 #endif
37
38 #if defined HAVE_DTRACE || defined HAVE_ETW || defined HAVE_SYSTEMTAP
39 #include "node_dtrace.h"
40 #endif
41
42 #if HAVE_SYSTEMTAP
43 #include "node_provider.h"
44 #endif
45
46 #include "ares.h"
47 #include "env.h"
48 #include "env-inl.h"
49 #include "handle_wrap.h"
50 #include "req_wrap.h"
51 #include "string_bytes.h"
52 #include "uv.h"
53 #include "v8-debug.h"
54 #include "zlib.h"
55
56 #include <assert.h>
57 #include <errno.h>
58 #include <limits.h>  // PATH_MAX
59 #include <locale.h>
60 #include <signal.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <sys/types.h>
65
66 #if defined(_MSC_VER)
67 #include <direct.h>
68 #include <io.h>
69 #include <process.h>
70 #define strcasecmp _stricmp
71 #define getpid _getpid
72 #define umask _umask
73 typedef int mode_t;
74 #else
75 #include <unistd.h>  // setuid, getuid
76 #endif
77
78 #if defined(__POSIX__) && !defined(__ANDROID__)
79 #include <pwd.h>  // getpwnam()
80 #include <grp.h>  // getgrnam()
81 #endif
82
83 #ifdef __APPLE__
84 #include <crt_externs.h>
85 #define environ (*_NSGetEnviron())
86 #elif !defined(_MSC_VER)
87 extern char **environ;
88 #endif
89
90 namespace node {
91
92 using v8::Array;
93 using v8::ArrayBuffer;
94 using v8::Boolean;
95 using v8::Context;
96 using v8::Exception;
97 using v8::Function;
98 using v8::FunctionCallbackInfo;
99 using v8::FunctionTemplate;
100 using v8::Handle;
101 using v8::HandleScope;
102 using v8::HeapStatistics;
103 using v8::Integer;
104 using v8::Isolate;
105 using v8::Local;
106 using v8::Locker;
107 using v8::Message;
108 using v8::Number;
109 using v8::Object;
110 using v8::ObjectTemplate;
111 using v8::PropertyCallbackInfo;
112 using v8::String;
113 using v8::ThrowException;
114 using v8::TryCatch;
115 using v8::Uint32;
116 using v8::V8;
117 using v8::Value;
118 using v8::kExternalUnsignedIntArray;
119
120 // FIXME(bnoordhuis) Make these per-context?
121 QUEUE handle_wrap_queue = { &handle_wrap_queue, &handle_wrap_queue };
122 QUEUE req_wrap_queue = { &req_wrap_queue, &req_wrap_queue };
123
124 static bool print_eval = false;
125 static bool force_repl = false;
126 static bool trace_deprecation = false;
127 static bool throw_deprecation = false;
128 static const char* eval_string = NULL;
129 static bool use_debug_agent = false;
130 static bool debug_wait_connect = false;
131 static int debug_port = 5858;
132
133 // used by C++ modules as well
134 bool no_deprecation = false;
135
136 // process-relative uptime base, initialized at start-up
137 static double prog_start_time;
138
139 static volatile bool debugger_running = false;
140 static uv_async_t dispatch_debug_messages_async;
141 static uv_async_t emit_debug_enabled_async;
142
143 // Declared in node_internals.h
144 Isolate* node_isolate = NULL;
145
146
147 class ArrayBufferAllocator : public ArrayBuffer::Allocator {
148  public:
149   // Impose an upper limit to avoid out of memory errors that bring down
150   // the process.
151   static const size_t kMaxLength = 0x3fffffff;
152   static ArrayBufferAllocator the_singleton;
153   virtual ~ArrayBufferAllocator() {}
154   virtual void* Allocate(size_t length);
155   virtual void Free(void* data);
156  private:
157   ArrayBufferAllocator() {}
158   ArrayBufferAllocator(const ArrayBufferAllocator&);
159   void operator=(const ArrayBufferAllocator&);
160 };
161
162 ArrayBufferAllocator ArrayBufferAllocator::the_singleton;
163
164
165 void* ArrayBufferAllocator::Allocate(size_t length) {
166   if (length > kMaxLength) return NULL;
167   return new char[length];
168 }
169
170
171 void ArrayBufferAllocator::Free(void* data) {
172   delete[] static_cast<char*>(data);
173 }
174
175
176 static void CheckImmediate(uv_check_t* handle, int status) {
177   Environment* env = Environment::from_immediate_check_handle(handle);
178   Context::Scope context_scope(env->context());
179   MakeCallback(env, env->process_object(), env->immediate_callback_string());
180 }
181
182
183 static void IdleImmediateDummy(uv_idle_t*, int) {
184   // Do nothing. Only for maintaining event loop.
185   // TODO(bnoordhuis) Maybe make libuv accept NULL idle callbacks.
186 }
187
188
189 static inline const char *errno_string(int errorno) {
190 #define ERRNO_CASE(e)  case e: return #e;
191   switch (errorno) {
192 #ifdef EACCES
193   ERRNO_CASE(EACCES);
194 #endif
195
196 #ifdef EADDRINUSE
197   ERRNO_CASE(EADDRINUSE);
198 #endif
199
200 #ifdef EADDRNOTAVAIL
201   ERRNO_CASE(EADDRNOTAVAIL);
202 #endif
203
204 #ifdef EAFNOSUPPORT
205   ERRNO_CASE(EAFNOSUPPORT);
206 #endif
207
208 #ifdef EAGAIN
209   ERRNO_CASE(EAGAIN);
210 #endif
211
212 #ifdef EWOULDBLOCK
213 # if EAGAIN != EWOULDBLOCK
214   ERRNO_CASE(EWOULDBLOCK);
215 # endif
216 #endif
217
218 #ifdef EALREADY
219   ERRNO_CASE(EALREADY);
220 #endif
221
222 #ifdef EBADF
223   ERRNO_CASE(EBADF);
224 #endif
225
226 #ifdef EBADMSG
227   ERRNO_CASE(EBADMSG);
228 #endif
229
230 #ifdef EBUSY
231   ERRNO_CASE(EBUSY);
232 #endif
233
234 #ifdef ECANCELED
235   ERRNO_CASE(ECANCELED);
236 #endif
237
238 #ifdef ECHILD
239   ERRNO_CASE(ECHILD);
240 #endif
241
242 #ifdef ECONNABORTED
243   ERRNO_CASE(ECONNABORTED);
244 #endif
245
246 #ifdef ECONNREFUSED
247   ERRNO_CASE(ECONNREFUSED);
248 #endif
249
250 #ifdef ECONNRESET
251   ERRNO_CASE(ECONNRESET);
252 #endif
253
254 #ifdef EDEADLK
255   ERRNO_CASE(EDEADLK);
256 #endif
257
258 #ifdef EDESTADDRREQ
259   ERRNO_CASE(EDESTADDRREQ);
260 #endif
261
262 #ifdef EDOM
263   ERRNO_CASE(EDOM);
264 #endif
265
266 #ifdef EDQUOT
267   ERRNO_CASE(EDQUOT);
268 #endif
269
270 #ifdef EEXIST
271   ERRNO_CASE(EEXIST);
272 #endif
273
274 #ifdef EFAULT
275   ERRNO_CASE(EFAULT);
276 #endif
277
278 #ifdef EFBIG
279   ERRNO_CASE(EFBIG);
280 #endif
281
282 #ifdef EHOSTUNREACH
283   ERRNO_CASE(EHOSTUNREACH);
284 #endif
285
286 #ifdef EIDRM
287   ERRNO_CASE(EIDRM);
288 #endif
289
290 #ifdef EILSEQ
291   ERRNO_CASE(EILSEQ);
292 #endif
293
294 #ifdef EINPROGRESS
295   ERRNO_CASE(EINPROGRESS);
296 #endif
297
298 #ifdef EINTR
299   ERRNO_CASE(EINTR);
300 #endif
301
302 #ifdef EINVAL
303   ERRNO_CASE(EINVAL);
304 #endif
305
306 #ifdef EIO
307   ERRNO_CASE(EIO);
308 #endif
309
310 #ifdef EISCONN
311   ERRNO_CASE(EISCONN);
312 #endif
313
314 #ifdef EISDIR
315   ERRNO_CASE(EISDIR);
316 #endif
317
318 #ifdef ELOOP
319   ERRNO_CASE(ELOOP);
320 #endif
321
322 #ifdef EMFILE
323   ERRNO_CASE(EMFILE);
324 #endif
325
326 #ifdef EMLINK
327   ERRNO_CASE(EMLINK);
328 #endif
329
330 #ifdef EMSGSIZE
331   ERRNO_CASE(EMSGSIZE);
332 #endif
333
334 #ifdef EMULTIHOP
335   ERRNO_CASE(EMULTIHOP);
336 #endif
337
338 #ifdef ENAMETOOLONG
339   ERRNO_CASE(ENAMETOOLONG);
340 #endif
341
342 #ifdef ENETDOWN
343   ERRNO_CASE(ENETDOWN);
344 #endif
345
346 #ifdef ENETRESET
347   ERRNO_CASE(ENETRESET);
348 #endif
349
350 #ifdef ENETUNREACH
351   ERRNO_CASE(ENETUNREACH);
352 #endif
353
354 #ifdef ENFILE
355   ERRNO_CASE(ENFILE);
356 #endif
357
358 #ifdef ENOBUFS
359   ERRNO_CASE(ENOBUFS);
360 #endif
361
362 #ifdef ENODATA
363   ERRNO_CASE(ENODATA);
364 #endif
365
366 #ifdef ENODEV
367   ERRNO_CASE(ENODEV);
368 #endif
369
370 #ifdef ENOENT
371   ERRNO_CASE(ENOENT);
372 #endif
373
374 #ifdef ENOEXEC
375   ERRNO_CASE(ENOEXEC);
376 #endif
377
378 #ifdef ENOLINK
379   ERRNO_CASE(ENOLINK);
380 #endif
381
382 #ifdef ENOLCK
383 # if ENOLINK != ENOLCK
384   ERRNO_CASE(ENOLCK);
385 # endif
386 #endif
387
388 #ifdef ENOMEM
389   ERRNO_CASE(ENOMEM);
390 #endif
391
392 #ifdef ENOMSG
393   ERRNO_CASE(ENOMSG);
394 #endif
395
396 #ifdef ENOPROTOOPT
397   ERRNO_CASE(ENOPROTOOPT);
398 #endif
399
400 #ifdef ENOSPC
401   ERRNO_CASE(ENOSPC);
402 #endif
403
404 #ifdef ENOSR
405   ERRNO_CASE(ENOSR);
406 #endif
407
408 #ifdef ENOSTR
409   ERRNO_CASE(ENOSTR);
410 #endif
411
412 #ifdef ENOSYS
413   ERRNO_CASE(ENOSYS);
414 #endif
415
416 #ifdef ENOTCONN
417   ERRNO_CASE(ENOTCONN);
418 #endif
419
420 #ifdef ENOTDIR
421   ERRNO_CASE(ENOTDIR);
422 #endif
423
424 #ifdef ENOTEMPTY
425   ERRNO_CASE(ENOTEMPTY);
426 #endif
427
428 #ifdef ENOTSOCK
429   ERRNO_CASE(ENOTSOCK);
430 #endif
431
432 #ifdef ENOTSUP
433   ERRNO_CASE(ENOTSUP);
434 #else
435 # ifdef EOPNOTSUPP
436   ERRNO_CASE(EOPNOTSUPP);
437 # endif
438 #endif
439
440 #ifdef ENOTTY
441   ERRNO_CASE(ENOTTY);
442 #endif
443
444 #ifdef ENXIO
445   ERRNO_CASE(ENXIO);
446 #endif
447
448
449 #ifdef EOVERFLOW
450   ERRNO_CASE(EOVERFLOW);
451 #endif
452
453 #ifdef EPERM
454   ERRNO_CASE(EPERM);
455 #endif
456
457 #ifdef EPIPE
458   ERRNO_CASE(EPIPE);
459 #endif
460
461 #ifdef EPROTO
462   ERRNO_CASE(EPROTO);
463 #endif
464
465 #ifdef EPROTONOSUPPORT
466   ERRNO_CASE(EPROTONOSUPPORT);
467 #endif
468
469 #ifdef EPROTOTYPE
470   ERRNO_CASE(EPROTOTYPE);
471 #endif
472
473 #ifdef ERANGE
474   ERRNO_CASE(ERANGE);
475 #endif
476
477 #ifdef EROFS
478   ERRNO_CASE(EROFS);
479 #endif
480
481 #ifdef ESPIPE
482   ERRNO_CASE(ESPIPE);
483 #endif
484
485 #ifdef ESRCH
486   ERRNO_CASE(ESRCH);
487 #endif
488
489 #ifdef ESTALE
490   ERRNO_CASE(ESTALE);
491 #endif
492
493 #ifdef ETIME
494   ERRNO_CASE(ETIME);
495 #endif
496
497 #ifdef ETIMEDOUT
498   ERRNO_CASE(ETIMEDOUT);
499 #endif
500
501 #ifdef ETXTBSY
502   ERRNO_CASE(ETXTBSY);
503 #endif
504
505 #ifdef EXDEV
506   ERRNO_CASE(EXDEV);
507 #endif
508
509   default: return "";
510   }
511 }
512
513 const char *signo_string(int signo) {
514 #define SIGNO_CASE(e)  case e: return #e;
515   switch (signo) {
516 #ifdef SIGHUP
517   SIGNO_CASE(SIGHUP);
518 #endif
519
520 #ifdef SIGINT
521   SIGNO_CASE(SIGINT);
522 #endif
523
524 #ifdef SIGQUIT
525   SIGNO_CASE(SIGQUIT);
526 #endif
527
528 #ifdef SIGILL
529   SIGNO_CASE(SIGILL);
530 #endif
531
532 #ifdef SIGTRAP
533   SIGNO_CASE(SIGTRAP);
534 #endif
535
536 #ifdef SIGABRT
537   SIGNO_CASE(SIGABRT);
538 #endif
539
540 #ifdef SIGIOT
541 # if SIGABRT != SIGIOT
542   SIGNO_CASE(SIGIOT);
543 # endif
544 #endif
545
546 #ifdef SIGBUS
547   SIGNO_CASE(SIGBUS);
548 #endif
549
550 #ifdef SIGFPE
551   SIGNO_CASE(SIGFPE);
552 #endif
553
554 #ifdef SIGKILL
555   SIGNO_CASE(SIGKILL);
556 #endif
557
558 #ifdef SIGUSR1
559   SIGNO_CASE(SIGUSR1);
560 #endif
561
562 #ifdef SIGSEGV
563   SIGNO_CASE(SIGSEGV);
564 #endif
565
566 #ifdef SIGUSR2
567   SIGNO_CASE(SIGUSR2);
568 #endif
569
570 #ifdef SIGPIPE
571   SIGNO_CASE(SIGPIPE);
572 #endif
573
574 #ifdef SIGALRM
575   SIGNO_CASE(SIGALRM);
576 #endif
577
578   SIGNO_CASE(SIGTERM);
579
580 #ifdef SIGCHLD
581   SIGNO_CASE(SIGCHLD);
582 #endif
583
584 #ifdef SIGSTKFLT
585   SIGNO_CASE(SIGSTKFLT);
586 #endif
587
588
589 #ifdef SIGCONT
590   SIGNO_CASE(SIGCONT);
591 #endif
592
593 #ifdef SIGSTOP
594   SIGNO_CASE(SIGSTOP);
595 #endif
596
597 #ifdef SIGTSTP
598   SIGNO_CASE(SIGTSTP);
599 #endif
600
601 #ifdef SIGBREAK
602   SIGNO_CASE(SIGBREAK);
603 #endif
604
605 #ifdef SIGTTIN
606   SIGNO_CASE(SIGTTIN);
607 #endif
608
609 #ifdef SIGTTOU
610   SIGNO_CASE(SIGTTOU);
611 #endif
612
613 #ifdef SIGURG
614   SIGNO_CASE(SIGURG);
615 #endif
616
617 #ifdef SIGXCPU
618   SIGNO_CASE(SIGXCPU);
619 #endif
620
621 #ifdef SIGXFSZ
622   SIGNO_CASE(SIGXFSZ);
623 #endif
624
625 #ifdef SIGVTALRM
626   SIGNO_CASE(SIGVTALRM);
627 #endif
628
629 #ifdef SIGPROF
630   SIGNO_CASE(SIGPROF);
631 #endif
632
633 #ifdef SIGWINCH
634   SIGNO_CASE(SIGWINCH);
635 #endif
636
637 #ifdef SIGIO
638   SIGNO_CASE(SIGIO);
639 #endif
640
641 #ifdef SIGPOLL
642 # if SIGPOLL != SIGIO
643   SIGNO_CASE(SIGPOLL);
644 # endif
645 #endif
646
647 #ifdef SIGLOST
648   SIGNO_CASE(SIGLOST);
649 #endif
650
651 #ifdef SIGPWR
652 # if SIGPWR != SIGLOST
653   SIGNO_CASE(SIGPWR);
654 # endif
655 #endif
656
657 #ifdef SIGSYS
658   SIGNO_CASE(SIGSYS);
659 #endif
660
661   default: return "";
662   }
663 }
664
665
666 Local<Value> ErrnoException(int errorno,
667                             const char *syscall,
668                             const char *msg,
669                             const char *path) {
670   Environment* env = Environment::GetCurrent(node_isolate);
671
672   Local<Value> e;
673   Local<String> estring = OneByteString(node_isolate, errno_string(errorno));
674   if (msg == NULL || msg[0] == '\0') {
675     msg = strerror(errorno);
676   }
677   Local<String> message = OneByteString(node_isolate, msg);
678
679   Local<String> cons1 =
680       String::Concat(estring, FIXED_ONE_BYTE_STRING(node_isolate, ", "));
681   Local<String> cons2 = String::Concat(cons1, message);
682
683   if (path) {
684     Local<String> cons3 =
685         String::Concat(cons2, FIXED_ONE_BYTE_STRING(node_isolate, " '"));
686     Local<String> cons4 =
687         String::Concat(cons3, String::NewFromUtf8(node_isolate, path));
688     Local<String> cons5 =
689         String::Concat(cons4, FIXED_ONE_BYTE_STRING(node_isolate, "'"));
690     e = Exception::Error(cons5);
691   } else {
692     e = Exception::Error(cons2);
693   }
694
695   Local<Object> obj = e->ToObject();
696   obj->Set(env->errno_string(), Integer::New(errorno, node_isolate));
697   obj->Set(env->code_string(), estring);
698
699   if (path != NULL) {
700     obj->Set(env->path_string(), String::NewFromUtf8(node_isolate, path));
701   }
702
703   if (syscall != NULL) {
704     obj->Set(env->syscall_string(), OneByteString(node_isolate, syscall));
705   }
706
707   return e;
708 }
709
710
711 // hack alert! copy of ErrnoException, tuned for uv errors
712 Local<Value> UVException(int errorno,
713                          const char *syscall,
714                          const char *msg,
715                          const char *path) {
716   Environment* env = Environment::GetCurrent(node_isolate);
717
718   if (!msg || !msg[0])
719     msg = uv_strerror(errorno);
720
721   Local<String> estring = OneByteString(node_isolate, uv_err_name(errorno));
722   Local<String> message = OneByteString(node_isolate, msg);
723   Local<String> cons1 =
724       String::Concat(estring, FIXED_ONE_BYTE_STRING(node_isolate, ", "));
725   Local<String> cons2 = String::Concat(cons1, message);
726
727   Local<Value> e;
728
729   Local<String> path_str;
730
731   if (path) {
732 #ifdef _WIN32
733     if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
734       path_str = String::Concat(FIXED_ONE_BYTE_STRING(node_isolate, "\\\\"),
735                                 String::NewFromUtf8(node_isolate, path + 8));
736     } else if (strncmp(path, "\\\\?\\", 4) == 0) {
737       path_str = String::NewFromUtf8(node_isolate, path + 4);
738     } else {
739       path_str = String::NewFromUtf8(node_isolate, path);
740     }
741 #else
742     path_str = String::NewFromUtf8(node_isolate, path);
743 #endif
744
745     Local<String> cons3 =
746         String::Concat(cons2, FIXED_ONE_BYTE_STRING(node_isolate, " '"));
747     Local<String> cons4 =
748         String::Concat(cons3, path_str);
749     Local<String> cons5 =
750         String::Concat(cons4, FIXED_ONE_BYTE_STRING(node_isolate, "'"));
751     e = Exception::Error(cons5);
752   } else {
753     e = Exception::Error(cons2);
754   }
755
756   Local<Object> obj = e->ToObject();
757   // TODO(piscisaureus) errno should probably go
758   obj->Set(env->errno_string(), Integer::New(errorno, node_isolate));
759   obj->Set(env->code_string(), estring);
760
761   if (path != NULL) {
762     obj->Set(env->path_string(), path_str);
763   }
764
765   if (syscall != NULL) {
766     obj->Set(env->syscall_string(), OneByteString(node_isolate, syscall));
767   }
768
769   return e;
770 }
771
772
773 #ifdef _WIN32
774 // Does about the same as strerror(),
775 // but supports all windows error messages
776 static const char *winapi_strerror(const int errorno) {
777   char *errmsg = NULL;
778
779   FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
780       FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
781       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL);
782
783   if (errmsg) {
784     // Remove trailing newlines
785     for (int i = strlen(errmsg) - 1;
786         i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
787       errmsg[i] = '\0';
788     }
789
790     return errmsg;
791   } else {
792     // FormatMessage failed
793     return "Unknown error";
794   }
795 }
796
797
798 Local<Value> WinapiErrnoException(int errorno,
799                                   const char* syscall,
800                                   const char* msg,
801                                   const char* path) {
802   Environment* env = Environment::GetCurrent(node_isolate);
803
804   Local<Value> e;
805   if (!msg || !msg[0]) {
806     msg = winapi_strerror(errorno);
807   }
808   Local<String> message = OneByteString(node_isolate, msg);
809
810   if (path) {
811     Local<String> cons1 =
812         String::Concat(message, FIXED_ONE_BYTE_STRING(node_isolate, " '"));
813     Local<String> cons2 =
814         String::Concat(cons1, String::NewFromUtf8(node_isolate, path));
815     Local<String> cons3 =
816         String::Concat(cons2, FIXED_ONE_BYTE_STRING(node_isolate, "'"));
817     e = Exception::Error(cons3);
818   } else {
819     e = Exception::Error(message);
820   }
821
822   Local<Object> obj = e->ToObject();
823   obj->Set(env->errno_string(), Integer::New(errorno, node_isolate));
824
825   if (path != NULL) {
826     obj->Set(env->path_string(), String::NewFromUtf8(node_isolate, path));
827   }
828
829   if (syscall != NULL) {
830     obj->Set(env->syscall_string(), OneByteString(node_isolate, syscall));
831   }
832
833   return e;
834 }
835 #endif
836
837
838 void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
839   Environment* env = Environment::GetCurrent(args.GetIsolate());
840
841   if (env->using_domains()) return;
842   env->set_using_domains(true);
843
844   HandleScope scope(node_isolate);
845   Local<Object> process_object = env->process_object();
846
847   Local<String> tick_callback_function_key =
848       FIXED_ONE_BYTE_STRING(node_isolate, "_tickDomainCallback");
849   Local<Function> tick_callback_function =
850       process_object->Get(tick_callback_function_key).As<Function>();
851
852   if (!tick_callback_function->IsFunction()) {
853     fprintf(stderr, "process._tickDomainCallback assigned to non-function\n");
854     abort();
855   }
856
857   process_object->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_tickCallback"),
858                       tick_callback_function);
859   env->set_tick_callback_function(tick_callback_function);
860
861   if (!args[0]->IsArray()) {
862     fprintf(stderr, "_setupDomainUse first argument must be an array\n");
863     abort();
864   }
865   env->set_domain_array(args[0].As<Array>());
866
867   if (!args[1]->IsObject()) {
868     fprintf(stderr, "_setupDomainUse second argument must be an object\n");
869     abort();
870   }
871
872   Local<Object> domain_flag_obj = args[1].As<Object>();
873   Environment::DomainFlag* domain_flag = env->domain_flag();
874   domain_flag_obj->SetIndexedPropertiesToExternalArrayData(
875       domain_flag->fields(),
876       kExternalUnsignedIntArray,
877       domain_flag->fields_count());
878 }
879
880
881 Handle<Value> MakeDomainCallback(Environment* env,
882                                  const Handle<Object> object,
883                                  const Handle<Function> callback,
884                                  int argc,
885                                  Handle<Value> argv[]) {
886   // If you hit this assertion, you forgot to enter the v8::Context first.
887   assert(env->context() == env->isolate()->GetCurrentContext());
888
889   // TODO(trevnorris) Hook for long stack traces to be made here.
890
891   Local<Value> domain_v = object->Get(env->domain_string());
892   Local<Object> domain;
893
894   TryCatch try_catch;
895   try_catch.SetVerbose(true);
896
897   bool has_domain = domain_v->IsObject();
898   if (has_domain) {
899     domain = domain_v.As<Object>();
900
901     if (domain->Get(env->disposed_string())->IsTrue()) {
902       // domain has been disposed of.
903       return Undefined(node_isolate);
904     }
905
906     Local<Function> enter =
907         domain->Get(env->enter_string()).As<Function>();
908     assert(enter->IsFunction());
909     enter->Call(domain, 0, NULL);
910
911     if (try_catch.HasCaught()) {
912       return Undefined(node_isolate);
913     }
914   }
915
916   Local<Value> ret = callback->Call(object, argc, argv);
917
918   if (try_catch.HasCaught()) {
919     return Undefined(node_isolate);
920   }
921
922   if (has_domain) {
923     Local<Function> exit =
924         domain->Get(env->exit_string()).As<Function>();
925     assert(exit->IsFunction());
926     exit->Call(domain, 0, NULL);
927
928     if (try_catch.HasCaught()) {
929       return Undefined(node_isolate);
930     }
931   }
932
933   Environment::TickInfo* tick_info = env->tick_info();
934
935   if (tick_info->last_threw() == 1) {
936     tick_info->set_last_threw(0);
937     return ret;
938   }
939
940   if (tick_info->in_tick() == 1) {
941     return ret;
942   }
943
944   if (tick_info->length() == 0) {
945     tick_info->set_index(0);
946     return ret;
947   }
948
949   // process nextTicks after call
950   Local<Object> process_object = env->process_object();
951   Local<Function> tick_callback_function = env->tick_callback_function();
952   tick_callback_function->Call(process_object, 0, NULL);
953
954   if (try_catch.HasCaught()) {
955     return Undefined(node_isolate);
956   }
957
958   return ret;
959 }
960
961
962 Handle<Value> MakeCallback(Environment* env,
963                            const Handle<Object> object,
964                            const Handle<Function> callback,
965                            int argc,
966                            Handle<Value> argv[]) {
967   // If you hit this assertion, you forgot to enter the v8::Context first.
968   assert(env->context() == env->isolate()->GetCurrentContext());
969
970   // TODO(trevnorris) Hook for long stack traces to be made here.
971   Local<Object> process_object = env->process_object();
972
973   if (env->using_domains())
974     return MakeDomainCallback(env, object, callback, argc, argv);
975
976   TryCatch try_catch;
977   try_catch.SetVerbose(true);
978
979   Local<Value> ret = callback->Call(object, argc, argv);
980
981   if (try_catch.HasCaught()) {
982     return Undefined(node_isolate);
983   }
984
985   Environment::TickInfo* tick_info = env->tick_info();
986
987   if (tick_info->in_tick() == 1) {
988     return ret;
989   }
990
991   if (tick_info->length() == 0) {
992     tick_info->set_index(0);
993     return ret;
994   }
995
996   // lazy load no domain next tick callbacks
997   Local<Function> tick_callback_function = env->tick_callback_function();
998   if (tick_callback_function.IsEmpty()) {
999     Local<String> tick_callback_function_key =
1000         FIXED_ONE_BYTE_STRING(node_isolate, "_tickCallback");
1001     tick_callback_function =
1002         process_object->Get(tick_callback_function_key).As<Function>();
1003     if (!tick_callback_function->IsFunction()) {
1004       fprintf(stderr, "process._tickCallback assigned to non-function\n");
1005       abort();
1006     }
1007     env->set_tick_callback_function(tick_callback_function);
1008   }
1009
1010   // process nextTicks after call
1011   tick_callback_function->Call(process_object, 0, NULL);
1012
1013   if (try_catch.HasCaught()) {
1014     return Undefined(node_isolate);
1015   }
1016
1017   return ret;
1018 }
1019
1020
1021 // Internal only.
1022 Handle<Value> MakeCallback(Environment* env,
1023                            const Handle<Object> object,
1024                            uint32_t index,
1025                            int argc,
1026                            Handle<Value> argv[]) {
1027   // If you hit this assertion, you forgot to enter the v8::Context first.
1028   assert(env->context() == env->isolate()->GetCurrentContext());
1029
1030   Local<Function> callback = object->Get(index).As<Function>();
1031   assert(callback->IsFunction());
1032
1033   if (env->using_domains()) {
1034     return MakeDomainCallback(env, object, callback, argc, argv);
1035   }
1036
1037   return MakeCallback(env, object, callback, argc, argv);
1038 }
1039
1040
1041 Handle<Value> MakeCallback(Environment* env,
1042                            const Handle<Object> object,
1043                            const Handle<String> symbol,
1044                            int argc,
1045                            Handle<Value> argv[]) {
1046   // If you hit this assertion, you forgot to enter the v8::Context first.
1047   assert(env->context() == env->isolate()->GetCurrentContext());
1048
1049   Local<Function> callback = object->Get(symbol).As<Function>();
1050   assert(callback->IsFunction());
1051
1052   if (env->using_domains()) {
1053     return MakeDomainCallback(env, object, callback, argc, argv);
1054   }
1055
1056   return MakeCallback(env, object, callback, argc, argv);
1057 }
1058
1059
1060 Handle<Value> MakeCallback(Environment* env,
1061                            const Handle<Object> object,
1062                            const char* method,
1063                            int argc,
1064                            Handle<Value> argv[]) {
1065   // If you hit this assertion, you forgot to enter the v8::Context first.
1066   assert(env->context() == env->isolate()->GetCurrentContext());
1067   Local<String> method_string = OneByteString(node_isolate, method);
1068   return MakeCallback(env, object, method_string, argc, argv);
1069 }
1070
1071
1072 Handle<Value> MakeCallback(const Handle<Object> object,
1073                            const char* method,
1074                            int argc,
1075                            Handle<Value> argv[]) {
1076   Local<Context> context = object->CreationContext();
1077   Environment* env = Environment::GetCurrent(context);
1078   Context::Scope context_scope(context);
1079   HandleScope handle_scope(env->isolate());
1080   return handle_scope.Close(MakeCallback(env, object, method, argc, argv));
1081 }
1082
1083
1084 Handle<Value> MakeCallback(const Handle<Object> object,
1085                            const Handle<String> symbol,
1086                            int argc,
1087                            Handle<Value> argv[]) {
1088   Local<Context> context = object->CreationContext();
1089   Environment* env = Environment::GetCurrent(context);
1090   Context::Scope context_scope(context);
1091   HandleScope handle_scope(env->isolate());
1092   return handle_scope.Close(MakeCallback(env, object, symbol, argc, argv));
1093 }
1094
1095
1096 Handle<Value> MakeCallback(const Handle<Object> object,
1097                            const Handle<Function> callback,
1098                            int argc,
1099                            Handle<Value> argv[]) {
1100   Local<Context> context = object->CreationContext();
1101   Environment* env = Environment::GetCurrent(context);
1102   Context::Scope context_scope(context);
1103   HandleScope handle_scope(env->isolate());
1104   return handle_scope.Close(MakeCallback(env, object, callback, argc, argv));
1105 }
1106
1107
1108 Handle<Value> MakeDomainCallback(const Handle<Object> object,
1109                                  const Handle<Function> callback,
1110                                  int argc,
1111                                  Handle<Value> argv[]) {
1112   Local<Context> context = object->CreationContext();
1113   Environment* env = Environment::GetCurrent(context);
1114   Context::Scope context_scope(context);
1115   HandleScope handle_scope(env->isolate());
1116   return handle_scope.Close(
1117       MakeDomainCallback(env, object, callback, argc, argv));
1118 }
1119
1120
1121 enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
1122   HandleScope scope(node_isolate);
1123
1124   if (!encoding_v->IsString()) return _default;
1125
1126   String::Utf8Value encoding(encoding_v);
1127
1128   if (strcasecmp(*encoding, "utf8") == 0) {
1129     return UTF8;
1130   } else if (strcasecmp(*encoding, "utf-8") == 0) {
1131     return UTF8;
1132   } else if (strcasecmp(*encoding, "ascii") == 0) {
1133     return ASCII;
1134   } else if (strcasecmp(*encoding, "base64") == 0) {
1135     return BASE64;
1136   } else if (strcasecmp(*encoding, "ucs2") == 0) {
1137     return UCS2;
1138   } else if (strcasecmp(*encoding, "ucs-2") == 0) {
1139     return UCS2;
1140   } else if (strcasecmp(*encoding, "utf16le") == 0) {
1141     return UCS2;
1142   } else if (strcasecmp(*encoding, "utf-16le") == 0) {
1143     return UCS2;
1144   } else if (strcasecmp(*encoding, "binary") == 0) {
1145     return BINARY;
1146   } else if (strcasecmp(*encoding, "buffer") == 0) {
1147     return BUFFER;
1148   } else if (strcasecmp(*encoding, "hex") == 0) {
1149     return HEX;
1150   } else if (strcasecmp(*encoding, "raw") == 0) {
1151     if (!no_deprecation) {
1152       fprintf(stderr, "'raw' (array of integers) has been removed. "
1153                       "Use 'binary'.\n");
1154     }
1155     return BINARY;
1156   } else if (strcasecmp(*encoding, "raws") == 0) {
1157     if (!no_deprecation) {
1158       fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1159                       "Please update your code.\n");
1160     }
1161     return BINARY;
1162   } else {
1163     return _default;
1164   }
1165 }
1166
1167 Local<Value> Encode(const void *buf, size_t len, enum encoding encoding) {
1168   return StringBytes::Encode(static_cast<const char*>(buf),
1169                              len,
1170                              encoding);
1171 }
1172
1173 // Returns -1 if the handle was not valid for decoding
1174 ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
1175   HandleScope scope(node_isolate);
1176
1177   if (val->IsArray()) {
1178     fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1179                     "Use 'binary'.\n");
1180     assert(0);
1181     return -1;
1182   }
1183
1184   return StringBytes::Size(val, encoding);
1185 }
1186
1187 #ifndef MIN
1188 # define MIN(a, b) ((a) < (b) ? (a) : (b))
1189 #endif
1190
1191 // Returns number of bytes written.
1192 ssize_t DecodeWrite(char *buf,
1193                     size_t buflen,
1194                     v8::Handle<v8::Value> val,
1195                     enum encoding encoding) {
1196   return StringBytes::Write(buf, buflen, val, encoding, NULL);
1197 }
1198
1199 void DisplayExceptionLine(Handle<Message> message) {
1200   // Prevent re-entry into this function.  For example, if there is
1201   // a throw from a program in vm.runInThisContext(code, filename, true),
1202   // then we want to show the original failure, not the secondary one.
1203   static bool displayed_error = false;
1204
1205   if (displayed_error) return;
1206   displayed_error = true;
1207
1208   uv_tty_reset_mode();
1209
1210   fprintf(stderr, "\n");
1211
1212   if (!message.IsEmpty()) {
1213     // Print (filename):(line number): (message).
1214     String::Utf8Value filename(message->GetScriptResourceName());
1215     const char* filename_string = *filename;
1216     int linenum = message->GetLineNumber();
1217     fprintf(stderr, "%s:%i\n", filename_string, linenum);
1218     // Print line of source code.
1219     String::Utf8Value sourceline(message->GetSourceLine());
1220     const char* sourceline_string = *sourceline;
1221
1222     // Because of how node modules work, all scripts are wrapped with a
1223     // "function (module, exports, __filename, ...) {"
1224     // to provide script local variables.
1225     //
1226     // When reporting errors on the first line of a script, this wrapper
1227     // function is leaked to the user. There used to be a hack here to
1228     // truncate off the first 62 characters, but it caused numerous other
1229     // problems when vm.runIn*Context() methods were used for non-module
1230     // code.
1231     //
1232     // If we ever decide to re-instate such a hack, the following steps
1233     // must be taken:
1234     //
1235     // 1. Pass a flag around to say "this code was wrapped"
1236     // 2. Update the stack frame output so that it is also correct.
1237     //
1238     // It would probably be simpler to add a line rather than add some
1239     // number of characters to the first line, since V8 truncates the
1240     // sourceline to 78 characters, and we end up not providing very much
1241     // useful debugging info to the user if we remove 62 characters.
1242
1243     int start = message->GetStartColumn();
1244     int end = message->GetEndColumn();
1245
1246     fprintf(stderr, "%s\n", sourceline_string);
1247     // Print wavy underline (GetUnderline is deprecated).
1248     for (int i = 0; i < start; i++) {
1249       fputc((sourceline_string[i] == '\t') ? '\t' : ' ', stderr);
1250     }
1251     for (int i = start; i < end; i++) {
1252       fputc('^', stderr);
1253     }
1254     fputc('\n', stderr);
1255   }
1256 }
1257
1258
1259 static void ReportException(Handle<Value> er, Handle<Message> message) {
1260   HandleScope scope(node_isolate);
1261
1262   DisplayExceptionLine(message);
1263
1264   Local<Value> trace_value(
1265       er->ToObject()->Get(FIXED_ONE_BYTE_STRING(node_isolate, "stack")));
1266   String::Utf8Value trace(trace_value);
1267
1268   // range errors have a trace member set to undefined
1269   if (trace.length() > 0 && !trace_value->IsUndefined()) {
1270     fprintf(stderr, "%s\n", *trace);
1271   } else {
1272     // this really only happens for RangeErrors, since they're the only
1273     // kind that won't have all this info in the trace, or when non-Error
1274     // objects are thrown manually.
1275     Local<Value> message;
1276     Local<Value> name;
1277
1278     if (er->IsObject()) {
1279       Local<Object> err_obj = er.As<Object>();
1280       message = err_obj->Get(FIXED_ONE_BYTE_STRING(node_isolate, "message"));
1281       name = err_obj->Get(FIXED_ONE_BYTE_STRING(node_isolate, "name"));
1282     }
1283
1284     if (message.IsEmpty() ||
1285         message->IsUndefined() ||
1286         name.IsEmpty() ||
1287         name->IsUndefined()) {
1288       // Not an error object. Just print as-is.
1289       String::Utf8Value message(er);
1290       fprintf(stderr, "%s\n", *message);
1291     } else {
1292       String::Utf8Value name_string(name);
1293       String::Utf8Value message_string(message);
1294       fprintf(stderr, "%s: %s\n", *name_string, *message_string);
1295     }
1296   }
1297
1298   fflush(stderr);
1299 }
1300
1301
1302 static void ReportException(const TryCatch& try_catch) {
1303   ReportException(try_catch.Exception(), try_catch.Message());
1304 }
1305
1306
1307 // Executes a str within the current v8 context.
1308 Local<Value> ExecuteString(Handle<String> source, Handle<Value> filename) {
1309   HandleScope scope(node_isolate);
1310   TryCatch try_catch;
1311
1312   // try_catch must be nonverbose to disable FatalException() handler,
1313   // we will handle exceptions ourself.
1314   try_catch.SetVerbose(false);
1315
1316   Local<v8::Script> script = v8::Script::Compile(source, filename);
1317   if (script.IsEmpty()) {
1318     ReportException(try_catch);
1319     exit(3);
1320   }
1321
1322   Local<Value> result = script->Run();
1323   if (result.IsEmpty()) {
1324     ReportException(try_catch);
1325     exit(4);
1326   }
1327
1328   return scope.Close(result);
1329 }
1330
1331
1332 static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
1333   HandleScope scope(node_isolate);
1334
1335   Local<Array> ary = Array::New();
1336   QUEUE* q = NULL;
1337   int i = 0;
1338
1339   QUEUE_FOREACH(q, &req_wrap_queue) {
1340     ReqWrap<uv_req_t>* w = container_of(q, ReqWrap<uv_req_t>, req_wrap_queue_);
1341     if (w->persistent().IsEmpty()) continue;
1342     ary->Set(i++, w->object());
1343   }
1344
1345   args.GetReturnValue().Set(ary);
1346 }
1347
1348
1349 // Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1350 // implemented here for consistency with GetActiveRequests().
1351 void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
1352   HandleScope scope(node_isolate);
1353
1354   Local<Array> ary = Array::New();
1355   QUEUE* q = NULL;
1356   int i = 0;
1357
1358   Local<String> owner_sym = FIXED_ONE_BYTE_STRING(node_isolate, "owner");
1359
1360   QUEUE_FOREACH(q, &handle_wrap_queue) {
1361     HandleWrap* w = container_of(q, HandleWrap, handle_wrap_queue_);
1362     if (w->persistent().IsEmpty() || (w->flags_ & HandleWrap::kUnref)) continue;
1363     Local<Object> object = w->object();
1364     Local<Value> owner = object->Get(owner_sym);
1365     if (owner->IsUndefined()) owner = object;
1366     ary->Set(i++, owner);
1367   }
1368
1369   args.GetReturnValue().Set(ary);
1370 }
1371
1372
1373 static void Abort(const FunctionCallbackInfo<Value>& args) {
1374   abort();
1375 }
1376
1377
1378 static void Chdir(const FunctionCallbackInfo<Value>& args) {
1379   HandleScope scope(node_isolate);
1380
1381   if (args.Length() != 1 || !args[0]->IsString()) {
1382     return ThrowError("Bad argument.");  // FIXME(bnoordhuis) ThrowTypeError?
1383   }
1384
1385   String::Utf8Value path(args[0]);
1386   int err = uv_chdir(*path);
1387   if (err) {
1388     return ThrowUVException(err, "uv_chdir");
1389   }
1390 }
1391
1392
1393 static void Cwd(const FunctionCallbackInfo<Value>& args) {
1394   HandleScope scope(node_isolate);
1395 #ifdef _WIN32
1396   /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1397   char buf[MAX_PATH * 4 + 1];
1398 #else
1399   char buf[PATH_MAX + 1];
1400 #endif
1401
1402   int err = uv_cwd(buf, ARRAY_SIZE(buf) - 1);
1403   if (err) {
1404     return ThrowUVException(err, "uv_cwd");
1405   }
1406
1407   buf[ARRAY_SIZE(buf) - 1] = '\0';
1408   Local<String> cwd = String::NewFromUtf8(node_isolate, buf);
1409
1410   args.GetReturnValue().Set(cwd);
1411 }
1412
1413
1414 static void Umask(const FunctionCallbackInfo<Value>& args) {
1415   HandleScope scope(node_isolate);
1416   uint32_t old;
1417
1418   if (args.Length() < 1 || args[0]->IsUndefined()) {
1419     old = umask(0);
1420     umask(static_cast<mode_t>(old));
1421   } else if (!args[0]->IsInt32() && !args[0]->IsString()) {
1422     return ThrowTypeError("argument must be an integer or octal string.");
1423   } else {
1424     int oct;
1425     if (args[0]->IsInt32()) {
1426       oct = args[0]->Uint32Value();
1427     } else {
1428       oct = 0;
1429       String::Utf8Value str(args[0]);
1430
1431       // Parse the octal string.
1432       for (int i = 0; i < str.length(); i++) {
1433         char c = (*str)[i];
1434         if (c > '7' || c < '0') {
1435           return ThrowTypeError("invalid octal string");
1436         }
1437         oct *= 8;
1438         oct += c - '0';
1439       }
1440     }
1441     old = umask(static_cast<mode_t>(oct));
1442   }
1443
1444   args.GetReturnValue().Set(old);
1445 }
1446
1447
1448 #if defined(__POSIX__) && !defined(__ANDROID__)
1449
1450 static const uid_t uid_not_found = static_cast<uid_t>(-1);
1451 static const gid_t gid_not_found = static_cast<gid_t>(-1);
1452
1453
1454 static uid_t uid_by_name(const char* name) {
1455   struct passwd pwd;
1456   struct passwd* pp;
1457   char buf[8192];
1458
1459   errno = 0;
1460   pp = NULL;
1461
1462   if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != NULL) {
1463     return pp->pw_uid;
1464   }
1465
1466   return uid_not_found;
1467 }
1468
1469
1470 static char* name_by_uid(uid_t uid) {
1471   struct passwd pwd;
1472   struct passwd* pp;
1473   char buf[8192];
1474   int rc;
1475
1476   errno = 0;
1477   pp = NULL;
1478
1479   if ((rc = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp)) == 0 && pp != NULL) {
1480     return strdup(pp->pw_name);
1481   }
1482
1483   if (rc == 0) {
1484     errno = ENOENT;
1485   }
1486
1487   return NULL;
1488 }
1489
1490
1491 static gid_t gid_by_name(const char* name) {
1492   struct group pwd;
1493   struct group* pp;
1494   char buf[8192];
1495
1496   errno = 0;
1497   pp = NULL;
1498
1499   if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != NULL) {
1500     return pp->gr_gid;
1501   }
1502
1503   return gid_not_found;
1504 }
1505
1506
1507 #if 0  // For future use.
1508 static const char* name_by_gid(gid_t gid) {
1509   struct group pwd;
1510   struct group* pp;
1511   char buf[8192];
1512   int rc;
1513
1514   errno = 0;
1515   pp = NULL;
1516
1517   if ((rc = getgrgid_r(gid, &pwd, buf, sizeof(buf), &pp)) == 0 && pp != NULL) {
1518     return strdup(pp->gr_name);
1519   }
1520
1521   if (rc == 0) {
1522     errno = ENOENT;
1523   }
1524
1525   return NULL;
1526 }
1527 #endif
1528
1529
1530 static uid_t uid_by_name(Handle<Value> value) {
1531   if (value->IsUint32()) {
1532     return static_cast<uid_t>(value->Uint32Value());
1533   } else {
1534     String::Utf8Value name(value);
1535     return uid_by_name(*name);
1536   }
1537 }
1538
1539
1540 static gid_t gid_by_name(Handle<Value> value) {
1541   if (value->IsUint32()) {
1542     return static_cast<gid_t>(value->Uint32Value());
1543   } else {
1544     String::Utf8Value name(value);
1545     return gid_by_name(*name);
1546   }
1547 }
1548
1549
1550 static void GetUid(const FunctionCallbackInfo<Value>& args) {
1551   // uid_t is an uint32_t on all supported platforms.
1552   args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
1553 }
1554
1555
1556 static void GetGid(const FunctionCallbackInfo<Value>& args) {
1557   // gid_t is an uint32_t on all supported platforms.
1558   args.GetReturnValue().Set(static_cast<uint32_t>(getgid()));
1559 }
1560
1561
1562 static void SetGid(const FunctionCallbackInfo<Value>& args) {
1563   HandleScope scope(node_isolate);
1564
1565   if (!args[0]->IsUint32() && !args[0]->IsString()) {
1566     return ThrowTypeError("setgid argument must be a number or a string");
1567   }
1568
1569   gid_t gid = gid_by_name(args[0]);
1570
1571   if (gid == gid_not_found) {
1572     return ThrowError("setgid group id does not exist");
1573   }
1574
1575   if (setgid(gid)) {
1576     return ThrowErrnoException(errno, "setgid");
1577   }
1578 }
1579
1580
1581 static void SetUid(const FunctionCallbackInfo<Value>& args) {
1582   HandleScope scope(node_isolate);
1583
1584   if (!args[0]->IsUint32() && !args[0]->IsString()) {
1585     return ThrowTypeError("setuid argument must be a number or a string");
1586   }
1587
1588   uid_t uid = uid_by_name(args[0]);
1589
1590   if (uid == uid_not_found) {
1591     return ThrowError("setuid user id does not exist");
1592   }
1593
1594   if (setuid(uid)) {
1595     return ThrowErrnoException(errno, "setuid");
1596   }
1597 }
1598
1599
1600 static void GetGroups(const FunctionCallbackInfo<Value>& args) {
1601   HandleScope scope(node_isolate);
1602
1603   int ngroups = getgroups(0, NULL);
1604
1605   if (ngroups == -1) {
1606     return ThrowErrnoException(errno, "getgroups");
1607   }
1608
1609   gid_t* groups = new gid_t[ngroups];
1610
1611   ngroups = getgroups(ngroups, groups);
1612
1613   if (ngroups == -1) {
1614     delete[] groups;
1615     return ThrowErrnoException(errno, "getgroups");
1616   }
1617
1618   Local<Array> groups_list = Array::New(ngroups);
1619   bool seen_egid = false;
1620   gid_t egid = getegid();
1621
1622   for (int i = 0; i < ngroups; i++) {
1623     groups_list->Set(i, Integer::New(groups[i], node_isolate));
1624     if (groups[i] == egid) seen_egid = true;
1625   }
1626
1627   delete[] groups;
1628
1629   if (seen_egid == false) {
1630     groups_list->Set(ngroups, Integer::New(egid, node_isolate));
1631   }
1632
1633   args.GetReturnValue().Set(groups_list);
1634 }
1635
1636
1637 static void SetGroups(const FunctionCallbackInfo<Value>& args) {
1638   HandleScope scope(node_isolate);
1639
1640   if (!args[0]->IsArray()) {
1641     return ThrowTypeError("argument 1 must be an array");
1642   }
1643
1644   Local<Array> groups_list = args[0].As<Array>();
1645   size_t size = groups_list->Length();
1646   gid_t* groups = new gid_t[size];
1647
1648   for (size_t i = 0; i < size; i++) {
1649     gid_t gid = gid_by_name(groups_list->Get(i));
1650
1651     if (gid == gid_not_found) {
1652       delete[] groups;
1653       return ThrowError("group name not found");
1654     }
1655
1656     groups[i] = gid;
1657   }
1658
1659   int rc = setgroups(size, groups);
1660   delete[] groups;
1661
1662   if (rc == -1) {
1663     return ThrowErrnoException(errno, "setgroups");
1664   }
1665 }
1666
1667
1668 static void InitGroups(const FunctionCallbackInfo<Value>& args) {
1669   HandleScope scope(node_isolate);
1670
1671   if (!args[0]->IsUint32() && !args[0]->IsString()) {
1672     return ThrowTypeError("argument 1 must be a number or a string");
1673   }
1674
1675   if (!args[1]->IsUint32() && !args[1]->IsString()) {
1676     return ThrowTypeError("argument 2 must be a number or a string");
1677   }
1678
1679   String::Utf8Value arg0(args[0]);
1680   gid_t extra_group;
1681   bool must_free;
1682   char* user;
1683
1684   if (args[0]->IsUint32()) {
1685     user = name_by_uid(args[0]->Uint32Value());
1686     must_free = true;
1687   } else {
1688     user = *arg0;
1689     must_free = false;
1690   }
1691
1692   if (user == NULL) {
1693     return ThrowError("initgroups user not found");
1694   }
1695
1696   extra_group = gid_by_name(args[1]);
1697
1698   if (extra_group == gid_not_found) {
1699     if (must_free) free(user);
1700     return ThrowError("initgroups extra group not found");
1701   }
1702
1703   int rc = initgroups(user, extra_group);
1704
1705   if (must_free) {
1706     free(user);
1707   }
1708
1709   if (rc) {
1710     return ThrowErrnoException(errno, "initgroups");
1711   }
1712 }
1713
1714 #endif  // __POSIX__ && !defined(__ANDROID__)
1715
1716
1717 void Exit(const FunctionCallbackInfo<Value>& args) {
1718   HandleScope scope(node_isolate);
1719   exit(args[0]->IntegerValue());
1720 }
1721
1722
1723 static void Uptime(const FunctionCallbackInfo<Value>& args) {
1724   HandleScope scope(node_isolate);
1725   double uptime;
1726   if (uv_uptime(&uptime)) return;
1727   args.GetReturnValue().Set(uptime - prog_start_time);
1728 }
1729
1730
1731 void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
1732   Environment* env = Environment::GetCurrent(args.GetIsolate());
1733   HandleScope handle_scope(args.GetIsolate());
1734
1735   size_t rss;
1736   int err = uv_resident_set_memory(&rss);
1737   if (err) {
1738     return ThrowUVException(err, "uv_resident_set_memory");
1739   }
1740
1741   // V8 memory usage
1742   HeapStatistics v8_heap_stats;
1743   node_isolate->GetHeapStatistics(&v8_heap_stats);
1744
1745   Local<Integer> heap_total =
1746       Integer::NewFromUnsigned(v8_heap_stats.total_heap_size(), node_isolate);
1747   Local<Integer> heap_used =
1748       Integer::NewFromUnsigned(v8_heap_stats.used_heap_size(), node_isolate);
1749
1750   Local<Object> info = Object::New();
1751   info->Set(env->rss_string(), Number::New(node_isolate, rss));
1752   info->Set(env->heap_total_string(), heap_total);
1753   info->Set(env->heap_used_string(), heap_used);
1754
1755   args.GetReturnValue().Set(info);
1756 }
1757
1758
1759 void Kill(const FunctionCallbackInfo<Value>& args) {
1760   HandleScope scope(node_isolate);
1761
1762   if (args.Length() != 2) {
1763     return ThrowError("Bad argument.");
1764   }
1765
1766   int pid = args[0]->IntegerValue();
1767   int sig = args[1]->Int32Value();
1768   int err = uv_kill(pid, sig);
1769   args.GetReturnValue().Set(err);
1770 }
1771
1772 // used in Hrtime() below
1773 #define NANOS_PER_SEC 1000000000
1774
1775 // Hrtime exposes libuv's uv_hrtime() high-resolution timer.
1776 // The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
1777 // so this function instead returns an Array with 2 entries representing seconds
1778 // and nanoseconds, to avoid any integer overflow possibility.
1779 // Pass in an Array from a previous hrtime() call to instead get a time diff.
1780 void Hrtime(const FunctionCallbackInfo<Value>& args) {
1781   HandleScope scope(node_isolate);
1782
1783   uint64_t t = uv_hrtime();
1784
1785   if (args.Length() > 0) {
1786     // return a time diff tuple
1787     if (!args[0]->IsArray()) {
1788       return ThrowTypeError("process.hrtime() only accepts an Array tuple.");
1789     }
1790     Local<Array> inArray = Local<Array>::Cast(args[0]);
1791     uint64_t seconds = inArray->Get(0)->Uint32Value();
1792     uint64_t nanos = inArray->Get(1)->Uint32Value();
1793     t -= (seconds * NANOS_PER_SEC) + nanos;
1794   }
1795
1796   Local<Array> tuple = Array::New(2);
1797   tuple->Set(0, Integer::NewFromUnsigned(t / NANOS_PER_SEC, node_isolate));
1798   tuple->Set(1, Integer::NewFromUnsigned(t % NANOS_PER_SEC, node_isolate));
1799   args.GetReturnValue().Set(tuple);
1800 }
1801
1802
1803 typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
1804
1805 // DLOpen is process.dlopen(module, filename).
1806 // Used to load 'module.node' dynamically shared objects.
1807 //
1808 // FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
1809 // when two contexts try to load the same shared object. Maybe have a shadow
1810 // cache that's a plain C list or hash table that's shared across contexts?
1811 void DLOpen(const FunctionCallbackInfo<Value>& args) {
1812   Environment* env = Environment::GetCurrent(args.GetIsolate());
1813   HandleScope handle_scope(args.GetIsolate());
1814   char symbol[1024], *base, *pos;
1815   uv_lib_t lib;
1816   int r;
1817
1818   if (args.Length() < 2) {
1819     return ThrowError("process.dlopen takes exactly 2 arguments.");
1820   }
1821
1822   Local<Object> module = args[0]->ToObject();  // Cast
1823   String::Utf8Value filename(args[1]);  // Cast
1824
1825   Local<String> exports_string = env->exports_string();
1826   Local<Object> exports = module->Get(exports_string)->ToObject();
1827
1828   if (uv_dlopen(*filename, &lib)) {
1829     Local<String> errmsg = OneByteString(env->isolate(), uv_dlerror(&lib));
1830 #ifdef _WIN32
1831     // Windows needs to add the filename into the error message
1832     errmsg = String::Concat(errmsg, args[1]->ToString());
1833 #endif  // _WIN32
1834     ThrowException(Exception::Error(errmsg));
1835     return;
1836   }
1837
1838   String::Utf8Value path(args[1]);
1839   base = *path;
1840
1841   /* Find the shared library filename within the full path. */
1842 #ifdef __POSIX__
1843   pos = strrchr(base, '/');
1844   if (pos != NULL) {
1845     base = pos + 1;
1846   }
1847 #else  // Windows
1848   for (;;) {
1849     pos = strpbrk(base, "\\/:");
1850     if (pos == NULL) {
1851       break;
1852     }
1853     base = pos + 1;
1854   }
1855 #endif  // __POSIX__
1856
1857   /* Strip the .node extension. */
1858   pos = strrchr(base, '.');
1859   if (pos != NULL) {
1860     *pos = '\0';
1861   }
1862
1863   /* Add the `_module` suffix to the extension name. */
1864   r = snprintf(symbol, sizeof symbol, "%s_module", base);
1865   if (r <= 0 || static_cast<size_t>(r) >= sizeof symbol) {
1866     return ThrowError("Out of memory.");
1867   }
1868
1869   /* Replace dashes with underscores. When loading foo-bar.node,
1870    * look for foo_bar_module, not foo-bar_module.
1871    */
1872   for (pos = symbol; *pos != '\0'; ++pos) {
1873     if (*pos == '-') *pos = '_';
1874   }
1875
1876   node_module_struct *mod;
1877   if (uv_dlsym(&lib, symbol, reinterpret_cast<void**>(&mod))) {
1878     char errmsg[1024];
1879     snprintf(errmsg, sizeof(errmsg), "Symbol %s not found.", symbol);
1880     return ThrowError(errmsg);
1881   }
1882
1883   if (mod->version != NODE_MODULE_VERSION) {
1884     char errmsg[1024];
1885     snprintf(errmsg,
1886              sizeof(errmsg),
1887              "Module version mismatch. Expected %d, got %d.",
1888              NODE_MODULE_VERSION, mod->version);
1889     return ThrowError(errmsg);
1890   }
1891
1892   // Execute the C++ module
1893   if (mod->register_context_func != NULL) {
1894     mod->register_context_func(exports, module, env->context());
1895   } else if (mod->register_func != NULL) {
1896     mod->register_func(exports, module);
1897   } else {
1898     return ThrowError("Module has no declared entry point.");
1899   }
1900
1901   // Tell coverity that 'handle' should not be freed when we return.
1902   // coverity[leaked_storage]
1903 }
1904
1905
1906 static void OnFatalError(const char* location, const char* message) {
1907   if (location) {
1908     fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
1909   } else {
1910     fprintf(stderr, "FATAL ERROR: %s\n", message);
1911   }
1912   fflush(stderr);
1913 #if defined(DEBUG)
1914   abort();
1915 #endif
1916   exit(5);
1917 }
1918
1919
1920 NO_RETURN void FatalError(const char* location, const char* message) {
1921   OnFatalError(location, message);
1922   // to supress compiler warning
1923   abort();
1924 }
1925
1926
1927 void FatalException(Handle<Value> error, Handle<Message> message) {
1928   HandleScope scope(node_isolate);
1929
1930   Environment* env = Environment::GetCurrent(node_isolate);
1931   Local<Object> process_object = env->process_object();
1932   Local<String> fatal_exception_string = env->fatal_exception_string();
1933   Local<Function> fatal_exception_function =
1934       process_object->Get(fatal_exception_string).As<Function>();
1935
1936   if (!fatal_exception_function->IsFunction()) {
1937     // failed before the process._fatalException function was added!
1938     // this is probably pretty bad.  Nothing to do but report and exit.
1939     ReportException(error, message);
1940     exit(6);
1941   }
1942
1943   TryCatch fatal_try_catch;
1944
1945   // Do not call FatalException when _fatalException handler throws
1946   fatal_try_catch.SetVerbose(false);
1947
1948   // this will return true if the JS layer handled it, false otherwise
1949   Local<Value> caught =
1950       fatal_exception_function->Call(process_object, 1, &error);
1951
1952   if (fatal_try_catch.HasCaught()) {
1953     // the fatal exception function threw, so we must exit
1954     ReportException(fatal_try_catch);
1955     exit(7);
1956   }
1957
1958   if (false == caught->BooleanValue()) {
1959     ReportException(error, message);
1960     exit(8);
1961   }
1962 }
1963
1964
1965 void FatalException(const TryCatch& try_catch) {
1966   HandleScope scope(node_isolate);
1967   // TODO(bajtos) do not call FatalException if try_catch is verbose
1968   // (requires V8 API to expose getter for try_catch.is_verbose_)
1969   FatalException(try_catch.Exception(), try_catch.Message());
1970 }
1971
1972
1973 void OnMessage(Handle<Message> message, Handle<Value> error) {
1974   // The current version of V8 sends messages for errors only
1975   // (thus `error` is always set).
1976   FatalException(error, message);
1977 }
1978
1979
1980 static void Binding(const FunctionCallbackInfo<Value>& args) {
1981   Environment* env = Environment::GetCurrent(args.GetIsolate());
1982   HandleScope handle_scope(args.GetIsolate());
1983
1984   Local<String> module = args[0]->ToString();
1985   String::Utf8Value module_v(module);
1986
1987   Local<Object> cache = env->binding_cache_object();
1988   Local<Object> exports;
1989
1990   if (cache->Has(module)) {
1991     exports = cache->Get(module)->ToObject();
1992     args.GetReturnValue().Set(exports);
1993     return;
1994   }
1995
1996   // Append a string to process.moduleLoadList
1997   char buf[1024];
1998   snprintf(buf, sizeof(buf), "Binding %s", *module_v);
1999
2000   Local<Array> modules = env->module_load_list_array();
2001   uint32_t l = modules->Length();
2002   modules->Set(l, OneByteString(node_isolate, buf));
2003
2004   node_module_struct* mod = get_builtin_module(*module_v);
2005   if (mod != NULL) {
2006     exports = Object::New();
2007     // Internal bindings don't have a "module" object, only exports.
2008     assert(mod->register_func == NULL);
2009     assert(mod->register_context_func != NULL);
2010     Local<Value> unused = Undefined(env->isolate());
2011     mod->register_context_func(exports, unused, env->context());
2012     cache->Set(module, exports);
2013   } else if (!strcmp(*module_v, "constants")) {
2014     exports = Object::New();
2015     DefineConstants(exports);
2016     cache->Set(module, exports);
2017   } else if (!strcmp(*module_v, "natives")) {
2018     exports = Object::New();
2019     DefineJavaScript(exports);
2020     cache->Set(module, exports);
2021   } else {
2022     return ThrowError("No such module");
2023   }
2024
2025   args.GetReturnValue().Set(exports);
2026 }
2027
2028
2029 static void ProcessTitleGetter(Local<String> property,
2030                                const PropertyCallbackInfo<Value>& info) {
2031   HandleScope scope(node_isolate);
2032   char buffer[512];
2033   uv_get_process_title(buffer, sizeof(buffer));
2034   info.GetReturnValue().Set(String::NewFromUtf8(node_isolate, buffer));
2035 }
2036
2037
2038 static void ProcessTitleSetter(Local<String> property,
2039                                Local<Value> value,
2040                                const PropertyCallbackInfo<void>& info) {
2041   HandleScope scope(node_isolate);
2042   String::Utf8Value title(value);
2043   // TODO(piscisaureus): protect with a lock
2044   uv_set_process_title(*title);
2045 }
2046
2047
2048 static void EnvGetter(Local<String> property,
2049                       const PropertyCallbackInfo<Value>& info) {
2050   HandleScope scope(node_isolate);
2051 #ifdef __POSIX__
2052   String::Utf8Value key(property);
2053   const char* val = getenv(*key);
2054   if (val) {
2055     return info.GetReturnValue().Set(String::NewFromUtf8(node_isolate, val));
2056   }
2057 #else  // _WIN32
2058   String::Value key(property);
2059   WCHAR buffer[32767];  // The maximum size allowed for environment variables.
2060   DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
2061                                          buffer,
2062                                          ARRAY_SIZE(buffer));
2063   // If result >= sizeof buffer the buffer was too small. That should never
2064   // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
2065   // not found.
2066   if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
2067       result < ARRAY_SIZE(buffer)) {
2068     const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
2069     Local<String> rc = String::NewFromTwoByte(node_isolate, two_byte_buffer);
2070     return info.GetReturnValue().Set(rc);
2071   }
2072 #endif
2073   // Not found.  Fetch from prototype.
2074   info.GetReturnValue().Set(
2075       info.Data().As<Object>()->Get(property));
2076 }
2077
2078
2079 static void EnvSetter(Local<String> property,
2080                       Local<Value> value,
2081                       const PropertyCallbackInfo<Value>& info) {
2082   HandleScope scope(node_isolate);
2083 #ifdef __POSIX__
2084   String::Utf8Value key(property);
2085   String::Utf8Value val(value);
2086   setenv(*key, *val, 1);
2087 #else  // _WIN32
2088   String::Value key(property);
2089   String::Value val(value);
2090   WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2091   // Environment variables that start with '=' are read-only.
2092   if (key_ptr[0] != L'=') {
2093     SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
2094   }
2095 #endif
2096   // Whether it worked or not, always return rval.
2097   info.GetReturnValue().Set(value);
2098 }
2099
2100
2101 static void EnvQuery(Local<String> property,
2102                      const PropertyCallbackInfo<Integer>& info) {
2103   HandleScope scope(node_isolate);
2104   int32_t rc = -1;  // Not found unless proven otherwise.
2105 #ifdef __POSIX__
2106   String::Utf8Value key(property);
2107   if (getenv(*key)) rc = 0;
2108 #else  // _WIN32
2109   String::Value key(property);
2110   WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2111   if (GetEnvironmentVariableW(key_ptr, NULL, 0) > 0 ||
2112       GetLastError() == ERROR_SUCCESS) {
2113     rc = 0;
2114     if (key_ptr[0] == L'=') {
2115       // Environment variables that start with '=' are hidden and read-only.
2116       rc = static_cast<int32_t>(v8::ReadOnly) |
2117            static_cast<int32_t>(v8::DontDelete) |
2118            static_cast<int32_t>(v8::DontEnum);
2119     }
2120   }
2121 #endif
2122   if (rc != -1) info.GetReturnValue().Set(rc);
2123 }
2124
2125
2126 static void EnvDeleter(Local<String> property,
2127                        const PropertyCallbackInfo<Boolean>& info) {
2128   HandleScope scope(node_isolate);
2129   bool rc = true;
2130 #ifdef __POSIX__
2131   String::Utf8Value key(property);
2132   rc = getenv(*key) != NULL;
2133   if (rc) unsetenv(*key);
2134 #else
2135   String::Value key(property);
2136   WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2137   if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, NULL)) {
2138     // Deletion failed. Return true if the key wasn't there in the first place,
2139     // false if it is still there.
2140     rc = GetEnvironmentVariableW(key_ptr, NULL, NULL) == 0 &&
2141          GetLastError() != ERROR_SUCCESS;
2142   }
2143 #endif
2144   info.GetReturnValue().Set(rc);
2145 }
2146
2147
2148 static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
2149   HandleScope scope(node_isolate);
2150 #ifdef __POSIX__
2151   int size = 0;
2152   while (environ[size]) size++;
2153
2154   Local<Array> env = Array::New(size);
2155
2156   for (int i = 0; i < size; ++i) {
2157     const char* var = environ[i];
2158     const char* s = strchr(var, '=');
2159     const int length = s ? s - var : strlen(var);
2160     Local<String> name = String::NewFromUtf8(node_isolate,
2161                                              var,
2162                                              String::kNormalString,
2163                                              length);
2164     env->Set(i, name);
2165   }
2166 #else  // _WIN32
2167   WCHAR* environment = GetEnvironmentStringsW();
2168   if (environment == NULL) return;  // This should not happen.
2169   Local<Array> env = Array::New();
2170   WCHAR* p = environment;
2171   int i = 0;
2172   while (*p != NULL) {
2173     WCHAR *s;
2174     if (*p == L'=') {
2175       // If the key starts with '=' it is a hidden environment variable.
2176       p += wcslen(p) + 1;
2177       continue;
2178     } else {
2179       s = wcschr(p, L'=');
2180     }
2181     if (!s) {
2182       s = p + wcslen(p);
2183     }
2184     const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
2185     const size_t two_byte_buffer_len = s - p;
2186     Local<String> value = String::NewFromTwoByte(node_isolate,
2187                                                  two_byte_buffer,
2188                                                  String::kNormalString,
2189                                                  two_byte_buffer_len);
2190     env->Set(i++, value);
2191     p = s + wcslen(s) + 1;
2192   }
2193   FreeEnvironmentStringsW(environment);
2194 #endif
2195
2196   info.GetReturnValue().Set(env);
2197 }
2198
2199
2200 static Handle<Object> GetFeatures() {
2201   HandleScope scope(node_isolate);
2202
2203   Local<Object> obj = Object::New();
2204 #if defined(DEBUG) && DEBUG
2205   Local<Value> debug = True(node_isolate);
2206 #else
2207   Local<Value> debug = False(node_isolate);
2208 #endif  // defined(DEBUG) && DEBUG
2209
2210   obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "debug"), debug);
2211
2212   obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "uv"), True(node_isolate));
2213   // TODO(bnoordhuis) ping libuv
2214   obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "ipv6"), True(node_isolate));
2215
2216 #ifdef OPENSSL_NPN_NEGOTIATED
2217   Local<Boolean> tls_npn = True(node_isolate);
2218 #else
2219   Local<Boolean> tls_npn = False(node_isolate);
2220 #endif
2221   obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "tls_npn"), tls_npn);
2222
2223 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
2224   Local<Boolean> tls_sni = True(node_isolate);
2225 #else
2226   Local<Boolean> tls_sni = False(node_isolate);
2227 #endif
2228   obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "tls_sni"), tls_sni);
2229
2230   obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "tls"),
2231            Boolean::New(get_builtin_module("crypto") != NULL));
2232
2233   return scope.Close(obj);
2234 }
2235
2236
2237 static void DebugPortGetter(Local<String> property,
2238                             const PropertyCallbackInfo<Value>& info) {
2239   HandleScope scope(node_isolate);
2240   info.GetReturnValue().Set(debug_port);
2241 }
2242
2243
2244 static void DebugPortSetter(Local<String> property,
2245                             Local<Value> value,
2246                             const PropertyCallbackInfo<void>& info) {
2247   HandleScope scope(node_isolate);
2248   debug_port = value->NumberValue();
2249 }
2250
2251
2252 static void DebugProcess(const FunctionCallbackInfo<Value>& args);
2253 static void DebugPause(const FunctionCallbackInfo<Value>& args);
2254 static void DebugEnd(const FunctionCallbackInfo<Value>& args);
2255
2256
2257 void NeedImmediateCallbackGetter(Local<String> property,
2258                                  const PropertyCallbackInfo<Value>& info) {
2259   Environment* env = Environment::GetCurrent(info.GetIsolate());
2260   const uv_check_t* immediate_check_handle = env->immediate_check_handle();
2261   bool active = uv_is_active(
2262       reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2263   info.GetReturnValue().Set(active);
2264 }
2265
2266
2267 static void NeedImmediateCallbackSetter(
2268     Local<String> property,
2269     Local<Value> value,
2270     const PropertyCallbackInfo<void>& info) {
2271   Environment* env = Environment::GetCurrent(info.GetIsolate());
2272   HandleScope handle_scope(info.GetIsolate());
2273
2274   uv_check_t* immediate_check_handle = env->immediate_check_handle();
2275   bool active = uv_is_active(
2276       reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2277
2278   if (active == value->BooleanValue())
2279     return;
2280
2281   uv_idle_t* immediate_idle_handle = env->immediate_idle_handle();
2282
2283   if (active) {
2284     uv_check_stop(immediate_check_handle);
2285     uv_idle_stop(immediate_idle_handle);
2286   } else {
2287     uv_check_start(immediate_check_handle, CheckImmediate);
2288     // Idle handle is needed only to stop the event loop from blocking in poll.
2289     uv_idle_start(immediate_idle_handle, IdleImmediateDummy);
2290   }
2291 }
2292
2293
2294 #define READONLY_PROPERTY(obj, str, var)                                      \
2295   do {                                                                        \
2296     obj->Set(OneByteString(node_isolate, str), var, v8::ReadOnly);            \
2297   } while (0)
2298
2299
2300 void SetupProcessObject(Environment* env,
2301                         int argc,
2302                         const char* const* argv,
2303                         int exec_argc,
2304                         const char* const* exec_argv) {
2305   HandleScope scope(node_isolate);
2306   int i, j;
2307
2308   Local<Object> process = env->process_object();
2309
2310   process->SetAccessor(FIXED_ONE_BYTE_STRING(node_isolate, "title"),
2311                        ProcessTitleGetter,
2312                        ProcessTitleSetter);
2313
2314   // process.version
2315   READONLY_PROPERTY(process,
2316                     "version",
2317                     FIXED_ONE_BYTE_STRING(node_isolate, NODE_VERSION));
2318
2319   // process.moduleLoadList
2320   READONLY_PROPERTY(process,
2321                     "moduleLoadList",
2322                     env->module_load_list_array());
2323
2324   // process.versions
2325   Local<Object> versions = Object::New();
2326   READONLY_PROPERTY(process, "versions", versions);
2327
2328   const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
2329                                      "."
2330                                      NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR);
2331   READONLY_PROPERTY(versions,
2332                     "http_parser",
2333                     FIXED_ONE_BYTE_STRING(node_isolate, http_parser_version));
2334
2335   // +1 to get rid of the leading 'v'
2336   READONLY_PROPERTY(versions,
2337                     "node",
2338                     OneByteString(node_isolate, NODE_VERSION + 1));
2339   READONLY_PROPERTY(versions,
2340                     "v8",
2341                     OneByteString(node_isolate, V8::GetVersion()));
2342   READONLY_PROPERTY(versions,
2343                     "uv",
2344                     OneByteString(node_isolate, uv_version_string()));
2345   READONLY_PROPERTY(versions,
2346                     "zlib",
2347                     FIXED_ONE_BYTE_STRING(node_isolate, ZLIB_VERSION));
2348
2349   const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
2350   READONLY_PROPERTY(versions,
2351                     "modules",
2352                     FIXED_ONE_BYTE_STRING(node_isolate, node_modules_version));
2353
2354 #if HAVE_OPENSSL
2355   // Stupid code to slice out the version string.
2356   int c, l = strlen(OPENSSL_VERSION_TEXT);
2357   for (i = j = 0; i < l; i++) {
2358     c = OPENSSL_VERSION_TEXT[i];
2359     if ('0' <= c && c <= '9') {
2360       for (j = i + 1; j < l; j++) {
2361         c = OPENSSL_VERSION_TEXT[j];
2362         if (c == ' ') break;
2363       }
2364       break;
2365     }
2366   }
2367   READONLY_PROPERTY(
2368       versions,
2369       "openssl",
2370       OneByteString(node_isolate, &OPENSSL_VERSION_TEXT[i], j - i));
2371 #endif
2372
2373   // process.arch
2374   READONLY_PROPERTY(process, "arch", OneByteString(node_isolate, ARCH));
2375
2376   // process.platform
2377   READONLY_PROPERTY(process,
2378                     "platform",
2379                     OneByteString(node_isolate, PLATFORM));
2380
2381   // process.argv
2382   Local<Array> arguments = Array::New(argc);
2383   for (int i = 0; i < argc; ++i) {
2384     arguments->Set(i, String::NewFromUtf8(node_isolate, argv[i]));
2385   }
2386   process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "argv"), arguments);
2387
2388   // process.execArgv
2389   Local<Array> exec_arguments = Array::New(exec_argc);
2390   for (int i = 0; i < exec_argc; ++i) {
2391     exec_arguments->Set(i, String::NewFromUtf8(node_isolate, exec_argv[i]));
2392   }
2393   process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "execArgv"), exec_arguments);
2394
2395   // create process.env
2396   Local<ObjectTemplate> process_env_template = ObjectTemplate::New();
2397   process_env_template->SetNamedPropertyHandler(EnvGetter,
2398                                                 EnvSetter,
2399                                                 EnvQuery,
2400                                                 EnvDeleter,
2401                                                 EnvEnumerator,
2402                                                 Object::New());
2403   Local<Object> process_env = process_env_template->NewInstance();
2404   process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "env"), process_env);
2405
2406   READONLY_PROPERTY(process, "pid", Integer::New(getpid(), node_isolate));
2407   READONLY_PROPERTY(process, "features", GetFeatures());
2408   process->SetAccessor(
2409       FIXED_ONE_BYTE_STRING(node_isolate, "_needImmediateCallback"),
2410       NeedImmediateCallbackGetter,
2411       NeedImmediateCallbackSetter);
2412
2413   // -e, --eval
2414   if (eval_string) {
2415     READONLY_PROPERTY(process,
2416                       "_eval",
2417                       String::NewFromUtf8(node_isolate, eval_string));
2418   }
2419
2420   // -p, --print
2421   if (print_eval) {
2422     READONLY_PROPERTY(process, "_print_eval", True(node_isolate));
2423   }
2424
2425   // -i, --interactive
2426   if (force_repl) {
2427     READONLY_PROPERTY(process, "_forceRepl", True(node_isolate));
2428   }
2429
2430   // --no-deprecation
2431   if (no_deprecation) {
2432     READONLY_PROPERTY(process, "noDeprecation", True(node_isolate));
2433   }
2434
2435   // --throw-deprecation
2436   if (throw_deprecation) {
2437     READONLY_PROPERTY(process, "throwDeprecation", True(node_isolate));
2438   }
2439
2440   // --trace-deprecation
2441   if (trace_deprecation) {
2442     READONLY_PROPERTY(process, "traceDeprecation", True(node_isolate));
2443   }
2444
2445   size_t exec_path_len = 2 * PATH_MAX;
2446   char* exec_path = new char[exec_path_len];
2447   Local<String> exec_path_value;
2448   if (uv_exepath(exec_path, &exec_path_len) == 0) {
2449     exec_path_value = String::NewFromUtf8(node_isolate,
2450                                           exec_path,
2451                                           String::kNormalString,
2452                                           exec_path_len);
2453   } else {
2454     exec_path_value = String::NewFromUtf8(node_isolate, argv[0]);
2455   }
2456   process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "execPath"),
2457                exec_path_value);
2458   delete[] exec_path;
2459
2460   process->SetAccessor(FIXED_ONE_BYTE_STRING(node_isolate, "debugPort"),
2461                        DebugPortGetter,
2462                        DebugPortSetter);
2463
2464   // define various internal methods
2465   NODE_SET_METHOD(process, "_getActiveRequests", GetActiveRequests);
2466   NODE_SET_METHOD(process, "_getActiveHandles", GetActiveHandles);
2467   NODE_SET_METHOD(process, "reallyExit", Exit);
2468   NODE_SET_METHOD(process, "abort", Abort);
2469   NODE_SET_METHOD(process, "chdir", Chdir);
2470   NODE_SET_METHOD(process, "cwd", Cwd);
2471
2472   NODE_SET_METHOD(process, "umask", Umask);
2473
2474 #if defined(__POSIX__) && !defined(__ANDROID__)
2475   NODE_SET_METHOD(process, "getuid", GetUid);
2476   NODE_SET_METHOD(process, "setuid", SetUid);
2477
2478   NODE_SET_METHOD(process, "setgid", SetGid);
2479   NODE_SET_METHOD(process, "getgid", GetGid);
2480
2481   NODE_SET_METHOD(process, "getgroups", GetGroups);
2482   NODE_SET_METHOD(process, "setgroups", SetGroups);
2483   NODE_SET_METHOD(process, "initgroups", InitGroups);
2484 #endif  // __POSIX__ && !defined(__ANDROID__)
2485
2486   NODE_SET_METHOD(process, "_kill", Kill);
2487
2488   NODE_SET_METHOD(process, "_debugProcess", DebugProcess);
2489   NODE_SET_METHOD(process, "_debugPause", DebugPause);
2490   NODE_SET_METHOD(process, "_debugEnd", DebugEnd);
2491
2492   NODE_SET_METHOD(process, "hrtime", Hrtime);
2493
2494   NODE_SET_METHOD(process, "dlopen", DLOpen);
2495
2496   NODE_SET_METHOD(process, "uptime", Uptime);
2497   NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
2498
2499   NODE_SET_METHOD(process, "binding", Binding);
2500
2501   NODE_SET_METHOD(process, "_setupDomainUse", SetupDomainUse);
2502
2503   // values use to cross communicate with processNextTick
2504   Local<Object> tick_info_obj = Object::New();
2505   tick_info_obj->SetIndexedPropertiesToExternalArrayData(
2506       env->tick_info()->fields(),
2507       kExternalUnsignedIntArray,
2508       env->tick_info()->fields_count());
2509   process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_tickInfo"), tick_info_obj);
2510
2511   // pre-set _events object for faster emit checks
2512   process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_events"), Object::New());
2513 }
2514
2515
2516 #undef READONLY_PROPERTY
2517
2518
2519 static void AtExit() {
2520   uv_tty_reset_mode();
2521 }
2522
2523
2524 static void SignalExit(int signal) {
2525   uv_tty_reset_mode();
2526   _exit(128 + signal);
2527 }
2528
2529
2530 // Most of the time, it's best to use `console.error` to write
2531 // to the process.stderr stream.  However, in some cases, such as
2532 // when debugging the stream.Writable class or the process.nextTick
2533 // function, it is useful to bypass JavaScript entirely.
2534 static void RawDebug(const FunctionCallbackInfo<Value>& args) {
2535   HandleScope scope(node_isolate);
2536
2537   assert(args.Length() == 1 && args[0]->IsString() &&
2538          "must be called with a single string");
2539
2540   String::Utf8Value message(args[0]);
2541   fprintf(stderr, "%s\n", *message);
2542   fflush(stderr);
2543 }
2544
2545
2546 void Load(Environment* env) {
2547   HandleScope handle_scope(node_isolate);
2548
2549   // Compile, execute the src/node.js file. (Which was included as static C
2550   // string in node_natives.h. 'natve_node' is the string containing that
2551   // source code.)
2552
2553   // The node.js file returns a function 'f'
2554   atexit(AtExit);
2555
2556   TryCatch try_catch;
2557
2558   // Disable verbose mode to stop FatalException() handler from trying
2559   // to handle the exception. Errors this early in the start-up phase
2560   // are not safe to ignore.
2561   try_catch.SetVerbose(false);
2562
2563   Local<String> script_name = FIXED_ONE_BYTE_STRING(node_isolate, "node.js");
2564   Local<Value> f_value = ExecuteString(MainSource(), script_name);
2565   if (try_catch.HasCaught())  {
2566     ReportException(try_catch);
2567     exit(10);
2568   }
2569   assert(f_value->IsFunction());
2570   Local<Function> f = Local<Function>::Cast(f_value);
2571
2572   // Now we call 'f' with the 'process' variable that we've built up with
2573   // all our bindings. Inside node.js we'll take care of assigning things to
2574   // their places.
2575
2576   // We start the process this way in order to be more modular. Developers
2577   // who do not like how 'src/node.js' setups the module system but do like
2578   // Node's I/O bindings may want to replace 'f' with their own function.
2579
2580   // Add a reference to the global object
2581   Local<Object> global = env->context()->Global();
2582
2583 #if defined HAVE_DTRACE || defined HAVE_ETW || defined HAVE_SYSTEMTAP
2584   InitDTrace(global);
2585 #endif
2586
2587 #if defined HAVE_PERFCTR
2588   InitPerfCounters(global);
2589 #endif
2590
2591   // Enable handling of uncaught exceptions
2592   // (FatalException(), break on uncaught exception in debugger)
2593   //
2594   // This is not strictly necessary since it's almost impossible
2595   // to attach the debugger fast enought to break on exception
2596   // thrown during process startup.
2597   try_catch.SetVerbose(true);
2598
2599   NODE_SET_METHOD(env->process_object(), "_rawDebug", RawDebug);
2600
2601   Local<Value> arg = env->process_object();
2602   f->Call(global, 1, &arg);
2603 }
2604
2605 static void PrintHelp();
2606
2607 static void ParseDebugOpt(const char* arg) {
2608   const char *p = 0;
2609
2610   if (strstr(arg, "--debug-port=") == arg) {
2611     p = 1 + strchr(arg, '=');
2612     debug_port = atoi(p);
2613   } else {
2614     use_debug_agent = true;
2615     if (!strcmp(arg, "--debug-brk")) {
2616       debug_wait_connect = true;
2617       return;
2618     } else if (!strcmp(arg, "--debug")) {
2619       return;
2620     } else if (strstr(arg, "--debug-brk=") == arg) {
2621       debug_wait_connect = true;
2622       p = 1 + strchr(arg, '=');
2623       debug_port = atoi(p);
2624     } else if (strstr(arg, "--debug=") == arg) {
2625       p = 1 + strchr(arg, '=');
2626       debug_port = atoi(p);
2627     }
2628   }
2629   if (p && debug_port > 1024 && debug_port <  65536)
2630       return;
2631
2632   fprintf(stderr, "Bad debug option.\n");
2633   if (p) fprintf(stderr, "Debug port must be in range 1025 to 65535.\n");
2634
2635   PrintHelp();
2636   exit(12);
2637 }
2638
2639 static void PrintHelp() {
2640   printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
2641          "       node debug script.js [arguments] \n"
2642          "\n"
2643          "Options:\n"
2644          "  -v, --version        print node's version\n"
2645          "  -e, --eval script    evaluate script\n"
2646          "  -p, --print          evaluate script and print result\n"
2647          "  -i, --interactive    always enter the REPL even if stdin\n"
2648          "                       does not appear to be a terminal\n"
2649          "  --no-deprecation     silence deprecation warnings\n"
2650          "  --trace-deprecation  show stack traces on deprecations\n"
2651          "  --v8-options         print v8 command line options\n"
2652          "  --max-stack-size=val set max v8 stack size (bytes)\n"
2653          "\n"
2654          "Environment variables:\n"
2655 #ifdef _WIN32
2656          "NODE_PATH              ';'-separated list of directories\n"
2657 #else
2658          "NODE_PATH              ':'-separated list of directories\n"
2659 #endif
2660          "                       prefixed to the module search path.\n"
2661          "NODE_MODULE_CONTEXTS   Set to 1 to load modules in their own\n"
2662          "                       global contexts.\n"
2663          "NODE_DISABLE_COLORS    Set to 1 to disable colors in the REPL\n"
2664          "\n"
2665          "Documentation can be found at http://nodejs.org/\n");
2666 }
2667
2668
2669 // Parse command line arguments.
2670 //
2671 // argv is modified in place. exec_argv and v8_argv are out arguments that
2672 // ParseArgs() allocates memory for and stores a pointer to the output
2673 // vector in.  The caller should free them with delete[].
2674 //
2675 // On exit:
2676 //
2677 //  * argv contains the arguments with node and V8 options filtered out.
2678 //  * exec_argv contains both node and V8 options and nothing else.
2679 //  * v8_argv contains argv[0] plus any V8 options
2680 static void ParseArgs(int* argc,
2681                       const char** argv,
2682                       int* exec_argc,
2683                       const char*** exec_argv,
2684                       int* v8_argc,
2685                       const char*** v8_argv) {
2686   const unsigned int nargs = static_cast<unsigned int>(*argc);
2687   const char** new_exec_argv = new const char*[nargs];
2688   const char** new_v8_argv = new const char*[nargs];
2689   const char** new_argv = new const char*[nargs];
2690
2691   for (unsigned int i = 0; i < nargs; ++i) {
2692     new_exec_argv[i] = NULL;
2693     new_v8_argv[i] = NULL;
2694     new_argv[i] = NULL;
2695   }
2696
2697   // exec_argv starts with the first option, the other two start with argv[0].
2698   unsigned int new_exec_argc = 0;
2699   unsigned int new_v8_argc = 1;
2700   unsigned int new_argc = 1;
2701   new_v8_argv[0] = argv[0];
2702   new_argv[0] = argv[0];
2703
2704   unsigned int index = 1;
2705   while (index < nargs && argv[index][0] == '-') {
2706     const char* const arg = argv[index];
2707     unsigned int args_consumed = 1;
2708
2709     if (strstr(arg, "--debug") == arg) {
2710       ParseDebugOpt(arg);
2711     } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
2712       printf("%s\n", NODE_VERSION);
2713       exit(0);
2714     } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
2715       PrintHelp();
2716       exit(0);
2717     } else if (strcmp(arg, "--eval") == 0 ||
2718                strcmp(arg, "-e") == 0 ||
2719                strcmp(arg, "--print") == 0 ||
2720                strcmp(arg, "-pe") == 0 ||
2721                strcmp(arg, "-p") == 0) {
2722       bool is_eval = strchr(arg, 'e') != NULL;
2723       bool is_print = strchr(arg, 'p') != NULL;
2724       print_eval = print_eval || is_print;
2725       // --eval, -e and -pe always require an argument.
2726       if (is_eval == true) {
2727         args_consumed += 1;
2728         eval_string = argv[index + 1];
2729         if (eval_string == NULL) {
2730           fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
2731           exit(1);
2732         }
2733       } else if (argv[index + 1] != NULL && argv[index + 1][0] != '-') {
2734         args_consumed += 1;
2735         eval_string = argv[index + 1];
2736         if (strncmp(eval_string, "\\-", 2) == 0) {
2737           // Starts with "\\-": escaped expression, drop the backslash.
2738           eval_string += 1;
2739         }
2740       }
2741     } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
2742       force_repl = true;
2743     } else if (strcmp(arg, "--no-deprecation") == 0) {
2744       no_deprecation = true;
2745     } else if (strcmp(arg, "--trace-deprecation") == 0) {
2746       trace_deprecation = true;
2747     } else if (strcmp(arg, "--throw-deprecation") == 0) {
2748       throw_deprecation = true;
2749     } else if (strcmp(arg, "--v8-options") == 0) {
2750       new_v8_argv[new_v8_argc] = "--help";
2751       new_v8_argc += 1;
2752     } else {
2753       // V8 option.  Pass through as-is.
2754       new_v8_argv[new_v8_argc] = arg;
2755       new_v8_argc += 1;
2756     }
2757
2758     memcpy(new_exec_argv + new_exec_argc,
2759            argv + index,
2760            args_consumed * sizeof(*argv));
2761
2762     new_exec_argc += args_consumed;
2763     index += args_consumed;
2764   }
2765
2766   // Copy remaining arguments.
2767   const unsigned int args_left = nargs - index;
2768   memcpy(new_argv + new_argc, argv + index, args_left * sizeof(*argv));
2769   new_argc += args_left;
2770
2771   *exec_argc = new_exec_argc;
2772   *exec_argv = new_exec_argv;
2773   *v8_argc = new_v8_argc;
2774   *v8_argv = new_v8_argv;
2775
2776   // Copy new_argv over argv and update argc.
2777   memcpy(argv, new_argv, new_argc * sizeof(*argv));
2778   delete[] new_argv;
2779   *argc = static_cast<int>(new_argc);
2780 }
2781
2782
2783 // Called from the main thread.
2784 static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle, int status) {
2785   v8::Debug::ProcessDebugMessages();
2786 }
2787
2788
2789 // Called from V8 Debug Agent TCP thread.
2790 static void DispatchMessagesDebugAgentCallback() {
2791   uv_async_send(&dispatch_debug_messages_async);
2792 }
2793
2794
2795 // Called from the main thread
2796 static void EmitDebugEnabledAsyncCallback(uv_async_t* handle, int status) {
2797   Environment* env = Environment::GetCurrent(node_isolate);
2798   Context::Scope context_scope(env->context());
2799   HandleScope handle_scope(env->isolate());
2800   Local<Object> message = Object::New();
2801   message->Set(FIXED_ONE_BYTE_STRING(node_isolate, "cmd"),
2802                FIXED_ONE_BYTE_STRING(node_isolate, "NODE_DEBUG_ENABLED"));
2803   Local<Value> args[] = {
2804     FIXED_ONE_BYTE_STRING(node_isolate, "internalMessage"),
2805     message
2806   };
2807   MakeCallback(env, env->process_object(), "emit", ARRAY_SIZE(args), args);
2808 }
2809
2810
2811 // Called from the signal watcher callback
2812 static void EmitDebugEnabled() {
2813   uv_async_send(&emit_debug_enabled_async);
2814 }
2815
2816
2817 static void EnableDebug(bool wait_connect) {
2818   // If we're called from another thread, make sure to enter the right
2819   // v8 isolate.
2820   node_isolate->Enter();
2821
2822   v8::Debug::SetDebugMessageDispatchHandler(DispatchMessagesDebugAgentCallback,
2823                                             false);
2824
2825   // Start the debug thread and it's associated TCP server on port 5858.
2826   bool r = v8::Debug::EnableAgent("node " NODE_VERSION,
2827                                   debug_port,
2828                                   wait_connect);
2829
2830   // Crappy check that everything went well. FIXME
2831   assert(r);
2832
2833   // Print out some information.
2834   fprintf(stderr, "debugger listening on port %d\n", debug_port);
2835   fflush(stderr);
2836
2837   debugger_running = true;
2838
2839   if (Environment::GetCurrentChecked(node_isolate) != NULL) {
2840     EmitDebugEnabled();
2841   }
2842
2843   node_isolate->Exit();
2844 }
2845
2846
2847 #ifdef __POSIX__
2848 static void EnableDebugSignalHandler(uv_signal_t* handle, int) {
2849   // Break once process will return execution to v8
2850   v8::Debug::DebugBreak(node_isolate);
2851
2852   if (!debugger_running) {
2853     fprintf(stderr, "Hit SIGUSR1 - starting debugger agent.\n");
2854     EnableDebug(false);
2855   }
2856 }
2857
2858
2859 static void RegisterSignalHandler(int signal, void (*handler)(int signal)) {
2860   struct sigaction sa;
2861
2862   memset(&sa, 0, sizeof(sa));
2863   sa.sa_handler = handler;
2864   sigfillset(&sa.sa_mask);
2865   sigaction(signal, &sa, NULL);
2866 }
2867
2868
2869 void DebugProcess(const FunctionCallbackInfo<Value>& args) {
2870   HandleScope scope(node_isolate);
2871
2872   if (args.Length() != 1) {
2873     return ThrowError("Invalid number of arguments.");
2874   }
2875
2876   pid_t pid;
2877   int r;
2878
2879   pid = args[0]->IntegerValue();
2880   r = kill(pid, SIGUSR1);
2881   if (r != 0) {
2882     return ThrowErrnoException(errno, "kill");
2883   }
2884 }
2885 #endif  // __POSIX__
2886
2887
2888 #ifdef _WIN32
2889 DWORD WINAPI EnableDebugThreadProc(void* arg) {
2890   // Break once process will return execution to v8
2891   if (!debugger_running) {
2892     for (int i = 0; i < 1; i++) {
2893       fprintf(stderr, "Starting debugger agent.\r\n");
2894       fflush(stderr);
2895       EnableDebug(false);
2896     }
2897   }
2898
2899   v8::Debug::DebugBreak(node_isolate);
2900
2901   return 0;
2902 }
2903
2904
2905 static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
2906     size_t buf_len) {
2907   return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
2908 }
2909
2910
2911 static int RegisterDebugSignalHandler() {
2912   wchar_t mapping_name[32];
2913   HANDLE mapping_handle;
2914   DWORD pid;
2915   LPTHREAD_START_ROUTINE* handler;
2916
2917   pid = GetCurrentProcessId();
2918
2919   if (GetDebugSignalHandlerMappingName(pid,
2920                                        mapping_name,
2921                                        ARRAY_SIZE(mapping_name)) < 0) {
2922     return -1;
2923   }
2924
2925   mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
2926                                       NULL,
2927                                       PAGE_READWRITE,
2928                                       0,
2929                                       sizeof *handler,
2930                                       mapping_name);
2931   if (mapping_handle == NULL) {
2932     return -1;
2933   }
2934
2935   handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
2936       MapViewOfFile(mapping_handle,
2937                     FILE_MAP_ALL_ACCESS,
2938                     0,
2939                     0,
2940                     sizeof *handler));
2941   if (handler == NULL) {
2942     CloseHandle(mapping_handle);
2943     return -1;
2944   }
2945
2946   *handler = EnableDebugThreadProc;
2947
2948   UnmapViewOfFile(static_cast<void*>(handler));
2949
2950   return 0;
2951 }
2952
2953
2954 static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
2955   HandleScope scope(node_isolate);
2956   DWORD pid;
2957   HANDLE process = NULL;
2958   HANDLE thread = NULL;
2959   HANDLE mapping = NULL;
2960   wchar_t mapping_name[32];
2961   LPTHREAD_START_ROUTINE* handler = NULL;
2962
2963   if (args.Length() != 1) {
2964     ThrowError("Invalid number of arguments.");
2965     goto out;
2966   }
2967
2968   pid = (DWORD) args[0]->IntegerValue();
2969
2970   process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
2971                             PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
2972                             PROCESS_VM_READ,
2973                         FALSE,
2974                         pid);
2975   if (process == NULL) {
2976     ThrowException(WinapiErrnoException(GetLastError(), "OpenProcess"));
2977     goto out;
2978   }
2979
2980   if (GetDebugSignalHandlerMappingName(pid,
2981                                        mapping_name,
2982                                        ARRAY_SIZE(mapping_name)) < 0) {
2983     ThrowErrnoException(errno, "sprintf");
2984     goto out;
2985   }
2986
2987   mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
2988   if (mapping == NULL) {
2989     ThrowException(WinapiErrnoException(GetLastError(), "OpenFileMappingW"));
2990     goto out;
2991   }
2992
2993   handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
2994       MapViewOfFile(mapping,
2995                     FILE_MAP_READ,
2996                     0,
2997                     0,
2998                     sizeof *handler));
2999   if (handler == NULL || *handler == NULL) {
3000     ThrowException(WinapiErrnoException(GetLastError(), "MapViewOfFile"));
3001     goto out;
3002   }
3003
3004   thread = CreateRemoteThread(process,
3005                               NULL,
3006                               0,
3007                               *handler,
3008                               NULL,
3009                               0,
3010                               NULL);
3011   if (thread == NULL) {
3012     ThrowException(WinapiErrnoException(GetLastError(), "CreateRemoteThread"));
3013     goto out;
3014   }
3015
3016   // Wait for the thread to terminate
3017   if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
3018     ThrowException(WinapiErrnoException(GetLastError(), "WaitForSingleObject"));
3019     goto out;
3020   }
3021
3022  out:
3023   if (process != NULL)
3024     CloseHandle(process);
3025   if (thread != NULL)
3026     CloseHandle(thread);
3027   if (handler != NULL)
3028     UnmapViewOfFile(handler);
3029   if (mapping != NULL)
3030     CloseHandle(mapping);
3031 }
3032 #endif  // _WIN32
3033
3034
3035 static void DebugPause(const FunctionCallbackInfo<Value>& args) {
3036   v8::Debug::DebugBreak(node_isolate);
3037 }
3038
3039
3040 static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
3041   if (debugger_running) {
3042     v8::Debug::DisableAgent();
3043     debugger_running = false;
3044   }
3045 }
3046
3047
3048 void Init(int* argc,
3049           const char** argv,
3050           int* exec_argc,
3051           const char*** exec_argv) {
3052   // Initialize prog_start_time to get relative uptime.
3053   uv_uptime(&prog_start_time);
3054
3055   // Make inherited handles noninheritable.
3056   uv_disable_stdio_inheritance();
3057
3058   // init async debug messages dispatching
3059   // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
3060   uv_async_init(uv_default_loop(),
3061                 &dispatch_debug_messages_async,
3062                 DispatchDebugMessagesAsyncCallback);
3063   uv_unref(reinterpret_cast<uv_handle_t*>(&dispatch_debug_messages_async));
3064
3065   // init async NODE_DEBUG_ENABLED emitter
3066   // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
3067   uv_async_init(uv_default_loop(),
3068                 &emit_debug_enabled_async,
3069                 EmitDebugEnabledAsyncCallback);
3070   uv_unref(reinterpret_cast<uv_handle_t*>(&emit_debug_enabled_async));
3071
3072   // Parse a few arguments which are specific to Node.
3073   int v8_argc;
3074   const char** v8_argv;
3075   ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv);
3076
3077   // The const_cast doesn't violate conceptual const-ness.  V8 doesn't modify
3078   // the argv array or the elements it points to.
3079   V8::SetFlagsFromCommandLine(&v8_argc, const_cast<char**>(v8_argv), true);
3080
3081   // Anything that's still in v8_argv is not a V8 or a node option.
3082   for (int i = 1; i < v8_argc; i++) {
3083     fprintf(stderr, "%s: bad option: %s\n", argv[0], v8_argv[i]);
3084   }
3085   delete[] v8_argv;
3086   v8_argv = NULL;
3087
3088   if (v8_argc > 1) {
3089     exit(1);
3090   }
3091
3092   if (debug_wait_connect) {
3093     const char expose_debug_as[] = "--expose_debug_as=v8debug";
3094     V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1);
3095   }
3096
3097   const char typed_arrays_flag[] = "--harmony_typed_arrays";
3098   V8::SetFlagsFromString(typed_arrays_flag, sizeof(typed_arrays_flag) - 1);
3099   V8::SetArrayBufferAllocator(&ArrayBufferAllocator::the_singleton);
3100
3101   // Fetch a reference to the main isolate, so we have a reference to it
3102   // even when we need it to access it from another (debugger) thread.
3103   node_isolate = Isolate::GetCurrent();
3104
3105 #ifdef __POSIX__
3106   // Ignore SIGPIPE
3107   RegisterSignalHandler(SIGPIPE, SIG_IGN);
3108   RegisterSignalHandler(SIGINT, SignalExit);
3109   RegisterSignalHandler(SIGTERM, SignalExit);
3110 #endif  // __POSIX__
3111
3112   V8::SetFatalErrorHandler(node::OnFatalError);
3113   V8::AddMessageListener(OnMessage);
3114
3115   // If the --debug flag was specified then initialize the debug thread.
3116   if (use_debug_agent) {
3117     EnableDebug(debug_wait_connect);
3118   } else {
3119 #ifdef _WIN32
3120     RegisterDebugSignalHandler();
3121 #else  // Posix
3122     // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
3123     static uv_signal_t signal_watcher;
3124     uv_signal_init(uv_default_loop(), &signal_watcher);
3125     uv_signal_start(&signal_watcher, EnableDebugSignalHandler, SIGUSR1);
3126     uv_unref(reinterpret_cast<uv_handle_t*>(&signal_watcher));
3127 #endif  // __POSIX__
3128   }
3129 }
3130
3131
3132 struct AtExitCallback {
3133   AtExitCallback* next_;
3134   void (*cb_)(void* arg);
3135   void* arg_;
3136 };
3137
3138 static AtExitCallback* at_exit_functions_;
3139
3140
3141 // TODO(bnoordhuis) Turn into per-context event.
3142 void RunAtExit(Environment* env) {
3143   AtExitCallback* p = at_exit_functions_;
3144   at_exit_functions_ = NULL;
3145
3146   while (p) {
3147     AtExitCallback* q = p->next_;
3148     p->cb_(p->arg_);
3149     delete p;
3150     p = q;
3151   }
3152 }
3153
3154
3155 void AtExit(void (*cb)(void* arg), void* arg) {
3156   AtExitCallback* p = new AtExitCallback;
3157   p->cb_ = cb;
3158   p->arg_ = arg;
3159   p->next_ = at_exit_functions_;
3160   at_exit_functions_ = p;
3161 }
3162
3163
3164 void EmitExit(Environment* env) {
3165   // process.emit('exit')
3166   Context::Scope context_scope(env->context());
3167   HandleScope handle_scope(env->isolate());
3168   Local<Object> process_object = env->process_object();
3169   process_object->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_exiting"),
3170                       True(node_isolate));
3171
3172   Handle<String> exitCode = FIXED_ONE_BYTE_STRING(node_isolate, "exitCode");
3173   int code = process_object->Get(exitCode)->IntegerValue();
3174
3175   Local<Value> args[] = {
3176     FIXED_ONE_BYTE_STRING(node_isolate, "exit"),
3177     Integer::New(code, node_isolate)
3178   };
3179
3180   MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args);
3181   exit(code);
3182 }
3183
3184
3185 Environment* CreateEnvironment(Isolate* isolate,
3186                                int argc,
3187                                const char* const* argv,
3188                                int exec_argc,
3189                                const char* const* exec_argv) {
3190   HandleScope handle_scope(isolate);
3191
3192   Local<Context> context = Context::New(isolate);
3193   Context::Scope context_scope(context);
3194   Environment* env = Environment::New(context);
3195
3196   uv_check_init(env->event_loop(), env->immediate_check_handle());
3197   uv_unref(
3198       reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()));
3199   uv_idle_init(env->event_loop(), env->immediate_idle_handle());
3200
3201   Local<FunctionTemplate> process_template = FunctionTemplate::New();
3202   process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "process"));
3203
3204   Local<Object> process_object = process_template->GetFunction()->NewInstance();
3205   env->set_process_object(process_object);
3206
3207   SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
3208   Load(env);
3209
3210   return env;
3211 }
3212
3213
3214 int Start(int argc, char** argv) {
3215   assert(argc > 0);
3216
3217   // Hack around with the argv pointer. Used for process.title = "blah".
3218   argv = uv_setup_args(argc, argv);
3219
3220   // This needs to run *before* V8::Initialize().  The const_cast is not
3221   // optional, in case you're wondering.
3222   int exec_argc;
3223   const char** exec_argv;
3224   Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
3225
3226   V8::Initialize();
3227   {
3228     Locker locker(node_isolate);
3229     Environment* env =
3230         CreateEnvironment(node_isolate, argc, argv, exec_argc, exec_argv);
3231     Context::Scope context_scope(env->context());
3232     HandleScope handle_scope(env->isolate());
3233     uv_run(env->event_loop(), UV_RUN_DEFAULT);
3234     EmitExit(env);
3235     RunAtExit(env);
3236     env->Dispose();
3237     env = NULL;
3238   }
3239
3240 #ifndef NDEBUG
3241   // Clean up. Not strictly necessary.
3242   V8::Dispose();
3243 #endif  // NDEBUG
3244
3245   delete[] exec_argv;
3246   exec_argv = NULL;
3247
3248   return 0;
3249 }
3250
3251
3252 }  // namespace node