From e1fe79a9e705e3cab8f632cdbe8e1774cdef2761 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Thu, 19 Feb 2015 04:13:20 +0000 Subject: - exit code overhaul: forx, forbacktickx, loopwhilex, if, ifelse, ifte, ifthenelse - new -o option to forx, forbacktickx, loopwhilex - documentation updated - version: rc for 2.1.0.0 --- INSTALL | 2 +- doc/exitcodes.html | 97 +++++++++++++++++++++++++++++++++ doc/forbacktickx.html | 18 ++++--- doc/foreground.html | 9 +++- doc/forx.html | 16 ++++-- doc/if.html | 4 +- doc/ifelse.html | 3 +- doc/ifte.html | 3 +- doc/ifthenelse.html | 3 +- doc/index.html | 4 +- doc/loopwhilex.html | 25 +++++---- doc/upgrade.html | 12 +++++ package/info | 2 +- src/execline/forbacktickx.c | 128 ++++++++++++++++++++++---------------------- src/execline/forx.c | 21 +++++--- src/execline/if.c | 8 +-- src/execline/ifelse.c | 6 +-- src/execline/ifte.c | 6 +-- src/execline/ifthenelse.c | 4 +- src/execline/loopwhilex.c | 25 +++++---- 20 files changed, 273 insertions(+), 123 deletions(-) create mode 100644 doc/exitcodes.html diff --git a/INSTALL b/INSTALL index 4f04ae1..9a8f893 100644 --- a/INSTALL +++ b/INSTALL @@ -6,7 +6,7 @@ Build Instructions - A POSIX-compliant C development environment - GNU make version 4.0 or later - - skalibs version 2.3.0.0 or later: http://skarnet.org/software/skalibs/ + - skalibs version 2.3.1.0 or later: http://skarnet.org/software/skalibs/ This software will run on any operating system that implements POSIX.1-2008, available at: diff --git a/doc/exitcodes.html b/doc/exitcodes.html new file mode 100644 index 0000000..4b8afda --- /dev/null +++ b/doc/exitcodes.html @@ -0,0 +1,97 @@ + + + + + execline: exit codes + + + + + + +

+execline
+Software
+skarnet.org +

+ +

How to propagate exit codes up a process dynasty

+ +

+ Say we have a parent process P, child of a grandparent process +G, spawning a child process C and waiting for it. +Either C dies normally with an exit code from 0 to 255, or it is +killed by a signal. + How can we make sure that P reports to G what happened +to C, with as much precision as possible ? +

+ +

+ The problem is, there's more information in a wstat (the +structure filled in by +waitpid()) +than a process can report by +simply exiting. P could exit with the same exit code as C, +but then what should it do if C has been killed by a signal ? +

+ +

+ An idea is to have P kill itself with the same signal that killed +C. +But that's actually not right, because P itself could be killed by a +signal from another source, and G needs that information. "P has been +killed by a signal" and "C has been killed by a signal" are two +different informations, so they should not be reported in the same way. +

+ +

+ So, any way you look at it, there is always more information than we +can report. +

+ +

+Shells have their own +convention +for reporting crashes, but since any exit code greater than 127 is reported +as is, the information given by the shell is unreliable: "child exited 129" +and "child was killed by SIGHUP" are indistinguishable. When shells get +nested, all bets are off - the information conveyed by exit codes becomes +devoid of meaning pretty fast. We need something better. +

+ +

execline's solution

+ +

+execline commands such as forx, that can report +a child's exit code, proceed that way when they're in the position of +P: +

+ + + +

+ Rationale: +

+ + + + + diff --git a/doc/forbacktickx.html b/doc/forbacktickx.html index d40799a..0780f3d 100644 --- a/doc/forbacktickx.html +++ b/doc/forbacktickx.html @@ -29,7 +29,7 @@ run another program.

-     forbacktickx [ -p | -x breakcode ] [ -n ] [ -C | -c ] [ -0 | -d delim ] variable { gen... } loop...
+     forbacktickx [ -p | -o okcodes | -x breakcodes ] [ -n ] [ -C | -c ] [ -0 | -d delim ] variable { gen... } loop...
 
