The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / src / node.cc @ 06810b29

History | View | Annotate | Download (73.3 KB)

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

    
34
#include <locale.h>
35
#include <signal.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#if !defined(_MSC_VER)
40
#include <strings.h>
41
#else
42
#define strcasecmp _stricmp
43
#endif
44
#include <limits.h> /* PATH_MAX */
45
#include <assert.h>
46
#if !defined(_MSC_VER)
47
#include <unistd.h> /* setuid, getuid */
48
#else
49
#include <direct.h>
50
#include <process.h>
51
#define getpid _getpid
52
#include <io.h>
53
#define umask _umask
54
typedef int mode_t;
55
#endif
56
#include <errno.h>
57
#include <sys/types.h>
58
#include "zlib.h"
59

    
60
#ifdef __POSIX__
61
# include <pwd.h> /* getpwnam() */
62
# include <grp.h> /* getgrnam() */
63
#endif
64

    
65
#include "node_buffer.h"
66
#include "node_file.h"
67
#include "node_http_parser.h"
68
#include "node_constants.h"
69
#include "node_javascript.h"
70
#include "node_version.h"
71
#include "node_string.h"
72
#if HAVE_OPENSSL
73
# include "node_crypto.h"
74
#endif
75
#if HAVE_SYSTEMTAP
76
#include "node_systemtap.h"
77
#endif
78
#include "node_script.h"
79
#include "v8_typed_array.h"
80

    
81
using namespace v8;
82

    
83
# ifdef __APPLE__
84
# include <crt_externs.h>
85
# define environ (*_NSGetEnviron())
86
# elif !defined(_MSC_VER)
87
extern char **environ;
88
# endif
89

    
90
namespace node {
91

    
92
ngx_queue_t handle_wrap_queue = { &handle_wrap_queue, &handle_wrap_queue };
93
ngx_queue_t req_wrap_queue = { &req_wrap_queue, &req_wrap_queue };
94

    
95
// declared in req_wrap.h
96
Persistent<String> process_symbol;
97
Persistent<String> domain_symbol;
98

    
99
static Persistent<Object> process;
100

    
101
static Persistent<String> errno_symbol;
102
static Persistent<String> syscall_symbol;
103
static Persistent<String> errpath_symbol;
104
static Persistent<String> code_symbol;
105

    
106
static Persistent<String> rss_symbol;
107
static Persistent<String> heap_total_symbol;
108
static Persistent<String> heap_used_symbol;
109

    
110
static Persistent<String> listeners_symbol;
111
static Persistent<String> uncaught_exception_symbol;
112
static Persistent<String> emit_symbol;
113

    
114
static Persistent<Function> process_makeCallback;
115

    
116

    
117
static bool print_eval = false;
118
static bool force_repl = false;
119
static bool trace_deprecation = false;
120
static char *eval_string = NULL;
121
static int option_end_index = 0;
122
static bool use_debug_agent = false;
123
static bool debug_wait_connect = false;
124
static int debug_port=5858;
125
static int max_stack_size = 0;
126

    
127
// used by C++ modules as well
128
bool no_deprecation = false;
129

    
130
static uv_idle_t tick_spinner;
131
static bool need_tick_cb;
132
static Persistent<String> tick_callback_sym;
133

    
134

    
135
#ifdef OPENSSL_NPN_NEGOTIATED
136
static bool use_npn = true;
137
#else
138
static bool use_npn = false;
139
#endif
140

    
141
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
142
static bool use_sni = true;
143
#else
144
static bool use_sni = false;
145
#endif
146

    
147
#ifdef __POSIX__
148
// Buffer for getpwnam_r(), getgrpam_r() and other misc callers; keep this
149
// scoped at file-level rather than method-level to avoid excess stack usage.
150
static char getbuf[PATH_MAX + 1];
151
#endif
152

    
153
// We need to notify V8 when we're idle so that it can run the garbage
154
// collector. The interface to this is V8::IdleNotification(). It returns
155
// true if the heap hasn't be fully compacted, and needs to be run again.
156
// Returning false means that it doesn't have anymore work to do.
157
//
158
// A rather convoluted algorithm has been devised to determine when Node is
159
// idle. You'll have to figure it out for yourself.
160
static uv_check_t gc_check;
161
static uv_idle_t gc_idle;
162
static uv_timer_t gc_timer;
163
bool need_gc;
164

    
165
// process-relative uptime base, initialized at start-up
166
static double prog_start_time;
167

    
168
#define FAST_TICK 700.
169
#define GC_WAIT_TIME 5000.
170
#define RPM_SAMPLES 100
171
#define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
172
static int64_t tick_times[RPM_SAMPLES];
173
static int tick_time_head;
174

    
175
static void CheckStatus(uv_timer_t* watcher, int status);
176

    
177
static void StartGCTimer () {
178
  if (!uv_is_active((uv_handle_t*) &gc_timer)) {
179
    uv_timer_start(&gc_timer, node::CheckStatus, 5000, 5000);
180
  }
181
}
182

    
183
static void StopGCTimer () {
184
  if (uv_is_active((uv_handle_t*) &gc_timer)) {
185
    uv_timer_stop(&gc_timer);
186
  }
187
}
188

    
189
static void Idle(uv_idle_t* watcher, int status) {
190
  assert((uv_idle_t*) watcher == &gc_idle);
191

    
192
  if (V8::IdleNotification()) {
193
    uv_idle_stop(&gc_idle);
194
    StopGCTimer();
195
  }
196
}
197

    
198

    
199
// Called directly after every call to select() (or epoll, or whatever)
200
static void Check(uv_check_t* watcher, int status) {
201
  assert(watcher == &gc_check);
202

    
203
  tick_times[tick_time_head] = uv_now(uv_default_loop());
204
  tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;
205

    
206
  StartGCTimer();
207

    
208
  for (int i = 0; i < (int)(GC_WAIT_TIME/FAST_TICK); i++) {
209
    double d = TICK_TIME(i+1) - TICK_TIME(i+2);
210
    //printf("d = %f\n", d);
211
    // If in the last 5 ticks the difference between
212
    // ticks was less than 0.7 seconds, then continue.
213
    if (d < FAST_TICK) {
214
      //printf("---\n");
215
      return;
216
    }
217
  }
218

    
219
  // Otherwise start the gc!
220

    
221
  //fprintf(stderr, "start idle 2\n");
222
  uv_idle_start(&gc_idle, node::Idle);
223
}
224

    
225

    
226
static void Tick(void) {
227
  // Avoid entering a V8 scope.
228
  if (!need_tick_cb) return;
229
  need_tick_cb = false;
230

    
231
  uv_idle_stop(&tick_spinner);
232

    
233
  HandleScope scope;
234

    
235
  if (tick_callback_sym.IsEmpty()) {
236
    // Lazily set the symbol
237
    tick_callback_sym = NODE_PSYMBOL("_tickCallback");
238
  }
239

    
240
  Local<Value> cb_v = process->Get(tick_callback_sym);
241
  if (!cb_v->IsFunction()) return;
242
  Local<Function> cb = Local<Function>::Cast(cb_v);
243

    
244
  TryCatch try_catch;
245

    
246
  // Let the tick callback know that this is coming from the spinner
247
  Handle<Value> argv[] = { True() };
248
  cb->Call(process, ARRAY_SIZE(argv), argv);
249

    
250
  if (try_catch.HasCaught()) {
251
    FatalException(try_catch);
252
  }
253
}
254

    
255

    
256
static void Spin(uv_idle_t* handle, int status) {
257
  assert((uv_idle_t*) handle == &tick_spinner);
258
  assert(status == 0);
259
  Tick();
260
}
261

    
262

    
263
static void StartTickSpinner() {
264
  need_tick_cb = true;
265
  // TODO: this tick_spinner shouldn't be necessary. An ev_prepare should be
266
  // sufficent, the problem is only in the case of the very last "tick" -
267
  // there is nothing left to do in the event loop and libev will exit. The
268
  // ev_prepare callback isn't called before exiting. Thus we start this
269
  // tick_spinner to keep the event loop alive long enough to handle it.
270
  uv_idle_start(&tick_spinner, Spin);
271
}
272

    
273

    
274
static Handle<Value> NeedTickCallback(const Arguments& args) {
275
  StartTickSpinner();
276
  return Undefined();
277
}
278

    
279

    
280
static inline const char *errno_string(int errorno) {
281
#define ERRNO_CASE(e)  case e: return #e;
282
  switch (errorno) {
283

    
284
#ifdef EACCES
285
  ERRNO_CASE(EACCES);
286
#endif
287

    
288
#ifdef EADDRINUSE
289
  ERRNO_CASE(EADDRINUSE);
290
#endif
291

    
292
#ifdef EADDRNOTAVAIL
293
  ERRNO_CASE(EADDRNOTAVAIL);
294
#endif
295

    
296
#ifdef EAFNOSUPPORT
297
  ERRNO_CASE(EAFNOSUPPORT);
298
#endif
299

    
300
#ifdef EAGAIN
301
  ERRNO_CASE(EAGAIN);
302
#endif
303

    
304
#ifdef EWOULDBLOCK
305
# if EAGAIN != EWOULDBLOCK
306
  ERRNO_CASE(EWOULDBLOCK);
307
# endif
308
#endif
309

    
310
#ifdef EALREADY
311
  ERRNO_CASE(EALREADY);
312
#endif
313

    
314
#ifdef EBADF
315
  ERRNO_CASE(EBADF);
316
#endif
317

    
318
#ifdef EBADMSG
319
  ERRNO_CASE(EBADMSG);
320
#endif
321

    
322
#ifdef EBUSY
323
  ERRNO_CASE(EBUSY);
324
#endif
325

    
326
#ifdef ECANCELED
327
  ERRNO_CASE(ECANCELED);
328
#endif
329

    
330
#ifdef ECHILD
331
  ERRNO_CASE(ECHILD);
332
#endif
333

    
334
#ifdef ECONNABORTED
335
  ERRNO_CASE(ECONNABORTED);
336
#endif
337

    
338
#ifdef ECONNREFUSED
339
  ERRNO_CASE(ECONNREFUSED);
340
#endif
341

    
342
#ifdef ECONNRESET
343
  ERRNO_CASE(ECONNRESET);
344
#endif
345

    
346
#ifdef EDEADLK
347
  ERRNO_CASE(EDEADLK);
348
#endif
349

    
350
#ifdef EDESTADDRREQ
351
  ERRNO_CASE(EDESTADDRREQ);
352
#endif
353

    
354
#ifdef EDOM
355
  ERRNO_CASE(EDOM);
356
#endif
357

    
358
#ifdef EDQUOT
359
  ERRNO_CASE(EDQUOT);
360
#endif
361

    
362
#ifdef EEXIST
363
  ERRNO_CASE(EEXIST);
364
#endif
365

    
366
#ifdef EFAULT
367
  ERRNO_CASE(EFAULT);
368
#endif
369

    
370
#ifdef EFBIG
371
  ERRNO_CASE(EFBIG);
372
#endif
373

    
374
#ifdef EHOSTUNREACH
375
  ERRNO_CASE(EHOSTUNREACH);
376
#endif
377

    
378
#ifdef EIDRM
379
  ERRNO_CASE(EIDRM);
380
#endif
381

    
382
#ifdef EILSEQ
383
  ERRNO_CASE(EILSEQ);
384
#endif
385

    
386
#ifdef EINPROGRESS
387
  ERRNO_CASE(EINPROGRESS);
388
#endif
389

    
390
#ifdef EINTR
391
  ERRNO_CASE(EINTR);
392
#endif
393

    
394
#ifdef EINVAL
395
  ERRNO_CASE(EINVAL);
396
#endif
397

    
398
#ifdef EIO
399
  ERRNO_CASE(EIO);
400
#endif
401

    
402
#ifdef EISCONN
403
  ERRNO_CASE(EISCONN);
404
#endif
405

    
406
#ifdef EISDIR
407
  ERRNO_CASE(EISDIR);
408
#endif
409

    
410
#ifdef ELOOP
411
  ERRNO_CASE(ELOOP);
412
#endif
413

    
414
#ifdef EMFILE
415
  ERRNO_CASE(EMFILE);
416
#endif
417

    
418
#ifdef EMLINK
419
  ERRNO_CASE(EMLINK);
420
#endif
421

    
422
#ifdef EMSGSIZE
423
  ERRNO_CASE(EMSGSIZE);
424
#endif
425

    
426
#ifdef EMULTIHOP
427
  ERRNO_CASE(EMULTIHOP);
428
#endif
429

    
430
#ifdef ENAMETOOLONG
431
  ERRNO_CASE(ENAMETOOLONG);
432
#endif
433

    
434
#ifdef ENETDOWN
435
  ERRNO_CASE(ENETDOWN);
436
#endif
437

    
438
#ifdef ENETRESET
439
  ERRNO_CASE(ENETRESET);
440
#endif
441

    
442
#ifdef ENETUNREACH
443
  ERRNO_CASE(ENETUNREACH);
444
#endif
445

    
446
#ifdef ENFILE
447
  ERRNO_CASE(ENFILE);
448
#endif
449

    
450
#ifdef ENOBUFS
451
  ERRNO_CASE(ENOBUFS);
452
#endif
453

    
454
#ifdef ENODATA
455
  ERRNO_CASE(ENODATA);
456
#endif
457

    
458
#ifdef ENODEV
459
  ERRNO_CASE(ENODEV);
460
#endif
461

    
462
#ifdef ENOENT
463
  ERRNO_CASE(ENOENT);
464
#endif
465

    
466
#ifdef ENOEXEC
467
  ERRNO_CASE(ENOEXEC);
468
#endif
469

    
470
#ifdef ENOLINK
471
  ERRNO_CASE(ENOLINK);
472
#endif
473

    
474
#ifdef ENOLCK
475
# if ENOLINK != ENOLCK
476
  ERRNO_CASE(ENOLCK);
477
# endif
478
#endif
479

    
480
#ifdef ENOMEM
481
  ERRNO_CASE(ENOMEM);
482
#endif
483

    
484
#ifdef ENOMSG
485
  ERRNO_CASE(ENOMSG);
486
#endif
487

    
488
#ifdef ENOPROTOOPT
489
  ERRNO_CASE(ENOPROTOOPT);
490
#endif
491

    
492
#ifdef ENOSPC
493
  ERRNO_CASE(ENOSPC);
494
#endif
495

    
496
#ifdef ENOSR
497
  ERRNO_CASE(ENOSR);
498
#endif
499

    
500
#ifdef ENOSTR
501
  ERRNO_CASE(ENOSTR);
502
#endif
503

    
504
#ifdef ENOSYS
505
  ERRNO_CASE(ENOSYS);
506
#endif
507

    
508
#ifdef ENOTCONN
509
  ERRNO_CASE(ENOTCONN);
510
#endif
511

    
512
#ifdef ENOTDIR
513
  ERRNO_CASE(ENOTDIR);
514
#endif
515

    
516
#ifdef ENOTEMPTY
517
  ERRNO_CASE(ENOTEMPTY);
518
#endif
519

    
520
#ifdef ENOTSOCK
521
  ERRNO_CASE(ENOTSOCK);
522
#endif
523

    
524
#ifdef ENOTSUP
525
  ERRNO_CASE(ENOTSUP);
526
#else
527
# ifdef EOPNOTSUPP
528
  ERRNO_CASE(EOPNOTSUPP);
529
# endif
530
#endif
531

    
532
#ifdef ENOTTY
533
  ERRNO_CASE(ENOTTY);
534
#endif
535

    
536
#ifdef ENXIO
537
  ERRNO_CASE(ENXIO);
538
#endif
539

    
540

    
541
#ifdef EOVERFLOW
542
  ERRNO_CASE(EOVERFLOW);
543
#endif
544

    
545
#ifdef EPERM
546
  ERRNO_CASE(EPERM);
547
#endif
548

    
549
#ifdef EPIPE
550
  ERRNO_CASE(EPIPE);
551
#endif
552

    
553
#ifdef EPROTO
554
  ERRNO_CASE(EPROTO);
555
#endif
556

    
557
#ifdef EPROTONOSUPPORT
558
  ERRNO_CASE(EPROTONOSUPPORT);
559
#endif
560

    
561
#ifdef EPROTOTYPE
562
  ERRNO_CASE(EPROTOTYPE);
563
#endif
564

    
565
#ifdef ERANGE
566
  ERRNO_CASE(ERANGE);
567
#endif
568

    
569
#ifdef EROFS
570
  ERRNO_CASE(EROFS);
571
#endif
572

    
573
#ifdef ESPIPE
574
  ERRNO_CASE(ESPIPE);
575
#endif
576

    
577
#ifdef ESRCH
578
  ERRNO_CASE(ESRCH);
579
#endif
580

    
581
#ifdef ESTALE
582
  ERRNO_CASE(ESTALE);
583
#endif
584

    
585
#ifdef ETIME
586
  ERRNO_CASE(ETIME);
587
#endif
588

    
589
#ifdef ETIMEDOUT
590
  ERRNO_CASE(ETIMEDOUT);
591
#endif
592

    
593
#ifdef ETXTBSY
594
  ERRNO_CASE(ETXTBSY);
595
#endif
596

    
597
#ifdef EXDEV
598
  ERRNO_CASE(EXDEV);
599
#endif
600

    
601
  default: return "";
602
  }
603
}
604

    
605
const char *signo_string(int signo) {
606
#define SIGNO_CASE(e)  case e: return #e;
607
  switch (signo) {
608

    
609
#ifdef SIGHUP
610
  SIGNO_CASE(SIGHUP);
611
#endif
612

    
613
#ifdef SIGINT
614
  SIGNO_CASE(SIGINT);
615
#endif
616

    
617
#ifdef SIGQUIT
618
  SIGNO_CASE(SIGQUIT);
619
#endif
620

    
621
#ifdef SIGILL
622
  SIGNO_CASE(SIGILL);
623
#endif
624

    
625
#ifdef SIGTRAP
626
  SIGNO_CASE(SIGTRAP);
627
#endif
628

    
629
#ifdef SIGABRT
630
  SIGNO_CASE(SIGABRT);
631
#endif
632

    
633
#ifdef SIGIOT
634
# if SIGABRT != SIGIOT
635
  SIGNO_CASE(SIGIOT);
636
# endif
637
#endif
638

    
639
#ifdef SIGBUS
640
  SIGNO_CASE(SIGBUS);
641
#endif
642

    
643
#ifdef SIGFPE
644
  SIGNO_CASE(SIGFPE);
645
#endif
646

    
647
#ifdef SIGKILL
648
  SIGNO_CASE(SIGKILL);
649
#endif
650

    
651
#ifdef SIGUSR1
652
  SIGNO_CASE(SIGUSR1);
653
#endif
654

    
655
#ifdef SIGSEGV
656
  SIGNO_CASE(SIGSEGV);
657
#endif
658

    
659
#ifdef SIGUSR2
660
  SIGNO_CASE(SIGUSR2);
661
#endif
662

    
663
#ifdef SIGPIPE
664
  SIGNO_CASE(SIGPIPE);
665
#endif
666

    
667
#ifdef SIGALRM
668
  SIGNO_CASE(SIGALRM);
669
#endif
670

    
671
  SIGNO_CASE(SIGTERM);
672

    
673
#ifdef SIGCHLD
674
  SIGNO_CASE(SIGCHLD);
675
#endif
676

    
677
#ifdef SIGSTKFLT
678
  SIGNO_CASE(SIGSTKFLT);
679
#endif
680

    
681

    
682
#ifdef SIGCONT
683
  SIGNO_CASE(SIGCONT);
684
#endif
685

    
686
#ifdef SIGSTOP
687
  SIGNO_CASE(SIGSTOP);
688
#endif
689

    
690
#ifdef SIGTSTP
691
  SIGNO_CASE(SIGTSTP);
692
#endif
693

    
694
#ifdef SIGBREAK
695
  SIGNO_CASE(SIGBREAK);
696
#endif
697

    
698
#ifdef SIGTTIN
699
  SIGNO_CASE(SIGTTIN);
700
#endif
701

    
702
#ifdef SIGTTOU
703
  SIGNO_CASE(SIGTTOU);
704
#endif
705

    
706
#ifdef SIGURG
707
  SIGNO_CASE(SIGURG);
708
#endif
709

    
710
#ifdef SIGXCPU
711
  SIGNO_CASE(SIGXCPU);
712
#endif
713

    
714
#ifdef SIGXFSZ
715
  SIGNO_CASE(SIGXFSZ);
716
#endif
717

    
718
#ifdef SIGVTALRM
719
  SIGNO_CASE(SIGVTALRM);
720
#endif
721

    
722
#ifdef SIGPROF
723
  SIGNO_CASE(SIGPROF);
724
#endif
725

    
726
#ifdef SIGWINCH
727
  SIGNO_CASE(SIGWINCH);
728
#endif
729

    
730
#ifdef SIGIO
731
  SIGNO_CASE(SIGIO);
732
#endif
733

    
734
#ifdef SIGPOLL
735
# if SIGPOLL != SIGIO
736
  SIGNO_CASE(SIGPOLL);
737
# endif
738
#endif
739

    
740
#ifdef SIGLOST
741
  SIGNO_CASE(SIGLOST);
742
#endif
743

    
744
#ifdef SIGPWR
745
# if SIGPWR != SIGLOST
746
  SIGNO_CASE(SIGPWR);
747
# endif
748
#endif
749

    
750
#ifdef SIGSYS
751
  SIGNO_CASE(SIGSYS);
752
#endif
753

    
754
  default: return "";
755
  }
756
}
757

    
758

    
759
Local<Value> ErrnoException(int errorno,
760
                            const char *syscall,
761
                            const char *msg,
762
                            const char *path) {
763
  Local<Value> e;
764
  Local<String> estring = String::NewSymbol(errno_string(errorno));
765
  if (!msg[0]) {
766
    msg = strerror(errorno);
767
  }
768
  Local<String> message = String::NewSymbol(msg);
769

    
770
  Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
771
  Local<String> cons2 = String::Concat(cons1, message);
772

    
773
  if (syscall_symbol.IsEmpty()) {
774
    syscall_symbol = NODE_PSYMBOL("syscall");
775
    errno_symbol = NODE_PSYMBOL("errno");
776
    errpath_symbol = NODE_PSYMBOL("path");
777
    code_symbol = NODE_PSYMBOL("code");
778
  }
779

    
780
  if (path) {
781
    Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
782
    Local<String> cons4 = String::Concat(cons3, String::New(path));
783
    Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
784
    e = Exception::Error(cons5);
785
  } else {
786
    e = Exception::Error(cons2);
787
  }
788

    
789
  Local<Object> obj = e->ToObject();
790

    
791
  obj->Set(errno_symbol, Integer::New(errorno));
792
  obj->Set(code_symbol, estring);
793
  if (path) obj->Set(errpath_symbol, String::New(path));
794
  if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
795
  return e;
796
}
797

    
798

    
799
static const char* get_uv_errno_string(int errorno) {
800
  uv_err_t err;
801
  memset(&err, 0, sizeof err);
802
  err.code = (uv_err_code)errorno;
803
  return uv_err_name(err);
804
}
805

    
806

    
807
static const char* get_uv_errno_message(int errorno) {
808
  uv_err_t err;
809
  memset(&err, 0, sizeof err);
810
  err.code = (uv_err_code)errorno;
811
  return uv_strerror(err);
812
}
813

    
814

    
815
// hack alert! copy of ErrnoException, tuned for uv errors
816
Local<Value> UVException(int errorno,
817
                         const char *syscall,
818
                         const char *msg,
819
                         const char *path) {
820
  if (syscall_symbol.IsEmpty()) {
821
    syscall_symbol = NODE_PSYMBOL("syscall");
822
    errno_symbol = NODE_PSYMBOL("errno");
823
    errpath_symbol = NODE_PSYMBOL("path");
824
    code_symbol = NODE_PSYMBOL("code");
825
  }
826

    
827
  if (!msg || !msg[0])
828
    msg = get_uv_errno_message(errorno);
829

    
830
  Local<String> estring = String::NewSymbol(get_uv_errno_string(errorno));
831
  Local<String> message = String::NewSymbol(msg);
832
  Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
833
  Local<String> cons2 = String::Concat(cons1, message);
834

    
835
  Local<Value> e;
836

    
837
  Local<String> path_str;
838

    
839
  if (path) {
840
#ifdef _WIN32
841
    if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
842
      path_str = String::Concat(String::New("\\\\"), String::New(path + 8));
843
    } else if (strncmp(path, "\\\\?\\", 4) == 0) {
844
      path_str = String::New(path + 4);
845
    } else {
846
      path_str = String::New(path);
847
    }
848
#else
849
    path_str = String::New(path);
850
#endif
851

    
852
    Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
853
    Local<String> cons4 = String::Concat(cons3, path_str);
854
    Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
855
    e = Exception::Error(cons5);
856
  } else {
857
    e = Exception::Error(cons2);
858
  }
859

    
860
  Local<Object> obj = e->ToObject();
861

    
862
  // TODO errno should probably go
863
  obj->Set(errno_symbol, Integer::New(errorno));
864
  obj->Set(code_symbol, estring);
865
  if (path) obj->Set(errpath_symbol, path_str);
866
  if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
867
  return e;
868
}
869

    
870

    
871
#ifdef _WIN32
872
// Does about the same as strerror(),
873
// but supports all windows error messages
874
static const char *winapi_strerror(const int errorno) {
875
  char *errmsg = NULL;
876

    
877
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
878
      FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
879
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL);
880

    
881
  if (errmsg) {
882
    // Remove trailing newlines
883
    for (int i = strlen(errmsg) - 1;
884
        i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
885
      errmsg[i] = '\0';
886
    }
887

    
888
    return errmsg;
889
  } else {
890
    // FormatMessage failed
891
    return "Unknown error";
892
  }
