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