[BACK]Return to main.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.bin / make

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/usr.bin/make/main.c between version 1.452 and 1.453

version 1.452, 2020/11/08 14:19:15 version 1.453, 2020/11/08 14:50:24
Line 116  __COPYRIGHT("@(#) Copyright (c) 1988, 19
Line 116  __COPYRIGHT("@(#) Copyright (c) 1988, 19
             "All rights reserved.");              "All rights reserved.");
 #endif  #endif
   
 #ifndef DEFMAXLOCAL  #ifndef DEFMAXLOCAL
 #define DEFMAXLOCAL DEFMAXJOBS  #define DEFMAXLOCAL DEFMAXJOBS
 #endif  #endif
   
 CmdOpts opts;  CmdOpts opts;
 time_t                  now;            /* Time at start of make */  time_t now;                     /* Time at start of make */
 GNode                   *DEFAULT;       /* .DEFAULT node */  GNode *DEFAULT;                 /* .DEFAULT node */
 Boolean                 allPrecious;    /* .PRECIOUS given on line by itself */  Boolean allPrecious;            /* .PRECIOUS given on line by itself */
 Boolean                 deleteOnError;  /* .DELETE_ON_ERROR: set */  Boolean deleteOnError;          /* .DELETE_ON_ERROR: set */
   
 static int              maxJobTokens;   /* -j argument */  static int maxJobTokens;        /* -j argument */
 Boolean                 enterFlagObj;   /* -w and objdir != srcdir */  Boolean enterFlagObj;           /* -w and objdir != srcdir */
   
 Boolean preserveUndefined;  Boolean preserveUndefined;
 static int jp_0 = -1, jp_1 = -1;        /* ends of parent job pipe */  static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */
 Boolean                 doing_depend;   /* Set while reading .depend */  Boolean doing_depend;           /* Set while reading .depend */
 static Boolean          jobsRunning;    /* TRUE if the jobs might be running */  static Boolean jobsRunning;     /* TRUE if the jobs might be running */
 static const char *     tracefile;  static const char *tracefile;
 static int              ReadMakefile(const char *);  static int ReadMakefile(const char *);
 static void             purge_cached_realpaths(void);  static void purge_cached_realpaths(void);
   
 static Boolean          ignorePWD;      /* if we use -C, PWD is meaningless */  static Boolean ignorePWD;       /* if we use -C, PWD is meaningless */
 static char objdir[MAXPATHLEN + 1];     /* where we chdir'ed to */  static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
 char curdir[MAXPATHLEN + 1];            /* Startup directory */  char curdir[MAXPATHLEN + 1];    /* Startup directory */
 char *progname;                         /* the program name */  char *progname;                 /* the program name */
 char *makeDependfile;  char *makeDependfile;
 pid_t myPid;  pid_t myPid;
 int makelevel;  int makelevel;
Line 155  static int errors = 0;
Line 155  static int errors = 0;
 static char *  static char *
 explode(const char *flags)  explode(const char *flags)
 {  {
     size_t len;          size_t len;
     char *nf, *st;          char *nf, *st;
     const char *f;          const char *f;
   
     if (flags == NULL)          if (flags == NULL)
         return NULL;                  return NULL;
   
     for (f = flags; *f; f++)          for (f = flags; *f; f++)
         if (!ch_isalpha(*f))                  if (!ch_isalpha(*f))
             break;                          break;
   
     if (*f)          if (*f)
         return bmake_strdup(flags);                  return bmake_strdup(flags);
   
     len = strlen(flags);          len = strlen(flags);
     st = nf = bmake_malloc(len * 3 + 1);          st = nf = bmake_malloc(len * 3 + 1);
     while (*flags) {          while (*flags) {
         *nf++ = '-';                  *nf++ = '-';
         *nf++ = *flags++;                  *nf++ = *flags++;
         *nf++ = ' ';                  *nf++ = ' ';
     }          }
     *nf = '\0';          *nf = '\0';
     return st;          return st;
 }  }
   
 /*  /*
Line 196  usage(void)
Line 196  usage(void)
 "            [-C directory] [-D variable] [-d flags] [-f makefile]\n"  "            [-C directory] [-D variable] [-d flags] [-f makefile]\n"
 "            [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n"  "            [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n"
 "            [-V variable] [-v variable] [variable=value] [target ...]\n",  "            [-V variable] [-v variable] [variable=value] [target ...]\n",
                       progname);              progname);
         exit(2);          exit(2);
 }  }
   
 static void  static void
 parse_debug_option_F(const char *modules)  parse_debug_option_F(const char *modules)
 {  {
     const char *mode;          const char *mode;
     size_t len;          size_t len;
     char *fname;          char *fname;
   
     if (opts.debug_file != stdout && opts.debug_file != stderr)          if (opts.debug_file != stdout && opts.debug_file != stderr)
         fclose(opts.debug_file);                  fclose(opts.debug_file);
   
     if (*modules == '+') {          if (*modules == '+') {
         modules++;                  modules++;
         mode = "a";                  mode = "a";
     } else          } else
         mode = "w";                  mode = "w";
   
     if (strcmp(modules, "stdout") == 0) {          if (strcmp(modules, "stdout") == 0) {
         opts.debug_file = stdout;                  opts.debug_file = stdout;
         return;                  return;
     }          }
     if (strcmp(modules, "stderr") == 0) {          if (strcmp(modules, "stderr") == 0) {
         opts.debug_file = stderr;                  opts.debug_file = stderr;
         return;                  return;
     }          }
   
     len = strlen(modules);          len = strlen(modules);
     fname = bmake_malloc(len + 20);          fname = bmake_malloc(len + 20);
     memcpy(fname, modules, len + 1);          memcpy(fname, modules, len + 1);
   
     /* Let the filename be modified by the pid */          /* Let the filename be modified by the pid */
     if (strcmp(fname + len - 3, ".%d") == 0)          if (strcmp(fname + len - 3, ".%d") == 0)
         snprintf(fname + len - 2, 20, "%d", getpid());                  snprintf(fname + len - 2, 20, "%d", getpid());
   
     opts.debug_file = fopen(fname, mode);          opts.debug_file = fopen(fname, mode);
     if (opts.debug_file == NULL) {          if (opts.debug_file == NULL) {
         fprintf(stderr, "Cannot open debug file %s\n",                  fprintf(stderr, "Cannot open debug file %s\n",
                 fname);                      fname);
         usage();                  usage();
     }          }
     free(fname);          free(fname);
 }  }
   
 static void  static void
