aboutsummaryrefslogtreecommitdiffstats
path: root/builtin.c
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2016-03-11 12:05:52 +0200
committerArnold D. Robbins <arnold@skeeve.com>2016-03-11 12:05:52 +0200
commit9e5f75aab2e89adca6feea801a91d14dacfb71ce (patch)
tree865255fbd4ef35355eb1b8cc166abb2bf87cbc6b /builtin.c
parent860e3ea8ad4343318d7c8886a05bcb6551dbe618 (diff)
parent31e83b72eb5a30c5d733c89e233fbbd5cfd60f1b (diff)
downloadegawk-9e5f75aab2e89adca6feea801a91d14dacfb71ce.tar.gz
egawk-9e5f75aab2e89adca6feea801a91d14dacfb71ce.tar.bz2
egawk-9e5f75aab2e89adca6feea801a91d14dacfb71ce.zip
Merge branch 'master' into feature/cmake
Diffstat (limited to 'builtin.c')
-rw-r--r--builtin.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/builtin.c b/builtin.c
index c28cd0a8..9bd8e5eb 100644
--- a/builtin.c
+++ b/builtin.c
@@ -2075,9 +2075,10 @@ NODE *
do_system(int nargs)
{
NODE *tmp;
- int ret = 0;
+ AWKNUM ret = 0; /* floating point on purpose, compat Unix awk */
char *cmd;
char save;
+ int status;
if (do_sandbox)
fatal(_("'system' function not allowed in sandbox mode"));
@@ -2094,9 +2095,33 @@ do_system(int nargs)
cmd[tmp->stlen] = '\0';
os_restore_mode(fileno(stdin));
- ret = system(cmd);
- if (ret != -1)
- ret = WEXITSTATUS(ret);
+ status = system(cmd);
+ /*
+ * 3/2016. What to do with ret? It's never simple.
+ * POSIX says to use the full return value. BWK awk
+ * divides the result by 256. That normally gives the
+ * exit status but gives a weird result for death-by-signal.
+ * So we compromise as follows:
+ */
+ ret = status;
+ if (status != -1) {
+ if (do_posix)
+ ; /* leave it alone, full 16 bits */
+ else if (do_traditional)
+ ret = (status / 256.0);
+ else if (WIFEXITED(status))
+ ret = WEXITSTATUS(status); /* normal exit */
+ else if (WIFSIGNALED(status)) {
+ bool coredumped = false;
+#ifdef WCOREDUMP
+ coredumped = WCOREDUMP(status);
+#endif
+ /* use 256 since exit values are 8 bits */
+ ret = WTERMSIG(status) +
+ (coredumped ? 512 : 256);
+ } else
+ ret = 0; /* shouldn't get here */
+ }
if ((BINMODE & BINMODE_INPUT) != 0)
os_setbinmode(fileno(stdin), O_BINARY);