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 @ f230a1cf

History | View | Annotate | Download (86.6 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 "node_buffer.h"
24
#include "node_constants.h"
25
#include "node_file.h"
26
#include "node_http_parser.h"
27
#include "node_javascript.h"
28
#include "node_version.h"
29

    
30
#if defined HAVE_PERFCTR
31
#include "node_counters.h"
32
#endif
33

    
34
#if HAVE_OPENSSL
35
#include "node_crypto.h"
36
#endif
37

    
38
#if defined HAVE_DTRACE || defined HAVE_ETW
39
#include "node_dtrace.h"
40
#endif
41

    
42
#include "ares.h"
43
#include "async-wrap.h"
44
#include "async-wrap-inl.h"
45
#include "env.h"
46
#include "env-inl.h"
47
#include "handle_wrap.h"
48
#include "req_wrap.h"
49
#include "string_bytes.h"
50
#include "uv.h"
51
#include "v8-debug.h"
52
#include "v8-profiler.h"
53
#include "zlib.h"
54

    
55
#include <assert.h>
56
#include <errno.h>
57
#include <limits.h>  // PATH_MAX
58
#include <locale.h>
59
#include <signal.h>
60
#include <stdio.h>
61
#include <stdlib.h>
62
#include <string.h>
63
#include <sys/types.h>
64

    
65
#if defined(_MSC_VER)
66
#include <direct.h>
67
#include <io.h>
68
#include <process.h>
69
#define strcasecmp _stricmp
70
#define getpid _getpid
71
#define umask _umask
72
typedef int mode_t;
73
#else
74
#include <sys/resource.h>  // getrlimit, setrlimit
75
#include <unistd.h>  // setuid, getuid
76
#endif
77

    
78
#if defined(__POSIX__) && !defined(__ANDROID__)
79
#include <pwd.h>  // getpwnam()
80
#include <grp.h>  // getgrnam()
81
#endif
82

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

    
90
namespace node {
91

    
92
using v8::Array;
93
using v8::ArrayBuffer;
94
using v8::Boolean;
95
using v8::Context;
96
using v8::Exception;
97
using v8::Function;
98
using v8::FunctionCallbackInfo;
99
using v8::FunctionTemplate;
100
using v8::Handle;
101
using v8::HandleScope;
102
using v8::HeapStatistics;
103
using v8::Integer;
104
using v8::Isolate;
105
using v8::Local;
106
using v8::Locker;
107
using v8::Message;
108
using v8::Number;
109
using v8::Object;
110
using v8::ObjectTemplate;
111
using v8::PropertyCallbackInfo;
112
using v8::String;
113
using v8::ThrowException;
114
using v8::TryCatch;
115
using v8::Uint32;
116
using v8::V8;
117
using v8::Value;
118
using v8::kExternalUnsignedIntArray;
119

    
120
// FIXME(bnoordhuis) Make these per-context?
121
QUEUE handle_wrap_queue = { &handle_wrap_queue, &handle_wrap_queue };
122
QUEUE req_wrap_queue = { &req_wrap_queue, &req_wrap_queue };
123

    
124
static bool print_eval = false;
125
static bool force_repl = false;
126
static bool trace_deprecation = false;
127
static bool throw_deprecation = false;
128
static const char* eval_string = NULL;
129
static bool use_debug_agent = false;
130
static bool debug_wait_connect = false;
131
static int debug_port = 5858;
132
static bool v8_is_profiling = false;
133

    
134
// used by C++ modules as well
135
bool no_deprecation = false;
136

    
137
// process-relative uptime base, initialized at start-up
138
static double prog_start_time;
139
static bool debugger_running;
140
static uv_async_t dispatch_debug_messages_async;
141

    
142
// Declared in node_internals.h
143
Isolate* node_isolate = NULL;
144

    
145

    
146
class ArrayBufferAllocator : public ArrayBuffer::Allocator {
147
 public:
148
  // Impose an upper limit to avoid out of memory errors that bring down
149
  // the process.
150
  static const size_t kMaxLength = 0x3fffffff;
151
  static ArrayBufferAllocator the_singleton;
152
  virtual ~ArrayBufferAllocator() {}
153
  virtual void* Allocate(size_t length);
154
  virtual void* AllocateUninitialized(size_t length);
155
  virtual void Free(void* data, size_t length);
156
 private:
157
  ArrayBufferAllocator() {}
158
  ArrayBufferAllocator(const ArrayBufferAllocator&);
159
  void operator=(const ArrayBufferAllocator&);
160
};
161

    
162
ArrayBufferAllocator ArrayBufferAllocator::the_singleton;
163

    
164

    
165
void* ArrayBufferAllocator::Allocate(size_t length) {
166
  if (length > kMaxLength)
167
    return NULL;
168
  return new char[length];
169
}
170

    
171

    
172
void* ArrayBufferAllocator::AllocateUninitialized(size_t length) {
173
  if (length > kMaxLength)
174
    return NULL;
175
  return new char[length];
176
}
177

    
178

    
179
void ArrayBufferAllocator::Free(void* data, size_t length) {
180
  delete[] static_cast<char*>(data);
181
}
182

    
183

    
184
static void CheckImmediate(uv_check_t* handle, int status) {
185
  Environment* env = Environment::from_immediate_check_handle(handle);
186
  Context::Scope context_scope(env->context());
187
  MakeCallback(env, env->process_object(), env->immediate_callback_string());
188
}
189

    
190

    
191
static void IdleImmediateDummy(uv_idle_t*, int) {
192
  // Do nothing. Only for maintaining event loop.
193
  // TODO(bnoordhuis) Maybe make libuv accept NULL idle callbacks.
194
}
195

    
196

    
197
static inline const char *errno_string(int errorno) {
198
#define ERRNO_CASE(e)  case e: return #e;
199
  switch (errorno) {
200
#ifdef EACCES
201
  ERRNO_CASE(EACCES);
202
#endif
203

    
204
#ifdef EADDRINUSE
205
  ERRNO_CASE(EADDRINUSE);
206
#endif
207

    
208
#ifdef EADDRNOTAVAIL
209
  ERRNO_CASE(EADDRNOTAVAIL);
210
#endif
211

    
212
#ifdef EAFNOSUPPORT
213
  ERRNO_CASE(EAFNOSUPPORT);
214
#endif
215

    
216
#ifdef EAGAIN
217
  ERRNO_CASE(EAGAIN);
218
#endif
219

    
220
#ifdef EWOULDBLOCK
221
# if EAGAIN != EWOULDBLOCK
222
  ERRNO_CASE(EWOULDBLOCK);
223
# endif
224
#endif
225

    
226
#ifdef EALREADY
227
  ERRNO_CASE(EALREADY);
228
#endif
229

    
230
#ifdef EBADF
231
  ERRNO_CASE(EBADF);
232
#endif
233

    
234
#ifdef EBADMSG
235
  ERRNO_CASE(EBADMSG);
236
#endif
237

    
238
#ifdef EBUSY
239
  ERRNO_CASE(EBUSY);
240
#endif
241

    
242
#ifdef ECANCELED
243
  ERRNO_CASE(ECANCELED);
244
#endif
245

    
246
#ifdef ECHILD
247
  ERRNO_CASE(ECHILD);
248
#endif
249

    
250
#ifdef ECONNABORTED
251
  ERRNO_CASE(ECONNABORTED);
252
#endif
253

    
254
#ifdef ECONNREFUSED
255
  ERRNO_CASE(ECONNREFUSED);
256
#endif
257

    
258
#ifdef ECONNRESET
259
  ERRNO_CASE(ECONNRESET);
260
#endif
261

    
262
#ifdef EDEADLK
263
  ERRNO_CASE(EDEADLK);
264
#endif
265

    
266
#ifdef EDESTADDRREQ
267
  ERRNO_CASE(EDESTADDRREQ);
268
#endif
269

    
270
#ifdef EDOM
271
  ERRNO_CASE(EDOM);
272
#endif
273

    
274
#ifdef EDQUOT
275
  ERRNO_CASE(EDQUOT);
276
#endif
277

    
278
#ifdef EEXIST
279
  ERRNO_CASE(EEXIST);
280
#endif
281

    
282
#ifdef EFAULT
283
  ERRNO_CASE(EFAULT);
284
#endif
285

    
286
#ifdef EFBIG
287
  ERRNO_CASE(EFBIG);
288
#endif
289

    
290
#ifdef EHOSTUNREACH
291
  ERRNO_CASE(EHOSTUNREACH);
292
#endif
293

    
294
#ifdef EIDRM
295
  ERRNO_CASE(EIDRM);
296
#endif
297

    
298
#ifdef EILSEQ
299
  ERRNO_CASE(EILSEQ);
300
#endif
301

    
302
#ifdef EINPROGRESS
303
  ERRNO_CASE(EINPROGRESS);
304
#endif
305

    
306
#ifdef EINTR
307
  ERRNO_CASE(EINTR);
308
#endif
309

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
390
#ifdef ENOLCK
391
# if ENOLINK != ENOLCK
392
  ERRNO_CASE(ENOLCK);
393
# endif
394
#endif
395

    
396
#ifdef ENOMEM
397
  ERRNO_CASE(ENOMEM);
398
#endif
399

    
400
#ifdef ENOMSG
401
  ERRNO_CASE(ENOMSG);
402
#endif
403

    
404
#ifdef ENOPROTOOPT
405
  ERRNO_CASE(ENOPROTOOPT);
406
#endif
407

    
408
#ifdef ENOSPC
409
  ERRNO_CASE(ENOSPC);
410
#endif
411

    
412
#ifdef ENOSR
413
  ERRNO_CASE(ENOSR);
414
#endif
415

    
416
#ifdef ENOSTR
417
  ERRNO_CASE(ENOSTR);
418
#endif
419

    
420
#ifdef ENOSYS
421
  ERRNO_CASE(ENOSYS);
422
#endif
423

    
424
#ifdef ENOTCONN
425
  ERRNO_CASE(ENOTCONN);
426
#endif
427

    
428
#ifdef ENOTDIR
429
  ERRNO_CASE(ENOTDIR);
430
#endif
431

    
432
#ifdef ENOTEMPTY
433
  ERRNO_CASE(ENOTEMPTY);
434
#endif
435

    
436
#ifdef ENOTSOCK
437
  ERRNO_CASE(ENOTSOCK);
438
#endif
439

    
440
#ifdef ENOTSUP
441
  ERRNO_CASE(ENOTSUP);
442
#else
443
# ifdef EOPNOTSUPP
444
  ERRNO_CASE(EOPNOTSUPP);
445
# endif
446
#endif
447

    
448
#ifdef ENOTTY
449
  ERRNO_CASE(ENOTTY);
450
#endif
451

    
452
#ifdef ENXIO
453
  ERRNO_CASE(ENXIO);
454
#endif
455

    
456

    
457
#ifdef EOVERFLOW
458
  ERRNO_CASE(EOVERFLOW);
459
#endif
460

    
461
#ifdef EPERM
462
  ERRNO_CASE(EPERM);
463
#endif
464

    
465
#ifdef EPIPE
466
  ERRNO_CASE(EPIPE);
467
#endif
468

    
469
#ifdef EPROTO
470
  ERRNO_CASE(EPROTO);
471
#endif
472

    
473
#ifdef EPROTONOSUPPORT
474
  ERRNO_CASE(EPROTONOSUPPORT);
475
#endif
476

    
477
#ifdef EPROTOTYPE
478
  ERRNO_CASE(EPROTOTYPE);
479
#endif
480

    
481
#ifdef ERANGE
482
  ERRNO_CASE(ERANGE);
483
#endif
484

    
485
#ifdef EROFS
486
  ERRNO_CASE(EROFS);
487
#endif
488

    
489
#ifdef ESPIPE
490
  ERRNO_CASE(ESPIPE);
491
#endif
492

    
493
#ifdef ESRCH
494
  ERRNO_CASE(ESRCH);
495
#endif
496

    
497
#ifdef ESTALE
498
  ERRNO_CASE(ESTALE);
499
#endif
500

    
501
#ifdef ETIME
502
  ERRNO_CASE(ETIME);
503
#endif
504

    
505
#ifdef ETIMEDOUT
506
  ERRNO_CASE(ETIMEDOUT);
507
#endif
508

    
509
#ifdef ETXTBSY
510
  ERRNO_CASE(ETXTBSY);
511
#endif
512

    
513
#ifdef EXDEV
514
  ERRNO_CASE(EXDEV);
515
#endif
516

    
517
  default: return "";
518
  }
519
}
520

    
521
const char *signo_string(int signo) {
522
#define SIGNO_CASE(e)  case e: return #e;
523
  switch (signo) {
524
#ifdef SIGHUP
525
  SIGNO_CASE(SIGHUP);
526
#endif
527

    
528
#ifdef SIGINT
529
  SIGNO_CASE(SIGINT);
530
#endif
531

    
532
#ifdef SIGQUIT
533
  SIGNO_CASE(SIGQUIT);
534
#endif
535

    
536
#ifdef SIGILL
537
  SIGNO_CASE(SIGILL);
538
#endif
539

    
540
#ifdef SIGTRAP
541
  SIGNO_CASE(SIGTRAP);
542
#endif
543

    
544
#ifdef SIGABRT
545
  SIGNO_CASE(SIGABRT);
546
#endif
547

    
548
#ifdef SIGIOT
549
# if SIGABRT != SIGIOT
550
  SIGNO_CASE(SIGIOT);
551
# endif
552
#endif
553

    
554
#ifdef SIGBUS
555
  SIGNO_CASE(SIGBUS);
556
#endif
557

    
558
#ifdef SIGFPE
559
  SIGNO_CASE(SIGFPE);
560
#endif
561

    
562
#ifdef SIGKILL
563
  SIGNO_CASE(SIGKILL);
564
#endif
565

    
566
#ifdef SIGUSR1
567
  SIGNO_CASE(SIGUSR1);
568
#endif
569

    
570
#ifdef SIGSEGV
571
  SIGNO_CASE(SIGSEGV);
572
#endif
573

    
574
#ifdef SIGUSR2
575
  SIGNO_CASE(SIGUSR2);
576
#endif
577

    
578
#ifdef SIGPIPE
579
  SIGNO_CASE(SIGPIPE);
580
#endif
581

    
582
#ifdef SIGALRM
583
  SIGNO_CASE(SIGALRM);
584
#endif
585

    
586
  SIGNO_CASE(SIGTERM);
587

    
588
#ifdef SIGCHLD
589
  SIGNO_CASE(SIGCHLD);
590
#endif
591

    
592
#ifdef SIGSTKFLT
593
  SIGNO_CASE(SIGSTKFLT);
594
#endif
595

    
596

    
597
#ifdef SIGCONT
598
  SIGNO_CASE(SIGCONT);
599
#endif
600

    
601
#ifdef SIGSTOP
602
  SIGNO_CASE(SIGSTOP);
603
#endif
604

    
605
#ifdef SIGTSTP
606
  SIGNO_CASE(SIGTSTP);
607
#endif
608

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

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

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

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

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

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

    
633
#ifdef SIGVTALRM
634
  SIGNO_CASE(SIGVTALRM);
635
#endif
636

    
637
#ifdef SIGPROF
638
  SIGNO_CASE(SIGPROF);
639
#endif
640

    
641
#ifdef SIGWINCH
642
  SIGNO_CASE(SIGWINCH);
643
#endif
644

    
645
#ifdef SIGIO
646
  SIGNO_CASE(SIGIO);
647
#endif
648

    
649
#ifdef SIGPOLL
650
# if SIGPOLL != SIGIO
651
  SIGNO_CASE(SIGPOLL);
652
# endif
653
#endif
654

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

    
659
#ifdef SIGPWR
660
# if SIGPWR != SIGLOST
661
  SIGNO_CASE(SIGPWR);
662
# endif
663
#endif
664

    
665
#ifdef SIGSYS
666
  SIGNO_CASE(SIGSYS);
667
#endif
668

    
669
  default: return "";
670
  }
671
}
672

    
673

    
674
Local<Value> ErrnoException(int errorno,
675
                            const char *syscall,
676
                            const char *msg,
677
                            const char *path) {
678
  Environment* env = Environment::GetCurrent(node_isolate);
679

    
680
  Local<Value> e;
681
  Local<String> estring = OneByteString(node_isolate, errno_string(errorno));
682
  if (msg == NULL || msg[0] == '\0') {
683
    msg = strerror(errorno);
684
  }
685
  Local<String> message = OneByteString(node_isolate, msg);
686

    
687
  Local<String> cons1 =
688
      String::Concat(estring, FIXED_ONE_BYTE_STRING(node_isolate, ", "));
689
  Local<String> cons2 = String::Concat(cons1, message);
690

    
691
  if (path) {
692
    Local<String> cons3 =
693
        String::Concat(cons2, FIXED_ONE_BYTE_STRING(node_isolate, " '"));
694
    Local<String> cons4 =
695
        String::Concat(cons3, String::NewFromUtf8(node_isolate, path));
696
    Local<String> cons5 =
697
        String::Concat(cons4, FIXED_ONE_BYTE_STRING(node_isolate, "'"));
698
    e = Exception::Error(cons5);
699
  } else {
700
    e = Exception::Error(cons2);
701
  }
702

    
703
  Local<Object> obj = e->ToObject();
704
  obj->Set(env->errno_string(), Integer::New(errorno, node_isolate));
705
  obj->Set(env->code_string(), estring);
706

    
707
  if (path != NULL) {
708
    obj->Set(env->path_string(), String::NewFromUtf8(node_isolate, path));
709
  }
710

    
711
  if (syscall != NULL) {
712
    obj->Set(env->syscall_string(), OneByteString(node_isolate, syscall));
713
  }
714

    
715
  return e;
716
}
717

    
718

    
719
// hack alert! copy of ErrnoException, tuned for uv errors
720
Local<Value> UVException(int errorno,
721
                         const char *syscall,
722
                         const char *msg,
723
                         const char *path) {
724
  Environment* env = Environment::GetCurrent(node_isolate);
725

    
726
  if (!msg || !msg[0])
727
    msg = uv_strerror(errorno);
728

    
729
  Local<String> estring = OneByteString(node_isolate, uv_err_name(errorno));
730
  Local<String> message = OneByteString(node_isolate, msg);
731
  Local<String> cons1 =
732
      String::Concat(estring, FIXED_ONE_BYTE_STRING(node_isolate, ", "));
733
  Local<String> cons2 = String::Concat(cons1, message);
734

    
735
  Local<Value> e;
736

    
737
  Local<String> path_str;
738

    
739
  if (path) {
740
#ifdef _WIN32
741
    if (strncmp(path, "\\\\?\\UNC\\", 8) == 0) {
742
      path_str = String::Concat(FIXED_ONE_BYTE_STRING(node_isolate, "\\\\"),
743
                                String::NewFromUtf8(node_isolate, path + 8));
744
    } else if (strncmp(path, "\\\\?\\", 4) == 0) {
745
      path_str = String::NewFromUtf8(node_isolate, path + 4);
746
    } else {
747
      path_str = String::NewFromUtf8(node_isolate, path);
748
    }
749
#else
750
    path_str = String::NewFromUtf8(node_isolate, path);
751
#endif
752

    
753
    Local<String> cons3 =
754
        String::Concat(cons2, FIXED_ONE_BYTE_STRING(node_isolate, " '"));
755
    Local<String> cons4 =
756
        String::Concat(cons3, path_str);
757
    Local<String> cons5 =
758
        String::Concat(cons4, FIXED_ONE_BYTE_STRING(node_isolate, "'"));
759
    e = Exception::Error(cons5);
760
  } else {
761
    e = Exception::Error(cons2);
762
  }
763

    
764
  Local<Object> obj = e->ToObject();
765
  // TODO(piscisaureus) errno should probably go
766
  obj->Set(env->errno_string(), Integer::New(errorno, node_isolate));
767
  obj->Set(env->code_string(), estring);
768

    
769
  if (path != NULL) {
770
    obj->Set(env->path_string(), path_str);
771
  }
772

    
773
  if (syscall != NULL) {
774
    obj->Set(env->syscall_string(), OneByteString(node_isolate, syscall));
775
  }
776

    
777
  return e;
778
}
779

    
780

    
781
#ifdef _WIN32
782
// Does about the same as strerror(),
783
// but supports all windows error messages
784
static const char *winapi_strerror(const int errorno) {
785
  char *errmsg = NULL;
786

    
787
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
788
      FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
789
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL);
790

    
791
  if (errmsg) {
792
    // Remove trailing newlines
793
    for (int i = strlen(errmsg) - 1;
794
        i >= 0 && (errmsg[i] == '\n' || errmsg[i] == '\r'); i--) {
795
      errmsg[i] = '\0';
796
    }
797

    
798
    return errmsg;
799
  } else {
800
    // FormatMessage failed
801
    return "Unknown error";
802
  }
803
}
804

    
805

    
806
Local<Value> WinapiErrnoException(int errorno,
807
                                  const char* syscall,
808
                                  const char* msg,
809
                                  const char* path) {
810
  Environment* env = Environment::GetCurrent(node_isolate);
811

    
812
  Local<Value> e;
813
  if (!msg || !msg[0]) {
814
    msg = winapi_strerror(errorno);
815
  }
816
  Local<String> message = OneByteString(node_isolate, msg);
817

    
818
  if (path) {
819
    Local<String> cons1 =
820
        String::Concat(message, FIXED_ONE_BYTE_STRING(node_isolate, " '"));
821
    Local<String> cons2 =
822
        String::Concat(cons1, String::NewFromUtf8(node_isolate, path));
823
    Local<String> cons3 =
824
        String::Concat(cons2, FIXED_ONE_BYTE_STRING(node_isolate, "'"));
825
    e = Exception::Error(cons3);
826
  } else {
827
    e = Exception::Error(message);
828
  }
829

    
830
  Local<Object> obj = e->ToObject();
831
  obj->Set(env->errno_string(), Integer::New(errorno, node_isolate));
832

    
833
  if (path != NULL) {
834
    obj->Set(env->path_string(), String::NewFromUtf8(node_isolate, path));
835
  }
836

    
837
  if (syscall != NULL) {
838
    obj->Set(env->syscall_string(), OneByteString(node_isolate, syscall));
839
  }
840

    
841
  return e;
842
}
843
#endif
844

    
845

    
846
void SetupAsyncListener(const FunctionCallbackInfo<Value>& args) {
847
  Environment* env = Environment::GetCurrent(args.GetIsolate());
848
  HandleScope handle_scope(args.GetIsolate());
849

    
850
  assert(args[0]->IsObject());
851
  assert(args[1]->IsFunction());
852
  assert(args[2]->IsFunction());
853
  assert(args[3]->IsFunction());
854
  assert(args[4]->IsFunction());
855
  assert(args[5]->IsFunction());
856

    
857
  env->set_async_listener_run_function(args[1].As<Function>());
858
  env->set_async_listener_load_function(args[2].As<Function>());
859
  env->set_async_listener_unload_function(args[3].As<Function>());
860
  env->set_async_listener_push_function(args[4].As<Function>());
861
  env->set_async_listener_strip_function(args[5].As<Function>());
862

    
863
  Local<Object> async_listener_flag_obj = args[0].As<Object>();
864
  Environment::AsyncListener* async_listener = env->async_listener();
865
  async_listener_flag_obj->SetIndexedPropertiesToExternalArrayData(
866
      async_listener->fields(),
867
      kExternalUnsignedIntArray,
868
      async_listener->fields_count());
869

    
870
  // Do a little housekeeping.
871
  env->process_object()->Delete(
872
      FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupAsyncListener"));
873
}
874

    
875

    
876
void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
877
  Environment* env = Environment::GetCurrent(args.GetIsolate());
878
  HandleScope handle_scope(args.GetIsolate());
879

    
880
  assert(args[0]->IsObject() && args[1]->IsFunction());
881

    
882
  // Values use to cross communicate with processNextTick.
883
  Local<Object> tick_info_obj = args[0].As<Object>();
884
  tick_info_obj->SetIndexedPropertiesToExternalArrayData(
885
      env->tick_info()->fields(),
886
      kExternalUnsignedIntArray,
887
      env->tick_info()->fields_count());
888

    
889
  env->set_tick_callback_function(args[1].As<Function>());
890

    
891
  // Do a little housekeeping.
892
  env->process_object()->Delete(
893
      FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupNextTick"));
894
}
895

    
896

    
897
Handle<Value> MakeCallback(Environment* env,
898
                           Handle<Object> object,
899
                           const Handle<Function> callback,
900
                           int argc,
901
                           Handle<Value> argv[]) {
902
  // If you hit this assertion, you forgot to enter the v8::Context first.
903
  assert(env->context() == env->isolate()->GetCurrentContext());
904

    
905
  Local<Object> process = env->process_object();
906

    
907
  TryCatch try_catch;
908
  try_catch.SetVerbose(true);
909

    
910
  // TODO(trevnorris): This is sucky for performance. Fix it.
911
  bool has_async_queue = object->Has(env->async_queue_string());
912
  if (has_async_queue) {
913
    Local<Value> argv[] = { object };
914
    env->async_listener_load_function()->Call(process, ARRAY_SIZE(argv), argv);
915

    
916
    if (try_catch.HasCaught())
917
      return Undefined(node_isolate);
918
  }
919

    
920
  Local<Value> ret = callback->Call(object, argc, argv);
921

    
922
  if (try_catch.HasCaught()) {
923
    return Undefined(node_isolate);
924
  }
925

    
926
  if (has_async_queue) {
927
    Local<Value> val = object.As<Value>();
928
    env->async_listener_unload_function()->Call(process, 1, &val);
929

    
930
    if (try_catch.HasCaught())
931
      return Undefined(node_isolate);
932
  }
933

    
934
  Environment::TickInfo* tick_info = env->tick_info();
935

    
936
  if (tick_info->in_tick()) {
937
    return ret;
938
  }
939

    
940
  if (tick_info->length() == 0) {
941
    tick_info->set_index(0);
942
    return ret;
943
  }
944

    
945
  tick_info->set_in_tick(true);
946

    
947
  // process nextTicks after call
948
  env->tick_callback_function()->Call(process, 0, NULL);
949

    
950
  tick_info->set_in_tick(false);
951

    
952
  if (try_catch.HasCaught()) {
953
    tick_info->set_last_threw(true);
954
    return Undefined(node_isolate);
955
  }
956

    
957
  return ret;
958
}
959

    
960

    
961
// Internal only.
962
Handle<Value> MakeCallback(Environment* env,
963
                           const Handle<Object> object,
964
                           uint32_t index,
965
                           int argc,
966
                           Handle<Value> argv[]) {
967
  Local<Function> callback = object->Get(index).As<Function>();
968
  assert(callback->IsFunction());
969

    
970
  return MakeCallback(env, object, callback, argc, argv);
971
}
972

    
973

    
974
Handle<Value> MakeCallback(Environment* env,
975
                           const Handle<Object> object,
976
                           const Handle<String> symbol,
977
                           int argc,
978
                           Handle<Value> argv[]) {
979
  Local<Function> callback = object->Get(symbol).As<Function>();
980
  assert(callback->IsFunction());
981
  return MakeCallback(env, object, callback, argc, argv);
982
}
983

    
984

    
985
Handle<Value> MakeCallback(Environment* env,
986
                           const Handle<Object> object,
987
                           const char* method,
988
                           int argc,
989
                           Handle<Value> argv[]) {
990
  Local<String> method_string = OneByteString(node_isolate, method);
991
  return MakeCallback(env, object, method_string, argc, argv);
992
}
993

    
994

    
995
Handle<Value> MakeCallback(const Handle<Object> object,
996
                           const char* method,
997
                           int argc,
998
                           Handle<Value> argv[]) {
999
  Local<Context> context = object->CreationContext();
1000
  Environment* env = Environment::GetCurrent(context);
1001
  Context::Scope context_scope(context);
1002
  HandleScope handle_scope(env->isolate());
1003
  return handle_scope.Close(MakeCallback(env, object, method, argc, argv));
1004
}
1005

    
1006

    
1007
Handle<Value> MakeCallback(const Handle<Object> object,
1008
                           const Handle<String> symbol,
1009
                           int argc,
1010
                           Handle<Value> argv[]) {
1011
  Local<Context> context = object->CreationContext();
1012
  Environment* env = Environment::GetCurrent(context);
1013
  Context::Scope context_scope(context);
1014
  HandleScope handle_scope(env->isolate());
1015
  return handle_scope.Close(MakeCallback(env, object, symbol, argc, argv));
1016
}
1017

    
1018

    
1019
Handle<Value> MakeCallback(const Handle<Object> object,
1020
                           const Handle<Function> callback,
1021
                           int argc,
1022
                           Handle<Value> argv[]) {
1023
  Local<Context> context = object->CreationContext();
1024
  Environment* env = Environment::GetCurrent(context);
1025
  Context::Scope context_scope(context);
1026
  HandleScope handle_scope(env->isolate());
1027
  return handle_scope.Close(MakeCallback(env, object, callback, argc, argv));
1028
}
1029

    
1030

    
1031
enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
1032
  HandleScope scope(node_isolate);
1033

    
1034
  if (!encoding_v->IsString())
1035
    return _default;
1036

    
1037
  String::Utf8Value encoding(encoding_v);
1038

    
1039
  if (strcasecmp(*encoding, "utf8") == 0) {
1040
    return UTF8;
1041
  } else if (strcasecmp(*encoding, "utf-8") == 0) {
1042
    return UTF8;
1043
  } else if (strcasecmp(*encoding, "ascii") == 0) {
1044
    return ASCII;
1045
  } else if (strcasecmp(*encoding, "base64") == 0) {
1046
    return BASE64;
1047
  } else if (strcasecmp(*encoding, "ucs2") == 0) {
1048
    return UCS2;
1049
  } else if (strcasecmp(*encoding, "ucs-2") == 0) {
1050
    return UCS2;
1051
  } else if (strcasecmp(*encoding, "utf16le") == 0) {
1052
    return UCS2;
1053
  } else if (strcasecmp(*encoding, "utf-16le") == 0) {
1054
    return UCS2;
1055
  } else if (strcasecmp(*encoding, "binary") == 0) {
1056
    return BINARY;
1057
  } else if (strcasecmp(*encoding, "buffer") == 0) {
1058
    return BUFFER;
1059
  } else if (strcasecmp(*encoding, "hex") == 0) {
1060
    return HEX;
1061
  } else if (strcasecmp(*encoding, "raw") == 0) {
1062
    if (!no_deprecation) {
1063
      fprintf(stderr, "'raw' (array of integers) has been removed. "
1064
                      "Use 'binary'.\n");
1065
    }
1066
    return BINARY;
1067
  } else if (strcasecmp(*encoding, "raws") == 0) {
1068
    if (!no_deprecation) {
1069
      fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
1070
                      "Please update your code.\n");
1071
    }
1072
    return BINARY;
1073
  } else {
1074
    return _default;
1075
  }
1076
}
1077

    
1078
Local<Value> Encode(const void *buf, size_t len, enum encoding encoding) {
1079
  return StringBytes::Encode(static_cast<const char*>(buf),
1080
                             len,
1081
                             encoding);
1082
}
1083

    
1084
// Returns -1 if the handle was not valid for decoding
1085
ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
1086
  HandleScope scope(node_isolate);
