From 827b1ceefdfdb3b4b55affb32f3c315abb7ad3fb Mon Sep 17 00:00:00 2001 From: "Jan \\\"Yenya\\\" Kasprzak" Date: Tue, 5 Jun 2012 16:26:58 +0200 Subject: [PATCH] flock: user-configurable exit code When locking the file fails with -n or -w option, caller has no way to distinguish between the exit code 1 of the -c command, and the exit code 1 of flock(1) caused by the conflicting lock. Add a new -E (--conflict-exit-code) option to set the exit code for the case of locking failure to any value. --- sys-utils/flock.1 | 19 ++++++++++++++++--- sys-utils/flock.c | 26 ++++++++++++++++---------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/sys-utils/flock.1 b/sys-utils/flock.1 index 5a6f27fbb..b50c619cf 100644 --- a/sys-utils/flock.1 +++ b/sys-utils/flock.1 @@ -71,13 +71,19 @@ cases, for example if the enclosed command group may have forked a background process which should not be holding the lock. .TP \fB\-n\fP, \fB\-\-nb\fP, \fB\-\-nonblock\fP -Fail (with an exit code of 1) rather than wait if the lock cannot be +Fail rather than wait if the lock cannot be immediately acquired. +See the +.I \-E +option for the exit code used. .TP \fB\-w\fP, \fB\-\-wait\fP, \fB\-\-timeout\fP \fIseconds\fP -Fail (with an exit code of 1) if the lock cannot be acquired within +Fail if the lock cannot be acquired within .IR seconds . Decimal fractional values are allowed. +See the +.I \-E +option for the exit code used. .TP \fB\-o\fP, \fB\-\-close\fP Close the file descriptor on which the lock is held before executing @@ -86,6 +92,11 @@ This is useful if .B command spawns a child process which should not be holding the lock. .TP +\fB\-E\fP, \fB\-\-conflict\-exit\-code\fP \fInumber\fP +The exit code used when the \fB\-n\fP option is in use, and the +conflicting lock exists, or the \fB\-w\fP option is in use, +and the timeout is reached. The default value is 1. +.TP \fB\-c\fP, \fB\-\-command\fP \fIcommand\fP Pass a single .IR command , @@ -134,7 +145,9 @@ return values for everything else but an options .I \-n or .I \-w -failures which return 1. +failures which return either the value given by the +.I \-E +option, or 1 by default. .SH AUTHOR .UR hpa@zytor.com H. Peter Anvin diff --git a/sys-utils/flock.c b/sys-utils/flock.c index 1db28a294..5a3422a1d 100644 --- a/sys-utils/flock.c +++ b/sys-utils/flock.c @@ -58,6 +58,7 @@ static void __attribute__((__noreturn__)) usage(int ex) fputs(_( " -u --unlock remove a lock\n"), stderr); fputs(_( " -n --nonblock fail rather than wait\n"), stderr); fputs(_( " -w --timeout wait for a limited amount of time\n"), stderr); + fputs(_( " -E --conflict-exit-code exit code after conflict or timeout\n"), stderr); fputs(_( " -o --close close file descriptor before running command\n"), stderr); fputs(_( " -c --command run a single command string through the shell\n"), stderr); fprintf(stderr, USAGE_SEPARATOR); @@ -141,6 +142,11 @@ int main(int argc, char *argv[]) int opt, ix; int do_close = 0; int status; + /* + * The default exit code for lock conflict or timeout + * is specified in man flock.1 + */ + int conflict_exit_code = 1; char **cmd_argv = NULL, *sh_c_argv[4]; const char *filename = NULL; struct sigaction sa, old_sa; @@ -153,6 +159,7 @@ int main(int argc, char *argv[]) {"nb", no_argument, NULL, 'n'}, {"timeout", required_argument, NULL, 'w'}, {"wait", required_argument, NULL, 'w'}, + {"conflict-exit-code", required_argument, NULL, 'E'}, {"close", no_argument, NULL, 'o'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, @@ -171,7 +178,7 @@ int main(int argc, char *argv[]) optopt = 0; while ((opt = - getopt_long(argc, argv, "+sexnouw:hV?", long_options, + getopt_long(argc, argv, "+sexnouw:E:hV?", long_options, &ix)) != EOF) { switch (opt) { case 's': @@ -194,6 +201,10 @@ int main(int argc, char *argv[]) have_timeout = 1; strtotimeval(optarg, &timeout.it_value); break; + case 'E': + conflict_exit_code = strtos32_or_err(optarg, + _("invalid exit code")); + break; case 'V': printf("flock (%s)\n", PACKAGE_STRING); exit(EX_OK); @@ -252,18 +263,13 @@ int main(int argc, char *argv[]) while (flock(fd, type | block)) { switch (errno) { case EWOULDBLOCK: - /* -n option set and failed to lock. The numeric - * exit value is specified in man flock.1 - */ - exit(1); + /* -n option set and failed to lock. */ + exit(conflict_exit_code); case EINTR: /* Signal received */ if (timeout_expired) - /* -w option set and failed to lock. The - * numeric exit value is specified in man - * flock.1 - */ - exit(1); + /* -w option set and failed to lock. */ + exit(conflict_exit_code); /* otherwise try again */ continue; case EIO: