aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2021-07-09 15:32:09 +0200
committerJohn Ankarström <john@ankarstrom.se>2021-07-09 15:33:54 +0200
commit3019c48804fb43f97d5c8e8ee15b5ae13ab1c4a9 (patch)
tree40fb553b67fbcdbc3a6d50a263cea3261680d800
parente57e5137040e65dd82474bc4c590c8c23cfce509 (diff)
downloadbuild-3019c48804fb43f97d5c8e8ee15b5ae13ab1c4a9.tar.gz
Use set -e, -x in shell process, handle exit status correctly
This makes the default behavior like make(1), but it is configurable. Furthermore, it is still a single shell process, which is arguably a benefit.
-rw-r--r--build.116
-rw-r--r--build.c34
2 files changed, 25 insertions, 25 deletions
diff --git a/build.1 b/build.1
index cf66324..10ae999 100644
--- a/build.1
+++ b/build.1
@@ -77,17 +77,9 @@ This means that you can keep state across multiple commands.
Note that all commands are executed
regardless of the exit status of previous commands.
.Pp
+If a command fails,
.Nm
-exits with a positive status if a command failed.
-Note that it checks the status
-of the entire command sent to the shell,
-not the individual command lines.
-To emulate the behavior of
-.Xr make 1 ,
-which fails if any individual command line fails,
-you can use
-.Ql set -e
-in your command line.
+exits with a positive status and aborts the build process.
.
.Sh EXAMPLES
.Pp
@@ -120,8 +112,8 @@ Assuming that the file
starts with the following text,
.Bd -literal -offset indent
\&.\\" This document is built with the following shell commands:
-\&.\\" $ refer -p refs doc.t | troff -ms | dpost > doc.ps &&
-\&.\\" $ ps2pdf doc.ps > doc.pdf &&
+\&.\\" $ refer -p refs doc.t | troff -ms | dpost > doc.ps
+\&.\\" $ ps2pdf doc.ps > doc.pdf
\&.\\" $ rm doc.ps
\&.
\&.\\" Apart from this file, it depends on the following files:
diff --git a/build.c b/build.c
index fc21925..600ac92 100644
--- a/build.c
+++ b/build.c
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
+#include <sys/wait.h>
#include <unistd.h>
#define USAGE "usage: %s file [...]\n", name
@@ -32,7 +33,7 @@ main(int argc, char *argv[])
{
char *b, buf[MAXBUF], *cmd[MAXCMDS], *d, *dep, *name, *tgt;
FILE *fp;
- int c, dflag, fflag, i, icmd, j, s, status;
+ int c, dflag, fflag, i, icmd, j, s;
struct stat sb, ssb;
/* allocate memory */
@@ -43,10 +44,9 @@ main(int argc, char *argv[])
dep = malloc(MAXDEP*sizeof(char));
if (!dep) err(1, "malloc");
tgt = malloc(MAXTGT*sizeof(char));
- if (!dep) err(1, "malloc");
+ if (!tgt) err(1, "malloc");
tgt[0] = dep[0] = 0;
- status = 0;
/* process arguments */
name = argv[0];
@@ -85,13 +85,13 @@ main(int argc, char *argv[])
/* command line */
if (strncmp(b, " $ ", 3) == 0
|| strncmp(b, " $ ", 3) == 0) {
- strncpy(cmd[icmd++],b+3,MAXBUF-1);
+ strncpy(cmd[icmd++], b+3, MAXBUF-1);
/* find target */
for (b = b+3; *b; b++) {
if (!(*b+1)) continue;
if (*b != '>') continue;
- strncpy(tgt,b+1,MAXTGT-1);
+ strncpy(tgt, b+1, MAXTGT-1);
}
@@ -113,7 +113,7 @@ main(int argc, char *argv[])
if (!icmd) {
fprintf(stderr, "%s: no command line found\n", argv[i]);
- continue;
+ goto next;
}
if (fflag || !*tgt)
@@ -153,25 +153,33 @@ main(int argc, char *argv[])
uptodate:
fprintf(stderr, "%s: already up-to-date\n", argv[i]);
- goto done;
+ goto next;
build:
/* run commands */
buf[0] = 0;
+ strcat(buf, "set -ex\n");
for (j = 0; j < icmd; j++) {
- fprintf(stderr, "%s: $ %s\n", argv[i], cmd[j]);
strncat(buf, cmd[j], MAXBUF-1);
strncat(buf, "\n", MAXBUF-1);
}
s = system(buf);
- if (s != -1)
- status += s;
+ if (s == 0)
+ goto next;
+
+ if (WIFEXITED(s)) {
+ fprintf(stderr, "%s: exited with %d\n",
+ argv[i], WEXITSTATUS(s));
+ exit(WEXITSTATUS(s));
+ } else if (WIFSIGNALED(s)) {
+ fprintf(stderr, "%s: terminated by signal %d\n",
+ argv[i], WTERMSIG(s));
+ exit(1);
+ }
-done:
+next:
fclose(fp);
}
-
- return status > 0;
}
void