1087

    
1088
  if (val->IsArray()) {
1089
    fprintf(stderr, "'raw' encoding (array of integers) has been removed. "
1090
                    "Use 'binary'.\n");
1091
    assert(0);
1092
    return -1;
1093
  }
1094

    
1095
  return StringBytes::Size(val, encoding);
1096
}
1097

    
1098
#ifndef MIN
1099
# define MIN(a, b) ((a) < (b) ? (a) : (b))
1100
#endif
1101

    
1102
// Returns number of bytes written.
1103
ssize_t DecodeWrite(char *buf,
1104
                    size_t buflen,
1105
                    v8::Handle<v8::Value> val,
1106
                    enum encoding encoding) {
1107
  return StringBytes::Write(buf, buflen, val, encoding, NULL);
1108
}
1109

    
1110
void DisplayExceptionLine(Handle<Message> message) {
1111
  // Prevent re-entry into this function.  For example, if there is
1112
  // a throw from a program in vm.runInThisContext(code, filename, true),
1113
  // then we want to show the original failure, not the secondary one.
1114
  static bool displayed_error = false;
1115

    
1116
  if (displayed_error)
1117
    return;
1118
  displayed_error = true;
1119

    
1120
  uv_tty_reset_mode();
1121

    
1122
  fprintf(stderr, "\n");
1123

    
1124
  if (!message.IsEmpty()) {
1125
    // Print (filename):(line number): (message).
1126
    String::Utf8Value filename(message->GetScriptResourceName());
1127
    const char* filename_string = *filename;
1128
    int linenum = message->GetLineNumber();
1129
    fprintf(stderr, "%s:%i\n", filename_string, linenum);
1130
    // Print line of source code.
1131
    String::Utf8Value sourceline(message->GetSourceLine());
1132
    const char* sourceline_string = *sourceline;
1133

    
1134
    // Because of how node modules work, all scripts are wrapped with a
1135
    // "function (module, exports, __filename, ...) {"
1136
    // to provide script local variables.
1137
    //
1138
    // When reporting errors on the first line of a script, this wrapper
1139
    // function is leaked to the user. There used to be a hack here to
1140
    // truncate off the first 62 characters, but it caused numerous other
1141
    // problems when vm.runIn*Context() methods were used for non-module
1142
    // code.
1143
    //
1144
    // If we ever decide to re-instate such a hack, the following steps
1145
    // must be taken:
1146
    //
1147
    // 1. Pass a flag around to say "this code was wrapped"
1148
    // 2. Update the stack frame output so that it is also correct.
1149
    //
1150
    // It would probably be simpler to add a line rather than add some
1151
    // number of characters to the first line, since V8 truncates the
1152
    // sourceline to 78 characters, and we end up not providing very much
1153
    // useful debugging info to the user if we remove 62 characters.
1154

    
1155
    int start = message->GetStartColumn();
1156
    int end = message->GetEndColumn();
1157

    
1158
    fprintf(stderr, "%s\n", sourceline_string);
1159
    // Print wavy underline (GetUnderline is deprecated).
1160
    for (int i = 0; i < start; i++) {
1161
      fputc((sourceline_string[i] == '\t') ? '\t' : ' ', stderr);
1162
    }
1163
    for (int i = start; i < end; i++) {
1164
      fputc('^', stderr);
1165
    }
1166
    fputc('\n', stderr);
1167
  }
1168
}
1169

    
1170

    
1171
static void ReportException(Handle<Value> er, Handle<Message> message) {
1172
  HandleScope scope(node_isolate);
1173

    
1174
  DisplayExceptionLine(message);
1175

    
1176
  Local<Value> trace_value(
1177
      er->ToObject()->Get(FIXED_ONE_BYTE_STRING(node_isolate, "stack")));
1178
  String::Utf8Value trace(trace_value);
1179

    
1180
  // range errors have a trace member set to undefined
1181
  if (trace.length() > 0 && !trace_value->IsUndefined()) {
1182
    fprintf(stderr, "%s\n", *trace);
1183
  } else {
1184
    // this really only happens for RangeErrors, since they're the only
1185
    // kind that won't have all this info in the trace, or when non-Error
1186
    // objects are thrown manually.
1187
    Local<Value> message;
1188
    Local<Value> name;
1189

    
1190
    if (er->IsObject()) {
1191
      Local<Object> err_obj = er.As<Object>();
1192
      message = err_obj->Get(FIXED_ONE_BYTE_STRING(node_isolate, "message"));
1193
      name = err_obj->Get(FIXED_ONE_BYTE_STRING(node_isolate, "name"));
1194
    }
1195

    
1196
    if (message.IsEmpty() ||
1197
        message->IsUndefined() ||
1198
        name.IsEmpty() ||
1199
        name->IsUndefined()) {
1200
      // Not an error object. Just print as-is.
1201
      String::Utf8Value message(er);
1202
      fprintf(stderr, "%s\n", *message);
1203
    } else {
1204
      String::Utf8Value name_string(name);
1205
      String::Utf8Value message_string(message);
1206
      fprintf(stderr, "%s: %s\n", *name_string, *message_string);
1207
    }
1208
  }
1209

    
1210
  fflush(stderr);
1211
}
1212

    
1213

    
1214
static void ReportException(const TryCatch& try_catch) {
1215
  ReportException(try_catch.Exception(), try_catch.Message());
1216
}
1217

    
1218

    
1219
// Executes a str within the current v8 context.
1220
Local<Value> ExecuteString(Handle<String> source, Handle<Value> filename) {
1221
  HandleScope scope(node_isolate);
1222
  TryCatch try_catch;
1223

    
1224
  // try_catch must be nonverbose to disable FatalException() handler,
1225
  // we will handle exceptions ourself.
1226
  try_catch.SetVerbose(false);
1227

    
1228
  Local<v8::Script> script = v8::Script::Compile(source, filename);
1229
  if (script.IsEmpty()) {
1230
    ReportException(try_catch);
1231
    exit(3);
1232
  }
1233

    
1234
  Local<Value> result = script->Run();
1235
  if (result.IsEmpty()) {
1236
    ReportException(try_catch);
1237
    exit(4);
1238
  }
1239

    
1240
  return scope.Close(result);
1241
}
1242

    
1243

    
1244
static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
1245
  HandleScope scope(node_isolate);