Line 253  parse_debug_options(const char *argvalue
Line 253  parse_debug_options(const char *argvalue
                         opts.debug &= DEBUG_LINT;                          opts.debug &= DEBUG_LINT;
                         break;                          break;
                 case 'A':                  case 'A':
                         opts.debug = ~(0|DEBUG_LINT);                          opts.debug = ~(0 | DEBUG_LINT);
                         break;                          break;
                 case 'a':                  case 'a':
                         opts.debug |= DEBUG_ARCH;                          opts.debug |= DEBUG_ARCH;
Line 334  parse_debug_options(const char *argvalue
Line 334  parse_debug_options(const char *argvalue
                         usage();                          usage();
                 }                  }
         }          }
   
 debug_setbuf:  debug_setbuf:
         /*          /*
          * Make the debug_file unbuffered, and make           * Make the debug_file unbuffered, and make
Line 359  is_relpath(const char *path)
Line 360  is_relpath(const char *path)
         while ((cp = strstr(cp, "/.")) != NULL) {          while ((cp = strstr(cp, "/.")) != NULL) {
                 cp += 2;                  cp += 2;
                 if (*cp == '.')                  if (*cp == '.')
                     cp++;                          cp++;
                 if (cp[0] == '/' || cp[0] == '\0')                  if (cp[0] == '/' || cp[0] == '\0')
                         return TRUE;                          return TRUE;
         }          }
Line 395  MainParseArgJobsInternal(const char *arg
Line 396  MainParseArgJobsInternal(const char *arg
         char end;          char end;
         if (sscanf(argvalue, "%d,%d%c", &jp_0, &jp_1, &end) != 2) {          if (sscanf(argvalue, "%d,%d%c", &jp_0, &jp_1, &end) != 2) {
                 (void)fprintf(stderr,                  (void)fprintf(stderr,
                               "%s: internal error -- J option malformed (%s)\n",                      "%s: internal error -- J option malformed (%s)\n",
                               progname, argvalue);                      progname, argvalue);
                 usage();                  usage();
         }          }
         if ((fcntl(jp_0, F_GETFD, 0) < 0) ||          if ((fcntl(jp_0, F_GETFD, 0) < 0) ||
Line 733  Main_SetObjdir(const char *fmt, ...)
Line 734  Main_SetObjdir(const char *fmt, ...)
                 if ((strcmp(path, curdir) != 0 && access(path, W_OK) != 0) ||                  if ((strcmp(path, curdir) != 0 && access(path, W_OK) != 0) ||
                     (chdir(path) != 0)) {                      (chdir(path) != 0)) {
                         (void)fprintf(stderr, "make warning: %s: %s.\n",                          (void)fprintf(stderr, "make warning: %s: %s.\n",
                                       path, strerror(errno));                              path, strerror(errno));
                 } else {                  } else {
                         snprintf(objdir, sizeof objdir, "%s", path);                          snprintf(objdir, sizeof objdir, "%s", path);
                         Var_Set(".OBJDIR", objdir, VAR_GLOBAL);                          Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
Line 781  Main_SetVarObjdir(const char *var, const
Line 782  Main_SetVarObjdir(const char *var, const
 int  int
 str2Lst_Append(StringList *lp, char *str, const char *sep)  str2Lst_Append(StringList *lp, char *str, const char *sep)
 {  {
     char *cp;          char *cp;
     int n;          int n;
   
     if (!sep)          if (!sep)
         sep = " \t";                  sep = " \t";
   
     for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) {          for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) {
         Lst_Append(lp, cp);                  Lst_Append(lp, cp);
         n++;                  n++;
     }          }
     return n;          return n;
 }  }
   
 #ifdef SIGINFO  #ifdef SIGINFO
Line 816  siginfo(int signo MAKE_ATTR_UNUSED)
Line 817  siginfo(int signo MAKE_ATTR_UNUSED)
 void  void
 MakeMode(const char *mode)  MakeMode(const char *mode)
 {  {
     char *mode_freeIt = NULL;          char *mode_freeIt = NULL;
   
     if (mode == NULL) {          if (mode == NULL) {
         (void)Var_Subst("${" MAKE_MODE ":tl}",                  (void)Var_Subst("${" MAKE_MODE ":tl}",
                   VAR_GLOBAL, VARE_WANTRES, &mode_freeIt);                      VAR_GLOBAL, VARE_WANTRES, &mode_freeIt);
         /* TODO: handle errors */                  /* TODO: handle errors */
         mode = mode_freeIt;                  mode = mode_freeIt;
     }  
   
     if (mode[0] != '\0') {  
         if (strstr(mode, "compat")) {  
             opts.compatMake = TRUE;  
             forceJobs = FALSE;  
         }          }
   
           if (mode[0] != '\0') {
                   if (strstr(mode, "compat")) {
                           opts.compatMake = TRUE;
                           forceJobs = FALSE;
                   }
 #if USE_META  #if USE_META
         if (strstr(mode, "meta"))                  if (strstr(mode, "meta"))
             meta_mode_init(mode);                          meta_mode_init(mode);
 #endif  #endif
     }          }
   
     free(mode_freeIt);          free(mode_freeIt);
 }  }
   
 static void  static void
