Logo Search packages:      
Sourcecode: ccache version File versions

execute.c

/*
   Copyright (C) Andrew Tridgell 2002
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "ccache.h"


/*
  execute a compiler backend, capturing all output to the given paths
  the full path to the compiler to run is in argv[0]
*/
int execute(char **argv, 
          const char *path_stdout,
          const char *path_stderr)
{
      pid_t pid;
      int status;

      pid = fork();
      if (pid == -1) fatal("Failed to fork");
      
      if (pid == 0) {
            int fd;

            unlink(path_stdout);
            fd = open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0666);
            if (fd == -1) {
                  exit(STATUS_NOCACHE);
            }
            dup2(fd, 1);
            close(fd);

            unlink(path_stderr);
            fd = open(path_stderr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0666);
            if (fd == -1) {
                  exit(STATUS_NOCACHE);
            }
            dup2(fd, 2);
            close(fd);

            exit(execv(argv[0], argv));
      }

      if (waitpid(pid, &status, 0) != pid) {
            fatal("waitpid failed");
      }

      if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) {
            return -1;
      }

      return WEXITSTATUS(status);
}


/*
  find an executable by name in $PATH. Exclude any that are links to exclude_name 
*/
char *find_executable(const char *name, const char *exclude_name)
{
      char *path;
      char *tok;
      struct stat st1, st2;

      path = getenv("CCACHE_PATH");
      if (!path) {
            path = getenv("PATH");
      }
      if (!path) {
            cc_log("no PATH variable!?\n");
            return NULL;
      }

      path = x_strdup(path);
      
      /* search the path looking for the first compiler of the right name
         that isn't us */
      for (tok=strtok(path,":"); tok; tok = strtok(NULL, ":")) {
            char *fname;
            x_asprintf(&fname, "%s/%s", tok, name);
            /* look for a normal executable file */
            if (access(fname, X_OK) == 0 &&
                lstat(fname, &st1) == 0 &&
                stat(fname, &st2) == 0 &&
                S_ISREG(st2.st_mode)) {
                  /* if its a symlink then ensure it doesn't
                           point at something called exclude_name */
                  if (S_ISLNK(st1.st_mode)) {
                        char *buf = x_realpath(fname);
                        if (buf) {
                              char *p = str_basename(buf);
                              if (strcmp(p, exclude_name) == 0) {
                                    /* its a link to "ccache" ! */
                                    free(p);
                                    free(buf);
                                    continue;
                              }
                              free(buf);
                              free(p);
                        }
                  }

                  /* found it! */
                  free(path);
                  return fname;
            }
            free(fname);
      }

      return NULL;
}

Generated by  Doxygen 1.6.0   Back to index