1246

    
1247
  Local<Array> ary = Array::New();
1248
  QUEUE* q = NULL;
1249
  int i = 0;
1250

    
1251
  QUEUE_FOREACH(q, &req_wrap_queue) {
1252
    ReqWrap<uv_req_t>* w = CONTAINER_OF(q, ReqWrap<uv_req_t>, req_wrap_queue_);
1253
    if (w->persistent().IsEmpty())
1254
      continue;
1255
    ary->Set(i++, w->object());
1256
  }
1257

    
1258
  args.GetReturnValue().Set(ary);
1259
}
1260

    
1261

    
1262
// Non-static, friend of HandleWrap. Could have been a HandleWrap method but
1263
// implemented here for consistency with GetActiveRequests().
1264
void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
1265
  HandleScope scope(node_isolate);
1266

    
1267
  Local<Array> ary = Array::New();
1268
  QUEUE* q = NULL;
1269
  int i = 0;
1270

    
1271
  Local<String> owner_sym = FIXED_ONE_BYTE_STRING(node_isolate, "owner");
1272

    
1273
  QUEUE_FOREACH(q, &handle_wrap_queue) {
1274
    HandleWrap* w = CONTAINER_OF(q, HandleWrap, handle_wrap_queue_);
1275
    if (w->persistent().IsEmpty() || (w->flags_ & HandleWrap::kUnref))
1276
      continue;
1277
    Local<Object> object = w->object();
1278
    Local<Value> owner = object->Get(owner_sym);
1279
    if (owner->IsUndefined())
1280
      owner = object;
1281
    ary->Set(i++, owner);
1282
  }
1283

    
1284
  args.GetReturnValue().Set(ary);
1285
}
1286

    
1287

    
1288
static void Abort(const FunctionCallbackInfo<Value>& args) {
1289
  abort();
1290
}
1291

    
1292

    
1293
static void Chdir(const FunctionCallbackInfo<Value>& args) {
1294
  HandleScope scope(node_isolate);
1295

    
1296
  if (args.Length() != 1 || !args[0]->IsString()) {
1297
    return ThrowError("Bad argument.");  // FIXME(bnoordhuis) ThrowTypeError?
1298
  }
1299

    
1300
  String::Utf8Value path(args[0]);
1301
  int err = uv_chdir(*path);
1302
  if (err) {
1303
    return ThrowUVException(err, "uv_chdir");
1304
  }
1305
}
1306

    
1307

    
1308
static void Cwd(const FunctionCallbackInfo<Value>& args) {
1309
  HandleScope scope(node_isolate);
1310
#ifdef _WIN32
1311
  /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
1312
  char buf[MAX_PATH * 4 + 1];
1313
#else
1314
  char buf[PATH_MAX + 1];
1315
#endif
1316

    
1317
  int err = uv_cwd(buf, ARRAY_SIZE(buf) - 1);
1318
  if (err) {
1319
    return ThrowUVException(err, "uv_cwd");
1320
  }
1321

    
1322
  buf[ARRAY_SIZE(buf) - 1] = '\0';
1323
  Local<String> cwd = String::NewFromUtf8(node_isolate, buf);
1324

    
1325
  args.GetReturnValue().Set(cwd);
1326
}
1327

    
1328

    
1329
static void Umask(const FunctionCallbackInfo<Value>& args) {
1330
  HandleScope scope(node_isolate);
1331
  uint32_t old;
1332

    
1333
  if (args.Length() < 1 || args[0]->IsUndefined()) {
1334
    old = umask(0);
1335
    umask(static_cast<mode_t>(old));
1336
  } else if (!args[0]->IsInt32() && !args[0]->IsString()) {
1337
    return ThrowTypeError("argument must be an integer or octal string.");
1338
  } else {
1339
    int oct;
1340
    if (args[0]->IsInt32()) {
1341
      oct = args[0]->Uint32Value();
1342
    } else {
1343
      oct = 0;
1344
      String::Utf8Value str(args[0]);
1345

    
1346
      // Parse the octal string.
1347
      for (int i = 0; i < str.length(); i++) {
1348
        char c = (*str)[i];
1349
        if (c > '7' || c < '0') {
1350
          return ThrowTypeError("invalid octal string");
1351
        }
1352
        oct *= 8;
1353
        oct += c - '0';
1354
      }
1355
    }
1356
    old = umask(static_cast<mode_t>(oct));
1357
  }
1358

    
1359
  args.GetReturnValue().Set(old);
1360
}
1361

    
1362

    
1363
#if defined(__POSIX__) && !defined(__ANDROID__)
1364

    
1365
static const uid_t uid_not_found = static_cast<uid_t>(-1);
1366
static const gid_t gid_not_found = static_cast<gid_t>(-1);
1367

    
1368

    
1369
static uid_t uid_by_name(const char* name) {
1370
  struct passwd pwd;
1371
  struct passwd* pp;
1372
  char buf[8192];
1373

    
1374
  errno = 0;
1375
  pp = NULL;
1376

    
1377
  if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != NULL) {
1378
    return pp->pw_uid;
1379
  }
1380

    
1381
  return uid_not_found;
1382
}
1383

    
1384

    
1385
static char* name_by_uid(uid_t uid) {
1386
  struct passwd pwd;
1387
  struct passwd* pp;
1388
  char buf[8192];
1389
  int rc;
1390

    
1391
  errno = 0;
1392
  pp = NULL;
1393

    
1394
  if ((rc = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pp)) == 0 && pp != NULL) {
1395
    return strdup(pp->pw_name);
1396
  }
