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