893
}
894

    
895

    
896
Local<Value> WinapiErrnoException(int errorno,
897
                                  const char* syscall,
898
                                  const char* msg,
899
                                  const char* path) {
900
  Local<Value> e;
901
  if (!msg || !msg[0]) {
902
    msg = winapi_strerror(errorno);
903
  }
904
  Local<String> message = String::NewSymbol(msg);
905

    
906
  if (syscall_symbol.IsEmpty()) {
907
    syscall_symbol = NODE_PSYMBOL("syscall");
908
    errno_symbol = NODE_PSYMBOL("errno");
909
    errpath_symbol = NODE_PSYMBOL("path");
910
    code_symbol = NODE_PSYMBOL("code");
911
  }
912

    
913
  if (path) {
914
    Local<String> cons1 = String::Concat(message, String::NewSymbol(" '"));
915
    Local<String> cons2 = String::Concat(cons1, String::New(path));
916
    Local<String> cons3 = String::Concat(cons2, String::NewSymbol("'"));
917
    e = Exception::Error(cons3);
918
  } else {
919
    e = Exception::Error(message);
920
  }
921

    
922
  Local<Object> obj = e->ToObject();
923

    
924
  obj->Set(errno_symbol, Integer::New(errorno));
925
  if (path) obj->Set(errpath_symbol, String::New(path));
926
  if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall));