1397

    
1398
  if (rc == 0) {
1399
    errno = ENOENT;
1400
  }
1401

    
1402
  return NULL;
1403
}
1404

    
1405

    
1406
static gid_t gid_by_name(const char* name) {
1407
  struct group pwd;
1408
  struct group* pp;
1409
  char buf[8192];
1410

    
1411
  errno = 0;
1412
  pp = NULL;
1413

    
1414
  if (getgrnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != NULL) {
1415
    return pp->gr_gid;
1416
  }
1417

    
1418
  return gid_not_found;
1419
}
1420

    
1421

    
1422
#if 0  // For future use.
1423
static const char* name_by_gid(gid_t gid) {
1424
  struct group pwd;
1425
  struct group* pp;
1426
  char buf[8192];
1427
  int rc;
1428

1429
  errno = 0;
1430
  pp = NULL;
1431

1432
  if ((rc = getgrgid_r(gid, &pwd, buf, sizeof(buf), &pp)) == 0 && pp != NULL) {
1433
    return strdup(pp->gr_name);
1434
  }
1435

1436
  if (rc == 0) {
1437
    errno = ENOENT;
1438
  }
1439

1440
  return NULL;
1441
}
1442
#endif
1443

    
1444

    
1445
static uid_t uid_by_name(Handle<Value> value) {
1446
  if (value->IsUint32()) {
1447
    return static_cast<uid_t>(value->Uint32Value());
1448
  } else {
1449
    String::Utf8Value name(value);
1450
    return uid_by_name(*name);
1451
  }
1452
}
1453

    
1454

    
1455
static gid_t gid_by_name(Handle<Value> value) {
1456
  if (value->IsUint32()) {
1457
    return static_cast<gid_t>(value->Uint32Value());
1458
  } else {
1459
    String::Utf8Value name(value);
1460
    return gid_by_name(*name);
1461
  }
1462
}
1463

    
1464

    
1465
static void GetUid(const FunctionCallbackInfo<Value>& args) {
1466
  // uid_t is an uint32_t on all supported platforms.
1467
  args.GetReturnValue().Set(static_cast<uint32_t>(getuid()));
1468
}
1469

    
1470

    
1471
static void GetGid(const FunctionCallbackInfo<Value>& args) {
1472
  // gid_t is an uint32_t on all supported platforms.
1473
  args.GetReturnValue().Set(static_cast<uint32_t>(getgid()));
1474
}
1475

    
1476

    
1477
static void SetGid(const FunctionCallbackInfo<Value>& args) {
1478
  HandleScope scope(node_isolate);
1479

    
1480
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1481
    return ThrowTypeError("setgid argument must be a number or a string");
1482
  }
1483

    
1484
  gid_t gid = gid_by_name(args[0]);
1485

    
1486
  if (gid == gid_not_found) {
1487
    return ThrowError("setgid group id does not exist");
1488
  }
1489

    
1490
  if (setgid(gid)) {
1491
    return ThrowErrnoException(errno, "setgid");
1492
  }
1493
}
1494

    
1495

    
1496
static void SetUid(const FunctionCallbackInfo<Value>& args) {
1497
  HandleScope scope(node_isolate);
1498

    
1499
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1500
    return ThrowTypeError("setuid argument must be a number or a string");
1501
  }
1502

    
1503
  uid_t uid = uid_by_name(args[0]);
1504

    
1505
  if (uid == uid_not_found) {
1506
    return ThrowError("setuid user id does not exist");
1507
  }
1508

    
1509
  if (setuid(uid)) {
1510
    return ThrowErrnoException(errno, "setuid");
1511
  }
1512
}
1513

    
1514

    
1515
static void GetGroups(const FunctionCallbackInfo<Value>& args) {
1516
  HandleScope scope(node_isolate);
1517

    
1518
  int ngroups = getgroups(0, NULL);
1519

    
1520
  if (ngroups == -1) {
1521
    return ThrowErrnoException(errno, "getgroups");
1522
  }
1523

    
1524
  gid_t* groups = new gid_t[ngroups];
1525

    
1526
  ngroups = getgroups(ngroups, groups);
1527

    
1528
  if (ngroups == -1) {
1529
    delete[] groups;
1530
    return ThrowErrnoException(errno, "getgroups");
1531
  }
1532

    
1533
  Local<Array> groups_list = Array::New(ngroups);
1534
  bool seen_egid = false;
1535
  gid_t egid = getegid();
1536

    
1537
  for (int i = 0; i < ngroups; i++) {
1538
    groups_list->Set(i, Integer::New(groups[i], node_isolate));
1539
    if (groups[i] == egid)
1540
      seen_egid = true;
1541
  }
1542

    
1543
  delete[] groups;
1544

    
1545
  if (seen_egid == false) {
1546
    groups_list->Set(ngroups, Integer::New(egid, node_isolate));
1547
  }
1548

    
1549
  args.GetReturnValue().Set(groups_list);
1550
}
1551

    
1552

    
1553
static void SetGroups(const FunctionCallbackInfo<Value>& args) {
1554
  HandleScope scope(node_isolate);
1555

    
1556
  if (!args[0]->IsArray()) {
1557
    return ThrowTypeError("argument 1 must be an array");
1558
  }
1559

    
1560
  Local<Array> groups_list = args[0].As<Array>();
1561
  size_t size = groups_list->Length();
1562
  gid_t* groups = new gid_t[size];
1563

    
1564
  for (size_t i = 0; i < size; i++) {
1565
    gid_t gid = gid_by_name(groups_list->Get(i));
1566

    
1567
    if (gid == gid_not_found) {
1568
      delete[] groups;
1569
      return ThrowError("group name not found");
1570
    }
1571

    
1572
    groups[i] = gid;
1573
  }
1574

    
1575
  int rc = setgroups(size, groups);
1576
  delete[] groups;
1577

    
1578
  if (rc == -1) {
1579
    return ThrowErrnoException(errno, "setgroups");
1580
  }
1581
}
1582

    
1583

    
1584
static void InitGroups(const FunctionCallbackInfo<Value>& args) {
1585
  HandleScope scope(node_isolate);
1586

    
1587
  if (!args[0]->IsUint32() && !args[0]->IsString()) {
1588
    return ThrowTypeError("argument 1 must be a number or a string");
1589
  }
1590

    
1591
  if (!args[1]->IsUint32() && !args[1]->IsString()) {
1592
    return ThrowTypeError("argument 2 must be a number or a string");
1593
  }
1594

    
1595
  String::Utf8Value arg0(args[0]);
1596
  gid_t extra_group;
1597
  bool must_free;
1598
  char* user;
1599

    
1600
  if (args[0]->IsUint32()) {
1601
    user = name_by_uid(args[0]->Uint32Value());
1602
    must_free = true;
1603
  } else {
1604
    user = *arg0;
1605
    must_free = false;
1606
  }
1607

    
1608
  if (user == NULL) {
1609
    return ThrowError("initgroups user not found");
1610
  }
1611

    
1612
  extra_group = gid_by_name(args[1]);
1613

    
1614
  if (extra_group == gid_not_found) {
1615
    if (must_free)
1616
      free(user);
1617
    return ThrowError("initgroups extra group not found");
1618
  }
1619

    
1620
  int rc = initgroups(user, extra_group);
1621

    
1622
  if (must_free) {
1623
    free(user);
1624
  }
1625

    
1626
  if (rc) {
1627
    return ThrowErrnoException(errno, "initgroups");
1628
  }
1629
}
1630

    
1631
#endif  // __POSIX__ && !defined(__ANDROID__)
1632

    
1633

    
1634
void Exit(const FunctionCallbackInfo<Value>& args) {
1635
  HandleScope scope(node_isolate);
1636
  exit(args[0]->IntegerValue());
1637
}
1638

    
1639

    
1640
static void Uptime(const FunctionCallbackInfo<Value>& args) {
1641
  HandleScope scope(node_isolate);
1642
  double uptime;
1643
  if (uv_uptime(&uptime))
1644
    return;
1645
  args.GetReturnValue().Set(uptime - prog_start_time);
1646
}
1647

    
1648

    
1649
void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
1650
  Environment* env = Environment::GetCurrent(args.GetIsolate());
1651
  HandleScope handle_scope(args.GetIsolate());
1652

    
1653
  size_t rss;
1654
  int err = uv_resident_set_memory(&rss);
1655
  if (err) {
1656
    return ThrowUVException(err, "uv_resident_set_memory");
1657
  }
1658

    
1659
  // V8 memory usage
1660
  HeapStatistics v8_heap_stats;
1661
  node_isolate->GetHeapStatistics(&v8_heap_stats);
1662

    
1663
  Local<Integer> heap_total =
1664
      Integer::NewFromUnsigned(v8_heap_stats.total_heap_size(), node_isolate);
1665
  Local<Integer> heap_used =
1666
      Integer::NewFromUnsigned(v8_heap_stats.used_heap_size(), node_isolate);
1667

    
1668
  Local<Object> info = Object::New();
1669
  info->Set(env->rss_string(), Number::New(node_isolate, rss));
1670
  info->Set(env->heap_total_string(), heap_total);
1671
  info->Set(env->heap_used_string(), heap_used);
1672

    
1673
  args.GetReturnValue().Set(info);
