diff options
author | Terry Burton | 2016-04-14 13:27:52 +0200 |
---|---|---|
committer | Terry Burton | 2016-04-16 00:15:22 +0200 |
commit | 703251401cb11ee5d00a6b8f8bd9dc80c160f476 (patch) | |
tree | 6574a97ba87fd28cec5b6c7c377094239469eb73 /sys-utils | |
parent | build-sys: add --enable-libuuid-force-uuidd (diff) | |
download | kernel-qcow2-util-linux-703251401cb11ee5d00a6b8f8bd9dc80c160f476.tar.gz kernel-qcow2-util-linux-703251401cb11ee5d00a6b8f8bd9dc80c160f476.tar.xz kernel-qcow2-util-linux-703251401cb11ee5d00a6b8f8bd9dc80c160f476.zip |
flock: Introduce no-fork option.
When guarding a command with flock it is sometimes preferable to not leave a
flock process waiting around for the command to exit.
Diffstat (limited to 'sys-utils')
-rw-r--r-- | sys-utils/flock.1 | 8 | ||||
-rw-r--r-- | sys-utils/flock.c | 68 |
2 files changed, 49 insertions, 27 deletions
diff --git a/sys-utils/flock.1 b/sys-utils/flock.1 index 8e9d5c29a..c10cde5ff 100644 --- a/sys-utils/flock.1 +++ b/sys-utils/flock.1 @@ -70,6 +70,14 @@ 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 \fB1\fR. .TP +.BR \-F , " \-\-no\-fork" +Do not fork before executing +.IR command . +Upon execution the flock process is replaced by +.IR command +which continues to hold the lock. This option is incompatible with +\fB\-\-close\fR as there would otherwise be nothing left to hold the lock. +.TP .BR \-e , " \-x" , " \-\-exclusive" Obtain an exclusive lock, sometimes called a write lock. This is the default. diff --git a/sys-utils/flock.c b/sys-utils/flock.c index b5c4d9189..ac473eecd 100644 --- a/sys-utils/flock.c +++ b/sys-utils/flock.c @@ -67,6 +67,7 @@ static void __attribute__((__noreturn__)) usage(int ex) fputs(_( " -E, --conflict-exit-code <number> exit code after conflict or timeout\n"), stderr); fputs(_( " -o, --close close file descriptor before running command\n"), stderr); fputs(_( " -c, --command <command> run a single command string through the shell\n"), stderr); + fputs(_( " -F, --no-fork execute command without forking\n"), stderr); fputs(_( " --verbose increase verbosity\n"), stderr); fprintf(stderr, USAGE_SEPARATOR); fprintf(stderr, USAGE_HELP); @@ -125,6 +126,7 @@ int main(int argc, char *argv[]) int fd = -1; int opt, ix; int do_close = 0; + int no_fork = 0; int status; int verbose = 0; struct timeval time_start, time_done; @@ -148,6 +150,7 @@ int main(int argc, char *argv[]) {"wait", required_argument, NULL, 'w'}, {"conflict-exit-code", required_argument, NULL, 'E'}, {"close", no_argument, NULL, 'o'}, + {"no-fork", no_argument, NULL, 'F'}, {"verbose", no_argument, NULL, OPT_VERBOSE}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, @@ -166,7 +169,7 @@ int main(int argc, char *argv[]) optopt = 0; while ((opt = - getopt_long(argc, argv, "+sexnouw:E:hV?", long_options, + getopt_long(argc, argv, "+sexnoFuw:E:hV?", long_options, &ix)) != EOF) { switch (opt) { case 's': @@ -182,6 +185,9 @@ int main(int argc, char *argv[]) case 'o': do_close = 1; break; + case 'F': + no_fork = 1; + break; case 'n': block = LOCK_NB; break; @@ -209,6 +215,10 @@ int main(int argc, char *argv[]) } } + if (no_fork && do_close) + errx(EX_USAGE, + _("the --no-fork and --close options are incompatible")); + if (argc > optind + 1) { /* Run command */ if (!strcmp(argv[optind + 1], "-c") || @@ -320,36 +330,40 @@ int main(int argc, char *argv[]) signal(SIGCHLD, SIG_DFL); if (verbose) printf(_("%s: executing %s\n"), program_invocation_short_name, cmd_argv[0]); - f = fork(); - if (f < 0) { - err(EX_OSERR, _("fork failed")); - } else if (f == 0) { - if (do_close) - close(fd); - execvp(cmd_argv[0], cmd_argv); - /* execvp() failed */ - warn(_("failed to execute %s"), cmd_argv[0]); - _exit((errno == ENOMEM) ? EX_OSERR : EX_UNAVAILABLE); - } else { - do { - w = waitpid(f, &status, 0); - if (w == -1 && errno != EINTR) - break; - } while (w != f); + if (!no_fork) { + f = fork(); + if (f < 0) { + err(EX_OSERR, _("fork failed")); + if (f != 0) { + do { + w = waitpid(f, &status, 0); + if (w == -1 && errno != EINTR) + break; + } while (w != f); - if (w == -1) { - status = EXIT_FAILURE; - warn(_("waitpid failed")); - } else if (WIFEXITED(status)) - status = WEXITSTATUS(status); - else if (WIFSIGNALED(status)) - status = WTERMSIG(status) + 128; - else - /* WTF? */ - status = EX_OSERR; + if (w == -1) { + status = EXIT_FAILURE; + warn(_("waitpid failed")); + } else if (WIFEXITED(status)) + status = WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + status = WTERMSIG(status) + 128; + else + /* WTF? */ + status = EX_OSERR; + } + goto out; + } } + if (do_close) + close(fd); + execvp(cmd_argv[0], cmd_argv); + /* execvp() failed */ + warn(_("failed to execute %s"), cmd_argv[0]); + _exit((errno == ENOMEM) ? EX_OSERR : EX_UNAVAILABLE); } +out: return status; } |