927
  return e;
928
}
929
#endif
930

    
931

    
932
Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate>& t,
933
                                      const Arguments& args) {
934
  HandleScope scope;
935

    
936
  const int argc = args.Length();
937
  Local<Value>* argv = new Local<Value>[argc];
938

    
939
  for (int i = 0; i < argc; ++i) {
940
    argv[i] = args[i];
941
  }
942

    
943
  Local<Object> instance = t->GetFunction()->NewInstance(argc, argv);
944

    
945
  delete[] argv;
946

    
947
  return scope.Close(instance);
948
}
949

    
950

    
951
// MakeCallback may only be made directly off the event loop.
952
// That is there can be no JavaScript stack frames underneath it.
953
// (Is there any way to assert that?)
954
//
955
// Maybe make this a method of a node::Handle super class
956
//
957
Handle<Value>
958
MakeCallback(const Handle<Object> object,
959
             const char* method,
960
             int argc,
961
             Handle<Value> argv[]) {
962
  HandleScope scope;
963

    
964
  Handle<Value> ret =
965
    MakeCallback(object, String::NewSymbol(method), argc, argv);
966

    
967
  return scope.Close(ret);
968
}
969

    
970
Handle<Value>
971
MakeCallback(const Handle<Object> object,
972
             const Handle<String> symbol,
973
             int argc,
974
             Handle<Value> argv[]) {
975
  HandleScope scope;
976

    
977
  Local<Value> callback_v = object->Get(symbol);
978
  if (!callback_v->IsFunction()) {
979
    String::Utf8Value method(symbol);
980
    // XXX: If the object has a domain attached, handle it there?
981
    // At least, would be good to get *some* sort of indication
982
    // of how we got here, even if it's not catchable.
983
    fprintf(stderr, "Non-function in MakeCallback. method = %s\n", *method);
984
    abort();
985
  }
986

    
987
  Local<Function> callback = Local<Function>::Cast(callback_v);
988

    
989
  return scope.Close(MakeCallback(object, callback, argc, argv));
990
}
991

    
992
Handle<Value>
993
MakeCallback(const Handle<Object> object,
994
             const Handle<Function> callback,
995
             int argc,
996
             Handle<Value> argv[]) {
997
  HandleScope scope;
998

    
999
  // TODO Hook for long stack traces to be made here.
1000

    
1001
  TryCatch try_catch;
1002

    
1003
  if (process_makeCallback.IsEmpty()) {
1004
    Local<Value> cb_v = process->Get(String::New("_makeCallback"));
1005
    if (!cb_v->IsFunction()) {
1006
      fprintf(stderr, "process._makeCallback assigned to non-function\n");
1007
      abort();
1008
    }
1009
    Local<Function> cb = cb_v.As<Function>();
1010
    process_makeCallback = Persistent<Function>::New(cb);
1011
  }
1012

    
1013
  Local<Array> argArray = Array::New(argc);
1014
  for (int i = 0; i < argc; i++) {
1015
    argArray->Set(Integer::New(i), argv[i]);
1016
  }
1017

    
1018
  Local<Value> object_l = Local<Value>::New(object);
1019
  Local<Value> callback_l = Local<Value>::New(callback);
1020

    
1021
  Local<Value> args[3] = { object_l, callback_l, argArray };
1022

    
1023
  Local<Value> ret = process_makeCallback->Call(process, ARRAY_SIZE(args), args);
1024

    
1025
  if (try_catch.HasCaught()) {
1026
    FatalException(try_catch);
1027
    return Undefined();
1028
  }
1029

    
1030
  return scope.Close(ret);
1031
}
1032

    
1033

    
1034
void SetErrno(uv_err_t err) {
1035
  HandleScope scope;
1036

    
1037
  if (errno_symbol.IsEmpty()) {
1038
    errno_symbol = NODE_PSYMBOL("errno");
1039
  }
1040

    
1041
  if (err.code == UV_UNKNOWN) {
1042
    char errno_buf[100];
1043
    snprintf(errno_buf, 100, "Unknown system errno %d", err.sys_errno_);
1044
    Context::GetCurrent()->Global()->Set(errno_symbol, String::New(errno_buf));
1045
  } else {
1046
    Context::GetCurrent()->Global()->Set(errno_symbol,
1047
                                         String::NewSymbol(uv_err_name(err)));
1048
  }
1049
}
1050

    
1051

    
1052
enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
1053
  HandleScope scope;
1054

    
1055
  if (!encoding_v->IsString()) return _default;
1056

    
1057
  String::Utf8Value encoding(encoding_v);
1058

    
1059
  if (strcasecmp(*encoding, "utf8") == 0) {
1060
    return UTF8;
1061
  } else if (strcasecmp(*encoding, "utf-8") == 0) {
1062
    return UTF8;
1063
  } else if (strcasecmp(*encoding, "ascii") == 0) {
1064
    return ASCII;
1065
  } else if (strcasecmp(*encoding, "base64") == 0) {
1066
    return BASE64;
1067
  } else if (strcasecmp(*encoding, "ucs2") == 0) {
1068
    return UCS2;
1069
  } else if (strcasecmp(*encoding, "ucs-2") == 0) {
1070
    return UCS2;
1071
  } else if (strcasecmp(*encoding, "utf16le") == 0) {
1072
    return UCS2;
1073
  } else if (strcasecmp(*encoding, "utf-16le") == 0) {
1074
    return UCS2;
1075
  } else if (strcasecmp(*encoding, "binary") == 0) {
1076
    return BINARY;
1077
  } else if (strcasecmp(*encoding, "buffer") == 0) {
1078
    return BUFFER;
1079
  } else if (strcasecmp(*encoding, "hex") == 0) {
1080
    return HEX;
1081
  } else if (strcasecmp(*encoding, "raw") == 0) {
1082
    if (!no_deprecation) {
1083
      fprintf(stderr, "'raw' (array of integers) has been removed. "
1084
                      "Use 'binary'.\n");
1085
    }
1086
    return BINARY;
1087
  } else if (strcasecmp(*encoding, "raws") == 0) {
1088
    if (!no_deprecation) {
1089
      fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1090
                      "Please update your code.\n");
1091
    }
1092
    return BINARY;
1093
  } else {
1094
    return _default;
1095
  }
1096
}
1097

    
1098
Local<Value> Encode(const void *buf, size_t len, enum encoding encoding) {
1099
  HandleScope scope;
1100

    
1101
  if (encoding == BUFFER) {
1102
    return scope.Close(
1103
        Buffer::New(static_cast<const char*>(buf), len)->handle_);
1104
  }
1105

    
1106
  if (!len) return scope.Close(String::Empty());
1107

    
1108
  if (encoding == BINARY) {
1109
    const unsigned char *cbuf = static_cast<const unsigned char*>(buf);
1110
    uint16_t * twobytebuf = new uint16_t[len];
1111
    for (size_t i = 0; i < len; i++) {
1112
      // XXX is the following line platform independent?
1113
      twobytebuf[i] = cbuf[i];
1114
    }
1115
    Local<String> chunk = String::New(twobytebuf, len);
1116
    delete [] twobytebuf; // TODO use ExternalTwoByteString?
1117
    return scope.Close(chunk);
1118
  }
1119

    
1120
  // utf8 or ascii encoding
1121
  Local<String> chunk = String::New((const char*)buf, len);
1122
  return scope.Close(chunk);
1123
}
1124

    
1125
// Returns -1 if the handle was not valid for decoding
1126
ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
1127
  HandleScope scope;
1128

    
1129
  if (val->IsArray()) {
1130
    fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1131
                    "Use 'binary'.\n");
1132
    assert(0);
1133
    return -1;
1134
  }
1135

    
1136
  if ((encoding == BUFFER || encoding == BINARY) && Buffer::HasInstance(val)) {
1137
    return Buffer::Length(val->ToObject());
1138
  }
1139

    
1140
  Local<String> str = val->ToString();
1141

    
1142
  if (encoding == UTF8) return str->Utf8Length();
1143
  else if (encoding == UCS2) return str->Length() * 2;
1144
  else if (encoding == HEX) return str->Length() / 2;
1145

    
1146
  return str->Length();
1147
}
1148

    
1149
#ifndef MIN
1150
# define MIN(a, b) ((a) < (b) ? (a) : (b))
1151
#endif
1152

    
1153
// Returns number of bytes written.
1154
ssize_t DecodeWrite(char *buf,
1155
                    size_t buflen,
1156
                    v8::Handle<v8::Value> val,
1157
                    enum encoding encoding) {
1158
  HandleScope scope;
1159

    
1160
  // XXX
1161
  // A lot of improvement can be made here. See:
1162
  // http://code.google.com/p/v8/issues/detail?id=270
1163
  // http://groups.google.com/group/v8-dev/browse_thread/thread/dba28a81d9215291/ece2b50a3b4022c
1164
  // http://groups.google.com/group/v8-users/browse_thread/thread/1f83b0ba1f0a611
1165

    
1166
  if (val->IsArray()) {
1167
    fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1168
                    "Use 'binary'.\n");
1169
    assert(0);
1170
    return -1;
1171
  }
1172

    
1173
  bool is_buffer = Buffer::HasInstance(val);
1174

    
1175
  if (is_buffer && (encoding == BINARY || encoding == BUFFER)) {
1176
    // fast path, copy buffer data
1177
    const char* data = Buffer::Data(val.As<Object>());
1178
    size_t size = Buffer::Length(val.As<Object>());
1179
    size_t len = size < buflen ? size : buflen;
1180
    memcpy(buf, data, len);
1181
    return len;
1182
  }
1183

    
1184
  Local<String> str;
1185

    
1186
  if (is_buffer) { // slow path, convert to binary string
1187
    Local<Value> arg = String::New("binary");
1188
    str = MakeCallback(val.As<Object>(), "toString", 1, &arg)->ToString();
1189
  }
1190
  else {
1191
    str = val->ToString();
1192
  }
1193

    
1194
  if (encoding == UTF8) {
1195
    str->WriteUtf8(buf, buflen, NULL, String::HINT_MANY_WRITES_EXPECTED);
1196
    return buflen;
1197
  }