1674
}
1675

    
1676

    
1677
void Kill(const FunctionCallbackInfo<Value>& args) {
1678
  HandleScope scope(node_isolate);
1679

    
1680
  if (args.Length() != 2) {
1681
    return ThrowError("Bad argument.");
1682
  }
1683

    
1684
  int pid = args[0]->IntegerValue();
1685
  int sig = args[1]->Int32Value();
1686
  int err = uv_kill(pid, sig);
1687
  args.GetReturnValue().Set(err);
1688
}
1689

    
1690
// used in Hrtime() below
1691
#define NANOS_PER_SEC 1000000000
1692

    
1693
// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
1694
// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
1695
// so this function instead returns an Array with 2 entries representing seconds
1696
// and nanoseconds, to avoid any integer overflow possibility.
1697
// Pass in an Array from a previous hrtime() call to instead get a time diff.
1698
void Hrtime(const FunctionCallbackInfo<Value>& args) {
1699
  HandleScope scope(node_isolate);
1700

    
1701
  uint64_t t = uv_hrtime();
1702

    
1703
  if (args.Length() > 0) {
1704
    // return a time diff tuple
1705
    if (!args[0]->IsArray()) {
1706
      return ThrowTypeError("process.hrtime() only accepts an Array tuple.");
1707
    }
1708
    Local<Array> inArray = Local<Array>::Cast(args[0]);
1709
    uint64_t seconds = inArray->Get(0)->Uint32Value();
1710
    uint64_t nanos = inArray->Get(1)->Uint32Value();
1711
    t -= (seconds * NANOS_PER_SEC) + nanos;
1712
  }
1713

    
1714
  Local<Array> tuple = Array::New(2);
1715
  tuple->Set(0, Integer::NewFromUnsigned(t / NANOS_PER_SEC, node_isolate));
1716
  tuple->Set(1, Integer::NewFromUnsigned(t % NANOS_PER_SEC, node_isolate));
1717
  args.GetReturnValue().Set(tuple);
1718
}
1719

    
1720

    
1721
typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
1722

    
1723
// DLOpen is process.dlopen(module, filename).
1724
// Used to load 'module.node' dynamically shared objects.
1725
//
1726
// FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
1727
// when two contexts try to load the same shared object. Maybe have a shadow
1728
// cache that's a plain C list or hash table that's shared across contexts?
1729
void DLOpen(const FunctionCallbackInfo<Value>& args) {
1730
  Environment* env = Environment::GetCurrent(args.GetIsolate());
1731
  HandleScope handle_scope(args.GetIsolate());
1732
  char symbol[1024], *base, *pos;
1733
  uv_lib_t lib;
1734
  int r;
1735

    
1736
  if (args.Length() < 2) {
1737
    return ThrowError("process.dlopen takes exactly 2 arguments.");
1738
  }
1739

    
1740
  Local<Object> module = args[0]->ToObject();  // Cast
1741
  String::Utf8Value filename(args[1]);  // Cast
1742

    
1743
  Local<String> exports_string = env->exports_string();
1744
  Local<Object> exports = module->Get(exports_string)->ToObject();
1745

    
1746
  if (uv_dlopen(*filename, &lib)) {
1747
    Local<String> errmsg = OneByteString(env->isolate(), uv_dlerror(&lib));
1748
#ifdef _WIN32
1749
    // Windows needs to add the filename into the error message
1750
    errmsg = String::Concat(errmsg, args[1]->ToString());
1751
#endif  // _WIN32
1752
    ThrowException(Exception::Error(errmsg));
1753
    return;
1754
  }
1755

    
1756
  String::Utf8Value path(args[1]);
1757
  base = *path;
1758

    
1759
  /* Find the shared library filename within the full path. */
1760
#ifdef __POSIX__
1761
  pos = strrchr(base, '/');
1762
  if (pos != NULL) {
1763
    base = pos + 1;
1764
  }
1765
#else  // Windows
1766
  for (;;) {
1767
    pos = strpbrk(base, "\\/:");
1768
    if (pos == NULL) {
1769
      break;
1770
    }
1771
    base = pos + 1;
1772
  }
1773
#endif  // __POSIX__
1774

    
1775
  /* Strip the .node extension. */
1776
  pos = strrchr(base, '.');
1777
  if (pos != NULL) {
1778
    *pos = '\0';
1779
  }
1780

    
1781
  /* Add the `_module` suffix to the extension name. */
1782
  r = snprintf(symbol, sizeof symbol, "%s_module", base);
1783
  if (r <= 0 || static_cast<size_t>(r) >= sizeof symbol) {
1784
    return ThrowError("Out of memory.");
1785
  }
1786

    
1787
  /* Replace dashes with underscores. When loading foo-bar.node,
1788
   * look for foo_bar_module, not foo-bar_module.
1789
   */
1790
  for (pos = symbol; *pos != '\0'; ++pos) {
1791
    if (*pos == '-')
1792
      *pos = '_';
1793
  }
1794

    
1795
  node_module_struct *mod;
1796
  if (uv_dlsym(&lib, symbol, reinterpret_cast<void**>(&mod))) {
1797
    char errmsg[1024];
1798
    snprintf(errmsg, sizeof(errmsg), "Symbol %s not found.", symbol);
1799
    return ThrowError(errmsg);
1800
  }
1801

    
1802
  if (mod->version != NODE_MODULE_VERSION) {
1803
    char errmsg[1024];
1804
    snprintf(errmsg,
1805
             sizeof(errmsg),
1806
             "Module version mismatch. Expected %d, got %d.",
1807
             NODE_MODULE_VERSION, mod->version);
1808
    return ThrowError(errmsg);
1809
  }
1810

    
1811
  // Execute the C++ module
1812
  if (mod->register_context_func != NULL) {
1813
    mod->register_context_func(exports, module, env->context());
1814
  } else if (mod->register_func != NULL) {
1815
    mod->register_func(exports, module);
1816
  } else {
1817
    return ThrowError("Module has no declared entry point.");
1818
  }
1819

    
1820
  // Tell coverity that 'handle' should not be freed when we return.
1821
  // coverity[leaked_storage]
1822
}
1823

    
1824

    
1825
static void OnFatalError(const char* location, const char* message) {
1826
  if (location) {
1827
    fprintf(stderr, "FATAL ERROR: %s %s\n", location, message);
1828
  } else {
1829
    fprintf(stderr, "FATAL ERROR: %s\n", message);
1830
  }
1831
  fflush(stderr);
1832
#if defined(DEBUG)
1833
  abort();
1834
#endif
1835
  exit(5);
1836
}
1837

    
1838

    
1839
NO_RETURN void FatalError(const char* location, const char* message) {
1840
  OnFatalError(location, message);
1841
  // to supress compiler warning
1842
  abort();
1843
}
1844

    
1845

    
1846
void FatalException(Handle<Value> error, Handle<Message> message) {
1847
  HandleScope scope(node_isolate);
1848

    
1849
  Environment* env = Environment::GetCurrent(node_isolate);
1850
  Local<Object> process_object = env->process_object();
1851
  Local<String> fatal_exception_string = env->fatal_exception_string();
1852
  Local<Function> fatal_exception_function =
1853
      process_object->Get(fatal_exception_string).As<Function>();
1854

    
1855
  if (!fatal_exception_function->IsFunction()) {
1856
    // failed before the process._fatalException function was added!
1857
    // this is probably pretty bad.  Nothing to do but report and exit.
1858
    ReportException(error, message);
1859
    exit(6);
1860
  }
1861

    
1862
  TryCatch fatal_try_catch;
1863

    
1864
  // Do not call FatalException when _fatalException handler throws
1865
  fatal_try_catch.SetVerbose(false);
1866

    
1867
  // this will return true if the JS layer handled it, false otherwise
1868
  Local<Value> caught =
1869
      fatal_exception_function->Call(process_object, 1, &error);
1870

    
1871
  if (fatal_try_catch.HasCaught()) {
1872
    // the fatal exception function threw, so we must exit
1873
    ReportException(fatal_try_catch);
1874
    exit(7);
1875
  }
1876

    
1877
  if (false == caught->BooleanValue()) {
1878
    ReportException(error, message);
1879
    exit(1);
1880
  }
1881
}
1882

    
1883

    
1884
void FatalException(const TryCatch& try_catch) {
1885
  HandleScope scope(node_isolate);
1886
  // TODO(bajtos) do not call FatalException if try_catch is verbose
1887
  // (requires V8 API to expose getter for try_catch.is_verbose_)
1888
  FatalException(try_catch.Exception(), try_catch.Message());
1889
}
1890

    
1891

    
1892
void OnMessage(Handle<Message> message, Handle<Value> error) {
1893
  // The current version of V8 sends messages for errors only
1894
  // (thus `error` is always set).
1895
  FatalException(error, message);
1896
}
1897

    
1898

    
1899
static void Binding(const FunctionCallbackInfo<Value>& args) {
1900
  Environment* env = Environment::GetCurrent(args.GetIsolate());
1901
  HandleScope handle_scope(args.GetIsolate());
1902

    
1903
  Local<String> module = args[0]->ToString();
1904
  String::Utf8Value module_v(module);
1905

    
1906
  Local<Object> cache = env->binding_cache_object();
1907
  Local<Object> exports;
1908

    
1909
  if (cache->Has(module)) {
1910
    exports = cache->Get(module)->ToObject();
1911
    args.GetReturnValue().Set(exports);
1912
    return;
1913
  }
1914

    
1915
  // Append a string to process.moduleLoadList
1916
  char buf[1024];
1917
  snprintf(buf, sizeof(buf), "Binding %s", *module_v);
1918

    
1919
  Local<Array> modules = env->module_load_list_array();
1920
  uint32_t l = modules->Length();
1921
  modules->Set(l, OneByteString(node_isolate, buf));
1922

    
1923
  node_module_struct* mod = get_builtin_module(*module_v);
1924
  if (mod != NULL) {
1925
    exports = Object::New();
1926
    // Internal bindings don't have a "module" object, only exports.
1927
    assert(mod->register_func == NULL);
1928
    assert(mod->register_context_func != NULL);
1929
    Local<Value> unused = Undefined(env->isolate());
1930
    mod->register_context_func(exports, unused, env->context());
1931
    cache->Set(module, exports);
1932
  } else if (!strcmp(*module_v, "constants")) {
1933
    exports = Object::New();
1934
    DefineConstants(exports);
1935
    cache->Set(module, exports);
1936
  } else if (!strcmp(*module_v, "natives")) {
1937
    exports = Object::New();
1938
    DefineJavaScript(exports);
1939
    cache->Set(module, exports);
1940
  } else {
1941
    return ThrowError("No such module");
1942
  }
1943

    
1944
  args.GetReturnValue().Set(exports);
1945
}
1946

    
1947

    
1948
static void ProcessTitleGetter(Local<String> property,
1949
                               const PropertyCallbackInfo<Value>& info) {
1950
  HandleScope scope(node_isolate);
1951
  char buffer[512];
1952
  uv_get_process_title(buffer, sizeof(buffer));
1953
  info.GetReturnValue().Set(String::NewFromUtf8(node_isolate, buffer));
1954
}
1955

    
1956

    
1957
static void ProcessTitleSetter(Local<String> property,
1958
                               Local<Value> value,
1959
                               const PropertyCallbackInfo<void>& info) {
1960
  HandleScope scope(node_isolate);
1961
  String::Utf8Value title(value);
1962
  // TODO(piscisaureus): protect with a lock
1963
  uv_set_process_title(*title);
1964
}
1965

    
1966

    
1967
static void EnvGetter(Local<String> property,
1968
                      const PropertyCallbackInfo<Value>& info) {
1969
  HandleScope scope(node_isolate);
1970
#ifdef __POSIX__
1971
  String::Utf8Value key(property);
1972
  const char* val = getenv(*key);
1973
  if (val) {
1974
    return info.GetReturnValue().Set(String::NewFromUtf8(node_isolate, val));
1975
  }
1976
#else  // _WIN32
1977
  String::Value key(property);
1978
  WCHAR buffer[32767];  // The maximum size allowed for environment variables.
1979
  DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
1980
                                         buffer,
1981
                                         ARRAY_SIZE(buffer));
1982
  // If result >= sizeof buffer the buffer was too small. That should never
1983
  // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
1984
  // not found.
1985
  if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
1986
      result < ARRAY_SIZE(buffer)) {
1987
    const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(buffer);
1988
    Local<String> rc = String::NewFromTwoByte(node_isolate, two_byte_buffer);
1989
    return info.GetReturnValue().Set(rc);
1990
  }
1991
#endif
1992
  // Not found.  Fetch from prototype.
1993
  info.GetReturnValue().Set(
1994
      info.Data().As<Object>()->Get(property));
1995
}
1996

    
1997

    
1998
static void EnvSetter(Local<String> property,
1999
                      Local<Value> value,
2000
                      const PropertyCallbackInfo<Value>& info) {
2001
  HandleScope scope(node_isolate);
2002
#ifdef __POSIX__
2003
  String::Utf8Value key(property);
2004
  String::Utf8Value val(value);
2005
  setenv(*key, *val, 1);
2006
#else  // _WIN32
2007
  String::Value key(property);
2008
  String::Value val(value);
2009
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2010
  // Environment variables that start with '=' are read-only.
2011
  if (key_ptr[0] != L'=') {
2012
    SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
2013
  }
2014
#endif
2015
  // Whether it worked or not, always return rval.
2016
  info.GetReturnValue().Set(value);
2017
}
2018

    
2019

    
2020
static void EnvQuery(Local<String> property,
2021
                     const PropertyCallbackInfo<Integer>& info) {
2022
  HandleScope scope(node_isolate);
2023
  int32_t rc = -1;  // Not found unless proven otherwise.
2024
#ifdef __POSIX__
2025
  String::Utf8Value key(property);
2026
  if (getenv(*key))
2027
    rc = 0;
2028
#else  // _WIN32
2029
  String::Value key(property);
2030
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2031
  if (GetEnvironmentVariableW(key_ptr, NULL, 0) > 0 ||
2032
      GetLastError() == ERROR_SUCCESS) {
2033
    rc = 0;
2034
    if (key_ptr[0] == L'=') {
2035
      // Environment variables that start with '=' are hidden and read-only.
2036
      rc = static_cast<int32_t>(v8::ReadOnly) |
2037
           static_cast<int32_t>(v8::DontDelete) |
2038
           static_cast<int32_t>(v8::DontEnum);
2039
    }
2040
  }
2041
#endif
2042
  if (rc != -1)
2043
    info.GetReturnValue().Set(rc);
2044
}
2045

    
2046

    
2047
static void EnvDeleter(Local<String> property,
2048
                       const PropertyCallbackInfo<Boolean>& info) {
2049
  HandleScope scope(node_isolate);
2050
  bool rc = true;
2051
#ifdef __POSIX__
2052
  String::Utf8Value key(property);
2053
  rc = getenv(*key) != NULL;
2054
  if (rc)
2055
    unsetenv(*key);
2056
#else
2057
  String::Value key(property);
2058
  WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
2059
  if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, NULL)) {
2060
    // Deletion failed. Return true if the key wasn't there in the first place,
2061
    // false if it is still there.
2062
    rc = GetEnvironmentVariableW(key_ptr, NULL, NULL) == 0 &&
2063
         GetLastError() != ERROR_SUCCESS;
2064
  }
2065
#endif
2066
  info.GetReturnValue().Set(rc);
2067
}
2068

    
2069

    
2070
static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
2071
  HandleScope scope(node_isolate);
2072
#ifdef __POSIX__
2073
  int size = 0;
2074
  while (environ[size])
2075
    size++;
2076

    
2077
  Local<Array> env = Array::New(size);
2078

    
2079
  for (int i = 0; i < size; ++i) {
2080
    const char* var = environ[i];
2081
    const char* s = strchr(var, '=');
2082
    const int length = s ? s - var : strlen(var);
2083
    Local<String> name = String::NewFromUtf8(node_isolate,
2084
                                             var,
2085
                                             String::kNormalString,
2086
                                             length);
2087
    env->Set(i, name);
2088
  }
2089
#else  // _WIN32
2090
  WCHAR* environment = GetEnvironmentStringsW();
2091
  if (environment == NULL)
2092
    return;  // This should not happen.
2093
  Local<Array> env = Array::New();
2094
  WCHAR* p = environment;
2095
  int i = 0;
2096
  while (*p != NULL) {
2097
    WCHAR *s;
2098
    if (*p == L'=') {
2099
      // If the key starts with '=' it is a hidden environment variable.
2100
      p += wcslen(p) + 1;
2101
      continue;
2102
    } else {
2103
      s = wcschr(p, L'=');
2104
    }
2105
    if (!s) {
2106
      s = p + wcslen(p);
2107
    }
2108
    const uint16_t* two_byte_buffer = reinterpret_cast<const uint16_t*>(p);
2109
    const size_t two_byte_buffer_len = s - p;
2110
    Local<String> value = String::NewFromTwoByte(node_isolate,
2111
                                                 two_byte_buffer,
2112
                                                 String::kNormalString,
2113
                                                 two_byte_buffer_len);
2114
    env->Set(i++, value);
2115
    p = s + wcslen(s) + 1;
2116
  }
2117
  FreeEnvironmentStringsW(environment);
2118
#endif
2119

    
2120
  info.GetReturnValue().Set(env);
2121
}
2122

    
2123

    
2124
static Handle<Object> GetFeatures() {
2125
  HandleScope scope(node_isolate);
2126

    
2127
  Local<Object> obj = Object::New();
2128
#if defined(DEBUG) && DEBUG
2129
  Local<Value> debug = True(node_isolate);
2130
#else
2131
  Local<Value> debug = False(node_isolate);
2132
#endif  // defined(DEBUG) && DEBUG
2133

    
2134
  obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "debug"), debug);
2135

    
2136
  obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "uv"), True(node_isolate));
2137
  // TODO(bnoordhuis) ping libuv
2138
  obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "ipv6"), True(node_isolate));
2139

    
2140
#ifdef OPENSSL_NPN_NEGOTIATED
2141
  Local<Boolean> tls_npn = True(node_isolate);
2142
#else
2143
  Local<Boolean> tls_npn = False(node_isolate);
2144
#endif
2145
  obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "tls_npn"), tls_npn);
2146

    
2147
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
2148
  Local<Boolean> tls_sni = True(node_isolate);
2149
#else
2150
  Local<Boolean> tls_sni = False(node_isolate);
2151
#endif
2152
  obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "tls_sni"), tls_sni);
2153

    
2154
  obj->Set(FIXED_ONE_BYTE_STRING(node_isolate, "tls"),
2155
           Boolean::New(get_builtin_module("crypto") != NULL));
2156

    
2157
  return scope.Close(obj);
