summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys-utils/flock.18
-rw-r--r--sys-utils/flock.c68
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;
}