| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 | 238 |
| 239 | 239 |
| 240 // Gets the optional timeouts from the arguments to the system() call. | 240 // Gets the optional timeouts from the arguments to the system() call. |
| 241 static bool GetTimeouts(const v8::FunctionCallbackInfo<v8::Value>& args, | 241 static bool GetTimeouts(const v8::FunctionCallbackInfo<v8::Value>& args, |
| 242 int* read_timeout, | 242 int* read_timeout, |
| 243 int* total_timeout) { | 243 int* total_timeout) { |
| 244 if (args.Length() > 3) { | 244 if (args.Length() > 3) { |
| 245 if (args[3]->IsNumber()) { | 245 if (args[3]->IsNumber()) { |
| 246 *total_timeout = args[3]->Int32Value(); | 246 *total_timeout = args[3]->Int32Value(); |
| 247 } else { | 247 } else { |
| 248 ThrowException(String::New("system: Argument 4 must be a number")); | 248 args.GetIsolate()->ThrowException( |
| 249 String::New("system: Argument 4 must be a number")); |
| 249 return false; | 250 return false; |
| 250 } | 251 } |
| 251 } | 252 } |
| 252 if (args.Length() > 2) { | 253 if (args.Length() > 2) { |
| 253 if (args[2]->IsNumber()) { | 254 if (args[2]->IsNumber()) { |
| 254 *read_timeout = args[2]->Int32Value(); | 255 *read_timeout = args[2]->Int32Value(); |
| 255 } else { | 256 } else { |
| 256 ThrowException(String::New("system: Argument 3 must be a number")); | 257 args.GetIsolate()->ThrowException( |
| 258 String::New("system: Argument 3 must be a number")); |
| 257 return false; | 259 return false; |
| 258 } | 260 } |
| 259 } | 261 } |
| 260 return true; | 262 return true; |
| 261 } | 263 } |
| 262 | 264 |
| 263 | 265 |
| 264 static const int kReadFD = 0; | 266 static const int kReadFD = 0; |
| 265 static const int kWriteFD = 1; | 267 static const int kWriteFD = 1; |
| 266 | 268 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 | 451 |
| 450 // Implementation of the system() function (see d8.h for details). | 452 // Implementation of the system() function (see d8.h for details). |
| 451 void Shell::System(const v8::FunctionCallbackInfo<v8::Value>& args) { | 453 void Shell::System(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 452 HandleScope scope(args.GetIsolate()); | 454 HandleScope scope(args.GetIsolate()); |
| 453 int read_timeout = -1; | 455 int read_timeout = -1; |
| 454 int total_timeout = -1; | 456 int total_timeout = -1; |
| 455 if (!GetTimeouts(args, &read_timeout, &total_timeout)) return; | 457 if (!GetTimeouts(args, &read_timeout, &total_timeout)) return; |
| 456 Handle<Array> command_args; | 458 Handle<Array> command_args; |
| 457 if (args.Length() > 1) { | 459 if (args.Length() > 1) { |
| 458 if (!args[1]->IsArray()) { | 460 if (!args[1]->IsArray()) { |
| 459 ThrowException(String::New("system: Argument 2 must be an array")); | 461 args.GetIsolate()->ThrowException( |
| 462 String::New("system: Argument 2 must be an array")); |
| 460 return; | 463 return; |
| 461 } | 464 } |
| 462 command_args = Handle<Array>::Cast(args[1]); | 465 command_args = Handle<Array>::Cast(args[1]); |
| 463 } else { | 466 } else { |
| 464 command_args = Array::New(0); | 467 command_args = Array::New(0); |
| 465 } | 468 } |
| 466 if (command_args->Length() > ExecArgs::kMaxArgs) { | 469 if (command_args->Length() > ExecArgs::kMaxArgs) { |
| 467 ThrowException(String::New("Too many arguments to system()")); | 470 args.GetIsolate()->ThrowException( |
| 471 String::New("Too many arguments to system()")); |
| 468 return; | 472 return; |
| 469 } | 473 } |
| 470 if (args.Length() < 1) { | 474 if (args.Length() < 1) { |
| 471 ThrowException(String::New("Too few arguments to system()")); | 475 args.GetIsolate()->ThrowException( |
| 476 String::New("Too few arguments to system()")); |
| 472 return; | 477 return; |
| 473 } | 478 } |
| 474 | 479 |
| 475 struct timeval start_time; | 480 struct timeval start_time; |
| 476 gettimeofday(&start_time, NULL); | 481 gettimeofday(&start_time, NULL); |
| 477 | 482 |
| 478 ExecArgs exec_args; | 483 ExecArgs exec_args; |
| 479 if (!exec_args.Init(args[0], command_args)) { | 484 if (!exec_args.Init(args[0], command_args)) { |
| 480 return; | 485 return; |
| 481 } | 486 } |
| 482 int exec_error_fds[2]; | 487 int exec_error_fds[2]; |
| 483 int stdout_fds[2]; | 488 int stdout_fds[2]; |
| 484 | 489 |
| 485 if (pipe(exec_error_fds) != 0) { | 490 if (pipe(exec_error_fds) != 0) { |
| 486 ThrowException(String::New("pipe syscall failed.")); | 491 args.GetIsolate()->ThrowException( |
| 492 String::New("pipe syscall failed.")); |
| 487 return; | 493 return; |
| 488 } | 494 } |
| 489 if (pipe(stdout_fds) != 0) { | 495 if (pipe(stdout_fds) != 0) { |
| 490 ThrowException(String::New("pipe syscall failed.")); | 496 args.GetIsolate()->ThrowException( |
| 497 String::New("pipe syscall failed.")); |
| 491 return; | 498 return; |
| 492 } | 499 } |
| 493 | 500 |
| 494 pid_t pid = fork(); | 501 pid_t pid = fork(); |
| 495 if (pid == 0) { // Child process. | 502 if (pid == 0) { // Child process. |
| 496 ExecSubprocess(exec_error_fds, stdout_fds, exec_args); | 503 ExecSubprocess(exec_error_fds, stdout_fds, exec_args); |
| 497 exit(1); | 504 exit(1); |
| 498 } | 505 } |
| 499 | 506 |
| 500 // Parent process. Ensure that we clean up if we exit this function early. | 507 // Parent process. Ensure that we clean up if we exit this function early. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 524 return; | 531 return; |
| 525 } | 532 } |
| 526 | 533 |
| 527 args.GetReturnValue().Set(accumulator); | 534 args.GetReturnValue().Set(accumulator); |
| 528 } | 535 } |
| 529 | 536 |
| 530 | 537 |
| 531 void Shell::ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) { | 538 void Shell::ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 532 if (args.Length() != 1) { | 539 if (args.Length() != 1) { |
| 533 const char* message = "chdir() takes one argument"; | 540 const char* message = "chdir() takes one argument"; |
| 534 ThrowException(String::New(message)); | 541 args.GetIsolate()->ThrowException(String::New(message)); |
| 535 return; | 542 return; |
| 536 } | 543 } |
| 537 String::Utf8Value directory(args[0]); | 544 String::Utf8Value directory(args[0]); |
| 538 if (*directory == NULL) { | 545 if (*directory == NULL) { |
| 539 const char* message = "os.chdir(): String conversion of argument failed."; | 546 const char* message = "os.chdir(): String conversion of argument failed."; |
| 540 ThrowException(String::New(message)); | 547 args.GetIsolate()->ThrowException(String::New(message)); |
| 541 return; | 548 return; |
| 542 } | 549 } |
| 543 if (chdir(*directory) != 0) { | 550 if (chdir(*directory) != 0) { |
| 544 ThrowException(String::New(strerror(errno))); | 551 args.GetIsolate()->ThrowException(String::New(strerror(errno))); |
| 545 return; | 552 return; |
| 546 } | 553 } |
| 547 } | 554 } |
| 548 | 555 |
| 549 | 556 |
| 550 void Shell::SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args) { | 557 void Shell::SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 551 if (args.Length() != 1) { | 558 if (args.Length() != 1) { |
| 552 const char* message = "umask() takes one argument"; | 559 const char* message = "umask() takes one argument"; |
| 553 ThrowException(String::New(message)); | 560 args.GetIsolate()->ThrowException(String::New(message)); |
| 554 return; | 561 return; |
| 555 } | 562 } |
| 556 if (args[0]->IsNumber()) { | 563 if (args[0]->IsNumber()) { |
| 557 mode_t mask = args[0]->Int32Value(); | 564 mode_t mask = args[0]->Int32Value(); |
| 558 int previous = umask(mask); | 565 int previous = umask(mask); |
| 559 args.GetReturnValue().Set(previous); | 566 args.GetReturnValue().Set(previous); |
| 560 return; | 567 return; |
| 561 } else { | 568 } else { |
| 562 const char* message = "umask() argument must be numeric"; | 569 const char* message = "umask() argument must be numeric"; |
| 563 ThrowException(String::New(message)); | 570 args.GetIsolate()->ThrowException(String::New(message)); |
| 564 return; | 571 return; |
| 565 } | 572 } |
| 566 } | 573 } |
| 567 | 574 |
| 568 | 575 |
| 569 static bool CheckItsADirectory(char* directory) { | 576 static bool CheckItsADirectory(char* directory) { |
| 570 struct stat stat_buf; | 577 struct stat stat_buf; |
| 571 int stat_result = stat(directory, &stat_buf); | 578 int stat_result = stat(directory, &stat_buf); |
| 572 if (stat_result != 0) { | 579 if (stat_result != 0) { |
| 573 ThrowException(String::New(strerror(errno))); | 580 ThrowException(String::New(strerror(errno))); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 } | 616 } |
| 610 | 617 |
| 611 | 618 |
| 612 void Shell::MakeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) { | 619 void Shell::MakeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 613 mode_t mask = 0777; | 620 mode_t mask = 0777; |
| 614 if (args.Length() == 2) { | 621 if (args.Length() == 2) { |
| 615 if (args[1]->IsNumber()) { | 622 if (args[1]->IsNumber()) { |
| 616 mask = args[1]->Int32Value(); | 623 mask = args[1]->Int32Value(); |
| 617 } else { | 624 } else { |
| 618 const char* message = "mkdirp() second argument must be numeric"; | 625 const char* message = "mkdirp() second argument must be numeric"; |
| 619 ThrowException(String::New(message)); | 626 args.GetIsolate()->ThrowException(String::New(message)); |
| 620 return; | 627 return; |
| 621 } | 628 } |
| 622 } else if (args.Length() != 1) { | 629 } else if (args.Length() != 1) { |
| 623 const char* message = "mkdirp() takes one or two arguments"; | 630 const char* message = "mkdirp() takes one or two arguments"; |
| 624 ThrowException(String::New(message)); | 631 args.GetIsolate()->ThrowException(String::New(message)); |
| 625 return; | 632 return; |
| 626 } | 633 } |
| 627 String::Utf8Value directory(args[0]); | 634 String::Utf8Value directory(args[0]); |
| 628 if (*directory == NULL) { | 635 if (*directory == NULL) { |
| 629 const char* message = "os.mkdirp(): String conversion of argument failed."; | 636 const char* message = "os.mkdirp(): String conversion of argument failed."; |
| 630 ThrowException(String::New(message)); | 637 args.GetIsolate()->ThrowException(String::New(message)); |
| 631 return; | 638 return; |
| 632 } | 639 } |
| 633 mkdirp(*directory, mask); | 640 mkdirp(*directory, mask); |
| 634 } | 641 } |
| 635 | 642 |
| 636 | 643 |
| 637 void Shell::RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) { | 644 void Shell::RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 638 if (args.Length() != 1) { | 645 if (args.Length() != 1) { |
| 639 const char* message = "rmdir() takes one or two arguments"; | 646 const char* message = "rmdir() takes one or two arguments"; |
| 640 ThrowException(String::New(message)); | 647 args.GetIsolate()->ThrowException(String::New(message)); |
| 641 return; | 648 return; |
| 642 } | 649 } |
| 643 String::Utf8Value directory(args[0]); | 650 String::Utf8Value directory(args[0]); |
| 644 if (*directory == NULL) { | 651 if (*directory == NULL) { |
| 645 const char* message = "os.rmdir(): String conversion of argument failed."; | 652 const char* message = "os.rmdir(): String conversion of argument failed."; |
| 646 ThrowException(String::New(message)); | 653 args.GetIsolate()->ThrowException(String::New(message)); |
| 647 return; | 654 return; |
| 648 } | 655 } |
| 649 rmdir(*directory); | 656 rmdir(*directory); |
| 650 } | 657 } |
| 651 | 658 |
| 652 | 659 |
| 653 void Shell::SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) { | 660 void Shell::SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 654 if (args.Length() != 2) { | 661 if (args.Length() != 2) { |
| 655 const char* message = "setenv() takes two arguments"; | 662 const char* message = "setenv() takes two arguments"; |
| 656 ThrowException(String::New(message)); | 663 args.GetIsolate()->ThrowException(String::New(message)); |
| 657 return; | 664 return; |
| 658 } | 665 } |
| 659 String::Utf8Value var(args[0]); | 666 String::Utf8Value var(args[0]); |
| 660 String::Utf8Value value(args[1]); | 667 String::Utf8Value value(args[1]); |
| 661 if (*var == NULL) { | 668 if (*var == NULL) { |
| 662 const char* message = | 669 const char* message = |
| 663 "os.setenv(): String conversion of variable name failed."; | 670 "os.setenv(): String conversion of variable name failed."; |
| 664 ThrowException(String::New(message)); | 671 args.GetIsolate()->ThrowException(String::New(message)); |
| 665 return; | 672 return; |
| 666 } | 673 } |
| 667 if (*value == NULL) { | 674 if (*value == NULL) { |
| 668 const char* message = | 675 const char* message = |
| 669 "os.setenv(): String conversion of variable contents failed."; | 676 "os.setenv(): String conversion of variable contents failed."; |
| 670 ThrowException(String::New(message)); | 677 args.GetIsolate()->ThrowException(String::New(message)); |
| 671 return; | 678 return; |
| 672 } | 679 } |
| 673 setenv(*var, *value, 1); | 680 setenv(*var, *value, 1); |
| 674 } | 681 } |
| 675 | 682 |
| 676 | 683 |
| 677 void Shell::UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) { | 684 void Shell::UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 678 if (args.Length() != 1) { | 685 if (args.Length() != 1) { |
| 679 const char* message = "unsetenv() takes one argument"; | 686 const char* message = "unsetenv() takes one argument"; |
| 680 ThrowException(String::New(message)); | 687 args.GetIsolate()->ThrowException(String::New(message)); |
| 681 return; | 688 return; |
| 682 } | 689 } |
| 683 String::Utf8Value var(args[0]); | 690 String::Utf8Value var(args[0]); |
| 684 if (*var == NULL) { | 691 if (*var == NULL) { |
| 685 const char* message = | 692 const char* message = |
| 686 "os.setenv(): String conversion of variable name failed."; | 693 "os.setenv(): String conversion of variable name failed."; |
| 687 ThrowException(String::New(message)); | 694 args.GetIsolate()->ThrowException(String::New(message)); |
| 688 return; | 695 return; |
| 689 } | 696 } |
| 690 unsetenv(*var); | 697 unsetenv(*var); |
| 691 } | 698 } |
| 692 | 699 |
| 693 | 700 |
| 694 void Shell::AddOSMethods(Handle<ObjectTemplate> os_templ) { | 701 void Shell::AddOSMethods(Handle<ObjectTemplate> os_templ) { |
| 695 os_templ->Set(String::New("system"), FunctionTemplate::New(System)); | 702 os_templ->Set(String::New("system"), FunctionTemplate::New(System)); |
| 696 os_templ->Set(String::New("chdir"), FunctionTemplate::New(ChangeDirectory)); | 703 os_templ->Set(String::New("chdir"), FunctionTemplate::New(ChangeDirectory)); |
| 697 os_templ->Set(String::New("setenv"), FunctionTemplate::New(SetEnvironment)); | 704 os_templ->Set(String::New("setenv"), FunctionTemplate::New(SetEnvironment)); |
| 698 os_templ->Set(String::New("unsetenv"), | 705 os_templ->Set(String::New("unsetenv"), |
| 699 FunctionTemplate::New(UnsetEnvironment)); | 706 FunctionTemplate::New(UnsetEnvironment)); |
| 700 os_templ->Set(String::New("umask"), FunctionTemplate::New(SetUMask)); | 707 os_templ->Set(String::New("umask"), FunctionTemplate::New(SetUMask)); |
| 701 os_templ->Set(String::New("mkdirp"), FunctionTemplate::New(MakeDirectory)); | 708 os_templ->Set(String::New("mkdirp"), FunctionTemplate::New(MakeDirectory)); |
| 702 os_templ->Set(String::New("rmdir"), FunctionTemplate::New(RemoveDirectory)); | 709 os_templ->Set(String::New("rmdir"), FunctionTemplate::New(RemoveDirectory)); |
| 703 } | 710 } |
| 704 | 711 |
| 705 } // namespace v8 | 712 } // namespace v8 |
| OLD | NEW |