1198

    
1199
  if (encoding == ASCII) {
1200
    str->WriteAscii(buf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
1201
    return buflen;
1202
  }
1203

    
1204
  // THIS IS AWFUL!!! FIXME
1205

    
1206
  assert(encoding == BINARY);
1207

    
1208
  uint16_t * twobytebuf = new uint16_t[buflen];
1209

    
1210
  str->Write(twobytebuf, 0, buflen, String::HINT_MANY_WRITES_EXPECTED);
1211

    
1212
  for (size_t i = 0; i < buflen; i++) {
1213
    unsigned char *b = reinterpret_cast<unsigned char*>(&twobytebuf[i]);
1214
    buf[i] = b[0];
1215
  }
1216

    
1217
  delete [] twobytebuf;
1218

    
1219
  return buflen;
1220
}
1221

    
1222
void DisplayExceptionLine (TryCatch &try_catch) {
1223
  // Prevent re-entry into this function.  For example, if there is
1224
  // a throw from a program in vm.runInThisContext(code, filename, true),
1225
  // then we want to show the original failure, not the secondary one.
1226
  static bool displayed_error = false;
1227

    
1228
  if (displayed_error) return;
1229
  displayed_error = true;
1230

    
1231
  HandleScope scope;
1232

    
1233
  Handle<Message> message = try_catch.Message();
1234

    
1235
  uv_tty_reset_mode();
1236

    
1237
  fprintf(stderr, "\n");
1238

    
1239
  if (!message.IsEmpty()) {
1240
    // Print (filename):(line number): (message).
1241
    String::Utf8Value filename(message->GetScriptResourceName());
1242
    const char* filename_string = *filename;
1243
    int linenum = message->GetLineNumber();
1244
    fprintf(stderr, "%s:%i\n", filename_string, linenum);
1245
    // Print line of source code.
1246
    String::Utf8Value sourceline(message->GetSourceLine());
1247
    const char* sourceline_string = *sourceline;
1248

    
1249
    // Because of how node modules work, all scripts are wrapped with a
1250
    // "function (module, exports, __filename, ...) {"
1251
    // to provide script local variables.
1252
    //
1253
    // When reporting errors on the first line of a script, this wrapper
1254
    // function is leaked to the user. There used to be a hack here to
1255
    // truncate off the first 62 characters, but it caused numerous other
1256
    // problems when vm.runIn*Context() methods were used for non-module
1257
    // code.
1258
    //
1259
    // If we ever decide to re-instate such a hack, the following steps
1260
    // must be taken:
1261
    //
1262
    // 1. Pass a flag around to say "this code was wrapped"
1263
    // 2. Update the stack frame output so that it is also correct.
1264
    //
1265
    // It would probably be simpler to add a line rather than add some
1266
    // number of characters to the first line, since V8 truncates the
1267
    // sourceline to 78 characters, and we end up not providing very much
1268
    // useful debugging info to the user if we remove 62 characters.
1269

    
1270
    int start = message->GetStartColumn();
1271
    int end = message->GetEndColumn();
1272

    
1273
    // fprintf(stderr, "---\nsourceline:%s\noffset:%d\nstart:%d\nend:%d\n---\n", sourceline_string, start, end);
1274

    
1275
    fprintf(stderr, "%s\n", sourceline_string);
1276
    // Print wavy underline (GetUnderline is deprecated).
1277
    for (int i = 0; i < start; i++) {
1278
      fputc((sourceline_string[i] == '\t') ? '\t' : ' ', stderr);
1279
    }
1280
    for (int i = start; i < end; i++) {
1281
      fputc('^', stderr);
1282
    }
1283
    fputc('\n', stderr);
1284
  }
1285
}
1286

    
1287

    
1288
static void ReportException(TryCatch &try_catch, bool show_line) {
1289
  HandleScope scope;
1290

    
1291
  if (show_line) DisplayExceptionLine(try_catch);
1292

    
1293
  String::Utf8Value trace(try_catch.StackTrace());
1294

    
1295
  // range errors have a trace member set to undefined
1296
  if (trace.length() > 0 && !try_catch.StackTrace()->IsUndefined()) {
1297
    fprintf(stderr, "%s\n", *trace);
1298
  } else {
1299
    // this really only happens for RangeErrors, since they're the only
1300
    // kind that won't have all this info in the trace, or when non-Error
1301
    // objects are thrown manually.
1302
    Local<Value> er = try_catch.Exception();
1303
    bool isErrorObject = er->IsObject() &&
1304
      !(er->ToObject()->Get(String::New("message"))->IsUndefined()) &&
1305
      !(er->ToObject()->Get(String::New("name"))->IsUndefined());
1306

    
1307
    if (isErrorObject) {
1308
      String::Utf8Value name(er->ToObject()->Get(String::New("name")));
1309
      fprintf(stderr, "%s: ", *name);
1310
    }
1311

    
1312
    String::Utf8Value msg(!isErrorObject ? er
1313
                         : er->ToObject()->Get(String::New("message")));
1314
    fprintf(stderr, "%s\n", *msg);
1315
  }
1316

    
1317
  fflush(stderr);
1318
}
1319

    
1320
// Executes a str within the current v8 context.
1321
Local<Value> ExecuteString(Handle<String> source, Handle<Value> filename) {
1322
  HandleScope scope;
1323
  TryCatch try_catch;
1324

    
1325
  Local<v8::Script> script = v8::Script::Compile(source, filename);
1326
  if (script.IsEmpty()) {
1327
    ReportException(try_catch, true);
1328
    exit(1);
1329
  }
1330

    
1331
  Local<Value> result = script->Run();
1332
  if (result.IsEmpty()) {
1333
    ReportException(try_catch, true);
1334
    exit(1);
1335
  }
1336

    
1337
  return scope.Close(result);
1338
}
1339

    
1340

    
1341
static Handle<Value> GetActiveRequests(const Arguments& args) {
1342
  HandleScope scope;
1343

    
1344
  Local<Array> ary = Array::New();
1345
  ngx_queue_t* q = NULL;
1346
  int i = 0;
1347

    
1348
  ngx_queue_foreach(q, &req_wrap_queue) {
1349
    ReqWrap<uv_req_t>* w = container_of(q, ReqWrap<uv_req_t>, req_wrap_queue_);
1350
    if (w->object_.IsEmpty()) continue;
1351
    ary->Set(i++, w->object_);
1352
  }
1353

    
1354
  return scope.Close(ary);
1355
}
1356

    
1357

    
1358
// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1359
// implemented here for consistency with GetActiveRequests().
1360
Handle<Value> GetActiveHandles(const Arguments& args) {
1361
  HandleScope scope;
1362

    
1363
  Local<Array> ary = Array::New();
1364
  ngx_queue_t* q = NULL;
1365
  int i = 0;
1366

    
1367
  Local<String> owner_sym = String::New("owner");
1368

    
1369
  ngx_queue_foreach(q, &handle_wrap_queue) {
1370
    HandleWrap* w = container_of(q, HandleWrap, handle_wrap_queue_);
1371
    if (w->object_.IsEmpty() || w->unref_) continue;
1372
    Local<Value> obj = w->object_->Get(owner_sym);
1373
    if (obj->IsUndefined()) obj = *w->object_;
1374
    ary->Set(i++, obj);
1375
  }
1376

    
1377
  return scope.Close(ary);
1378
}
1379

    
1380

    
1381
static Handle<Value> Abort(const Arguments& args) {
1382
  abort();
1383
  return Undefined();
1384
}
1385

    
1386

    
1387
static Handle<Value> Chdir(const Arguments& args) {
1388
  HandleScope scope;
1389

    
1390
  if (args.Length() != 1 || !args[0]->IsString()) {
1391
    return ThrowException(Exception::Error(String::New("Bad argument.")));
1392
  }
1393

    
1394
  String::Utf8Value path(args[0]);
1395

    
1396
  uv_err_t r = uv_chdir(*path);
1397

    
1398
  if (r.code != UV_OK) {
1399
    return ThrowException(UVException(r.code, "uv_chdir"));
1400
  }
1401

    
1402
  return Undefined();
1403
}
1404

    
1405

    
1406
static Handle<Value> Cwd(const Arguments& args) {
1407
  HandleScope scope;
1408
#ifdef _WIN32
1409
  /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1410
  char buf[MAX_PATH * 4 + 1];
1411
#else
1412
  char buf[PATH_MAX + 1];
1413
#endif
1414

    
1415
  uv_err_t r = uv_cwd(buf, ARRAY_SIZE(buf) - 1);
1416
  if (r.code != UV_OK) {
1417
    return ThrowException(UVException(r.code, "uv_cwd"));
1418
  }
1419

    
1420
  buf[ARRAY_SIZE(buf) - 1] = '\0';
1421
  Local<String> cwd = String::New(buf);
1422

    
1423
  return scope.Close(cwd);
1424
}
1425

    
1426

    
1427
static Handle<Value> Umask(const Arguments& args) {
1428
  HandleScope scope;
1429
  unsigned int old;
1430

    
1431
  if (args.Length() < 1 || args[0]->IsUndefined()) {
1432
    old = umask(0);
1433
    umask((mode_t)old);
1434

    
1435
  } else if(!args[0]->IsInt32() && !args[0]->IsString()) {
1436
    return ThrowException(Exception::TypeError(
1437
          String::New("argument must be an integer or octal string.")));
1438

    
1439
  } else {
1440
    int oct;
1441
    if(args[0]->IsInt32()) {
1442
      oct = args[0]->Uint32Value();
1443
    } else {
1444
      oct = 0;
1445
      String::Utf8Value str(args[0]);
1446

    
1447
      // Parse the octal string.
1448
      for (int i = 0; i < str.length(); i++) {
1449
        char c = (*str)[i];
1450
        if (c > '7' || c < '0') {
1451
          return ThrowException(Exception::TypeError(
1452
                String::New("invalid octal string")));
1453
        }
1454
        oct *= 8;
1455
        oct += c - '0';
1456
      }
1457
    }
1458
    old = umask(static_cast<mode_t>(oct));
1459
  }
1460

    
1461
  return scope.Close(Uint32::New(old));
1462
}
1463

    
1464

    
1465
#ifdef __POSIX__
1466

    
1467
static Handle<Value> GetUid(const Arguments& args) {
1468
  HandleScope scope;
1469
  int uid = getuid();
1470
  return scope.Close(Integer::New(uid));
1471
}
1472

    
1473

    
1474
static Handle<Value> GetGid(const Arguments& args) {
1475
  HandleScope scope;
1476
  int gid = getgid();
1477
  return scope.Close(Integer::New(gid));
1478
}
1479

    
1480

    
1481
static Handle<Value> SetGid(const Arguments& args) {
1482
  HandleScope scope;
1483

    
1484
  if (args.Length() < 1) {
1485
    return ThrowException(Exception::Error(
1486
      String::New("setgid requires 1 argument")));
1487
  }
1488

    
1489
  int gid;
1490

    
1491
  if (args[0]->IsNumber()) {
1492
    gid = args[0]->Int32Value();
1493
  } else if (args[0]->IsString()) {
1494
    String::Utf8Value grpnam(args[0]);
1495
    struct group grp, *grpp = NULL;
1496
    int err;
1497

    
1498
    errno = 0;
1499
    if ((err = getgrnam_r(*grpnam, &grp, getbuf, ARRAY_SIZE(getbuf), &grpp)) ||
1500
        grpp == NULL) {
1501
      if (errno == 0)
1502
        return ThrowException(Exception::Error(
1503
          String::New("setgid group id does not exist")));
1504
      else
1505
        return ThrowException(ErrnoException(errno, "getgrnam_r"));
1506
    }
1507

    
1508
    gid = grpp->gr_gid;
1509
  } else {
1510
    return ThrowException(Exception::Error(
1511
      String::New("setgid argument must be a number or a string")));
1512
  }
1513

    
1514
  int result;
1515
  if ((result = setgid(gid)) != 0) {
1516
    return ThrowException(ErrnoException(errno, "setgid"));
1517
  }
1518
  return Undefined();
1519
}
1520

    
1521

    
1522
static Handle<Value> SetUid(const Arguments& args) {
1523
  HandleScope scope;
1524

    
1525
  if (args.Length() < 1) {
1526
    return ThrowException(Exception::Error(
1527
          String::New("setuid requires 1 argument")));
1528
  }
1529

    
1530
  int uid;
1531

    
1532
  if (args[0]->IsNumber()) {
1533
    uid = args[0]->Int32Value();
1534
  } else if (args[0]->IsString()) {
1535
    String::Utf8Value pwnam(args[0]);
1536
    struct passwd pwd, *pwdp = NULL;
1537
    int err;
1538

    
1539
    errno = 0;
1540
    if ((err = getpwnam_r(*pwnam, &pwd, getbuf, ARRAY_SIZE(getbuf), &pwdp)) ||
1541
        pwdp == NULL) {
1542
      if (errno == 0)
1543
        return ThrowException(Exception::Error(
1544
          String::New("setuid user id does not exist")));
1545
      else
1546
        return ThrowException(ErrnoException(errno, "getpwnam_r"));
1547
    }
1548

    
1549
    uid = pwdp->pw_uid;
1550
  } else {
1551
    return ThrowException(Exception::Error(
1552
      String::New("setuid argument must be a number or a string")));
1553
  }
1554

    
1555
  int result;
1556
  if ((result = setuid(uid)) != 0) {
1557
    return ThrowException(ErrnoException(errno, "setuid"));
1558
  }
1559
  return Undefined();
1560
}
1561

    
1562

    
1563
#endif // __POSIX__
1564

    
1565

    
1566
v8::Handle<v8::Value> Exit(const v8::Arguments& args) {
1567
  HandleScope scope;
1568
  exit(args[0]->IntegerValue());
1569
  return Undefined();
1570
}
1571

    
1572

    
1573
static void CheckStatus(uv_timer_t* watcher, int status) {
1574
  assert(watcher == &gc_timer);
1575

    
1576
  // check memory
1577
  if (!uv_is_active((uv_handle_t*) &gc_idle)) {
1578
    HeapStatistics stats;
1579
    V8::GetHeapStatistics(&stats);
1580
    if (stats.total_heap_size() > 1024 * 1024 * 128) {
1581
      // larger than 128 megs, just start the idle watcher
1582
      uv_idle_start(&gc_idle, node::Idle);
1583
      return;
1584
    }
1585
  }
1586

    
1587
  double d = uv_now(uv_default_loop()) - TICK_TIME(3);
1588

    
1589
  //printfb("timer d = %f\n", d);
1590

    
1591
  if (d  >= GC_WAIT_TIME - 1.) {
1592
    //fprintf(stderr, "start idle\n");
1593
    uv_idle_start(&gc_idle, node::Idle);
1594
  }
1595
}
1596

    
1597

    
1598
static Handle<Value> Uptime(const Arguments& args) {
1599
  HandleScope scope;
1600
  double uptime;
1601

    
1602
  uv_err_t err = uv_uptime(&uptime);
1603

    
1604
  if (err.code != UV_OK) {
1605
    return Undefined();
1606
  }
1607

    
1608
  return scope.Close(Number::New(uptime - prog_start_time));
1609
}
1610

    
1611

    
1612
v8::Handle<v8::Value> MemoryUsage(const v8::Arguments& args) {
1613
  HandleScope scope;
1614

    
1615
  size_t rss;
1616

    
1617
  uv_err_t err = uv_resident_set_memory(&rss);
1618

    
1619
  if (err.code != UV_OK) {
1620
    return ThrowException(UVException(err.code, "uv_resident_set_memory"));
1621
  }
1622

    
1623
  Local<Object> info = Object::New();
1624

    
1625
  if (rss_symbol.IsEmpty()) {
1626
    rss_symbol = NODE_PSYMBOL("rss");
1627
    heap_total_symbol = NODE_PSYMBOL("heapTotal");
1628
    heap_used_symbol = NODE_PSYMBOL("heapUsed");
1629
  }
1630

    
1631
  info->Set(rss_symbol, Number::New(rss));
1632

    
1633
  // V8 memory usage
1634
  HeapStatistics v8_heap_stats;
1635
  V8::GetHeapStatistics(&v8_heap_stats);
1636
  info->Set(heap_total_symbol,
1637
            Integer::NewFromUnsigned(v8_heap_stats.total_heap_size()));
1638
  info->Set(heap_used_symbol,
1639
            Integer::NewFromUnsigned(v8_heap_stats.used_heap_size()));
1640

    
1641
  return scope.Close(info);
1642
}
1643

    
1644

    
1645
Handle<Value> Kill(const Arguments& args) {
1646
  HandleScope scope;
1647

    
1648
  if (args.Length() != 2) {
1649
    return ThrowException(Exception::Error(String::New("Bad argument.")));
1650
  }
1651

    
1652
  int pid = args[0]->IntegerValue();
1653
  int sig = args[1]->Int32Value();
1654
  uv_err_t err = uv_kill(pid, sig);
1655

    
1656
  if (err.code != UV_OK) {
1657
    SetErrno(err);
1658
    return scope.Close(Integer::New(-1));
1659
  }
1660

    
1661
  return Undefined();
1662
}
1663

    
1664
// used in Hrtime() below
1665
#define NANOS_PER_SEC 1000000000
1666

    
1667
// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
1668
// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
1669
// so this function instead returns an Array with 2 entries representing seconds
1670
// and nanoseconds, to avoid any integer overflow possibility.
1671
// Pass in an Array from a previous hrtime() call to instead get a time diff.
1672
Handle<Value> Hrtime(const v8::Arguments& args) {
1673
  HandleScope scope;
1674

    
1675
  uint64_t t = uv_hrtime();
1676

    
1677
  if (args.Length() > 0) {
1678
    // return a time diff tuple
1679
    if (!args[0]->IsArray()) {
1680
      Local<Value> exception = Exception::TypeError(
1681
          String::New("process.hrtime() only accepts an Array tuple."));
1682
      return ThrowException(exception);
1683
    }
1684
    Local<Array> inArray = Local<Array>::Cast(args[0]);
1685
    uint64_t seconds = inArray->Get(0)->Uint32Value();
1686
    uint64_t nanos = inArray->Get(1)->Uint32Value();
1687
    t -= (seconds * NANOS_PER_SEC) + nanos;
1688
  }
1689

    
1690
  Local<Array> tuple = Array::New(2);
1691
  tuple->Set(0, Integer::NewFromUnsigned(t / NANOS_PER_SEC));
1692
  tuple->Set(1, Integer::NewFromUnsigned(t % NANOS_PER_SEC));
1693

    
1694
  return scope.Close(tuple);
1695
}
1696

    
1697

    
1698
typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
1699

    
1700
// DLOpen is node.dlopen(). Used to load 'module.node' dynamically shared
1701
// objects.
1702
Handle<Value> DLOpen(const v8::Arguments& args) {
1703
  HandleScope scope;
1704
  char symbol[1024], *base, *pos;
1705
  uv_lib_t lib;
1706
  int r;
1707

    
1708
  if (args.Length() < 2) {
1709
    Local<Value> exception = Exception::Error(
1710
        String::New("process.dlopen takes exactly 2 arguments."));
1711
    return ThrowException(exception);
1712
  }
1713

    
1714
  String::Utf8Value filename(args[0]); // Cast
1715
  Local<Object> target = args[1]->ToObject(); // Cast
1716

    
1717
  if (uv_dlopen(*filename, &lib)) {
1718
    Local<String> errmsg = String::New(uv_dlerror(&lib));
1719
#ifdef _WIN32
1720
    // Windows needs to add the filename into the error message
1721
    errmsg = String::Concat(errmsg, args[0]->ToString());
1722
#endif
1723
    return ThrowException(Exception::Error(errmsg));
1724
  }
1725

    
1726
  String::Utf8Value path(args[0]);
1727
  base = *path;
1728

    
1729
  /* Find the shared library filename within the full path. */
1730
#ifdef __POSIX__
1731
  pos = strrchr(base, '/');
1732
  if (pos != NULL) {
1733
    base = pos + 1;
1734
  }
1735
#else // Windows
1736
  for (;;) {
1737
    pos = strpbrk(base, "\\/:");
1738
    if (pos == NULL) {
1739
      break;
1740
    }
1741
    base = pos + 1;
1742
  }
1743
#endif
1744

    
1745
  /* Strip the .node extension. */
1746
  pos = strrchr(base, '.');
1747
  if (pos != NULL) {
1748
    *pos = '\0';
1749
  }
1750

    
1751
  /* Add the `_module` suffix to the extension name. */
1752
  r = snprintf(symbol, sizeof symbol, "%s_module", base);
1753
  if (r <= 0 || static_cast<size_t>(r) >= sizeof symbol) {
1754
    Local<Value> exception =
1755
        Exception::Error(String::New("Out of memory."));
1756
    return ThrowException(exception);
1757
  }
1758

    
1759
  node_module_struct *mod;
1760
  if (uv_dlsym(&lib, symbol, reinterpret_cast<void**>(&mod))) {
1761
    char errmsg[1024];
1762
    snprintf(errmsg, sizeof(errmsg), "Symbol %s not found.", symbol);
1763
    return ThrowError(errmsg);
1764
  }
1765

    
1766
  if (mod->version != NODE_MODULE_VERSION) {
1767
    char errmsg[1024];
1768
    snprintf(errmsg,
1769
             sizeof(errmsg),
1770
             "Module version mismatch. Expected %d, got %d.",
1771
             NODE_MODULE_VERSION, mod->version);
1772
    return ThrowError(errmsg);
1773
  }
1774

    
1775
  // Execute the C++ module
1776
  mod->register_func(target);
1777

    
1778
  // Tell coverity that 'handle' should not be freed when we return.
1779
  // coverity[leaked_storage]
1780
  return Undefined();
1781
}
1782

    
1783

    
1784
static void OnFatalError(const char* location, const char* message) {
1785
  if (location) {
1786
    fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
1787
  } else {
1788
    fprintf(stderr, "FATAL ERROR: %s\n", message);
1789
  }
1790
  exit(1);
1791
}
1792

    
1793
void FatalException(TryCatch &try_catch) {
1794
  HandleScope scope;
1795

    
1796
  if (listeners_symbol.IsEmpty()) {
1797
    listeners_symbol = NODE_PSYMBOL("listeners");
1798
    uncaught_exception_symbol = NODE_PSYMBOL("uncaughtException");
1799
    emit_symbol = NODE_PSYMBOL("emit");
1800
  }
1801

    
1802
  Local<Value> listeners_v = process->Get(listeners_symbol);
1803
  assert(listeners_v->IsFunction());
1804

    
1805
  Local<Function> listeners = Local<Function>::Cast(listeners_v);
1806

    
1807
  Local<String> uncaught_exception_symbol_l = Local<String>::New(uncaught_exception_symbol);
1808
  Local<Value> argv[1] = { uncaught_exception_symbol_l  };
1809
  Local<Value> ret = listeners->Call(process, 1, argv);
1810

    
1811
  assert(ret->IsArray());
1812

    
1813
  Local<Array> listener_array = Local<Array>::Cast(ret);
1814

    
1815
  uint32_t length = listener_array->Length();
1816
  // Report and exit if process has no "uncaughtException" listener
1817
  if (length == 0) {
1818
    ReportException(try_catch, true);
1819
    exit(1);
1820
  }
1821

    
1822
  // Otherwise fire the process "uncaughtException" event
1823
  Local<Value> emit_v = process->Get(emit_symbol);
1824
  assert(emit_v->IsFunction());
1825

    
1826
  Local<Function> emit = Local<Function>::Cast(emit_v);
1827

    
1828
  Local<Value> error = try_catch.Exception();
1829
  Local<Value> event_argv[2] = { uncaught_exception_symbol_l, error };
1830

    
1831
  TryCatch event_try_catch;
1832
  emit->Call(process, 2, event_argv);
1833

    
1834
  if (event_try_catch.HasCaught()) {
1835
    // the uncaught exception event threw, so we must exit.
1836
    ReportException(event_try_catch, true);
1837
    exit(1);
1838
  }
1839
}
1840

    
1841

    
1842
Persistent<Object> binding_cache;
1843
Persistent<Array> module_load_list;
1844

    
1845
static Handle<Value> Binding(const Arguments& args) {
1846
  HandleScope scope;
1847

    
1848
  Local<String> module = args[0]->ToString();
1849
  String::Utf8Value module_v(module);
1850
  node_module_struct* modp;
1851

    
1852
  if (binding_cache.IsEmpty()) {
1853
    binding_cache = Persistent<Object>::New(Object::New());
1854
  }
1855

    
1856
  Local<Object> exports;
1857

    
1858
  if (binding_cache->Has(module)) {
1859
    exports = binding_cache->Get(module)->ToObject();
1860
    return scope.Close(exports);
1861
  }
1862

    
1863
  // Append a string to process.moduleLoadList
1864
  char buf[1024];
1865
  snprintf(buf, 1024, "Binding %s", *module_v);
1866
  uint32_t l = module_load_list->Length();
1867
  module_load_list->Set(l, String::New(buf));
1868

    
1869
  if ((modp = get_builtin_module(*module_v)) != NULL) {
1870
    exports = Object::New();
1871
    modp->register_func(exports);
1872
    binding_cache->Set(module, exports);
1873

    
1874
  } else if (!strcmp(*module_v, "constants")) {
1875
    exports = Object::New();
1876
    DefineConstants(exports);
1877
    binding_cache->Set(module, exports);
1878

    
1879
  } else if (!strcmp(*module_v, "natives")) {
1880
    exports = Object::New();
1881
    DefineJavaScript(exports);
1882
    binding_cache->Set(module, exports);
1883

    
1884
  } else {
1885

    
1886
    return ThrowException(Exception::Error(String::New("No such module")));
1887
  }
1888

    
1889
  return scope.Close(exports);
1890
}
1891

    
1892

    
1893
static Handle<Value> ProcessTitleGetter(Local<String> property,
1894
                                        const AccessorInfo& info) {
1895
  HandleScope scope;
1896
  char buffer[512];
1897
  uv_get_process_title(buffer, sizeof(buffer));
1898
  return scope.Close(String::New(buffer));
1899
}
1900

    
1901

    
1902
static void ProcessTitleSetter(Local<String> property,
1903
                               Local<Value> value,
1904
                               const AccessorInfo& info) {
1905
  HandleScope scope;
1906
  String::Utf8Value title(value);
1907
  // TODO: protect with a lock
1908
  uv_set_process_title(*title);
1909
}
1910

    
1911

    
1912
static Handle<Value> EnvGetter(Local<String> property,
1913
                               const AccessorInfo& info) {
1914
  HandleScope scope;
1915
#ifdef __POSIX__
1916
  String::Utf8Value key(property);
1917
  const char* val = getenv(*key);
1918
  if (val) {
1919
    return scope.Close(String::New(val));
1920
  }
1921
#else  // _WIN32
1922
  String::Value key(property);
1923
  WCHAR buffer[32767]; // The maximum size allowed for environment variables.
1924
  DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
1925
                                         buffer,
1926
                                         ARRAY_SIZE(buffer));