@@ -51,6 +52,12 @@ wrap external commands that exit instead of natively supporting the
  • foreground prog1... "" prog2... is equivalent to sh -c 'prog1... ; exec prog2...'.
  • +
  • 256 and above are not valid exit codes for commands, so when the +? environment variable contains 256 or more, it means that the +previous command was killed by a signal. There is no ambiguity here, and +? reports exactly what happened to the previous command; +foreground does not exit, so there is no need for +exit code approximation.
  • diff --git a/doc/forx.html b/doc/forx.html index 0349a85..0ed4799 100644 --- a/doc/forx.html +++ b/doc/forx.html @@ -28,7 +28,7 @@

    -     forx [ -p | -x breakcodes ] variable { args... } loop...
    +     forx [ -p | -o okcodes | -x breakcodes ] variable { args... } loop...
     

    Notes

    diff --git a/doc/if.html b/doc/if.html index 2157a07..5723ef7 100644 --- a/doc/if.html +++ b/doc/if.html @@ -35,8 +35,8 @@
  • if reads prog1... in a block. It forks and executes it, then waits for it to complete.
  • -
  • If prog1 crashes, if exits 1 with a special -error message.
  • +
  • If prog1 crashes, if prints an error message +then exits 128 plus the number of the signal that killed prog1.
  • If prog1 exits a non-zero status, if exits 1.
  • Else if execs into prog2.
  • diff --git a/doc/ifelse.html b/doc/ifelse.html index 2298cf8..06d2e9c 100644 --- a/doc/ifelse.html +++ b/doc/ifelse.html @@ -34,7 +34,8 @@
  • ifelse reads prog1... in a block. It forks and executes it, then waits for it to complete.
  • -
  • If prog1 crashes, ifelse exits 1 with an error message.
  • +
  • If prog1 crashes, ifelse prints an error message +and exits 128 plus the number of the signal that killed prog1.
  • If prog1 exits with a return code equal to 0, ifelse execs into prog2.
  • Else ifelse execs into prog3.
  • diff --git a/doc/ifte.html b/doc/ifte.html index 40b0ec9..9cbfdcc 100644 --- a/doc/ifte.html +++ b/doc/ifte.html @@ -37,7 +37,8 @@ consecutive blocks.
  • ifte runs progif... as a child process and waits for it to complete.
  • If progif... crashes (i.e. is killed by a signal), ifte -exits 1 with an error message.
  • +prints an error message, then exits 128 plus the number of the signal that +killed progif.
  • If progif... exits zero, ifte execs into progthen..., else it execs into progelse....
  • diff --git a/doc/ifthenelse.html b/doc/ifthenelse.html index 3180412..97aec39 100644 --- a/doc/ifthenelse.html +++ b/doc/ifthenelse.html @@ -38,7 +38,8 @@ consecutive blocks.
  • ifthenelse runs progif... as a child process and waits for it to complete.
  • If progif... crashes (i.e. is killed by a signal), ifthenelse -exits 1 with an error message.
  • +prints an error message, then exits 128 plus the number of the signal +that killed progif.
  • If progif... exits zero, ifthenelse runs progthen... as a child process, else it runs progelse....
  • ifthenelse waits for its child to complete and puts the exit diff --git a/doc/index.html b/doc/index.html index 5fdfb46..5b19477 100644 --- a/doc/index.html +++ b/doc/index.html @@ -51,7 +51,7 @@ shell's syntax, and has no security issues.
  • GNU make, version 4.0 or later. Please be aware that execline will not build with an earlier version.
  • skalibs version -2.3.0.0 or later. It's a build-time requirement. It's also a run-time +2.3.1.0 or later. It's a build-time requirement. It's also a run-time requirement if you link against the shared version of the skalibs library.
  • @@ -66,7 +66,7 @@ library.

    Download

    diff --git a/doc/loopwhilex.html b/doc/loopwhilex.html index 91e9fb1..8c8d760 100644 --- a/doc/loopwhilex.html +++ b/doc/loopwhilex.html @@ -24,31 +24,38 @@

    Interface

    -     loopwhilex [ -n ] [ -x exitcodes ] prog...
    +     loopwhilex [ -n ] [ -o okcodes | -x breakcodes ] prog...
     

    Options

    Notes