Line 876  PrintVar(const char *varname, Boolean ex
Line 877  PrintVar(const char *varname, Boolean ex
 static Boolean  static Boolean
 GetBooleanVar(const char *varname, Boolean fallback)  GetBooleanVar(const char *varname, Boolean fallback)
 {  {
     char *expr = str_concat3("${", varname, ":U}");          char *expr = str_concat3("${", varname, ":U}");
     char *value;          char *value;
     Boolean res;          Boolean res;
   
     (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &value);          (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &value);
     /* TODO: handle errors */          /* TODO: handle errors */
     res = ParseBoolean(value, fallback);          res = ParseBoolean(value, fallback);
     free(value);          free(value);
     free(expr);          free(expr);
     return res;          return res;
 }  }
   
 static void  static void
Line 910  doPrintVars(void)
Line 911  doPrintVars(void)
 static Boolean  static Boolean
 runTargets(void)  runTargets(void)
 {  {
         GNodeList *targs; /* target nodes to create -- passed to Make_Init */          GNodeList *targs;       /* target nodes to create */
         Boolean outOfDate;      /* FALSE if all targets up to date */          Boolean outOfDate;      /* FALSE if all targets up to date */
   
         /*          /*
Line 1060  HandlePWD(const struct stat *curdir_st)
Line 1061  HandlePWD(const struct stat *curdir_st)
         if (ignorePWD || (pwd = getenv("PWD")) == NULL)          if (ignorePWD || (pwd = getenv("PWD")) == NULL)
                 return;                  return;
   
         if (Var_Value("MAKEOBJDIRPREFIX", VAR_CMDLINE, &prefix_freeIt) != NULL) {          if (Var_Value("MAKEOBJDIRPREFIX", VAR_CMDLINE, &prefix_freeIt) !=
               NULL) {
                 bmake_free(prefix_freeIt);                  bmake_free(prefix_freeIt);
                 return;                  return;
         }          }
Line 1211  ReadBuiltinRules(void)
Line 1213  ReadBuiltinRules(void)
         StringList *sysMkPath = Lst_New();          StringList *sysMkPath = Lst_New();
   
         Dir_Expand(_PATH_DEFSYSMK,          Dir_Expand(_PATH_DEFSYSMK,
                    Lst_IsEmpty(sysIncPath) ? defSysIncPath : sysIncPath,              Lst_IsEmpty(sysIncPath) ? defSysIncPath : sysIncPath,
                    sysMkPath);              sysMkPath);
         if (Lst_IsEmpty(sysMkPath))          if (Lst_IsEmpty(sysMkPath))
                 Fatal("%s: no system rules (%s).", progname, _PATH_DEFSYSMK);                  Fatal("%s: no system rules (%s).", progname, _PATH_DEFSYSMK);
   
Line 1222  ReadBuiltinRules(void)
Line 1224  ReadBuiltinRules(void)
   
         if (ln == NULL)          if (ln == NULL)
                 Fatal("%s: cannot open %s.",                  Fatal("%s: cannot open %s.",
                       progname, (const char *)sysMkPath->first->datum);                      progname, (const char *)sysMkPath->first->datum);
   
         /* Free the list but not the actual filenames since these may still          /* Free the list but not the actual filenames since these may still
          * be used in GNodes. */           * be used in GNodes. */
Line 1244  InitMaxJobs(void)
Line 1246  InitMaxJobs(void)
         n = (int)strtol(value, NULL, 0);          n = (int)strtol(value, NULL, 0);
         if (n < 1) {          if (n < 1) {
                 (void)fprintf(stderr,                  (void)fprintf(stderr,
                               "%s: illegal value for .MAKE.JOBS "                      "%s: illegal value for .MAKE.JOBS "
                               "-- must be positive integer!\n",                      "-- must be positive integer!\n",
                               progname);                      progname);
                 exit(1);                  exit(1);
         }          }
   
Line 1312  ReadFirstDefaultMakefile(void)
Line 1314  ReadFirstDefaultMakefile(void)
         char *prefs;          char *prefs;
   
         (void)Var_Subst("${" MAKE_MAKEFILE_PREFERENCE "}",          (void)Var_Subst("${" MAKE_MAKEFILE_PREFERENCE "}",
                         VAR_CMDLINE, VARE_WANTRES, &prefs);              VAR_CMDLINE, VARE_WANTRES, &prefs);
         /* TODO: handle errors */          /* TODO: handle errors */
   
         /* XXX: This should use a local list instead of opts.makefiles          /* XXX: This should use a local list instead of opts.makefiles
Line 1358  main_Init(int argc, char **argv)
Line 1360  main_Init(int argc, char **argv)
   
         if (uname(&utsname) == -1) {          if (uname(&utsname) == -1) {
                 (void)fprintf(stderr, "%s: uname failed (%s).\n", progname,                  (void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
                               strerror(errno));                      strerror(errno));
                 exit(2);                  exit(2);
         }          }
   
Line 1393  main_Init(int argc, char **argv)
Line 1395  main_Init(int argc, char **argv)
 #ifndef MAKEFILE_PREFERENCE_LIST  #ifndef MAKEFILE_PREFERENCE_LIST
 # define MAKEFILE_PREFERENCE_LIST "makefile Makefile"  # define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
 #endif  #endif
         Var_Set(MAKE_MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST,          Var_Set(MAKE_MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST, VAR_GLOBAL);
                 VAR_GLOBAL);  
         Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL);          Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL);
   
         CmdOpts_Init();          CmdOpts_Init();
Line 1472  main_Init(int argc, char **argv)
Line 1473  main_Init(int argc, char **argv)
          */           */
         if (getcwd(curdir, MAXPATHLEN) == NULL) {          if (getcwd(curdir, MAXPATHLEN) == NULL) {
                 (void)fprintf(stderr, "%s: getcwd: %s.\n",                  (void)fprintf(stderr, "%s: getcwd: %s.\n",
                               progname, strerror(errno));                      progname, strerror(errno));
                 exit(2);                  exit(2);
         }          }
   
Line 1486  main_Init(int argc, char **argv)
Line 1487  main_Init(int argc, char **argv)
          */           */
         if (stat(curdir, &sa) == -1) {          if (stat(curdir, &sa) == -1) {
                 (void)fprintf(stderr, "%s: %s: %s.\n",                  (void)fprintf(stderr, "%s: %s: %s.\n",
                               progname, curdir, strerror(errno));                      progname, curdir, strerror(errno));
                 exit(2);                  exit(2);
         }          }
   
Line 1539  main_PrepareMaking(void)
Line 1540  main_PrepareMaking(void)
         if (!opts.noBuiltins || opts.printVars == PVM_NONE) {          if (!opts.noBuiltins || opts.printVars == PVM_NONE) {
                 /* ignore /dev/null and anything starting with "no" */                  /* ignore /dev/null and anything starting with "no" */
                 (void)Var_Subst("${.MAKE.DEPENDFILE:N/dev/null:Nno*:T}",                  (void)Var_Subst("${.MAKE.DEPENDFILE:N/dev/null:Nno*:T}",
                                 VAR_CMDLINE, VARE_WANTRES, &makeDependfile);                      VAR_CMDLINE, VARE_WANTRES, &makeDependfile);
                 if (makeDependfile[0] != '\0') {                  if (makeDependfile[0] != '\0') {
                         /* TODO: handle errors */                          /* TODO: handle errors */
                         doing_depend = TRUE;                          doing_depend = TRUE;
Line 1556  main_PrepareMaking(void)
Line 1557  main_PrepareMaking(void)
         {          {
                 void *freeIt;                  void *freeIt;
                 Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &freeIt),                  Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &freeIt),
                            VAR_GLOBAL);                      VAR_GLOBAL);
                 bmake_free(freeIt);                  bmake_free(freeIt);
   
         }          }
   
         InitMaxJobs();          InitMaxJobs();
Line 1573  main_PrepareMaking(void)
Line 1573  main_PrepareMaking(void)
         if (!opts.compatMake)          if (!opts.compatMake)
                 Job_ServerStart(maxJobTokens, jp_0, jp_1);                  Job_ServerStart(maxJobTokens, jp_0, jp_1);
         DEBUG5(JOB, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",          DEBUG5(JOB, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
                jp_0, jp_1, opts.maxJobs, maxJobTokens, opts.compatMake ? 1 : 0);              jp_0, jp_1, opts.maxJobs, maxJobTokens, opts.compatMake ? 1 : 0);
   
         if (opts.printVars == PVM_NONE)          if (opts.printVars == PVM_NONE)
                 Main_ExportMAKEFLAGS(TRUE);     /* initial export */                  Main_ExportMAKEFLAGS(TRUE);     /* initial export */
Line 1731  found:
Line 1731  found:
         return 0;          return 0;
 }  }
   
   
   
 /*-  /*-
  * Cmd_Exec --   * Cmd_Exec --
  *      Execute the command in cmd, and return the output of that command   *      Execute the command in cmd, and return the output of that command
Line 1749  found:
Line 1747  found:
 char *  char *
 Cmd_Exec(const char *cmd, const char **errfmt)  Cmd_Exec(const char *cmd, const char **errfmt)
 {  {
     const char  *args[4];       /* Args for invoking the shell */          const char *args[4];    /* Args for invoking the shell */
     int         fds[2];         /* Pipe streams */          int fds[2];             /* Pipe streams */
     int         cpid;           /* Child PID */          int cpid;               /* Child PID */
     int         pid;            /* PID from wait() */          int pid;                /* PID from wait() */
     int         status;         /* command exit status */          int status;             /* command exit status */
     Buffer      buf;            /* buffer to store the result */          Buffer buf;             /* buffer to store the result */
     ssize_t     bytes_read;          ssize_t bytes_read;
     char        *res;           /* result */          char *res;              /* result */
     size_t      res_len;          size_t res_len;
     char        *cp;          char *cp;
     int         savederr;       /* saved errno */          int savederr;           /* saved errno */
   
     *errfmt = NULL;          *errfmt = NULL;
   
     if (!shellName)          if (!shellName)
         Shell_Init();                  Shell_Init();
     /*          /*
      * Set up arguments for shell           * Set up arguments for shell
      */  
     args[0] = shellName;  
     args[1] = "-c";  
     args[2] = cmd;  
     args[3] = NULL;  
   
     /*  
      * Open a pipe for fetching its output  
      */  
     if (pipe(fds) == -1) {  
         *errfmt = "Couldn't create pipe for \"%s\"";  
         goto bad;  
     }  
   
     /*  
      * Fork  
      */  
     switch (cpid = vFork()) {  
     case 0:  
         (void)close(fds[0]);    /* Close input side of pipe */  
   
         /*  
          * Duplicate the output stream to the shell's output, then  
          * shut the extra thing down. Note we don't fetch the error  
          * stream...why not? Why?  
          */           */
         (void)dup2(fds[1], 1);          args[0] = shellName;
         (void)close(fds[1]);          args[1] = "-c";
           args[2] = cmd;
           args[3] = NULL;
   
         Var_ExportVars();          /*
            * Open a pipe for fetching its output
            */
           if (pipe(fds) == -1) {
                   *errfmt = "Couldn't create pipe for \"%s\"";
                   goto bad;
           }
   
         (void)execv(shellPath, UNCONST(args));          /*
         _exit(1);           * Fork
         /*NOTREACHED*/           */
           switch (cpid = vFork()) {
           case 0:
                   (void)close(fds[0]);    /* Close input side of pipe */
   
                   /*
                    * Duplicate the output stream to the shell's output, then
                    * shut the extra thing down. Note we don't fetch the error
                    * stream...why not? Why?
                    */
                   (void)dup2(fds[1], 1);
                   (void)close(fds[1]);
   
     case -1:                  Var_ExportVars();
         *errfmt = "Couldn't exec \"%s\"";  
         goto bad;  
   
     default:                  (void)execv(shellPath, UNCONST(args));
         (void)close(fds[1]);    /* No need for the writing half */                  _exit(1);
                   /*NOTREACHED*/
   
           case -1:
                   *errfmt = "Couldn't exec \"%s\"";
                   goto bad;
   
         savederr = 0;          default:
         Buf_Init(&buf);                  (void)close(fds[1]);    /* No need for the writing half */
   
         do {                  savederr = 0;
             char result[BUFSIZ];                  Buf_Init(&buf);
             bytes_read = read(fds[0], result, sizeof result);  
             if (bytes_read > 0)                  do {
                 Buf_AddBytes(&buf, result, (size_t)bytes_read);                          char result[BUFSIZ];
         } while (bytes_read > 0 || (bytes_read == -1 && errno == EINTR));                          bytes_read = read(fds[0], result, sizeof result);
         if (bytes_read == -1)                          if (bytes_read > 0)
             savederr = errno;                                  Buf_AddBytes(&buf, result, (size_t)bytes_read);
                   } while (bytes_read > 0 ||
         (void)close(fds[0]);    /* Close the input side of the pipe. */                           (bytes_read == -1 && errno == EINTR));
                   if (bytes_read == -1)
         /* Wait for the process to exit. */                          savederr = errno;
         while((pid = waitpid(cpid, &status, 0)) != cpid && pid >= 0)  
             JobReapChild(pid, status, FALSE);                  (void)close(
                       fds[0]);    /* Close the input side of the pipe. */
         res_len = Buf_Len(&buf);  
         res = Buf_Destroy(&buf, FALSE);                  /* Wait for the process to exit. */
                   while ((pid = waitpid(cpid, &status, 0)) != cpid && pid >= 0)
         if (savederr != 0)                          JobReapChild(pid, status, FALSE);
             *errfmt = "Couldn't read shell's output for \"%s\"";  
                   res_len = Buf_Len(&buf);
         if (WIFSIGNALED(status))                  res = Buf_Destroy(&buf, FALSE);
             *errfmt = "\"%s\" exited on a signal";  
         else if (WEXITSTATUS(status) != 0)                  if (savederr != 0)
             *errfmt = "\"%s\" returned non-zero status";                          *errfmt = "Couldn't read shell's output for \"%s\"";
   
         /* Convert newlines to spaces.  A final newline is just stripped */                  if (WIFSIGNALED(status))
         if (res_len > 0 && res[res_len - 1] == '\n')                          *errfmt = "\"%s\" exited on a signal";
             res[res_len - 1] = '\0';                  else if (WEXITSTATUS(status) != 0)
         for (cp = res; *cp != '\0'; cp++)                          *errfmt = "\"%s\" returned non-zero status";
             if (*cp == '\n')  
                 *cp = ' ';                  /* Convert newlines to spaces.  A final newline is just stripped */
         break;                  if (res_len > 0 && res[res_len - 1] == '\n')
     }                          res[res_len - 1] = '\0';
     return res;                  for (cp = res; *cp != '\0'; cp++)
                           if (*cp == '\n')
                                   *cp = ' ';
                   break;
           }
           return res;
 bad:  bad:
     return bmake_strdup("");          return bmake_strdup("");
 }  }
   
 /* Print a printf-style error message.  /* Print a printf-style error message.
Line 2017  static GNode *
Line 2017  static GNode *
 get_cached_realpaths(void)  get_cached_realpaths(void)
 {  {
   
     if (!cached_realpaths) {          if (!cached_realpaths) {
         cached_realpaths = Targ_NewGN("Realpath");                  cached_realpaths = Targ_NewGN("Realpath");
 #ifndef DEBUG_REALPATH_CACHE  #ifndef DEBUG_REALPATH_CACHE
         cached_realpaths->flags = INTERNAL;                  cached_realpaths->flags = INTERNAL;
 #endif  #endif
     }          }
   
     return cached_realpaths;          return cached_realpaths;
 }  }
   
 /* purge any relative paths */  /* purge any relative paths */
 static void  static void
 purge_cached_realpaths(void)  purge_cached_realpaths(void)
 {  {
     GNode *cache = get_cached_realpaths();          GNode *cache = get_cached_realpaths();
     HashEntry *he, *nhe;          HashEntry *he, *nhe;
     HashIter hi;          HashIter hi;
   
     HashIter_Init(&hi, &cache->context);          HashIter_Init(&hi, &cache->context);
     he = HashIter_Next(&hi);          he = HashIter_Next(&hi);
     while (he != NULL) {          while (he != NULL) {
         nhe = HashIter_Next(&hi);                  nhe = HashIter_Next(&hi);
         if (he->key[0] != '/') {                  if (he->key[0] != '/') {
             if (DEBUG(DIR))                          if (DEBUG(DIR))
                 fprintf(stderr, "cached_realpath: purging %s\n", he->key);                                  fprintf(stderr, "cached_realpath: purging %s\n",
             HashTable_DeleteEntry(&cache->context, he);                                      he->key);
                           HashTable_DeleteEntry(&cache->context, he);
                   }
                   he = nhe;
         }          }
         he = nhe;  
     }  
 }  }
   
 char *  char *
 cached_realpath(const char *pathname, char *resolved)  cached_realpath(const char *pathname, char *resolved)
 {  {
     GNode *cache;          GNode *cache;
     const char *rp;          const char *rp;
     void *freeIt;          void *freeIt;
   
     if (pathname == NULL || pathname[0] == '\0')          if (pathname == NULL || pathname[0] == '\0')
         return NULL;                  return NULL;
   
     cache = get_cached_realpaths();          cache = get_cached_realpaths();
   
     if ((rp = Var_Value(pathname, cache, &freeIt)) != NULL) {          if ((rp = Var_Value(pathname, cache, &freeIt)) != NULL) {
         /* a hit */                  /* a hit */
         strncpy(resolved, rp, MAXPATHLEN);                  strncpy(resolved, rp, MAXPATHLEN);
         resolved[MAXPATHLEN - 1] = '\0';                  resolved[MAXPATHLEN - 1] = '\0';
     } else if ((rp = realpath(pathname, resolved)) != NULL) {          } else if ((rp = realpath(pathname, resolved)) != NULL) {
         Var_Set(pathname, rp, cache);                  Var_Set(pathname, rp, cache);
     } /* else should we negative-cache? */          } /* else should we negative-cache? */
   
     bmake_free(freeIt);          bmake_free(freeIt);
     return rp ? resolved : NULL;          return rp ? resolved : NULL;
 }  }
   
 /*  /*
Line 2079  cached_realpath(const char *pathname, ch
Line 2080  cached_realpath(const char *pathname, ch
 Boolean  Boolean
 shouldDieQuietly(GNode *gn, int bf)  shouldDieQuietly(GNode *gn, int bf)
 {  {
     static int quietly = -1;          static int quietly = -1;
   
     if (quietly < 0) {          if (quietly < 0) {
         if (DEBUG(JOB) || !GetBooleanVar(".MAKE.DIE_QUIETLY", TRUE))                  if (DEBUG(JOB) || !GetBooleanVar(".MAKE.DIE_QUIETLY", TRUE))
             quietly = 0;                          quietly = 0;
         else if (bf >= 0)                  else if (bf >= 0)
             quietly = bf;                          quietly = bf;
         else                  else
             quietly = gn != NULL && (gn->type & OP_MAKE);                          quietly = gn != NULL && (gn->type & OP_MAKE);
     }          }
     return quietly;          return quietly;
 }  }
   
 static void  static void
 SetErrorVars(GNode *gn)  SetErrorVars(GNode *gn)
 {  {
     StringListNode *ln;          StringListNode *ln;
   
     /*          /*
      * We can print this even if there is no .ERROR target.           * We can print this even if there is no .ERROR target.
      */           */
     Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL);          Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL);
     Var_Delete(".ERROR_CMD", VAR_GLOBAL);          Var_Delete(".ERROR_CMD", VAR_GLOBAL);
   
     for (ln = gn->commands->first; ln != NULL; ln = ln->next) {          for (ln = gn->commands->first; ln != NULL; ln = ln->next) {
         const char *cmd = ln->datum;                  const char *cmd = ln->datum;
   
         if (cmd == NULL)                  if (cmd == NULL)
             break;                          break;
         Var_Append(".ERROR_CMD", cmd, VAR_GLOBAL);                  Var_Append(".ERROR_CMD", cmd, VAR_GLOBAL);
     }          }
 }  }
   
 void  void
 PrintOnError(GNode *gn, const char *s)  PrintOnError(GNode *gn, const char *s)
 {  {
     static GNode *en = NULL;          static GNode *en = NULL;
     const char *expr;          const char *expr;
     char *cp;          char *cp;
   
     if (DEBUG(HASH)) {  
         Targ_Stats();  
         Var_Stats();  
     }  
   
     /* we generally want to keep quiet if a sub-make died */          if (DEBUG(HASH)) {
     if (shouldDieQuietly(gn, -1))                  Targ_Stats();
         return;                  Var_Stats();
           }
   
           /* we generally want to keep quiet if a sub-make died */
           if (shouldDieQuietly(gn, -1))
                   return;
   
     if (s)          if (s)
         printf("%s", s);                  printf("%s", s);
   
     printf("\n%s: stopped in %s\n", progname, curdir);          printf("\n%s: stopped in %s\n", progname, curdir);
   
     if (en)          if (en)
         return;                         /* we've been here! */                  return;         /* we've been here! */
     if (gn)          if (gn)
         SetErrorVars(gn);                  SetErrorVars(gn);
     expr = "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}";          expr = "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}";
     (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &cp);          (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &cp);
     /* TODO: handle errors */          /* TODO: handle errors */
     printf("%s", cp);          printf("%s", cp);
     free(cp);          free(cp);
     fflush(stdout);          fflush(stdout);
   
     /*          /*
      * Finally, see if there is a .ERROR target, and run it if so.           * Finally, see if there is a .ERROR target, and run it if so.
      */           */
     en = Targ_FindNode(".ERROR");          en = Targ_FindNode(".ERROR");
     if (en) {          if (en) {
         en->type |= OP_SPECIAL;                  en->type |= OP_SPECIAL;
         Compat_Make(en, en);                  Compat_Make(en, en);
     }          }
 }  }
   
 void  void
 Main_ExportMAKEFLAGS(Boolean first)  Main_ExportMAKEFLAGS(Boolean first)
 {  {
     static Boolean once = TRUE;          static Boolean once = TRUE;
     const char *expr;          const char *expr;
     char *s;          char *s;
   
     if (once != first)          if (once != first)
         return;                  return;
     once = FALSE;          once = FALSE;
   
     expr = "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}";          expr = "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}";
     (void)Var_Subst(expr, VAR_CMDLINE, VARE_WANTRES, &s);          (void)Var_Subst(expr, VAR_CMDLINE, VARE_WANTRES, &s);
     /* TODO: handle errors */          /* TODO: handle errors */
     if (s[0] != '\0') {          if (s[0] != '\0') {
 #ifdef POSIX  #ifdef POSIX
         setenv("MAKEFLAGS", s, 1);                  setenv("MAKEFLAGS", s, 1);
 #else  #else
         setenv("MAKE", s, 1);                  setenv("MAKE", s, 1);
 #endif  #endif
     }          }
 }  }
   
 char *  char *
 getTmpdir(void)  getTmpdir(void)
 {  {
     static char *tmpdir = NULL;          static char *tmpdir = NULL;
   
     if (!tmpdir) {          if (!tmpdir) {
         struct stat st;                  struct stat st;
   
         /*                  /*
          * Honor $TMPDIR but only if it is valid.                   * Honor $TMPDIR but only if it is valid.
          * Ensure it ends with /.                   * Ensure it ends with /.
          */                   */
         (void)Var_Subst("${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL,                  (void)Var_Subst("${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL,
                         VARE_WANTRES, &tmpdir);                      VARE_WANTRES, &tmpdir);
         /* TODO: handle errors */                  /* TODO: handle errors */
         if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {                  if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
             free(tmpdir);                          free(tmpdir);
             tmpdir = bmake_strdup(_PATH_TMP);                          tmpdir = bmake_strdup(_PATH_TMP);
                   }
         }          }
     }          return tmpdir;
     return tmpdir;  
 }  }
   
 /*  /*
Line 2208  getTmpdir(void)
Line 2209  getTmpdir(void)
 int  int
 mkTempFile(const char *pattern, char **out_fname)  mkTempFile(const char *pattern, char **out_fname)
 {  {
     static char *tmpdir = NULL;          static char *tmpdir = NULL;
     char tfile[MAXPATHLEN];          char tfile[MAXPATHLEN];
     int fd;          int fd;
   
     if (pattern == NULL)          if (pattern == NULL)
         pattern = TMPPAT;                  pattern = TMPPAT;
     if (tmpdir == NULL)          if (tmpdir == NULL)
         tmpdir = getTmpdir();                  tmpdir = getTmpdir();
     if (pattern[0] == '/') {          if (pattern[0] == '/') {
         snprintf(tfile, sizeof tfile, "%s", pattern);                  snprintf(tfile, sizeof tfile, "%s", pattern);
     } else {          } else {
         snprintf(tfile, sizeof tfile, "%s%s", tmpdir, pattern);                  snprintf(tfile, sizeof tfile, "%s%s", tmpdir, pattern);
     }          }
     if ((fd = mkstemp(tfile)) < 0)          if ((fd = mkstemp(tfile)) < 0)
         Punt("Could not create temporary file %s: %s", tfile, strerror(errno));                  Punt("Could not create temporary file %s: %s", tfile,
     if (out_fname) {                      strerror(errno));
         *out_fname = bmake_strdup(tfile);          if (out_fname) {
     } else {                  *out_fname = bmake_strdup(tfile);
         unlink(tfile);                  /* we just want the descriptor */          } else {
     }                  unlink(
     return fd;                      tfile);     /* we just want the descriptor */
           }
           return fd;
 }  }
   
 /*  /*
Line 2239  mkTempFile(const char *pattern, char **o
Line 2242  mkTempFile(const char *pattern, char **o
 Boolean  Boolean
 ParseBoolean(const char *s, Boolean bf)  ParseBoolean(const char *s, Boolean bf)
 {  {
     switch(s[0]) {          switch (s[0]) {
     case '\0':                  /* not set - the default wins */          case '\0':              /* not set - the default wins */
         break;                  break;
     case '0':          case '0':
     case 'F':          case 'F':
     case 'f':          case 'f':
     case 'N':          case 'N':
     case 'n':          case 'n':
         return FALSE;                  return FALSE;
     case 'O':          case 'O':
     case 'o':          case 'o':
         return s[1] != 'F' && s[1] != 'f';                  return s[1] != 'F' && s[1] != 'f';
     default:          default:
         return TRUE;                  return TRUE;
     }          }
     return bf;          return bf;
 }  }

Legend:
Removed from v.1.452  
changed lines
  Added in v.1.453

CVSweb <webmaster@jp.NetBSD.org>