1927
  // If result >= sizeof buffer the buffer was too small. That should never
1928
  // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
1929
  // not found.
1930
  if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
1931
      result < ARRAY_SIZE(buffer)) {
1932
    return scope.Close(String::New(reinterpret_cast<uint16_t*>(buffer), result));
1933
  }
1934
#endif
1935
  // Not found.  Fetch from prototype.
1936
  return scope.Close(info.Data().As<Object>()->Get(property));
1937
}
1938

    
1939

    
1940
static Handle<Value> EnvSetter(Local<String> property,
1941
                               Local<Value> value,
1942
                               const AccessorInfo& info) {
1943
  HandleScope scope;
1944
#ifdef __POSIX__
1945
  String::Utf8Value key(property);
1946
  String::Utf8Value val(value);
1947
  setenv(*key, *val, 1);
1948
#else  // _WIN32
1949
  String::Value key(property);
1950
  String::Value val(value);
1951
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
1952
  // Environment variables that start with '=' are read-only.
1953
  if (key_ptr[0] != L'=') {
1954
    SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
1955
  }
1956
#endif
1957
  // Whether it worked or not, always return rval.
1958
  return scope.Close(value);
1959
}
1960

    
1961

    
1962
static Handle<Integer> EnvQuery(Local<String> property,
1963
                                const AccessorInfo& info) {
1964
  HandleScope scope;
1965
#ifdef __POSIX__
1966
  String::Utf8Value key(property);
1967
  if (getenv(*key)) {
1968
    return scope.Close(Integer::New(None));
1969
  }
1970
#else  // _WIN32
1971
  String::Value key(property);
1972
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
1973
  if (GetEnvironmentVariableW(key_ptr, NULL, 0) > 0 ||
1974
      GetLastError() == ERROR_SUCCESS) {
1975
    if (key_ptr[0] == L'=') {
1976
      // Environment variables that start with '=' are hidden and read-only.
1977
      return scope.Close(Integer::New(v8::ReadOnly ||
1978
                                      v8::DontDelete ||
1979
                                      v8::DontEnum));
1980
    } else {
1981
      return scope.Close(Integer::New(None));
1982
    }
1983
  }
1984
#endif
1985
  // Not found
1986
  return scope.Close(Handle<Integer>());
1987
}
1988

    
1989

    
1990
static Handle<Boolean> EnvDeleter(Local<String> property,
1991
                                  const AccessorInfo& info) {
1992
  HandleScope scope;
1993
#ifdef __POSIX__
1994
  String::Utf8Value key(property);
1995
  if (!getenv(*key)) return False();
1996
  unsetenv(*key); // can't check return value, it's void on some platforms
1997
  return True();
1998
#else
1999
  String::Value key(property);
2000
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2001
  if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, NULL)) {
2002
    // Deletion failed. Return true if the key wasn't there in the first place,
2003
    // false if it is still there.
2004
    bool rv = GetEnvironmentVariableW(key_ptr, NULL, NULL) == 0 &&
2005
              GetLastError() != ERROR_SUCCESS;
2006
    return scope.Close(Boolean::New(rv));
2007
  }
