Re: make -k does not exit with appropriate error code if errors are encountered



* Max Khon <fjoe@xxxxxxxxxxxxxx> wrote:
BSD make does not exit with appropriate error code (2) if it is run with
"-k" and errors are encountered.

Please review this patch that fixes this bug:

http://people.freebsd.org/~fjoe/make.diff

Sample BSDmakefile is:

--- cut here ---
all: a b

a:
exit 1

b:
touch ${.TARGET}
--- cut here ---

I'd like to commit the to HEAD soon.

/fjoe

Could you take at the attached patches as well? One patch adds support
for the -p flag, which is described in POSIX. The other patch adds a
small optimization, by ignoring execution when the command is a comment.

Thanks!

--
Ed Schouten <ed@xxxxxxxx>
WWW: http://g-rave.nl/
--- src/usr.bin/make/main.c Sun Jul 9 14:13:59 2006
+++ src/usr.bin/make/main.c Sun Jul 9 14:16:59 2006
@@ -127,6 +127,7 @@
Boolean jobsRunning; /* TRUE if the jobs might be running */
Boolean keepgoing; /* -k flag */
Boolean noExecute; /* -n flag */
+Boolean printGraphOnly; /* -p flag */
Boolean queryFlag; /* -q flag */
Boolean touchFlag; /* -t flag */
Boolean usePipes; /* !-P flag */
@@ -335,7 +336,7 @@
rearg:
optind = 1; /* since we're called more than once */
optreset = 1;
-#define OPTFLAGS "ABC:D:E:I:PSV:Xd:ef:ij:km:nqrstvx:"
+#define OPTFLAGS "ABC:D:E:I:PSV:Xd:ef:ij:km:npqrstvx:"
for (;;) {
if ((optind < argc) && strcmp(argv[optind], "--") == 0) {
found_dd = TRUE;
@@ -477,6 +478,10 @@
noExecute = TRUE;
MFLAGS_append("-n", NULL);
break;
+ case 'p':
+ printGraphOnly = TRUE;
+ debug |= DEBUG_GRAPH1;
+ break;
case 'q':
queryFlag = TRUE;
/* Kind of nonsensical, wot? */
@@ -685,6 +690,7 @@
beSilent = FALSE; /* Print commands as executed */
ignoreErrors = FALSE; /* Pay attention to non-zero returns */
noExecute = FALSE; /* Execute all commands */
+ printGraphOnly = FALSE; /* Do not print processed output */
keepgoing = FALSE; /* Stop on error */
allPrecious = FALSE; /* Remove targets when interrupted */
queryFlag = FALSE; /* This is not just a check-run */
@@ -1026,7 +1032,7 @@
Targ_PrintGraph(1);

/* print the values of any variables requested by the user */
- if (Lst_IsEmpty(&variables)) {
+ if (Lst_IsEmpty(&variables) && !printGraphOnly) {
/*
* Since the user has not requested that any variables
* be printed, we can build targets.
@@ -1069,7 +1075,7 @@
}
Lst_Destroy(&targs, NOFREE);

- } else {
+ } else if (!printGraphOnly) {
Var_Print(&variables, expandVars);
}

--- src/usr.bin/make/make.1 Sun Jul 9 14:14:02 2006
+++ src/usr.bin/make/make.1 Sun Jul 9 14:22:53 2006
@@ -40,7 +40,7 @@
.Nd maintain program dependencies
.Sh SYNOPSIS
.Nm
-.Op Fl ABPSXeiknqrstv
+.Op Fl ABPSXeiknpqrstv
.Op Fl C Ar directory
.Op Fl D Ar variable
.Op Fl d Ar flags
@@ -242,6 +242,15 @@
This option has no effect unless
.Fl j
is used too.
+.It Fl p
+Only print the input graph, do not executing any commands. The output is the
+same as
+.Fl d Ar g1 .
+When combined with
+.Fl f Pa /dev/null ,
+only the builtin rules of
+.Nm
+are displayed.
.It Fl q
Do not execute any commands, but exit 0 if the specified targets are
up-to-date and 1, otherwise.
Index: job.c
===================================================================
RCS file: /datadump/cvs/freebsd/src/usr.bin/make/job.c,v
retrieving revision 1.126
diff -u -r1.126 job.c
--- job.c 8 Mar 2007 09:16:10 -0000 1.126
+++ job.c 10 Jun 2007 11:39:45 -0000
@@ -2817,6 +2817,24 @@
}

/**
+ * shellskip
+ *
+ * Results:
+ * Returns a non-zero value if execution of the command wouldn't
+ * have an effect at all, which allows us to skip this line. This
+ * is useful for lines starting with '#'.
+ */
+static int
+shellskip(char *cmd)
+{
+ if (commandShell->skipfirst != NULL &&
+ strchr(commandShell->skipfirst, cmd[0]) != NULL)
+ return (1);
+
+ return (0);
+}
+
+/**
* shellneed
*
* Results:
@@ -2958,6 +2976,13 @@
return (0);
}

+ /*
+ * Don't execute the command if it's just a comment.
+ */
+ if (shellskip(cmd)) {
+ return (0);
+ }
+
ps.in = STDIN_FILENO;
ps.out = STDOUT_FILENO;
ps.err = STDERR_FILENO;
Index: shell.c
===================================================================
RCS file: /datadump/cvs/freebsd/src/usr.bin/make/shell.c,v
retrieving revision 1.1
diff -u -r1.1 shell.c
--- shell.c 24 May 2005 15:30:03 -0000 1.1
+++ shell.c 10 Jun 2007 11:51:31 -0000
@@ -82,7 +82,7 @@
"name=csh path='" PATH_DEFSHELLDIR "/csh' "
"quiet='unset verbose' echo='set verbose' filter='unset verbose' "
"hasErrCtl=N check='echo \"%s\"\n' ignore='csh -c \"%s || exit 0\"' "
- "echoFlag=v errFlag=e "
+ "echoFlag=v errFlag=e skipfirst=# "
"meta='" CSH_META "' builtins='" CSH_BUILTINS "'",

/*
@@ -92,7 +92,7 @@
"name=sh path='" PATH_DEFSHELLDIR "/sh' "
"quiet='set -' echo='set -v' filter='set -' "
"hasErrCtl=Y check='set -e' ignore='set +e' "
- "echoFlag=v errFlag=e "
+ "echoFlag=v errFlag=e skipfirst=# "
"meta='" SH_META "' builtins='" SH_BUILTINS "'",

/*
@@ -103,7 +103,7 @@
"name=ksh path='" PATH_DEFSHELLDIR "/ksh' "
"quiet='set -' echo='set -v' filter='set -' "
"hasErrCtl=Y check='set -e' ignore='set +e' "
- "echoFlag=v errFlag=e "
+ "echoFlag=v errFlag=e skipfirst=# "
"meta='" SH_META "' builtins='" SH_BUILTINS "' unsetenv=T",

NULL
@@ -150,6 +150,7 @@
free(sh->echo);
free(sh->exit);
ArgArray_Done(&sh->builtins);
+ free(sh->skipfirst);
free(sh->meta);
free(sh);
}
@@ -174,7 +175,8 @@
fprintf(stderr, " builtins=%d\n", sh->builtins.argc - 1);
for (i = 1; i < sh->builtins.argc; i++)
fprintf(stderr, " '%s'", sh->builtins.argv[i]);
- fprintf(stderr, "\n meta='%s'\n", sh->meta);
+ fprintf(stderr, "\n skipfirst='%s'\n", sh->skipfirst);
+ fprintf(stderr, " meta='%s'\n", sh->meta);
fprintf(stderr, " unsetenv=%d\n", sh->unsetenv);
}

@@ -260,6 +262,10 @@
qsort(sh->builtins.argv + 1, sh->builtins.argc - 1,
sizeof(char *), sort_builtins);
*fullSpec = TRUE;
+ } else if (strcmp(keyw, "skipfirst") == 0) {
+ free(sh->skipfirst);
+ sh->skipfirst = estrdup(eq);
+ *fullSpec = TRUE;
} else if (strcmp(keyw, "meta") == 0) {
free(sh->meta);
sh->meta = estrdup(eq);
@@ -379,6 +385,8 @@
* execute the command directly. If this list is empty
* it is assumed, that the command must always be
* handed over to the shell.
+ * skipfirst Skip execution of the command if the first
+ * character has a certain value.
* meta The shell meta characters. If this is not specified
* or empty, commands are alway passed to the shell.
* Otherwise they are not passed when they contain
Index: shell.h
===================================================================
RCS file: /datadump/cvs/freebsd/src/usr.bin/make/shell.h,v
retrieving revision 1.1
diff -u -r1.1 shell.h
--- shell.h 24 May 2005 15:30:03 -0000 1.1
+++ shell.h 10 Jun 2007 11:39:45 -0000
@@ -96,6 +96,7 @@
char *exit; /* command line flag: exit on error */

ArgArray builtins; /* ordered list of shell builtins */
+ char *skipfirst; /* characters that determine if we can skip the line */
char *meta; /* shell meta characters */

Boolean unsetenv; /* unsetenv("ENV") before exec */

Attachment: pgpNADhv4unVL.pgp
Description: PGP signature



Relevant Pages

  • Re: Most dependable way to run system commands
    ... Eventually I'd like to bring the execution of a few system commands ... specific execution issue (it dealt more with executing Perl code)). ... Unix and many similar systems, the exit status is an integer, with 0 ... variable after running a command via system or backticks. ...
    (perl.beginners)
  • SUSE Security Announcement: sudo (SUSE-SA:2005:036)
    ... Sudoallows the execution of commands as another user and gives the ... command needs to follow the attackers entry. ... It is recommended to install the updated packages. ... patch rpm: ...
    (Bugtraq)
  • Re: How to terminate execution of m-file programatically?
    ... I'm looking for command to terminate the execution of an m-file ... I've only found "exit" which ... I could use some kind of "goto" command to jump to the ...
    (comp.soft-sys.matlab)
  • Re: How to terminate execution of m-file programatically?
    ... I'm looking for command to terminate the execution of an m-file ... I've only found "exit" ... I could use some kind of "goto" command to jump to ...
    (comp.soft-sys.matlab)
  • Re: Can cobol be framed-up legally?...
    ... PaintMyWindow section. ... the Exit section command should return the ... execution back to the perform statement. ...
    (comp.lang.cobol)