2158
}
2159

    
2160

    
2161
static void DebugPortGetter(Local<String> property,
2162
                            const PropertyCallbackInfo<Value>& info) {
2163
  HandleScope scope(node_isolate);
2164
  info.GetReturnValue().Set(debug_port);
2165
}
2166

    
2167

    
2168
static void DebugPortSetter(Local<String> property,
2169
                            Local<Value> value,
2170
                            const PropertyCallbackInfo<void>& info) {
2171
  HandleScope scope(node_isolate);
2172
  debug_port = value->NumberValue();
2173
}
2174

    
2175

    
2176
static void DebugProcess(const FunctionCallbackInfo<Value>& args);
2177
static void DebugPause(const FunctionCallbackInfo<Value>& args);
2178
static void DebugEnd(const FunctionCallbackInfo<Value>& args);
2179

    
2180

    
2181
void NeedImmediateCallbackGetter(Local<String> property,
2182
                                 const PropertyCallbackInfo<Value>& info) {
2183
  Environment* env = Environment::GetCurrent(info.GetIsolate());
2184
  const uv_check_t* immediate_check_handle = env->immediate_check_handle();
2185
  bool active = uv_is_active(
2186
      reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2187
  info.GetReturnValue().Set(active);
2188
}
2189

    
2190

    
2191
static void NeedImmediateCallbackSetter(
2192
    Local<String> property,
2193
    Local<Value> value,
2194
    const PropertyCallbackInfo<void>& info) {
2195
  Environment* env = Environment::GetCurrent(info.GetIsolate());
2196
  HandleScope handle_scope(info.GetIsolate());
2197

    
2198
  uv_check_t* immediate_check_handle = env->immediate_check_handle();
2199
  bool active = uv_is_active(
2200
      reinterpret_cast<const uv_handle_t*>(immediate_check_handle));
2201

    
2202
  if (active == value->BooleanValue())
2203
    return;
2204

    
2205
  uv_idle_t* immediate_idle_handle = env->immediate_idle_handle();
2206

    
2207
  if (active) {
2208
    uv_check_stop(immediate_check_handle);
2209
    uv_idle_stop(immediate_idle_handle);
2210
  } else {
2211
    uv_check_start(immediate_check_handle, CheckImmediate);
2212
    // Idle handle is needed only to stop the event loop from blocking in poll.
2213
    uv_idle_start(immediate_idle_handle, IdleImmediateDummy);
2214
  }
2215
}
2216

    
2217

    
2218
void SetIdle(uv_prepare_t* handle, int) {
2219
  Environment* env = Environment::from_idle_prepare_handle(handle);
2220
  env->isolate()->GetCpuProfiler()->SetIdle(true);
2221
}
2222

    
2223

    
2224
void ClearIdle(uv_check_t* handle, int) {
2225
  Environment* env = Environment::from_idle_check_handle(handle);
2226
  env->isolate()->GetCpuProfiler()->SetIdle(false);
2227
}
2228

    
2229

    
2230
void StartProfilerIdleNotifier(Environment* env) {
2231
  uv_prepare_start(env->idle_prepare_handle(), SetIdle);
2232
  uv_check_start(env->idle_check_handle(), ClearIdle);
2233
}
2234

    
2235

    
2236
void StopProfilerIdleNotifier(Environment* env) {
2237
  uv_prepare_stop(env->idle_prepare_handle());
2238
  uv_check_stop(env->idle_check_handle());
2239
}
2240

    
2241

    
2242
void StartProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2243
  StartProfilerIdleNotifier(Environment::GetCurrent(args.GetIsolate()));
2244
}
2245

    
2246

    
2247
void StopProfilerIdleNotifier(const FunctionCallbackInfo<Value>& args) {
2248
  StopProfilerIdleNotifier(Environment::GetCurrent(args.GetIsolate()));
2249
}
2250

    
2251

    
2252
#define READONLY_PROPERTY(obj, str, var)                                      \
2253
  do {                                                                        \
2254
    obj->Set(OneByteString(node_isolate, str), var, v8::ReadOnly);            \
2255
  } while (0)
2256

    
2257

    
2258
void SetupProcessObject(Environment* env,
2259
                        int argc,
2260
                        const char* const* argv,
2261
                        int exec_argc,
2262
                        const char* const* exec_argv) {
2263
  HandleScope scope(node_isolate);
2264

    
2265
  Local<Object> process = env->process_object();
2266

    
2267
  process->SetAccessor(FIXED_ONE_BYTE_STRING(node_isolate, "title"),
2268
                       ProcessTitleGetter,
2269
                       ProcessTitleSetter);
2270

    
2271
  // process.version
2272
  READONLY_PROPERTY(process,
2273
                    "version",
2274
                    FIXED_ONE_BYTE_STRING(node_isolate, NODE_VERSION));
2275

    
2276
  // process.moduleLoadList
2277
  READONLY_PROPERTY(process,
2278
                    "moduleLoadList",
2279
                    env->module_load_list_array());
2280

    
2281
  // process.versions
2282
  Local<Object> versions = Object::New();
2283
  READONLY_PROPERTY(process, "versions", versions);
2284

    
2285
  const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
2286
                                     "."
2287
                                     NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR);
2288
  READONLY_PROPERTY(versions,
2289
                    "http_parser",
2290
                    FIXED_ONE_BYTE_STRING(node_isolate, http_parser_version));
2291

    
2292
  // +1 to get rid of the leading 'v'
2293
  READONLY_PROPERTY(versions,
2294
                    "node",
2295
                    OneByteString(node_isolate, NODE_VERSION + 1));
2296
  READONLY_PROPERTY(versions,
2297
                    "v8",
2298
                    OneByteString(node_isolate, V8::GetVersion()));
2299
  READONLY_PROPERTY(versions,
2300
                    "uv",
2301
                    OneByteString(node_isolate, uv_version_string()));
2302
  READONLY_PROPERTY(versions,
2303
                    "zlib",
2304
                    FIXED_ONE_BYTE_STRING(node_isolate, ZLIB_VERSION));
2305

    
2306
  const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
2307
  READONLY_PROPERTY(versions,
2308
                    "modules",
2309
                    FIXED_ONE_BYTE_STRING(node_isolate, node_modules_version));
2310

    
2311
#if HAVE_OPENSSL
2312
  // Stupid code to slice out the version string.
2313
  {  // NOLINT(whitespace/braces)
2314
    size_t i, j, k;
2315
    int c;
2316
    for (i = j = 0, k = sizeof(OPENSSL_VERSION_TEXT) - 1; i < k; ++i) {
2317
      c = OPENSSL_VERSION_TEXT[i];
2318
      if ('0' <= c && c <= '9') {
2319
        for (j = i + 1; j < k; ++j) {
2320
          c = OPENSSL_VERSION_TEXT[j];
2321
          if (c == ' ')
2322
            break;
2323
        }
2324
        break;
2325
      }
2326
    }
2327
    READONLY_PROPERTY(
2328
        versions,
2329
        "openssl",
2330
        OneByteString(node_isolate, &OPENSSL_VERSION_TEXT[i], j - i));
2331
  }
2332
#endif
2333

    
2334
  // process.arch
2335
  READONLY_PROPERTY(process, "arch", OneByteString(node_isolate, ARCH));
2336

    
2337
  // process.platform
2338
  READONLY_PROPERTY(process,
2339
                    "platform",
2340
                    OneByteString(node_isolate, PLATFORM));
2341

    
2342
  // process.argv
2343
  Local<Array> arguments = Array::New(argc);
2344
  for (int i = 0; i < argc; ++i) {
2345
    arguments->Set(i, String::NewFromUtf8(node_isolate, argv[i]));
2346
  }
2347
  process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "argv"), arguments);
2348

    
2349
  // process.execArgv
2350
  Local<Array> exec_arguments = Array::New(exec_argc);
2351
  for (int i = 0; i < exec_argc; ++i) {
2352
    exec_arguments->Set(i, String::NewFromUtf8(node_isolate, exec_argv[i]));
2353
  }
2354
  process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "execArgv"), exec_arguments);
2355

    
2356
  // create process.env
2357
  Local<ObjectTemplate> process_env_template = ObjectTemplate::New();
2358
  process_env_template->SetNamedPropertyHandler(EnvGetter,
2359
                                                EnvSetter,
2360
                                                EnvQuery,
2361
                                                EnvDeleter,
2362
                                                EnvEnumerator,
2363
                                                Object::New());
2364
  Local<Object> process_env = process_env_template->NewInstance();
2365
  process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "env"), process_env);
2366

    
2367
  READONLY_PROPERTY(process, "pid", Integer::New(getpid(), node_isolate));
2368
  READONLY_PROPERTY(process, "features", GetFeatures());
2369
  process->SetAccessor(
2370
      FIXED_ONE_BYTE_STRING(node_isolate, "_needImmediateCallback"),
2371
      NeedImmediateCallbackGetter,
2372
      NeedImmediateCallbackSetter);
2373

    
2374
  // -e, --eval
2375
  if (eval_string) {
2376
    READONLY_PROPERTY(process,
2377
                      "_eval",
2378
                      String::NewFromUtf8(node_isolate, eval_string));
2379
  }
2380

    
2381
  // -p, --print
2382
  if (print_eval) {
2383
    READONLY_PROPERTY(process, "_print_eval", True(node_isolate));
2384
  }
2385

    
2386
  // -i, --interactive
2387
  if (force_repl) {
2388
    READONLY_PROPERTY(process, "_forceRepl", True(node_isolate));
2389
  }
2390

    
2391
  // --no-deprecation
2392
  if (no_deprecation) {
2393
    READONLY_PROPERTY(process, "noDeprecation", True(node_isolate));
2394
  }
2395

    
2396
  // --throw-deprecation
2397
  if (throw_deprecation) {
2398
    READONLY_PROPERTY(process, "throwDeprecation", True(node_isolate));
2399
  }
2400

    
2401
  // --trace-deprecation
2402
  if (trace_deprecation) {
2403
    READONLY_PROPERTY(process, "traceDeprecation", True(node_isolate));
2404
  }
2405

    
2406
  size_t exec_path_len = 2 * PATH_MAX;
2407
  char* exec_path = new char[exec_path_len];
2408
  Local<String> exec_path_value;
2409
  if (uv_exepath(exec_path, &exec_path_len) == 0) {
2410
    exec_path_value = String::NewFromUtf8(node_isolate,
2411
                                          exec_path,
2412
                                          String::kNormalString,
2413
                                          exec_path_len);
2414
  } else {
2415
    exec_path_value = String::NewFromUtf8(node_isolate, argv[0]);
2416
  }
2417
  process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "execPath"),
2418
               exec_path_value);
2419
  delete[] exec_path;
2420

    
2421
  process->SetAccessor(FIXED_ONE_BYTE_STRING(node_isolate, "debugPort"),
2422
                       DebugPortGetter,
2423
                       DebugPortSetter);
2424

    
2425
  // define various internal methods
2426
  NODE_SET_METHOD(process,
2427
                  "_startProfilerIdleNotifier",
2428
                  StartProfilerIdleNotifier);
2429
  NODE_SET_METHOD(process,
2430
                  "_stopProfilerIdleNotifier",
2431
                  StopProfilerIdleNotifier);
2432
  NODE_SET_METHOD(process, "_getActiveRequests", GetActiveRequests);
2433
  NODE_SET_METHOD(process, "_getActiveHandles", GetActiveHandles);
2434
  NODE_SET_METHOD(process, "reallyExit", Exit);
2435
  NODE_SET_METHOD(process, "abort", Abort);
2436
  NODE_SET_METHOD(process, "chdir", Chdir);
2437
  NODE_SET_METHOD(process, "cwd", Cwd);
2438

    
2439
  NODE_SET_METHOD(process, "umask", Umask);
2440

    
2441
#if defined(__POSIX__) && !defined(__ANDROID__)
2442
  NODE_SET_METHOD(process, "getuid", GetUid);
2443
  NODE_SET_METHOD(process, "setuid", SetUid);
2444

    
2445
  NODE_SET_METHOD(process, "setgid", SetGid);
2446
  NODE_SET_METHOD(process, "getgid", GetGid);
2447

    
2448
  NODE_SET_METHOD(process, "getgroups", GetGroups);
2449
  NODE_SET_METHOD(process, "setgroups", SetGroups);
2450
  NODE_SET_METHOD(process, "initgroups", InitGroups);
2451
#endif  // __POSIX__ && !defined(__ANDROID__)
2452

    
2453
  NODE_SET_METHOD(process, "_kill", Kill);
2454

    
2455
  NODE_SET_METHOD(process, "_debugProcess", DebugProcess);
2456
  NODE_SET_METHOD(process, "_debugPause", DebugPause);
2457
  NODE_SET_METHOD(process, "_debugEnd", DebugEnd);
2458

    
2459
  NODE_SET_METHOD(process, "hrtime", Hrtime);
2460

    
2461
  NODE_SET_METHOD(process, "dlopen", DLOpen);
2462

    
2463
  NODE_SET_METHOD(process, "uptime", Uptime);
2464
  NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
2465

    
2466
  NODE_SET_METHOD(process, "binding", Binding);
2467

    
2468
  NODE_SET_METHOD(process, "_setupAsyncListener", SetupAsyncListener);
2469
  NODE_SET_METHOD(process, "_setupNextTick", SetupNextTick);
2470

    
2471
  // values use to cross communicate with processNextTick
2472
  Local<Object> tick_info_obj = Object::New();
2473
  tick_info_obj->SetIndexedPropertiesToExternalArrayData(
2474
      env->tick_info()->fields(),
2475
      kExternalUnsignedIntArray,
2476
      env->tick_info()->fields_count());
2477
  process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_tickInfo"), tick_info_obj);
2478

    
2479
  // pre-set _events object for faster emit checks
2480
  process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_events"), Object::New());