2008
  return True();
2009
#endif
2010
}
2011

    
2012

    
2013
static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
2014
  HandleScope scope;
2015
#ifdef __POSIX__
2016
  int size = 0;
2017
  while (environ[size]) size++;
2018

    
2019
  Local<Array> env = Array::New(size);
2020

    
2021
  for (int i = 0; i < size; ++i) {
2022
    const char* var = environ[i];
2023
    const char* s = strchr(var, '=');
2024
    const int length = s ? s - var : strlen(var);
2025
    env->Set(i, String::New(var, length));
2026
  }
2027
#else  // _WIN32
2028
  WCHAR* environment = GetEnvironmentStringsW();
2029
  if (environment == NULL) {
2030
    // This should not happen.
2031
    return scope.Close(Handle<Array>());
2032
  }
2033
  Local<Array> env = Array::New();
2034
  WCHAR* p = environment;
2035
  int i = 0;
2036
  while (*p != NULL) {
2037
    WCHAR *s;
2038
    if (*p == L'=') {
2039
      // If the key starts with '=' it is a hidden environment variable.
2040
      p += wcslen(p) + 1;
2041
      continue;
2042
    } else {
2043
      s = wcschr(p, L'=');
2044
    }
2045
    if (!s) {
2046
      s = p + wcslen(p);
2047
    }
2048
    env->Set(i++, String::New(reinterpret_cast<uint16_t*>(p), s - p));
2049
    p = s + wcslen(s) + 1;
2050
  }
2051
  FreeEnvironmentStringsW(environment);
2052
#endif
2053
  return scope.Close(env);
2054
}
2055

    
2056

    
2057
static Handle<Object> GetFeatures() {
2058
  HandleScope scope;
2059

    
2060
  Local<Object> obj = Object::New();
2061
  obj->Set(String::NewSymbol("debug"),
2062
#if defined(DEBUG) && DEBUG
2063
    True()
2064
#else
2065
    False()
2066
#endif
2067
  );
2068

    
2069
  obj->Set(String::NewSymbol("uv"), True());
2070
  obj->Set(String::NewSymbol("ipv6"), True()); // TODO ping libuv
2071
  obj->Set(String::NewSymbol("tls_npn"), Boolean::New(use_npn));
2072
  obj->Set(String::NewSymbol("tls_sni"), Boolean::New(use_sni));
2073
  obj->Set(String::NewSymbol("tls"),
2074
      Boolean::New(get_builtin_module("crypto") != NULL));
2075

    
2076
  return scope.Close(obj);
2077
}
2078

    
2079

    
2080
static Handle<Value> DebugPortGetter(Local<String> property,
2081
                                     const AccessorInfo& info) {
2082
  HandleScope scope;
2083
  return scope.Close(Integer::NewFromUnsigned(debug_port));
2084
}
2085

    
2086

    
2087
static void DebugPortSetter(Local<String> property,
2088
                            Local<Value> value,
2089
                            const AccessorInfo& info) {
2090
  HandleScope scope;
2091
  debug_port = value->NumberValue();
2092
}
2093

    
2094

    
2095
static Handle<Value> DebugProcess(const Arguments& args);
2096
static Handle<Value> DebugPause(const Arguments& args);
2097
static Handle<Value> DebugEnd(const Arguments& args);
2098

    
2099
Handle<Object> SetupProcessObject(int argc, char *argv[]) {
2100
  HandleScope scope;
2101

    
2102
  int i, j;
2103

    
2104
  Local<FunctionTemplate> process_template = FunctionTemplate::New();
2105

    
2106
  process_template->SetClassName(String::NewSymbol("process"));
2107

    
2108
  process = Persistent<Object>::New(process_template->GetFunction()->NewInstance());
2109

    
2110
  process->SetAccessor(String::New("title"),
2111
                       ProcessTitleGetter,
2112
                       ProcessTitleSetter);
2113

    
2114
  // process.version
2115
  process->Set(String::NewSymbol("version"), String::New(NODE_VERSION));
2116

    
2117
  // process.moduleLoadList
2118
  module_load_list = Persistent<Array>::New(Array::New());
2119
  process->Set(String::NewSymbol("moduleLoadList"), module_load_list);
2120

    
2121
  // process.versions
2122
  Local<Object> versions = Object::New();
2123
  process->Set(String::NewSymbol("versions"), versions);
2124
  versions->Set(String::NewSymbol("http_parser"), String::New(
2125
               NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR) "."
2126
               NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR)));
2127
  // +1 to get rid of the leading 'v'
2128
  versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
2129
  versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
2130
  versions->Set(String::NewSymbol("ares"), String::New(ARES_VERSION_STR));
2131
  versions->Set(String::NewSymbol("uv"), String::New(
2132
               NODE_STRINGIFY(UV_VERSION_MAJOR) "."
2133
               NODE_STRINGIFY(UV_VERSION_MINOR)));
2134
  versions->Set(String::NewSymbol("zlib"), String::New(ZLIB_VERSION));
2135
#if HAVE_OPENSSL
2136
  // Stupid code to slice out the version string.
2137
  int c, l = strlen(OPENSSL_VERSION_TEXT);
2138
  for (i = j = 0; i < l; i++) {
2139
    c = OPENSSL_VERSION_TEXT[i];
2140
    if ('0' <= c && c <= '9') {
2141
      for (j = i + 1; j < l; j++) {
2142
        c = OPENSSL_VERSION_TEXT[j];
2143
        if (c == ' ') break;
2144
      }
2145
      break;
2146
    }
2147
  }
2148
  versions->Set(String::NewSymbol("openssl"),
2149
                String::New(OPENSSL_VERSION_TEXT + i, j - i));
2150
#endif
2151

    
2152

    
2153

    
2154
  // process.arch
2155
  process->Set(String::NewSymbol("arch"), String::New(ARCH));
2156

    
2157
  // process.platform
2158
  process->Set(String::NewSymbol("platform"), String::New(PLATFORM));
2159

    
2160
  // process.argv
2161
  Local<Array> arguments = Array::New(argc - option_end_index + 1);
2162
  arguments->Set(Integer::New(0), String::New(argv[0]));
2163
  for (j = 1, i = option_end_index; i < argc; j++, i++) {
2164
    Local<String> arg = String::New(argv[i]);
2165
    arguments->Set(Integer::New(j), arg);
2166
  }
2167
  // assign it
2168
  process->Set(String::NewSymbol("argv"), arguments);
2169

    
2170
  // process.execArgv
2171
  Local<Array> execArgv = Array::New(option_end_index - 1);
2172
  for (j = 1, i = 0; j < option_end_index; j++, i++) {
2173
    execArgv->Set(Integer::New(i), String::New(argv[j]));
2174
  }
2175
  // assign it
2176
  process->Set(String::NewSymbol("execArgv"), execArgv);
2177

    
2178

    
2179
  // create process.env
2180
  Local<ObjectTemplate> envTemplate = ObjectTemplate::New();
2181
  envTemplate->SetNamedPropertyHandler(EnvGetter,
2182
                                       EnvSetter,
2183
                                       EnvQuery,
2184
                                       EnvDeleter,
2185
                                       EnvEnumerator,
2186
                                       Object::New());
2187
  Local<Object> env = envTemplate->NewInstance();
2188
  process->Set(String::NewSymbol("env"), env);
2189

    
2190
  process->Set(String::NewSymbol("pid"), Integer::New(getpid()));
2191
  process->Set(String::NewSymbol("features"), GetFeatures());
2192

    
2193
  // -e, --eval
2194
  if (eval_string) {
2195
    process->Set(String::NewSymbol("_eval"), String::New(eval_string));
2196
  }
2197

    
2198
  // -p, --print
2199
  if (print_eval) {
2200
    process->Set(String::NewSymbol("_print_eval"), True());
2201
  }
2202

    
2203
  // -i, --interactive
2204
  if (force_repl) {
2205
    process->Set(String::NewSymbol("_forceRepl"), True());
2206
  }
2207

    
2208
  // --no-deprecation
2209
  if (no_deprecation) {
2210
    process->Set(String::NewSymbol("noDeprecation"), True());
2211
  }
2212

    
2213
  // --trace-deprecation
2214
  if (trace_deprecation) {
2215
    process->Set(String::NewSymbol("traceDeprecation"), True());
2216
  }
2217

    
2218
  size_t size = 2*PATH_MAX;
2219
  char* execPath = new char[size];
2220
  if (uv_exepath(execPath, &size) != 0) {
2221
    // as a last ditch effort, fallback on argv[0] ?
2222
    process->Set(String::NewSymbol("execPath"), String::New(argv[0]));
2223
  } else {
2224
    process->Set(String::NewSymbol("execPath"), String::New(execPath, size));
2225
  }
2226
  delete [] execPath;
2227

    
2228
  process->SetAccessor(String::New("debugPort"),
2229
                       DebugPortGetter,
2230
                       DebugPortSetter);
2231

    
2232

    
2233
  // define various internal methods
2234
  NODE_SET_METHOD(process, "_getActiveRequests", GetActiveRequests);
2235
  NODE_SET_METHOD(process, "_getActiveHandles", GetActiveHandles);
2236
  NODE_SET_METHOD(process, "_needTickCallback", NeedTickCallback);
2237
  NODE_SET_METHOD(process, "reallyExit", Exit);
2238
  NODE_SET_METHOD(process, "abort", Abort);
2239
  NODE_SET_METHOD(process, "chdir", Chdir);
2240
  NODE_SET_METHOD(process, "cwd", Cwd);
2241

    
2242
  NODE_SET_METHOD(process, "umask", Umask);
