1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "browse.h"
16
17 #include <errno.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <vector>
22
23 #include "build/browse_py.h"
24
RunBrowsePython(State * state,const char * ninja_command,const char * input_file,int argc,char * argv[])25 void RunBrowsePython(State* state, const char* ninja_command,
26 const char* input_file, int argc, char* argv[]) {
27 // Fork off a Python process and have it run our code via its stdin.
28 // (Actually the Python process becomes the parent.)
29 int pipefd[2];
30 if (pipe(pipefd) < 0) {
31 perror("ninja: pipe");
32 return;
33 }
34
35 pid_t pid = fork();
36 if (pid < 0) {
37 perror("ninja: fork");
38 return;
39 }
40
41 if (pid > 0) { // Parent.
42 close(pipefd[1]);
43 do {
44 if (dup2(pipefd[0], 0) < 0) {
45 perror("ninja: dup2");
46 break;
47 }
48
49 std::vector<const char *> command;
50 command.push_back(NINJA_PYTHON);
51 command.push_back("-");
52 command.push_back("--ninja-command");
53 command.push_back(ninja_command);
54 command.push_back("-f");
55 command.push_back(input_file);
56 for (int i = 0; i < argc; i++) {
57 command.push_back(argv[i]);
58 }
59 command.push_back(NULL);
60 execvp(command[0], (char**)&command[0]);
61 if (errno == ENOENT) {
62 printf("ninja: %s is required for the browse tool\n", NINJA_PYTHON);
63 } else {
64 perror("ninja: execvp");
65 }
66 } while (false);
67 _exit(1);
68 } else { // Child.
69 close(pipefd[0]);
70
71 // Write the script file into the stdin of the Python process.
72 ssize_t len = write(pipefd[1], kBrowsePy, sizeof(kBrowsePy));
73 if (len < (ssize_t)sizeof(kBrowsePy))
74 perror("ninja: write");
75 close(pipefd[1]);
76 exit(0);
77 }
78 }
79