2481
}
2482

    
2483

    
2484
#undef READONLY_PROPERTY
2485

    
2486

    
2487
static void AtExit() {
2488
  uv_tty_reset_mode();
2489
}
2490

    
2491

    
2492
static void SignalExit(int signal) {
2493
  uv_tty_reset_mode();
2494
  _exit(128 + signal);
2495
}
2496

    
2497

    
2498
// Most of the time, it's best to use `console.error` to write
2499
// to the process.stderr stream.  However, in some cases, such as
2500
// when debugging the stream.Writable class or the process.nextTick
2501
// function, it is useful to bypass JavaScript entirely.
2502
static void RawDebug(const FunctionCallbackInfo<Value>& args) {
2503
  HandleScope scope(node_isolate);
2504

    
2505
  assert(args.Length() == 1 && args[0]->IsString() &&
2506
         "must be called with a single string");
2507

    
2508
  String::Utf8Value message(args[0]);
2509
  fprintf(stderr, "%s\n", *message);
2510
  fflush(stderr);
2511
}
2512

    
2513

    
2514
void Load(Environment* env) {
2515
  HandleScope handle_scope(node_isolate);
2516

    
2517
  // Compile, execute the src/node.js file. (Which was included as static C
2518
  // string in node_natives.h. 'natve_node' is the string containing that
2519
  // source code.)
2520

    
2521
  // The node.js file returns a function 'f'
2522
  atexit(AtExit);
2523

    
2524
  TryCatch try_catch;
2525

    
2526
  // Disable verbose mode to stop FatalException() handler from trying
2527
  // to handle the exception. Errors this early in the start-up phase
2528
  // are not safe to ignore.
2529
  try_catch.SetVerbose(false);
2530

    
2531
  Local<String> script_name = FIXED_ONE_BYTE_STRING(node_isolate, "node.js");
2532
  Local<Value> f_value = ExecuteString(MainSource(), script_name);
2533
  if (try_catch.HasCaught())  {
2534
    ReportException(try_catch);
2535
    exit(10);
2536
  }
2537
  assert(f_value->IsFunction());
2538
  Local<Function> f = Local<Function>::Cast(f_value);
2539

    
2540
  // Now we call 'f' with the 'process' variable that we've built up with
2541
  // all our bindings. Inside node.js we'll take care of assigning things to
2542
  // their places.
2543

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

    
2548
  // Add a reference to the global object
2549
  Local<Object> global = env->context()->Global();
2550

    
2551
#if defined HAVE_DTRACE || defined HAVE_ETW
2552
  InitDTrace(global);
2553
#endif
2554

    
2555
#if defined HAVE_PERFCTR
2556
  InitPerfCounters(global);
2557
#endif
2558

    
2559
  // Enable handling of uncaught exceptions
2560
  // (FatalException(), break on uncaught exception in debugger)
2561
  //
2562
  // This is not strictly necessary since it's almost impossible
2563
  // to attach the debugger fast enought to break on exception
2564
  // thrown during process startup.
2565
  try_catch.SetVerbose(true);
2566

    
2567
  NODE_SET_METHOD(env->process_object(), "_rawDebug", RawDebug);
2568

    
2569
  Local<Value> arg = env->process_object();
2570
  f->Call(global, 1, &arg);
2571
}
2572

    
2573
static void PrintHelp();
2574

    
2575
static void ParseDebugOpt(const char* arg) {
2576
  const char *p = 0;
2577

    
2578
  if (strstr(arg, "--debug-port=") == arg) {
2579
    p = 1 + strchr(arg, '=');
2580
    debug_port = atoi(p);
2581
  } else {
2582
    use_debug_agent = true;
2583
    if (!strcmp(arg, "--debug-brk")) {
2584
      debug_wait_connect = true;
2585
      return;
2586
    } else if (!strcmp(arg, "--debug")) {
2587
      return;
2588
    } else if (strstr(arg, "--debug-brk=") == arg) {
2589
      debug_wait_connect = true;
2590
      p = 1 + strchr(arg, '=');
2591
      debug_port = atoi(p);
2592
    } else if (strstr(arg, "--debug=") == arg) {
2593
      p = 1 + strchr(arg, '=');
2594
      debug_port = atoi(p);
2595
    }
2596
  }
2597
  if (p && debug_port > 1024 && debug_port <  65536)
2598
      return;
2599

    
2600
  fprintf(stderr, "Bad debug option.\n");
2601
  if (p)
2602
    fprintf(stderr, "Debug port must be in range 1025 to 65535.\n");
2603

    
2604
  PrintHelp();
2605
  exit(12);
2606
}
2607

    
2608
static void PrintHelp() {
2609
  printf("Usage: node [options] [ -e script | script.js ] [arguments] \n"
2610
         "       node debug script.js [arguments] \n"
2611
         "\n"
2612
         "Options:\n"
2613
         "  -v, --version        print node's version\n"
2614
         "  -e, --eval script    evaluate script\n"
2615
         "  -p, --print          evaluate script and print result\n"
2616
         "  -i, --interactive    always enter the REPL even if stdin\n"
2617
         "                       does not appear to be a terminal\n"
2618
         "  --no-deprecation     silence deprecation warnings\n"
2619
         "  --trace-deprecation  show stack traces on deprecations\n"
2620
         "  --v8-options         print v8 command line options\n"
2621
         "  --max-stack-size=val set max v8 stack size (bytes)\n"
2622
         "\n"
2623
         "Environment variables:\n"
2624
#ifdef _WIN32
2625
         "NODE_PATH              ';'-separated list of directories\n"
2626
#else
2627
         "NODE_PATH              ':'-separated list of directories\n"
2628
#endif
2629
         "                       prefixed to the module search path.\n"
2630
         "NODE_MODULE_CONTEXTS   Set to 1 to load modules in their own\n"
2631
         "                       global contexts.\n"
2632
         "NODE_DISABLE_COLORS    Set to 1 to disable colors in the REPL\n"
2633
         "\n"
2634
         "Documentation can be found at http://nodejs.org/\n");
2635
}
2636

    
2637

    
2638
// Parse command line arguments.
2639
//
2640
// argv is modified in place. exec_argv and v8_argv are out arguments that
2641
// ParseArgs() allocates memory for and stores a pointer to the output
2642
// vector in.  The caller should free them with delete[].
2643
//
2644
// On exit:
2645
//
2646
//  * argv contains the arguments with node and V8 options filtered out.
2647
//  * exec_argv contains both node and V8 options and nothing else.
2648
//  * v8_argv contains argv[0] plus any V8 options
2649
static void ParseArgs(int* argc,
2650
                      const char** argv,
2651
                      int* exec_argc,
2652
                      const char*** exec_argv,
2653
                      int* v8_argc,
2654
                      const char*** v8_argv) {
2655
  const unsigned int nargs = static_cast<unsigned int>(*argc);
2656
  const char** new_exec_argv = new const char*[nargs];
2657
  const char** new_v8_argv = new const char*[nargs];
2658
  const char** new_argv = new const char*[nargs];
2659

    
2660
  for (unsigned int i = 0; i < nargs; ++i) {
2661
    new_exec_argv[i] = NULL;
2662
    new_v8_argv[i] = NULL;
2663
    new_argv[i] = NULL;
2664
  }
2665

    
2666
  // exec_argv starts with the first option, the other two start with argv[0].
2667
  unsigned int new_exec_argc = 0;
2668
  unsigned int new_v8_argc = 1;
2669
  unsigned int new_argc = 1;
2670
  new_v8_argv[0] = argv[0];
2671
  new_argv[0] = argv[0];
2672

    
2673
  unsigned int index = 1;
2674
  while (index < nargs && argv[index][0] == '-') {
2675
    const char* const arg = argv[index];
2676
    unsigned int args_consumed = 1;
2677

    
2678
    if (strstr(arg, "--debug") == arg) {
2679
      ParseDebugOpt(arg);
2680
    } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
2681
      printf("%s\n", NODE_VERSION);
2682
      exit(0);
2683
    } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
2684
      PrintHelp();
2685
      exit(0);
2686
    } else if (strcmp(arg, "--eval") == 0 ||
2687
               strcmp(arg, "-e") == 0 ||
2688
               strcmp(arg, "--print") == 0 ||
2689
               strcmp(arg, "-pe") == 0 ||
2690
               strcmp(arg, "-p") == 0) {
2691
      bool is_eval = strchr(arg, 'e') != NULL;
2692
      bool is_print = strchr(arg, 'p') != NULL;
2693
      print_eval = print_eval || is_print;
2694
      // --eval, -e and -pe always require an argument.
2695
      if (is_eval == true) {
2696
        args_consumed += 1;
2697
        eval_string = argv[index + 1];
2698
        if (eval_string == NULL) {
2699
          fprintf(stderr, "%s: %s requires an argument\n", argv[0], arg);
2700
          exit(9);
2701
        }
2702
      } else if (argv[index + 1] != NULL && argv[index + 1][0] != '-') {
2703
        args_consumed += 1;
2704
        eval_string = argv[index + 1];
2705
        if (strncmp(eval_string, "\\-", 2) == 0) {
2706
          // Starts with "\\-": escaped expression, drop the backslash.
2707
          eval_string += 1;
2708
        }
2709
      }
2710
    } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) {
2711
      force_repl = true;
2712
    } else if (strcmp(arg, "--no-deprecation") == 0) {
2713
      no_deprecation = true;
2714
    } else if (strcmp(arg, "--trace-deprecation") == 0) {
2715
      trace_deprecation = true;
2716
    } else if (strcmp(arg, "--throw-deprecation") == 0) {
2717
      throw_deprecation = true;
2718
    } else if (strcmp(arg, "--v8-options") == 0) {
2719
      new_v8_argv[new_v8_argc] = "--help";
2720
      new_v8_argc += 1;
2721
    } else {
2722
      // V8 option.  Pass through as-is.
2723
      new_v8_argv[new_v8_argc] = arg;
2724
      new_v8_argc += 1;
2725
    }
2726

    
2727
    memcpy(new_exec_argv + new_exec_argc,
2728
           argv + index,
2729
           args_consumed * sizeof(*argv));
2730

    
2731
    new_exec_argc += args_consumed;
2732
    index += args_consumed;
2733
  }
2734

    
2735
  // Copy remaining arguments.
2736
  const unsigned int args_left = nargs - index;
2737
  memcpy(new_argv + new_argc, argv + index, args_left * sizeof(*argv));
2738
  new_argc += args_left;
2739

    
2740
  *exec_argc = new_exec_argc;
2741
  *exec_argv = new_exec_argv;
2742
  *v8_argc = new_v8_argc;
2743
  *v8_argv = new_v8_argv;
2744

    
2745
  // Copy new_argv over argv and update argc.
2746
  memcpy(argv, new_argv, new_argc * sizeof(*argv));
2747
  delete[] new_argv;
2748
  *argc = static_cast<int>(new_argc);
2749
}
2750

    
2751

    
2752
// Called from V8 Debug Agent TCP thread.
2753
static void DispatchMessagesDebugAgentCallback() {
2754
  uv_async_send(&dispatch_debug_messages_async);
2755
}
2756

    
2757

    
2758
// Called from the main thread.
2759
static void EnableDebug(bool wait_connect) {
2760
  assert(debugger_running == false);
2761
  Isolate* isolate = node_isolate;  // TODO(bnoordhuis) Multi-isolate support.
2762
  Isolate::Scope isolate_scope(isolate);
2763
  v8::Debug::SetDebugMessageDispatchHandler(DispatchMessagesDebugAgentCallback,
2764
                                            false);
2765
  debugger_running = v8::Debug::EnableAgent("node " NODE_VERSION,
2766
                                            debug_port,
2767
                                            wait_connect);
2768
  if (debugger_running == false) {
2769
    fprintf(stderr, "Starting debugger on port %d failed\n", debug_port);
2770
    fflush(stderr);
2771
    return;
2772
  }
2773
  fprintf(stderr, "Debugger listening on port %d\n", debug_port);
2774
  fflush(stderr);
2775

    
2776
  Environment* env = Environment::GetCurrentChecked(isolate);
2777
  if (env == NULL)
2778
    return;  // Still starting up.
2779

    
2780
  Context::Scope context_scope(env->context());
2781
  HandleScope handle_scope(env->isolate());
2782
  Local<Object> message = Object::New();
2783
  message->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "cmd"),
2784
               FIXED_ONE_BYTE_STRING(env->isolate(), "NODE_DEBUG_ENABLED"));
2785
  Local<Value> argv[] = {
2786
    FIXED_ONE_BYTE_STRING(env->isolate(), "internalMessage"),
2787
    message
2788
  };
2789
  MakeCallback(env, env->process_object(), "emit", ARRAY_SIZE(argv), argv);
2790
}
2791

    
2792

    
2793
// Called from the main thread.
2794
static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle, int status) {
2795
  if (debugger_running == false) {
2796
    fprintf(stderr, "Starting debugger agent.\n");
2797
    EnableDebug(false);
2798
  }
2799
  Isolate::Scope isolate_scope(node_isolate);
2800
  v8::Debug::ProcessDebugMessages();
2801
}
2802

    
2803

    
2804
#ifdef __POSIX__
2805
static volatile sig_atomic_t caught_early_debug_signal;
2806

    
2807

    
2808
static void EarlyDebugSignalHandler(int signo) {
2809
  caught_early_debug_signal = 1;
2810
}
2811

    
2812

    
2813
static void InstallEarlyDebugSignalHandler() {
2814
  struct sigaction sa;
2815
  memset(&sa, 0, sizeof(sa));
2816
  sa.sa_handler = EarlyDebugSignalHandler;
2817
  sigaction(SIGUSR1, &sa, NULL);
2818
}
2819

    
2820

    
2821
static void EnableDebugSignalHandler(int signo) {
2822
  // Call only async signal-safe functions here!
2823
  v8::Debug::DebugBreak(*static_cast<Isolate* volatile*>(&node_isolate));
2824
  uv_async_send(&dispatch_debug_messages_async);
2825
}
2826

    
2827

    
2828
static void RegisterSignalHandler(int signal, void (*handler)(int signal)) {
2829
  struct sigaction sa;
2830
  memset(&sa, 0, sizeof(sa));
2831
  sa.sa_handler = handler;
2832
  sigfillset(&sa.sa_mask);
2833
  sigaction(signal, &sa, NULL);
2834
}
2835

    
2836

    
2837
void DebugProcess(const FunctionCallbackInfo<Value>& args) {
2838
  HandleScope scope(node_isolate);
2839

    
2840
  if (args.Length() != 1) {
2841
    return ThrowError("Invalid number of arguments.");
2842
  }
2843

    
2844
  pid_t pid;
2845
  int r;
2846

    
2847
  pid = args[0]->IntegerValue();
2848
  r = kill(pid, SIGUSR1);
2849
  if (r != 0) {
2850
    return ThrowErrnoException(errno, "kill");
2851
  }
2852
}
2853

    
2854

    
2855
static int RegisterDebugSignalHandler() {
2856
  // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
2857
  RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
2858
  // If we caught a SIGUSR1 during the bootstrap process, re-raise it
2859
  // now that the debugger infrastructure is in place.
2860
  if (caught_early_debug_signal)
2861
    raise(SIGUSR1);
2862
  return 0;
2863
}
2864
#endif  // __POSIX__
2865

    
2866

    
2867
#ifdef _WIN32
2868
DWORD WINAPI EnableDebugThreadProc(void* arg) {
2869
  v8::Debug::DebugBreak(*static_cast<Isolate* volatile*>(&node_isolate));
2870
  uv_async_send(&dispatch_debug_messages_async);
2871
  return 0;
2872
}
2873

    
2874

    
2875
static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
2876
    size_t buf_len) {
2877
  return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
2878
}
2879

    
2880

    
2881
static int RegisterDebugSignalHandler() {
2882
  wchar_t mapping_name[32];
2883
  HANDLE mapping_handle;
2884
  DWORD pid;
2885
  LPTHREAD_START_ROUTINE* handler;
2886

    
2887
  pid = GetCurrentProcessId();
2888

    
2889
  if (GetDebugSignalHandlerMappingName(pid,
2890
                                       mapping_name,
2891
                                       ARRAY_SIZE(mapping_name)) < 0) {
2892
    return -1;
2893
  }
2894

    
2895
  mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
2896
                                      NULL,
2897
                                      PAGE_READWRITE,
2898
                                      0,
2899
                                      sizeof *handler,
2900
                                      mapping_name);
