version 1.45, 2000/11/24 14:36:34 |
version 1.46, 2001/05/03 13:41:07 |
|
|
/* $OpenBSD$ */ |
/* $OpenPackages$ */ |
|
/* $OpenBSD$ */ |
/* $NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $ */ |
/* $NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $ */ |
|
|
/* |
/* |
|
|
#include "dir.h" |
#include "dir.h" |
#include "job.h" |
#include "job.h" |
#include "pathnames.h" |
#include "pathnames.h" |
|
#include "stats.h" |
|
|
#ifndef lint |
#ifndef lint |
UNUSED |
UNUSED |
|
|
#endif /* not lint */ |
#endif /* not lint */ |
|
|
|
|
#ifndef DEFMAXLOCAL |
#ifndef DEFMAXLOCAL |
#define DEFMAXLOCAL DEFMAXJOBS |
#define DEFMAXLOCAL DEFMAXJOBS |
#endif /* DEFMAXLOCAL */ |
#endif /* DEFMAXLOCAL */ |
|
|
#define MAKEFLAGS ".MAKEFLAGS" |
#define MAKEFLAGS ".MAKEFLAGS" |
|
|
LIST create; /* Targets to be made */ |
LIST create; /* Targets to be made */ |
TIMESTAMP now; /* Time at start of make */ |
TIMESTAMP 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 */ |
|
|
static Boolean noBuiltins; /* -r flag */ |
static Boolean noBuiltins; /* -r flag */ |
static LIST makefiles; /* ordered list of makefiles to read */ |
static LIST makefiles; /* ordered list of makefiles to read */ |
|
|
static LIST variables; /* list of variables to print */ |
static LIST variables; /* list of variables to print */ |
int maxJobs; /* -j argument */ |
int maxJobs; /* -j argument */ |
static int maxLocal; /* -L argument */ |
static int maxLocal; /* -L argument */ |
Boolean compatMake; /* -B argument */ |
Boolean compatMake; /* -B argument */ |
Boolean debug; /* -d flag */ |
Boolean debug; /* -d flag */ |
Boolean noExecute; /* -n flag */ |
Boolean noExecute; /* -n flag */ |
Boolean keepgoing; /* -k flag */ |
Boolean keepgoing; /* -k flag */ |
Boolean queryFlag; /* -q flag */ |
Boolean queryFlag; /* -q flag */ |
Boolean touchFlag; /* -t flag */ |
Boolean touchFlag; /* -t flag */ |
Boolean usePipes; /* !-P flag */ |
Boolean usePipes; /* !-P flag */ |
Boolean ignoreErrors; /* -i flag */ |
Boolean ignoreErrors; /* -i flag */ |
Boolean beSilent; /* -s flag */ |
Boolean beSilent; /* -s flag */ |
Boolean oldVars; /* variable substitution style */ |
Boolean oldVars; /* variable substitution style */ |
Boolean checkEnvFirst; /* -e flag */ |
Boolean checkEnvFirst; /* -e flag */ |
static Boolean jobsRunning; /* TRUE if the jobs might be running */ |
static Boolean jobsRunning; /* TRUE if the jobs might be running */ |
|
|
static void MainParseArgs __P((int, char **)); |
static void MainParseArgs(int, char **); |
char * chdir_verify_path __P((char *, char *)); |
static char * chdir_verify_path(char *, char *); |
static int ReadMakefile __P((void *, void *)); |
static int ReadMakefile(void *, void *); |
static void add_dirpath __P((Lst, const char *)); |
static void add_dirpath(Lst, const char *); |
static void usage __P((void)); |
static void usage(void); |
static void posixParseOptLetter __P((char)); |
static void posixParseOptLetter(int); |
int main __P((int, char **)); |
|
|
|
static char *curdir; /* startup directory */ |
static char *curdir; /* startup directory */ |
static char *objdir; /* where we chdir'ed to */ |
static char *objdir; /* where we chdir'ed to */ |
|
|
|
|
static void |
static void |
posixParseOptLetter(c) |
posixParseOptLetter(c) |
char c; |
int c; |
{ |
{ |
switch(c) { |
switch(c) { |
case 'B': |
case 'B': |
|
|
* |
* |
* XXX: Deal with command line overriding .MAKEFLAGS in makefile |
* XXX: Deal with command line overriding .MAKEFLAGS in makefile |
* |
* |
* Results: |
|
* None |
|
* |
|
* Side Effects: |
* Side Effects: |
* Various global and local flags will be set depending on the flags |
* Various global and local flags will be set depending on the flags |
* given |
* given |
|
|
# define OPTFLAGS "BD:I:PSV:d:ef:ij:km:nqrst" |
# define OPTFLAGS "BD:I:PSV:d:ef:ij:km:nqrst" |
#endif |
#endif |
# define OPTLETTERS "BPSiknqrst" |
# define OPTLETTERS "BPSiknqrst" |
rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) { |
rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != -1) { |
switch(c) { |
switch (c) { |
case 'D': |
case 'D': |
Var_Set(optarg, "1", VAR_GLOBAL); |
Var_Set(optarg, "1", VAR_GLOBAL); |
Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); |
Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); |
|
|
case 'j': |
case 'j': |
debug |= DEBUG_JOB; |
debug |= DEBUG_JOB; |
break; |
break; |
|
case 'l': |
|
debug |= DEBUG_LOUD; |
|
break; |
case 'm': |
case 'm': |
debug |= DEBUG_MAKE; |
debug |= DEBUG_MAKE; |
break; |
break; |
|
|
Punt("illegal (null) argument."); |
Punt("illegal (null) argument."); |
if (**argv == '-') { |
if (**argv == '-') { |
if ((*argv)[1]) |
if ((*argv)[1]) |
optind = 0; /* -flag... */ |
optind = 0; /* -flag... */ |
else |
else |
optind = 1; /* - */ |
optind = 1; /* - */ |
goto rearg; |
goto rearg; |
} |
} |
Lst_AtEnd(&create, estrdup(*argv)); |
Lst_AtEnd(&create, estrdup(*argv)); |
|
|
|
|
/*- |
/*- |
* Main_ParseArgLine -- |
* Main_ParseArgLine -- |
* Used by the parse module when a .MFLAGS or .MAKEFLAGS target |
* Used by the parse module when a .MFLAGS or .MAKEFLAGS target |
* is encountered and by main() when reading the .MAKEFLAGS envariable. |
* is encountered and by main() when reading the .MAKEFLAGS envariable. |
* Takes a line of arguments and breaks it into its |
* Takes a line of arguments and breaks it into its |
* component words and passes those words and the number of them to the |
* component words and passes those words and the number of them to the |
* MainParseArgs function. |
* MainParseArgs function. |
* The line should have all its leading whitespace removed. |
* The line should have all its leading whitespace removed. |
* |
* |
* Results: |
|
* None |
|
* |
|
* Side Effects: |
* Side Effects: |
* Only those that come from the various arguments. |
* Only those that come from the various arguments. |
*/ |
*/ |
|
|
char *argv0; |
char *argv0; |
char *s; |
char *s; |
|
|
|
|
if (line == NULL) |
if (line == NULL) |
return; |
return; |
for (; *line == ' '; ++line) |
for (; *line == ' '; ++line) |
|
|
* any blanks or dashes. */ |
* any blanks or dashes. */ |
for (s = line;; s++) { |
for (s = line;; s++) { |
if (*s == '\0') { |
if (*s == '\0') { |
while (line != s) |
while (line != s) |
posixParseOptLetter(*line++); |
posixParseOptLetter(*line++); |
return; |
return; |
} |
} |
if (strchr(OPTLETTERS, *s) == NULL) |
if (strchr(OPTLETTERS, *s) == NULL) |
break; |
break; |
} |
} |
argv0 = Var_Value(".MAKE", VAR_GLOBAL); |
argv0 = Var_Value(".MAKE"); |
buf = emalloc(strlen(line) + strlen(argv0) + 2); |
buf = emalloc(strlen(line) + strlen(argv0) + 2); |
(void)sprintf(buf, "%s %s", argv0, line); |
(void)sprintf(buf, "%s %s", argv0, line); |
|
|
argv = brk_string(buf, &argc, TRUE, &args); |
argv = brk_string(buf, &argc, &args); |
free(buf); |
free(buf); |
MainParseArgs(argc, argv); |
MainParseArgs(argc, argv); |
|
|
|
|
|
|
char * |
char * |
chdir_verify_path(path, obpath) |
chdir_verify_path(path, obpath) |
char *path; |
char *path; |
char *obpath; |
char *obpath; |
{ |
{ |
struct stat sb; |
struct stat sb; |
|
|
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { |
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { |
if (chdir(path)) { |
if (chdir(path)) { |
(void)fprintf(stderr, "make warning: %s: %s.\n", |
(void)fprintf(stderr, "make warning: %s: %s.\n", |
path, strerror(errno)); |
path, strerror(errno)); |
return 0; |
return NULL; |
} |
} else { |
else { |
if (path[0] != '/') { |
if (path[0] != '/') { |
(void)snprintf(obpath, MAXPATHLEN, "%s/%s", curdir, path); |
(void) snprintf(obpath, MAXPATHLEN, "%s/%s", |
return obpath; |
curdir, path); |
} |
return obpath; |
else |
} |
return path; |
else |
|
return path; |
|
} |
|
} |
} |
|
} |
|
|
return 0; |
return NULL; |
} |
} |
|
|
|
|
/* Add a :-separated path to a Lst of directories. */ |
/* Add a :-separated path to a Lst of directories. */ |
static void |
static void |
add_dirpath(l, n) |
add_dirpath(l, n) |
Lst l; |
Lst l; |
const char *n; |
const char *n; |
{ |
{ |
const char *start; |
const char *start; |
const char *cp; |
const char *cp; |
|
|
} |
} |
} |
} |
|
|
|
int main(int, char **); |
/*- |
/*- |
* main -- |
* main -- |
* The main function, for obvious reasons. Initializes variables |
* The main function, for obvious reasons. Initializes variables |
|
|
int argc; |
int argc; |
char **argv; |
char **argv; |
{ |
{ |
LIST targs; /* target nodes to create -- passed to Make_Init */ |
LIST targs; /* target nodes to create */ |
Boolean outOfDate = TRUE; /* FALSE if all targets up to date */ |
Boolean outOfDate = TRUE; /* FALSE if all targets up to date */ |
struct stat sb, sa; |
struct stat sb, sa; |
char *p, *path, *pathp, *pwd; |
char *p, *path, *pathp, *pwd; |
char mdpath[MAXPATHLEN + 1]; |
char mdpath[MAXPATHLEN + 1]; |
char obpath[MAXPATHLEN + 1]; |
char obpath[MAXPATHLEN + 1]; |
char cdpath[MAXPATHLEN + 1]; |
char cdpath[MAXPATHLEN + 1]; |
char *machine = getenv("MACHINE"); |
char *machine = getenv("MACHINE"); |
char *machine_arch = getenv("MACHINE_ARCH"); |
char *machine_arch = getenv("MACHINE_ARCH"); |
/* avoid faults on read-only strings */ |
/* avoid faults on read-only strings */ |
static char syspath[] = _PATH_DEFSYSPATH; |
static char syspath[] = _PATH_DEFSYSPATH; |
|
|
set_out_of_date(now); |
set_out_of_date(now); |
|
#ifdef HAS_STATS |
|
Init_Stats(); |
|
#endif |
|
|
#ifdef RLIMIT_NOFILE |
#ifdef RLIMIT_NOFILE |
/* |
/* |
* get rid of resource limit on file descriptors |
* get rid of resource limit on file descriptors |
|
|
if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && |
if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && |
rl.rlim_cur != rl.rlim_max) { |
rl.rlim_cur != rl.rlim_max) { |
rl.rlim_cur = rl.rlim_max; |
rl.rlim_cur = rl.rlim_max; |
(void) setrlimit(RLIMIT_NOFILE, &rl); |
(void)setrlimit(RLIMIT_NOFILE, &rl); |
} |
} |
} |
} |
#endif |
#endif |
|
|
if ((pwd = getenv("PWD")) != NULL) { |
if ((pwd = getenv("PWD")) != NULL) { |
if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino && |
if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino && |
sa.st_dev == sb.st_dev) |
sa.st_dev == sb.st_dev) |
(void) strcpy(curdir, pwd); |
(void)strcpy(curdir, pwd); |
} |
} |
|
|
/* |
/* |
|
|
if (!(path = getenv("MAKEOBJDIR"))) { |
if (!(path = getenv("MAKEOBJDIR"))) { |
path = _PATH_OBJDIR; |
path = _PATH_OBJDIR; |
pathp = _PATH_OBJDIRPREFIX; |
pathp = _PATH_OBJDIRPREFIX; |
(void) snprintf(mdpath, MAXPATHLEN, "%s.%s", |
(void)snprintf(mdpath, MAXPATHLEN, "%s.%s", |
path, machine); |
path, machine); |
if (!(objdir = chdir_verify_path(mdpath, obpath))) |
if (!(objdir = chdir_verify_path(mdpath, obpath))) |
if (!(objdir=chdir_verify_path(path, obpath))) { |
if (!(objdir=chdir_verify_path(path, obpath))) { |
(void) snprintf(mdpath, MAXPATHLEN, |
(void)snprintf(mdpath, MAXPATHLEN, |
"%s%s", pathp, curdir); |
"%s%s", pathp, curdir); |
if (!(objdir=chdir_verify_path(mdpath, |
if (!(objdir=chdir_verify_path(mdpath, |
obpath))) |
obpath))) |
|
|
objdir = curdir; |
objdir = curdir; |
} |
} |
else { |
else { |
(void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir); |
(void)snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir); |
if (!(objdir = chdir_verify_path(mdpath, obpath))) |
if (!(objdir = chdir_verify_path(mdpath, obpath))) |
objdir = curdir; |
objdir = curdir; |
} |
} |
|
|
debug = 0; /* No debug verbosity, please. */ |
debug = 0; /* No debug verbosity, please. */ |
jobsRunning = FALSE; |
jobsRunning = FALSE; |
|
|
maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */ |
maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */ |
#ifdef REMOTE |
#ifdef REMOTE |
maxJobs = DEFMAXJOBS; /* Set default max concurrency */ |
maxJobs = DEFMAXJOBS; /* Set default max concurrency */ |
#else |
#else |
|
|
Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL); |
Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL); |
|
|
/* |
/* |
* First snag any flags out of the MAKE environment variable. |
* First snag any flags out of the MAKEFLAGS environment variable. |
* (Note this is *not* MAKEFLAGS since /bin/make uses that and it's |
|
* in a different format). |
|
*/ |
*/ |
#ifdef POSIX |
|
Main_ParseArgLine(getenv("MAKEFLAGS")); |
Main_ParseArgLine(getenv("MAKEFLAGS")); |
#else |
|
Main_ParseArgLine(getenv("MAKE")); |
|
#endif |
|
|
|
MainParseArgs(argc, argv); |
MainParseArgs(argc, argv); |
|
|
#ifdef POSIX |
/* And set up everything for sub-makes */ |
Var_AddCmdline(MAKEFLAGS); |
Var_AddCmdline(MAKEFLAGS); |
#endif |
|
|
|
|
|
/* |
/* |
* Initialize archive, target and suffix modules in preparation for |
* Initialize archive, target and suffix modules in preparation for |
* parsing the makefile(s) |
* parsing the makefile(s) |
|
|
|
|
/* |
/* |
* Read in the built-in rules first, followed by the specified |
* Read in the built-in rules first, followed by the specified |
* makefile, if it was (makefile != (char *) NULL), or the default |
* makefile, if it was (makefile != (char *)NULL), or the default |
* Makefile and makefile, in that order, if it wasn't. |
* Makefile and makefile, in that order, if it wasn't. |
*/ |
*/ |
if (!noBuiltins) { |
if (!noBuiltins) { |
LstNode ln; |
LstNode ln; |
LIST sysMkPath; /* Path of sys.mk */ |
LIST sysMkPath; /* Path of sys.mk */ |
|
|
Lst_Init(&sysMkPath); |
Lst_Init(&sysMkPath); |
Dir_Expand(_PATH_DEFSYSMK, &sysIncPath, &sysMkPath); |
Dir_Expand(_PATH_DEFSYSMK, &sysIncPath, &sysMkPath); |
|
|
|
|
(void)ReadMakefile(".depend", NULL); |
(void)ReadMakefile(".depend", NULL); |
|
|
Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL), VAR_GLOBAL); |
Var_Append("MFLAGS", Var_Value(MAKEFLAGS), |
|
VAR_GLOBAL); |
|
|
/* Install all the flags into the MAKE envariable. */ |
/* Install all the flags into the MAKEFLAGS env variable. */ |
if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL)) != NULL) && *p) |
if (((p = Var_Value(MAKEFLAGS)) != NULL) && *p) |
#ifdef POSIX |
|
esetenv("MAKEFLAGS", p); |
esetenv("MAKEFLAGS", p); |
#else |
|
esetenv("MAKE", p); |
|
#endif |
|
|
|
/* |
/* |
* For compatibility, look at the directories in the VPATH variable |
* For compatibility, look at the directories in the VPATH variable |
|
|
* variable's value is in the same format as the PATH envariable, i.e. |
* variable's value is in the same format as the PATH envariable, i.e. |
* <directory>:<directory>:<directory>... |
* <directory>:<directory>:<directory>... |
*/ |
*/ |
if (Var_Exists("VPATH", VAR_CMD)) { |
if (Var_Value("VPATH") != NULL) { |
char *vpath; |
char *vpath; |
/* |
|
* GCC stores string constants in read-only memory, but |
|
* Var_Subst will want to write this thing, so store it |
|
* in an array |
|
*/ |
|
static char VPATH[] = "${VPATH}"; |
|
|
|
vpath = Var_Subst(VPATH, (SymTable *)VAR_CMD, FALSE); |
vpath = Var_Subst("${VPATH}", NULL, FALSE); |
add_dirpath(&dirSearchPath, vpath); |
add_dirpath(&dirSearchPath, vpath); |
(void)free(vpath); |
(void)free(vpath); |
} |
} |
|
|
/* |
/* Now that all search paths have been read for suffixes et al, it's |
* Now that all search paths have been read for suffixes et al, it's |
* time to add the default search path to their lists... */ |
* time to add the default search path to their lists... |
|
*/ |
|
Suff_DoPaths(); |
Suff_DoPaths(); |
|
|
/* print the initial graph, if the user requested it */ |
/* Print the initial graph, if the user requested it. */ |
if (DEBUG(GRAPH1)) |
if (DEBUG(GRAPH1)) |
Targ_PrintGraph(1); |
Targ_PrintGraph(1); |
|
|
/* print the values of any variables requested by the user */ |
/* Print the values of any variables requested by the user. */ |
if (printVars) { |
if (printVars) { |
LstNode ln; |
LstNode ln; |
|
|
for (ln = Lst_First(&variables); ln != NULL; ln = Lst_Adv(ln)) { |
for (ln = Lst_First(&variables); ln != NULL; ln = Lst_Adv(ln)) { |
char *value = Var_Value((char *)Lst_Datum(ln), |
char *value = Var_Value((char *)Lst_Datum(ln)); |
VAR_GLOBAL); |
|
|
|
printf("%s\n", value ? value : ""); |
printf("%s\n", value ? value : ""); |
} |
} |
} |
} |
|
|
/* |
/* Have now read the entire graph and need to make a list of targets |
* Have now read the entire graph and need to make a list of targets |
|
* to create. If none was given on the command line, we consult the |
* to create. If none was given on the command line, we consult the |
* parsing module to find the main target(s) to create. |
* parsing module to find the main target(s) to create. */ |
*/ |
|
Lst_Init(&targs); |
Lst_Init(&targs); |
if (!Lst_IsEmpty(&create)) |
if (!Lst_IsEmpty(&create)) |
Targ_FindList(&targs, &create); |
Targ_FindList(&targs, &create); |
|
|
Parse_MainName(&targs); |
Parse_MainName(&targs); |
|
|
if (!compatMake && !printVars) { |
if (!compatMake && !printVars) { |
/* |
/* Initialize job module before traversing the graph, now that |
* Initialize job module before traversing the graph, now that |
* any .BEGIN and .END targets have been read. This is done |
* any .BEGIN and .END targets have been read. This is done |
|
* only if the -q flag wasn't given (to prevent the .BEGIN from |
* only if the -q flag wasn't given (to prevent the .BEGIN from |
* being executed should it exist). |
* being executed should it exist). */ |
*/ |
|
if (!queryFlag) { |
if (!queryFlag) { |
if (maxLocal == -1) |
if (maxLocal == -1) |
maxLocal = maxJobs; |
maxLocal = maxJobs; |
|
|
jobsRunning = TRUE; |
jobsRunning = TRUE; |
} |
} |
|
|
/* Traverse the graph, checking on all the targets */ |
/* Traverse the graph, checking on all the targets. */ |
outOfDate = Make_Run(&targs); |
outOfDate = Make_Run(&targs); |
} else if (!printVars) { |
} else if (!printVars) { |
/* |
/* Compat_Init will take care of creating all the targets as |
* Compat_Init will take care of creating all the targets as |
* well as initializing the module. */ |
* well as initializing the module. |
|
*/ |
|
Compat_Run(&targs); |
Compat_Run(&targs); |
} |
} |
|
|
|
|
Targ_PrintGraph(2); |
Targ_PrintGraph(2); |
|
|
Suff_End(); |
Suff_End(); |
Targ_End(); |
Targ_End(); |
Arch_End(); |
Arch_End(); |
Var_End(); |
Var_End(); |
Parse_End(); |
Parse_End(); |
|
|
Job_End(); |
Job_End(); |
|
|
if (queryFlag && outOfDate) |
if (queryFlag && outOfDate) |
return(1); |
return 1; |
else |
else |
return(0); |
return 0; |
} |
} |
|
|
/*- |
/*- |
|
|
*/ |
*/ |
static Boolean |
static Boolean |
ReadMakefile(p, q) |
ReadMakefile(p, q) |
void *p; |
void * p; |
void *q; |
void * q UNUSED; |
{ |
{ |
char *fname = p; /* makefile to read */ |
char *fname = p; /* makefile to read */ |
extern LIST parseIncPath; |
extern LIST parseIncPath; |
|
|
char *name, path[MAXPATHLEN + 1]; |
char *name, path[MAXPATHLEN + 1]; |
|
|
if (!strcmp(fname, "-")) { |
if (!strcmp(fname, "-")) { |
Parse_File(estrdup("(stdin)"), stdin); |
|
Var_Set("MAKEFILE", "", VAR_GLOBAL); |
Var_Set("MAKEFILE", "", VAR_GLOBAL); |
|
Parse_File(estrdup("(stdin)"), stdin); |
} else { |
} else { |
if ((stream = fopen(fname, "r")) != NULL) |
if ((stream = fopen(fname, "r")) != NULL) |
goto found; |
goto found; |
|
|
if (!name) |
if (!name) |
name = Dir_FindFile(fname, &sysIncPath); |
name = Dir_FindFile(fname, &sysIncPath); |
if (!name || !(stream = fopen(name, "r"))) |
if (!name || !(stream = fopen(name, "r"))) |
return(FALSE); |
return FALSE; |
fname = name; |
fname = name; |
/* |
/* |
* set the MAKEFILE variable desired by System V fans -- the |
* set the MAKEFILE variable desired by System V fans -- the |
|
|
Parse_File(fname, stream); |
Parse_File(fname, stream); |
(void)fclose(stream); |
(void)fclose(stream); |
} |
} |
return(TRUE); |
return TRUE; |
} |
} |
|
|
/*- |
/*- |
|
|
*/ |
*/ |
char * |
char * |
Cmd_Exec(cmd, err) |
Cmd_Exec(cmd, err) |
char *cmd; |
const char *cmd; |
char **err; |
char **err; |
{ |
{ |
char *args[4]; /* Args for invoking the shell */ |
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() */ |
char *res; /* result */ |
char *res; /* result */ |
int status; /* command exit status */ |
int status; /* command exit status */ |
BUFFER buf; /* buffer to store the result */ |
BUFFER buf; /* buffer to store the result */ |
char *cp; |
char *cp; |
ssize_t cc; |
ssize_t cc; |
size_t length; |
size_t length; |
|
|
|
|
*err = NULL; |
*err = NULL; |
|
|
*/ |
*/ |
args[0] = "sh"; |
args[0] = "sh"; |
args[1] = "-c"; |
args[1] = "-c"; |
args[2] = cmd; |
args[2] = (char *)cmd; |
args[3] = NULL; |
args[3] = NULL; |
|
|
/* |
/* |
|
|
/* |
/* |
* Close input side of pipe |
* Close input side of pipe |
*/ |
*/ |
(void) close(fds[0]); |
(void)close(fds[0]); |
|
|
/* |
/* |
* Duplicate the output stream to the shell's output, then |
* Duplicate the output stream to the shell's output, then |
* shut the extra thing down. Note we don't fetch the error |
* shut the extra thing down. Note we don't fetch the error |
* stream...why not? Why? |
* stream...why not? Why? |
*/ |
*/ |
(void) dup2(fds[1], 1); |
(void)dup2(fds[1], 1); |
(void) close(fds[1]); |
if (fds[1] != 1) |
|
(void)close(fds[1]); |
|
|
(void) execv("/bin/sh", args); |
(void)execv("/bin/sh", args); |
_exit(1); |
_exit(1); |
/*NOTREACHED*/ |
/*NOTREACHED*/ |
|
|
|
|
/* |
/* |
* No need for the writing half |
* No need for the writing half |
*/ |
*/ |
(void) close(fds[1]); |
(void)close(fds[1]); |
|
|
Buf_Init(&buf, MAKE_BSIZE); |
Buf_Init(&buf, MAKE_BSIZE); |
|
|
|
|
/* |
/* |
* Close the input side of the pipe. |
* Close the input side of the pipe. |
*/ |
*/ |
(void) close(fds[0]); |
(void)close(fds[0]); |
|
|
/* |
/* |
* Wait for the process to exit. |
* Wait for the process to exit. |
*/ |
*/ |
while(((pid = wait(&status)) != cpid) && (pid >= 0)) |
while ((pid = wait(&status)) != cpid && pid >= 0) |
continue; |
continue; |
|
|
res = Buf_Retrieve(&buf); |
|
length = Buf_Size(&buf); |
|
|
|
if (cc == -1) |
if (cc == -1) |
*err = "Couldn't read shell's output for \"%s\""; |
*err = "Couldn't read shell's output for \"%s\""; |
|
|
if (status) |
if (status) |
*err = "\"%s\" returned non-zero status"; |
*err = "\"%s\" returned non-zero status"; |
|
|
/* |
length = Buf_Size(&buf); |
* Null-terminate the result, convert newlines to spaces and |
res = Buf_Retrieve(&buf); |
* install it in the variable. |
|
*/ |
/* The result is null terminated, Convert newlines to spaces and |
res[length] = '\0'; |
* install in the variable. */ |
cp = res + length - 1; |
cp = res + length - 1; |
|
|
if (*cp == '\n') { |
if (*cp == '\n') |
/* |
/* A final newline is just stripped. */ |
* A final newline is just stripped |
|
*/ |
|
*cp-- = '\0'; |
*cp-- = '\0'; |
} |
|
while (cp >= res) { |
while (cp >= res) { |
if (*cp == '\n') { |
if (*cp == '\n') |
*cp = ' '; |
*cp = ' '; |
} |
|
cp--; |
cp--; |
} |
} |
break; |
break; |
} |
} |
return res; |
return res; |
bad: |
bad: |
res = emalloc(1); |
return estrdup(""); |
*res = '\0'; |
|
return res; |
|
} |
} |
|
|
/*- |
/*- |
* Error -- |
* Error -- |
* Print an error message given its format. |
* Print an error message given its format. |
* |
|
* Results: |
|
* None. |
|
* |
|
* Side Effects: |
|
* The message is printed. |
|
*/ |
*/ |
/* VARARGS */ |
/* VARARGS */ |
void |
void |
|
|
(void)vfprintf(stderr, fmt, ap); |
(void)vfprintf(stderr, fmt, ap); |
va_end(ap); |
va_end(ap); |
(void)fprintf(stderr, "\n"); |
(void)fprintf(stderr, "\n"); |
(void)fflush(stderr); |
|
} |
} |
|
|
/*- |
/*- |
|
|
* Produce a Fatal error message. If jobs are running, waits for them |
* Produce a Fatal error message. If jobs are running, waits for them |
* to finish. |
* to finish. |
* |
* |
* Results: |
|
* None |
|
* |
|
* Side Effects: |
* Side Effects: |
* The program exits |
* The program exits |
*/ |
*/ |
|
|
(void)vfprintf(stderr, fmt, ap); |
(void)vfprintf(stderr, fmt, ap); |
va_end(ap); |
va_end(ap); |
(void)fprintf(stderr, "\n"); |
(void)fprintf(stderr, "\n"); |
(void)fflush(stderr); |
|
|
|
if (DEBUG(GRAPH2)) |
if (DEBUG(GRAPH2)) |
Targ_PrintGraph(2); |
Targ_PrintGraph(2); |
|
|
* Major exception once jobs are being created. Kills all jobs, prints |
* Major exception once jobs are being created. Kills all jobs, prints |
* a message and exits. |
* a message and exits. |
* |
* |
* Results: |
|
* None |
|
* |
|
* Side Effects: |
* Side Effects: |
* All children are killed indiscriminately and the program Lib_Exits |
* All children are killed indiscriminately and the program Lib_Exits |
*/ |
*/ |
|
|
(void)vfprintf(stderr, fmt, ap); |
(void)vfprintf(stderr, fmt, ap); |
va_end(ap); |
va_end(ap); |
(void)fprintf(stderr, "\n"); |
(void)fprintf(stderr, "\n"); |
(void)fflush(stderr); |
|
|
|
DieHorribly(); |
DieHorribly(); |
} |
} |
|
|
* DieHorribly -- |
* DieHorribly -- |
* Exit without giving a message. |
* Exit without giving a message. |
* |
* |
* Results: |
|
* None |
|
* |
|
* Side Effects: |
* Side Effects: |
* A big one... |
* A big one... |
*/ |
*/ |
|
|
* Called when aborting due to errors in child shell to signal |
* Called when aborting due to errors in child shell to signal |
* abnormal exit. |
* abnormal exit. |
* |
* |
* Results: |
|
* None |
|
* |
|
* Side Effects: |
* Side Effects: |
* The program exits |
* The program exits |
*/ |
*/ |
|
|
Fatal("%d error%s", errors, errors == 1 ? "" : "s"); |
Fatal("%d error%s", errors, errors == 1 ? "" : "s"); |
} |
} |
|
|
|
|
/* |
/* |
* usage -- |
* usage -- |
* exit with usage message |
* exit with usage message |
|
|
{ |
{ |
(void)fprintf(stderr, |
(void)fprintf(stderr, |
"usage: make [-Beiknqrst] [-D variable] [-d flags] [-f makefile ]\n\ |
"usage: make [-Beiknqrst] [-D variable] [-d flags] [-f makefile ]\n\ |
[-I directory] [-j max_jobs] [-m directory] [-V variable]\n\ |
[-I directory] [-j max_jobs] [-m directory] [-V variable]\n\ |
[variable=value] [target ...]\n"); |
[variable=value] [target ...]\n"); |
exit(2); |
exit(2); |
} |
} |
|
|
|
|
PrintAddr(a) |
PrintAddr(a) |
void *a; |
void *a; |
{ |
{ |
printf("%lx ", (unsigned long) a); |
printf("%lx ", (unsigned long)a); |
} |
} |