2243

    
2244
#ifdef __POSIX__
2245
  NODE_SET_METHOD(process, "getuid", GetUid);
2246
  NODE_SET_METHOD(process, "setuid", SetUid);
2247

    
2248
  NODE_SET_METHOD(process, "setgid", SetGid);
2249
  NODE_SET_METHOD(process, "getgid", GetGid);
2250
#endif // __POSIX__
2251

    
2252
  NODE_SET_METHOD(process, "_kill", Kill);
2253

    
2254
  NODE_SET_METHOD(process, "_debugProcess", DebugProcess);
2255
  NODE_SET_METHOD(process, "_debugPause", DebugPause);
2256
  NODE_SET_METHOD(process, "_debugEnd", DebugEnd);
2257

    
2258
  NODE_SET_METHOD(process, "hrtime", Hrtime);
2259

    
2260
  NODE_SET_METHOD(process, "dlopen", DLOpen);
2261

    
2262
  NODE_SET_METHOD(process, "uptime", Uptime);
2263
  NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
2264

    
2265
  NODE_SET_METHOD(process, "binding", Binding);
2266

    
2267
  return process;
2268
}
2269

    
2270

    
2271
static void AtExit() {
2272
  uv_tty_reset_mode();
2273
}
2274

    
2275

    
2276
static void SignalExit(int signal) {
2277
  uv_tty_reset_mode();
2278
  _exit(1);
2279
}
2280

    
2281

    
2282
void Load(Handle<Object> process_l) {
2283
  // Compile, execute the src/node.js file. (Which was included as static C
2284
  // string in node_natives.h. 'natve_node' is the string containing that
2285
  // source code.)
2286

    
2287
  // The node.js file returns a function 'f'
2288
  atexit(AtExit);
2289

    
2290
  TryCatch try_catch;
2291

    
2292
  Local<Value> f_value = ExecuteString(MainSource(),
2293
                                       IMMUTABLE_STRING("node.js"));
2294
  if (try_catch.HasCaught())  {
2295
    ReportException(try_catch, true);
2296
    exit(10);
2297
  }
2298
  assert(f_value->IsFunction());
2299
  Local<Function> f = Local<Function>::Cast(f_value);
2300

    
2301
  // Now we call 'f' with the 'process' variable that we've built up with
2302
  // all our bindings. Inside node.js we'll take care of assigning things to
2303
  // their places.
2304

    
2305
  // We start the process this way in order to be more modular. Developers
2306
  // who do not like how 'src/node.js' setups the module system but do like
2307
  // Node's I/O bindings may want to replace 'f' with their own function.
2308

    
2309
  // Add a reference to the global object
2310
  Local<Object> global = v8::Context::GetCurrent()->Global();
2311
  Local<Value> args[1] = { Local<Value>::New(process_l) };
2312

    
2313
#if defined HAVE_DTRACE || defined HAVE_ETW || defined HAVE_SYSTEMTAP
2314
  InitDTrace(global);
2315
#endif
2316

    
2317
  f->Call(global, 1, args);
2318

    
2319
  if (try_catch.HasCaught())  {
2320
    ReportException(try_catch, true);
2321
    exit(11);
2322
  }
2323
}
2324

    
2325
static void PrintHelp();
2326

    
2327
static void ParseDebugOpt(const char* arg) {
2328
  const char *p = 0;
2329

    
2330
  use_debug_agent = true;
2331
  if (!strcmp (arg, "--debug-brk")) {
2332
    debug_wait_connect = true;
2333
    return;
2334
  } else if (!strcmp(arg, "--debug")) {
2335
    return;
2336
  } else if (strstr(arg, "--debug-brk=") == arg) {
2337
    debug_wait_connect = true;
2338
    p = 1 + strchr(arg, '=');
2339
    debug_port = atoi(p);
2340
  } else if (strstr(arg, "--debug=") == arg) {
2341
    p = 1 + strchr(arg, '=');
2342
    debug_port = atoi(p);
2343
  }
2344
  if (p && debug_port > 1024 && debug_port <  65536)
2345
      return;
2346

    
2347
  fprintf(stderr, "Bad debug option.\n");
2348
  if (p) fprintf(stderr, "Debug port must be in range 1025 to 65535.\n");
2349

    
2350
  PrintHelp();
2351
  exit(1);
2352
}
2353

    
2354
static void PrintHelp() {
2355
  printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
2356
         "       node debug script.js [arguments] \n"
2357
         "\n"
2358
         "Options:\n"
2359
         "  -v, --version        print node's version\n"
2360
         "  -e, --eval script    evaluate script\n"
2361
         "  -p, --print          evaluate script and print result\n"
2362
         "  -i, --interactive    always enter the REPL even if stdin\n"
2363
         "                       does not appear to be a terminal\n"
2364
         "  --no-deprecation     silence deprecation warnings\n"
2365
         "  --trace-deprecation  show stack traces on deprecations\n"
2366
         "  --v8-options         print v8 command line options\n"
2367
         "  --max-stack-size=val set max v8 stack size (bytes)\n"
2368
         "\n"
2369
         "Environment variables:\n"
2370
#ifdef _WIN32
2371
         "NODE_PATH              ';'-separated list of directories\n"
2372
#else
2373
         "NODE_PATH              ':'-separated list of directories\n"
2374
#endif
2375
         "                       prefixed to the module search path.\n"
2376
         "NODE_MODULE_CONTEXTS   Set to 1 to load modules in their own\n"
2377
         "                       global contexts.\n"
2378
         "NODE_DISABLE_COLORS    Set to 1 to disable colors in the REPL\n"
2379
         "\n"
2380
         "Documentation can be found at http://nodejs.org/\n");
2381
}
2382

    
2383
// Parse node command line arguments.
2384
static void ParseArgs(int argc, char **argv) {
2385
  int i;
2386

    
2387
  // TODO use parse opts
2388
  for (i = 1; i < argc; i++) {
2389
    const char *arg = argv[i];
2390
    if (strstr(arg, "--debug") == arg) {
2391
      ParseDebugOpt(arg);
2392
      argv[i] = const_cast<char*>("");
2393
    } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
2394
      printf("%s\n", NODE_VERSION);
2395
      exit(0);
2396
    } else if (strstr(arg, "--max-stack-size=") == arg) {
2397
      const char *p = 0;
2398
      p = 1 + strchr(arg, '=');
2399
      max_stack_size = atoi(p);
2400
      argv[i] = const_cast<char*>("");
2401
    } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
2402
      PrintHelp();
2403
      exit(0);
2404
    } else if (strcmp(arg, "--eval") == 0   ||
2405
               strcmp(arg, "-e") == 0       ||
2406
               strcmp(arg, "--print") == 0  ||
2407
               strcmp(arg, "-pe") == 0      ||
2408
               strcmp(arg, "-p") == 0) {
2409
      bool is_eval = strchr(arg, 'e') != NULL;
2410
      bool is_print = strchr(arg, 'p') != NULL;
2411

    
2412
      // argument to -p and --print is optional
2413
      if (is_eval == true && i + 1 >= argc) {
2414
        fprintf(stderr, "Error: %s requires an argument\n", arg);
2415
        exit(1);
2416
      }
2417

    
2418
      print_eval = print_eval || is_print;
2419
      argv[i] = const_cast<char*>("");
2420

    
2421
      // --eval, -e and -pe always require an argument
2422
      if (is_eval == true) {
2423
        eval_string = argv[++i];
2424
        continue;
2425
      }
2426

    
2427
      // next arg is the expression to evaluate unless it starts with:
2428
      //  - a dash, then it's another switch
2429
      //  - "\\-", then it's an escaped expression, drop the backslash
2430
      if (argv[i + 1] == NULL) continue;
2431
      if (argv[i + 1][0] == '-') continue;
2432
      eval_string = argv[++i];
2433
      if (strncmp(eval_string, "\\-", 2) == 0) ++eval_string;
2434
    } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
2435
      force_repl = true;
2436
      argv[i] = const_cast<char*>("");
2437
    } else if (strcmp(arg, "--v8-options") == 0) {
2438
      argv[i] = const_cast<char*>("--help");
2439
    } else if (strcmp(arg, "--no-deprecation") == 0) {
2440
      argv[i] = const_cast<char*>("");
2441
      no_deprecation = true;
2442
    } else if (strcmp(arg, "--trace-deprecation") == 0) {
2443
      argv[i] = const_cast<char*>("");
2444
      trace_deprecation = true;
2445
    } else if (argv[i][0] != '-') {
2446
      break;
2447
    }
2448
  }
2449

    
2450
  option_end_index = i;
2451
}
2452

    
2453

    
2454
static Isolate* node_isolate = NULL;
2455
static volatile bool debugger_running = false;
2456

    
2457

    
2458
static uv_async_t dispatch_debug_messages_async;
2459

    
2460

    
2461
// Called from the main thread.
2462
static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle, int status) {
2463
  v8::Debug::ProcessDebugMessages();
2464
}
2465

    
2466

    
2467
// Called from V8 Debug Agent TCP thread.
2468
static void DispatchMessagesDebugAgentCallback() {
2469
  uv_async_send(&dispatch_debug_messages_async);
2470
}
2471

    
2472

    
2473
static void EnableDebug(bool wait_connect) {
2474
  // If we're called from another thread, make sure to enter the right
2475
  // v8 isolate.
2476
  node_isolate->Enter();
2477

    
2478
  v8::Debug::SetDebugMessageDispatchHandler(DispatchMessagesDebugAgentCallback,
2479
                                            false);
2480

    
2481
  uv_async_init(uv_default_loop(),
2482
                &dispatch_debug_messages_async,
2483
                DispatchDebugMessagesAsyncCallback);
2484
  uv_unref((uv_handle_t*) &dispatch_debug_messages_async);
2485

    
2486
  // Start the debug thread and it's associated TCP server on port 5858.
2487
  bool r = v8::Debug::EnableAgent("node " NODE_VERSION,
2488
                                  debug_port,
2489
                                  wait_connect);
2490

    
2491
  // Crappy check that everything went well. FIXME
2492
  assert(r);
2493

    
2494
  // Print out some information.
2495
  fprintf(stderr, "debugger listening on port %d\n", debug_port);
2496
  fflush(stderr);
2497

    
2498
  debugger_running = true;
2499

    
2500
  node_isolate->Exit();
2501
}
2502

    
2503

    
2504
#ifdef __POSIX__
2505
static void EnableDebugSignalHandler(int signal) {
2506
  // Break once process will return execution to v8
2507
  v8::Debug::DebugBreak(node_isolate);
2508

    
2509
  if (!debugger_running) {
2510
    fprintf(stderr, "Hit SIGUSR1 - starting debugger agent.\n");
2511
    EnableDebug(false);
2512
  }
2513
}
2514

    
2515

    
2516
static void RegisterSignalHandler(int signal, void (*handler)(int)) {
2517
  struct sigaction sa;
2518

    
2519
  memset(&sa, 0, sizeof(sa));
2520
  sa.sa_handler = handler;
2521
  sigfillset(&sa.sa_mask);
2522
  sigaction(signal, &sa, NULL);
2523
}
2524

    
2525

    
2526
Handle<Value> DebugProcess(const Arguments& args) {
2527
  HandleScope scope;
2528

    
2529
  if (args.Length() != 1) {
2530
    return ThrowException(Exception::Error(
2531
        String::New("Invalid number of arguments.")));
2532
  }
2533

    
2534
  pid_t pid;
2535
  int r;
2536

    
2537
  pid = args[0]->IntegerValue();
2538
  r = kill(pid, SIGUSR1);
2539
  if (r != 0) {
2540
    return ThrowException(ErrnoException(errno, "kill"));
2541
  }
2542

    
2543
  return Undefined();
2544
}
2545
#endif // __POSIX__
2546

    
2547

    
2548
#ifdef _WIN32
2549
DWORD WINAPI EnableDebugThreadProc(void* arg) {
2550
  // Break once process will return execution to v8
2551
  if (!debugger_running) {
2552
    for (int i = 0; i < 1; i++) {
2553
      fprintf(stderr, "Starting debugger agent.\r\n");
2554
      fflush(stderr);
2555
      EnableDebug(false);
2556
    }
2557
  }
2558

    
2559
  v8::Debug::DebugBreak();
2560

    
2561
  return 0;
2562
}
2563

    
2564

    
2565
static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
2566
    size_t buf_len) {
2567
  return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
2568
}
2569

    
2570

    
2571
static int RegisterDebugSignalHandler() {
2572
  wchar_t mapping_name[32];
2573
  HANDLE mapping_handle;
2574
  DWORD pid;
2575
  LPTHREAD_START_ROUTINE* handler;
2576

    
2577
  pid = GetCurrentProcessId();
2578

    
2579
  if (GetDebugSignalHandlerMappingName(pid,
2580
                                       mapping_name,
2581
                                       ARRAY_SIZE(mapping_name)) < 0) {
2582
    return -1;
2583
  }
2584

    
2585
  mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
2586
                                      NULL,
2587
                                      PAGE_READWRITE,
2588
                                      0,
2589
                                      sizeof *handler,
2590
                                      mapping_name);