2901
  if (mapping_handle == NULL) {
2902
    return -1;
2903
  }
2904

    
2905
  handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
2906
      MapViewOfFile(mapping_handle,
2907
                    FILE_MAP_ALL_ACCESS,
2908
                    0,
2909
                    0,
2910
                    sizeof *handler));
2911
  if (handler == NULL) {
2912
    CloseHandle(mapping_handle);
2913
    return -1;
2914
  }
2915

    
2916
  *handler = EnableDebugThreadProc;
2917

    
2918
  UnmapViewOfFile(static_cast<void*>(handler));
2919

    
2920
  return 0;
2921
}
2922

    
2923

    
2924
static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
2925
  HandleScope scope(node_isolate);
2926
  DWORD pid;
2927
  HANDLE process = NULL;
2928
  HANDLE thread = NULL;
2929
  HANDLE mapping = NULL;
2930
  wchar_t mapping_name[32];
2931
  LPTHREAD_START_ROUTINE* handler = NULL;
2932

    
2933
  if (args.Length() != 1) {
2934
    ThrowError("Invalid number of arguments.");
2935
    goto out;
2936
  }
2937

    
2938
  pid = (DWORD) args[0]->IntegerValue();
2939

    
2940
  process = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
2941
                            PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
2942
                            PROCESS_VM_READ,
2943
                        FALSE,
2944
                        pid);
2945
  if (process == NULL) {
2946
    ThrowException(WinapiErrnoException(GetLastError(), "OpenProcess"));
2947
    goto out;
2948
  }
2949

    
2950
  if (GetDebugSignalHandlerMappingName(pid,
2951
                                       mapping_name,
2952
                                       ARRAY_SIZE(mapping_name)) < 0) {
2953
    ThrowErrnoException(errno, "sprintf");
2954
    goto out;
2955
  }
2956

    
2957
  mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
2958
  if (mapping == NULL) {
2959
    ThrowException(WinapiErrnoException(GetLastError(), "OpenFileMappingW"));
2960
    goto out;
2961
  }
2962

    
2963
  handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
2964
      MapViewOfFile(mapping,
2965
                    FILE_MAP_READ,
2966
                    0,
2967
                    0,
2968
                    sizeof *handler));
2969
  if (handler == NULL || *handler == NULL) {
2970
    ThrowException(WinapiErrnoException(GetLastError(), "MapViewOfFile"));
2971
    goto out;
2972
  }
2973

    
2974
  thread = CreateRemoteThread(process,
2975
                              NULL,
2976
                              0,
2977
                              *handler,
2978
                              NULL,
2979
                              0,
2980
                              NULL);
2981
  if (thread == NULL) {
2982
    ThrowException(WinapiErrnoException(GetLastError(), "CreateRemoteThread"));
2983
    goto out;
2984
  }
2985

    
2986
  // Wait for the thread to terminate
2987
  if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
2988
    ThrowException(WinapiErrnoException(GetLastError(), "WaitForSingleObject"));
2989
    goto out;
2990
  }
2991

    
2992
 out:
2993
  if (process != NULL)
2994
    CloseHandle(process);
2995
  if (thread != NULL)
2996
    CloseHandle(thread);
2997
  if (handler != NULL)
2998
    UnmapViewOfFile(handler);
2999
  if (mapping != NULL)
3000
    CloseHandle(mapping);
3001
}
3002
#endif  // _WIN32
3003

    
3004

    
3005
static void DebugPause(const FunctionCallbackInfo<Value>& args) {
3006
  v8::Debug::DebugBreak(node_isolate);
3007
}
3008

    
3009

    
3010
static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
3011
  if (debugger_running) {
3012
    v8::Debug::DisableAgent();
3013
    debugger_running = false;
3014
  }
3015
}
3016

    
3017

    
3018
void Init(int* argc,
3019
          const char** argv,
3020
          int* exec_argc,
3021
          const char*** exec_argv) {
3022
  // Initialize prog_start_time to get relative uptime.
3023
  uv_uptime(&prog_start_time);
3024

    
3025
  // Make inherited handles noninheritable.
3026
  uv_disable_stdio_inheritance();
3027

    
3028
  // init async debug messages dispatching
3029
  // FIXME(bnoordhuis) Should be per-isolate or per-context, not global.
3030
  uv_async_init(uv_default_loop(),
3031
                &dispatch_debug_messages_async,
3032
                DispatchDebugMessagesAsyncCallback);
3033
  uv_unref(reinterpret_cast<uv_handle_t*>(&dispatch_debug_messages_async));
3034

    
3035
  // Parse a few arguments which are specific to Node.
3036
  int v8_argc;
3037
  const char** v8_argv;
3038
  ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv);
3039

    
3040
  // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
3041
  // manually?  That would give us a little more control over its runtime
3042
  // behavior but it could also interfere with the user's intentions in ways
3043
  // we fail to anticipate.  Dillema.
3044
  for (int i = 1; i < v8_argc; ++i) {
3045
    if (strncmp(v8_argv[i], "--prof", sizeof("--prof") - 1) == 0) {
3046
      v8_is_profiling = true;
3047
      break;
3048
    }
3049
  }
3050

    
3051
  // The const_cast doesn't violate conceptual const-ness.  V8 doesn't modify
3052
  // the argv array or the elements it points to.
3053
  V8::SetFlagsFromCommandLine(&v8_argc, const_cast<char**>(v8_argv), true);
3054

    
3055
  // Anything that's still in v8_argv is not a V8 or a node option.
3056
  for (int i = 1; i < v8_argc; i++) {
3057
    fprintf(stderr, "%s: bad option: %s\n", argv[0], v8_argv[i]);
3058
  }
3059
  delete[] v8_argv;
3060
  v8_argv = NULL;
3061

    
3062
  if (v8_argc > 1) {
3063
    exit(9);
3064
  }
3065

    
3066
  if (debug_wait_connect) {
3067
    const char expose_debug_as[] = "--expose_debug_as=v8debug";
3068
    V8::SetFlagsFromString(expose_debug_as, sizeof(expose_debug_as) - 1);
3069
  }
3070

    
3071
  V8::SetArrayBufferAllocator(&ArrayBufferAllocator::the_singleton);
3072

    
3073
  // Fetch a reference to the main isolate, so we have a reference to it
3074
  // even when we need it to access it from another (debugger) thread.
3075
  node_isolate = Isolate::GetCurrent();
3076

    
3077
#ifdef __POSIX__
3078
  // Raise the open file descriptor limit.
3079
  {  // NOLINT (whitespace/braces)
3080
    struct rlimit lim;
3081
    if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
3082
      // Do a binary search for the limit.
3083
      rlim_t min = lim.rlim_cur;
3084
      rlim_t max = 1 << 20;
3085
      // But if there's a defined upper bound, don't search, just set it.
3086
      if (lim.rlim_max != RLIM_INFINITY) {
3087
        min = lim.rlim_max;
3088
        max = lim.rlim_max;
3089
      }
3090
      do {
3091
        lim.rlim_cur = min + (max - min) / 2;
3092
        if (setrlimit(RLIMIT_NOFILE, &lim)) {
3093
          max = lim.rlim_cur;
3094
        } else {
3095
          min = lim.rlim_cur;
3096
        }
3097
      } while (min + 1 < max);
3098
    }
3099
  }
3100
  // Ignore SIGPIPE
3101
  RegisterSignalHandler(SIGPIPE, SIG_IGN);
3102
  RegisterSignalHandler(SIGINT, SignalExit);
3103
  RegisterSignalHandler(SIGTERM, SignalExit);
3104
#endif  // __POSIX__
3105

    
3106
  V8::SetFatalErrorHandler(node::OnFatalError);
3107
  V8::AddMessageListener(OnMessage);
3108

    
3109
  // If the --debug flag was specified then initialize the debug thread.
3110
  if (use_debug_agent) {
3111
    EnableDebug(debug_wait_connect);
3112
  } else {
3113
    RegisterDebugSignalHandler();
3114
  }
3115
}
3116

    
3117

    
3118
struct AtExitCallback {
3119
  AtExitCallback* next_;
3120
  void (*cb_)(void* arg);
3121
  void* arg_;
3122
};
3123

    
3124
static AtExitCallback* at_exit_functions_;
3125

    
3126

    
3127
// TODO(bnoordhuis) Turn into per-context event.
3128
void RunAtExit(Environment* env) {
3129
  AtExitCallback* p = at_exit_functions_;
3130
  at_exit_functions_ = NULL;
3131

    
3132
  while (p) {
3133
    AtExitCallback* q = p->next_;
3134
    p->cb_(p->arg_);
3135
    delete p;
3136
    p = q;
3137
  }
3138
}
3139

    
3140

    
3141
void AtExit(void (*cb)(void* arg), void* arg) {
3142
  AtExitCallback* p = new AtExitCallback;
3143
  p->cb_ = cb;
3144
  p->arg_ = arg;
3145
  p->next_ = at_exit_functions_;
3146
  at_exit_functions_ = p;
3147
}
3148

    
3149

    
3150
void EmitExit(Environment* env) {
3151
  // process.emit('exit')
3152
  Context::Scope context_scope(env->context());
3153
  HandleScope handle_scope(env->isolate());
3154
  Local<Object> process_object = env->process_object();
3155
  process_object->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_exiting"),
3156
                      True(node_isolate));
3157

    
3158
  Handle<String> exitCode = FIXED_ONE_BYTE_STRING(node_isolate, "exitCode");
3159
  int code = process_object->Get(exitCode)->IntegerValue();
3160

    
3161
  Local<Value> args[] = {
3162
    FIXED_ONE_BYTE_STRING(node_isolate, "exit"),
3163
    Integer::New(code, node_isolate)
3164
  };
3165

    
3166
  MakeCallback(env, process_object, "emit", ARRAY_SIZE(args), args);
3167
  exit(code);
3168
}
3169

    
3170

    
3171
Environment* CreateEnvironment(Isolate* isolate,
3172
                               int argc,
3173
                               const char* const* argv,
3174
                               int exec_argc,
3175
                               const char* const* exec_argv) {
3176
  HandleScope handle_scope(isolate);
3177

    
3178
  Local<Context> context = Context::New(isolate);
3179
  Context::Scope context_scope(context);
3180
  Environment* env = Environment::New(context);
3181

    
3182
  uv_check_init(env->event_loop(), env->immediate_check_handle());
3183
  uv_unref(
3184
      reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()));
3185
  uv_idle_init(env->event_loop(), env->immediate_idle_handle());
3186

    
3187
  // Inform V8's CPU profiler when we're idle.  The profiler is sampling-based
3188
  // but not all samples are created equal; mark the wall clock time spent in
3189
  // epoll_wait() and friends so profiling tools can filter it out.  The samples
3190
  // still end up in v8.log but with state=IDLE rather than state=EXTERNAL.
3191
  // TODO(bnoordhuis) Depends on a libuv implementation detail that we should
3192
  // probably fortify in the API contract, namely that the last started prepare
3193
  // or check watcher runs first.  It's not 100% foolproof; if an add-on starts
3194
  // a prepare or check watcher after us, any samples attributed to its callback
3195
  // will be recorded with state=IDLE.
3196
  uv_prepare_init(env->event_loop(), env->idle_prepare_handle());
3197
  uv_check_init(env->event_loop(), env->idle_check_handle());
3198
  uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()));
3199
  uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_check_handle()));
3200

    
3201
  if (v8_is_profiling) {
3202
    StartProfilerIdleNotifier(env);
3203
  }
3204

    
3205
  Local<FunctionTemplate> process_template = FunctionTemplate::New();
3206
  process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "process"));
3207

    
3208
  Local<Object> process_object = process_template->GetFunction()->NewInstance();
3209
  env->set_process_object(process_object);
3210

    
3211
  SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
3212
  Load(env);
3213

    
3214
  return env;
3215
}
3216

    
3217

    
3218
int Start(int argc, char** argv) {
3219
#if !defined(_WIN32)
3220
  // Try hard not to lose SIGUSR1 signals during the bootstrap process.
3221
  InstallEarlyDebugSignalHandler();
3222
#endif
3223

    
3224
  assert(argc > 0);
3225

    
3226
  // Hack around with the argv pointer. Used for process.title = "blah".
3227
  argv = uv_setup_args(argc, argv);
3228

    
3229
  // This needs to run *before* V8::Initialize().  The const_cast is not
3230
  // optional, in case you're wondering.
3231
  int exec_argc;
3232
  const char** exec_argv;
3233
  Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);
3234

    
3235
#if HAVE_OPENSSL
3236
  // V8 on Windows doesn't have a good source of entropy. Seed it from
3237
  // OpenSSL's pool.
3238
  V8::SetEntropySource(crypto::EntropySource);
3239
#endif
3240

    
3241
  V8::Initialize();
3242
  {
3243
    Locker locker(node_isolate);
3244
    Environment* env =
3245
        CreateEnvironment(node_isolate, argc, argv, exec_argc, exec_argv);
3246
    Context::Scope context_scope(env->context());
3247
    HandleScope handle_scope(env->isolate());
3248
    uv_run(env->event_loop(), UV_RUN_DEFAULT);
3249
    EmitExit(env);
3250
    RunAtExit(env);
3251
    env->Dispose();
3252
    env = NULL;
3253
  }
3254

    
3255
#ifndef NDEBUG
3256
  // Clean up. Not strictly necessary.
3257
  V8::Dispose();
3258
#endif  // NDEBUG
3259

    
3260
  delete[] exec_argv;
3261
  exec_argv = NULL;
3262

    
3263
  return 0;
3264
}
3265

    
3266

    
3267
}  // namespace node