github.com/maruel/nin@v0.0.0-20220112143044-f35891e3ce7e/src/browse.cc (about)

     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  
    25  using namespace std;
    26  
    27  void 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  }