2591
  if (mapping_handle == NULL) {
2592
    return -1;
2593
  }
2594

    
2595
  handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
2596
      MapViewOfFile(mapping_handle,
2597
                    FILE_MAP_ALL_ACCESS,
2598
                    0,
2599
                    0,
2600
                    sizeof *handler));
2601
  if (handler == NULL) {
2602
    CloseHandle(mapping_handle);
2603
    return -1;
2604
  }
2605

    
2606
  *handler = EnableDebugThreadProc;
2607

    
2608
  UnmapViewOfFile((void*) handler);
2609

    
2610
  return 0;
2611
}
2612

    
2613

    
2614
static Handle<Value> DebugProcess(const Arguments& args) {
2615
  HandleScope scope;
2616
  Handle<Value> rv = Undefined();
2617
  DWORD pid;
2618
  HANDLE process = NULL;
2619
  HANDLE thread = NULL;
2620
  HANDLE mapping = NULL;
2621
  wchar_t mapping_name[32];
2622
  LPTHREAD_START_ROUTINE* handler = NULL;
2623

    
2624
  if (args.Length() != 1) {
2625
    rv = ThrowException(Exception::Error(String::New("Invalid number of arguments.")));
2626
    goto out;
2627
  }
2628

    
2629
  pid = (DWORD) args[0]->IntegerValue();
2630

    
2631
  process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
2632
                            PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
2633
                            PROCESS_VM_READ,
2634
                        FALSE,
2635
                        pid);
2636
  if (process == NULL) {
2637
    rv = ThrowException(WinapiErrnoException(GetLastError(), "OpenProcess"));
2638
    goto out;
2639
  }
2640

    
2641
  if (GetDebugSignalHandlerMappingName(pid,
2642
                                       mapping_name,
2643
                                       ARRAY_SIZE(mapping_name)) < 0) {
2644
    rv = ThrowException(ErrnoException(errno, "sprintf"));
2645
    goto out;
2646
  }
2647

    
2648
  mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
2649
  if (mapping == NULL) {
2650
    rv = ThrowException(WinapiErrnoException(GetLastError(),
2651
                                             "OpenFileMappingW"));
2652
    goto out;
2653
  }
2654

    
2655
  handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
2656
      MapViewOfFile(mapping,
2657
                    FILE_MAP_READ,
2658
                    0,
2659
                    0,
2660
                    sizeof *handler));
2661
  if (handler == NULL || *handler == NULL) {
2662
    rv = ThrowException(WinapiErrnoException(GetLastError(), "MapViewOfFile"));
2663
    goto out;
2664
  }
2665

    
2666
  thread = CreateRemoteThread(process,
2667
                              NULL,
2668
                              0,
2669
                              *handler,
2670
                              NULL,
2671
                              0,
2672
                              NULL);
2673
  if (thread == NULL) {
2674
    rv = ThrowException(WinapiErrnoException(GetLastError(),
2675
                                             "CreateRemoteThread"));
2676
    goto out;
2677
  }
2678

    
2679
  // Wait for the thread to terminate
2680
  if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
2681
    rv = ThrowException(WinapiErrnoException(GetLastError(),
2682
                                             "WaitForSingleObject"));
2683
    goto out;
2684
  }
2685

    
2686
 out:
2687
  if (process != NULL) {
2688
   CloseHandle(process);
2689
  }
2690
  if (thread != NULL) {
2691
    CloseHandle(thread);
2692
  }
2693
  if (handler != NULL) {
2694
    UnmapViewOfFile(handler);
2695
  }
2696
  if (mapping != NULL) {
2697
    CloseHandle(mapping);
2698
  }
2699

    
2700
  return Undefined();
2701
}
2702
#endif // _WIN32
2703

    
2704

    
2705
static Handle<Value> DebugPause(const Arguments& args) {
2706
  v8::Debug::DebugBreak(node_isolate);
2707
  return Undefined();
2708
}
2709

    
2710

    
2711
static Handle<Value> DebugEnd(const Arguments& args) {
2712
  if (debugger_running) {
2713
    v8::Debug::DisableAgent();
2714
    debugger_running = false;
2715
  }
2716

    
2717
  return Undefined();
2718
}
2719

    
2720

    
2721
char** Init(int argc, char *argv[]) {
2722
  // Initialize prog_start_time to get relative uptime.
2723
  uv_uptime(&prog_start_time);
2724

    
2725
  // Make inherited handles noninheritable.
2726
  uv_disable_stdio_inheritance();
2727

    
2728
  // Parse a few arguments which are specific to Node.
2729
  node::ParseArgs(argc, argv);
2730
  // Parse the rest of the args (up to the 'option_end_index' (where '--' was
2731
  // in the command line))
2732
  int v8argc = option_end_index;
2733
  char **v8argv = argv;
2734

    
2735
  if (debug_wait_connect) {
2736
    // v8argv is a copy of argv up to the script file argument +2 if --debug-brk
2737
    // to expose the v8 debugger js object so that node.js can set
2738
    // a breakpoint on the first line of the startup script
2739
    v8argc += 2;
2740
    v8argv = new char*[v8argc];
2741
    memcpy(v8argv, argv, sizeof(*argv) * option_end_index);
2742
    v8argv[option_end_index] = const_cast<char*>("--expose_debug_as");
2743
    v8argv[option_end_index + 1] = const_cast<char*>("v8debug");
2744
  }
2745

    
2746
  // For the normal stack which moves from high to low addresses when frames
2747
  // are pushed, we can compute the limit as stack_size bytes below the
2748
  // the address of a stack variable (e.g. &stack_var) as an approximation
2749
  // of the start of the stack (we're assuming that we haven't pushed a lot
2750
  // of frames yet).
2751
  if (max_stack_size != 0) {
2752
    uint32_t stack_var;
2753
    ResourceConstraints constraints;
2754

    
2755
    uint32_t *stack_limit = &stack_var - (max_stack_size / sizeof(uint32_t));
2756
    constraints.set_stack_limit(stack_limit);
2757
    SetResourceConstraints(&constraints); // Must be done before V8::Initialize
2758
  }
2759
  V8::SetFlagsFromCommandLine(&v8argc, v8argv, false);
2760

    
2761
#ifdef __POSIX__
2762
  // Ignore SIGPIPE
2763
  RegisterSignalHandler(SIGPIPE, SIG_IGN);
2764
  RegisterSignalHandler(SIGINT, SignalExit);
2765
  RegisterSignalHandler(SIGTERM, SignalExit);
2766
#endif // __POSIX__
2767

    
2768
  uv_idle_init(uv_default_loop(), &tick_spinner);
2769

    
2770
  uv_check_init(uv_default_loop(), &gc_check);
2771
  uv_check_start(&gc_check, node::Check);
2772
  uv_unref(reinterpret_cast<uv_handle_t*>(&gc_check));
2773

    
2774
  uv_idle_init(uv_default_loop(), &gc_idle);
2775
  uv_unref(reinterpret_cast<uv_handle_t*>(&gc_idle));
2776

    
2777
  uv_timer_init(uv_default_loop(), &gc_timer);
2778
  uv_unref(reinterpret_cast<uv_handle_t*>(&gc_timer));
2779

    
2780
  V8::SetFatalErrorHandler(node::OnFatalError);
2781

    
2782
  // Fetch a reference to the main isolate, so we have a reference to it
2783
  // even when we need it to access it from another (debugger) thread.
2784
  node_isolate = Isolate::GetCurrent();
2785

    
2786
  // If the --debug flag was specified then initialize the debug thread.
2787
  if (use_debug_agent) {
2788
    EnableDebug(debug_wait_connect);
2789
  } else {
2790
#ifdef _WIN32
2791
    RegisterDebugSignalHandler();
2792
#else // Posix
2793
    RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
2794
#endif // __POSIX__
2795
  }
2796

    
2797
  return argv;
2798
}
2799

    
2800

    
2801
struct AtExitCallback {
2802
  AtExitCallback* next_;
2803
  void (*cb_)(void* arg);
2804
  void* arg_;
2805
};
2806

    
2807
static AtExitCallback* at_exit_functions_;
2808

    
2809

    
2810
void RunAtExit() {
2811
  AtExitCallback* p = at_exit_functions_;
2812
  at_exit_functions_ = NULL;
2813

    
2814
  while (p) {
2815
    AtExitCallback* q = p->next_;
2816
    p->cb_(p->arg_);
2817
    delete p;
2818
    p = q;
2819
  }
2820
}
2821

    
2822

    
2823
void AtExit(void (*cb)(void* arg), void* arg) {
2824
  AtExitCallback* p = new AtExitCallback;
2825
  p->cb_ = cb;
2826
  p->arg_ = arg;
2827
  p->next_ = at_exit_functions_;
2828
  at_exit_functions_ = p;
2829
}
2830

    
2831

    
2832
void EmitExit(v8::Handle<v8::Object> process_l) {
2833
  // process.emit('exit')
2834
  process_l->Set(String::NewSymbol("_exiting"), True());
2835
  Local<Value> emit_v = process_l->Get(String::New("emit"));
2836
  assert(emit_v->IsFunction());
2837
  Local<Function> emit = Local<Function>::Cast(emit_v);
2838
  Local<Value> args[] = { String::New("exit"), Integer::New(0) };
2839
  TryCatch try_catch;
2840
  emit->Call(process_l, 2, args);
2841
  if (try_catch.HasCaught()) {
2842
    FatalException(try_catch);
2843
  }
2844
}
2845

    
2846
static char **copy_argv(int argc, char **argv) {
2847
  size_t strlen_sum;
2848
  char **argv_copy;
2849
  char *argv_data;
2850
  size_t len;
2851
  int i;
2852

    
2853
  strlen_sum = 0;
2854
  for(i = 0; i < argc; i++) {
2855
    strlen_sum += strlen(argv[i]) + 1;
2856
  }
2857

    
2858
  argv_copy = (char **) malloc(sizeof(char *) * (argc + 1) + strlen_sum);
2859
  if (!argv_copy) {
2860
    return NULL;
2861
  }
2862

    
2863
  argv_data = (char *) argv_copy + sizeof(char *) * (argc + 1);
2864

    
2865
  for(i = 0; i < argc; i++) {
2866
    argv_copy[i] = argv_data;
2867
    len = strlen(argv[i]) + 1;
2868
    memcpy(argv_data, argv[i], len);
2869
    argv_data += len;
2870
  }
2871

    
2872
  argv_copy[argc] = NULL;
2873

    
2874
  return argv_copy;
2875
}
2876

    
2877
int Start(int argc, char *argv[]) {
2878
  // Hack aroung with the argv pointer. Used for process.title = "blah".
2879
  argv = uv_setup_args(argc, argv);
2880

    
2881
  // Logic to duplicate argv as Init() modifies arguments
2882
  // that are passed into it.
2883
  char **argv_copy = copy_argv(argc, argv);
2884

    
2885
  // This needs to run *before* V8::Initialize()
2886
  // Use copy here as to not modify the original argv:
2887
  Init(argc, argv_copy);
2888

    
2889
  V8::Initialize();
2890
  {
2891
    Locker locker;
2892
    HandleScope handle_scope;
2893

    
2894
    // Create the one and only Context.
2895
    Persistent<Context> context = Context::New();
2896
    Context::Scope context_scope(context);
2897

    
2898
    process_symbol = NODE_PSYMBOL("process");
2899
    domain_symbol = NODE_PSYMBOL("domain");
2900

    
2901
    // Use original argv, as we're just copying values out of it.
2902
    Handle<Object> process_l = SetupProcessObject(argc, argv);
2903
    v8_typed_array::AttachBindings(context->Global());
2904

    
2905
    // Create all the objects, load modules, do everything.
2906
    // so your next reading stop should be node::Load()!
2907
    Load(process_l);
2908

    
2909
    // All our arguments are loaded. We've evaluated all of the scripts. We
2910
    // might even have created TCP servers. Now we enter the main eventloop. If
2911
    // there are no watchers on the loop (except for the ones that were
2912
    // uv_unref'd) then this function exits. As long as there are active
2913
    // watchers, it blocks.
2914
    uv_run(uv_default_loop());
2915

    
2916
    EmitExit(process_l);
2917
    RunAtExit();
2918

    
2919
#ifndef NDEBUG
2920
    context.Dispose();
2921
#endif
2922
  }
2923

    
2924
#ifndef NDEBUG
2925
  // Clean up. Not strictly necessary.
2926
  V8::Dispose();
2927
#endif  // NDEBUG
2928

    
2929
  // Clean up the copy:
2930
  free(argv_copy);
2931

    
2932
  return 0;
2933
}
2934

    
2935

    
2936
}  // namespace node