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
25using namespace std;
26
27void RunBrowsePython(State* state, const char* ninja_command,
28 const char* input_file, int argc, char* argv[]) {
29 // Fork off a Python process and have it run our code via its stdin.
30 // (Actually the Python process becomes the parent.)
31 int pipefd[2];
32 if (pipe(pipefd) < 0) {
33 perror("ninja: pipe");
34 return;
35 }
36
37 pid_t pid = fork();
38 if (pid < 0) {
39 perror("ninja: fork");
40 return;
41 }
42
43 if (pid > 0) { // Parent.
44 close(pipefd[1]);
45 do {
46 if (dup2(pipefd[0], 0) < 0) {
47 perror("ninja: dup2");
48 break;
49 }
50
51 std::vector<const char *> command;
52 command.push_back(NINJA_PYTHON);
53 command.push_back("-");
54 command.push_back("--ninja-command");
55 command.push_back(ninja_command);
56 command.push_back("-f");
57 command.push_back(input_file);
58 for (int i = 0; i < argc; i++) {
59 command.push_back(argv[i]);
60 }
61 command.push_back(NULL);
62 execvp(command[0], (char**)&command[0]);
63 if (errno == ENOENT) {
64 printf("ninja: %s is required for the browse tool\n", NINJA_PYTHON);
65 } else {
66 perror("ninja: execvp");
67 }
68 } while (false);
69 _exit(1);
70 } else { // Child.
71 close(pipefd[0]);
72
73 // Write the script file into the stdin of the Python process.
74 ssize_t len = write(pipefd[1], kBrowsePy, sizeof(kBrowsePy));
75 if (len < (ssize_t)sizeof(kBrowsePy))
76 perror("ninja: write");
77 close(pipefd[1]);
78 exit(0);
79 }
80}
81