From: joeyh Date: Thu, 6 Sep 2007 01:28:28 +0000 (+0000) Subject: * Don't strip binaries for debian package if built with X-Git-Tag: 0.23~2 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=70564cb95575300bd77dd8035f2d010e9030de4c;p=moreutils * Don't strip binaries for debian package if built with DEB_BUILD_OPTIONS=nostrip. Closes: #437577 * Include Michael Tokarev's lckdo program and replace / conflict with the current lckdo package. (Robert Edmonds) Closes: #432906 * lckdo: Don't clear other flags when setting close on exec. --- diff --git a/Makefile b/Makefile index 8f9db54..a15226e 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ -BINS=isutf8 ifdata pee sponge mispipe +BINS=isutf8 ifdata pee sponge mispipe lckdo PERLSCRIPTS=vidir vipe ts combine zrun -MANS=sponge.1 vidir.1 vipe.1 isutf8.1 ts.1 combine.1 ifdata.1 pee.1 zrun.1 mispipe.1 +MANS=sponge.1 vidir.1 vipe.1 isutf8.1 ts.1 combine.1 ifdata.1 pee.1 zrun.1 mispipe.1 lckdo.1 CFLAGS=-O2 -g -Wall +INSTALL_BIN=install -s all: $(BINS) $(MANS) @@ -10,7 +11,7 @@ clean: install: mkdir -p $(PREFIX)/usr/bin - install -s $(BINS) $(PREFIX)/usr/bin + $(INSTALL_BIN) $(BINS) $(PREFIX)/usr/bin install $(PERLSCRIPTS) $(PREFIX)/usr/bin mkdir -p $(PREFIX)/usr/share/man/man1 @@ -34,5 +35,8 @@ sponge.1: sponge.docbook mispipe.1: mispipe.docbook docbook2x-man $< +lckdo.1: lckdo.docbook + docbook2x-man $< + %.1: % pod2man --center=" " --release="moreutils" $< > $@; diff --git a/README b/README index c07e565..702bb0d 100644 --- a/README +++ b/README @@ -7,6 +7,8 @@ ifdata get network interface info without parsing ifconfig output isutf8 check if a file or standard input is utf-8 +lckdo + execute a program with a lock held mispipe pipe two commands, returning the exit status of the first pee diff --git a/debian/changelog b/debian/changelog index 52e97b5..a87665b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,13 @@ moreutils (0.23) UNRELEASED; urgency=low * Add pointer to join from combine's man page. Closes: #435516 + * Don't strip binaries for debian package if built with + DEB_BUILD_OPTIONS=nostrip. Closes: #437577 + * Include Michael Tokarev's lckdo program and replace / conflict with the + current lckdo package. (Robert Edmonds) Closes: #432906 + * lckdo: Don't clear other flags when setting close on exec. - -- Joey Hess Wed, 01 Aug 2007 13:45:23 -0400 + -- Joey Hess Wed, 05 Sep 2007 21:21:29 -0400 moreutils (0.22) unstable; urgency=low diff --git a/debian/control b/debian/control index 7fb0cb9..06b7339 100644 --- a/debian/control +++ b/debian/control @@ -10,6 +10,8 @@ Package: moreutils Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} Suggests: libtime-duration-perl, libtimedate-perl +Conflicts: lckdo +Replaces: lckdo Description: additional unix utilities This is a growing collection of the unix tools that nobody thought to write thirty years ago. @@ -25,3 +27,4 @@ Description: additional unix utilities - zrun: automatically uncompress arguments to command - mispipe: pipe two commands, returning the exit status of the first - isutf8: check if a file or standard input is utf-8 + - lckdo: execute a program with a lock held diff --git a/debian/copyright b/debian/copyright index 22e443e..6b65c16 100644 --- a/debian/copyright +++ b/debian/copyright @@ -19,6 +19,8 @@ zrun is Copyright (c) Chung-chieh Shan, under the terms of the GPL, version mispipe is Copyright (c) Nathanael Nerode, under the terms of the GPL, version 2 or later. (It's also dual-licensed under the MIT/Expat licence.) +lckdo is public domain code released by Michael Tokarev. + Everything else is copyright 2006 by Joey Hess, under the terms of GPL. The full text of the GNU GPL can be found in /usr/share/common-licenses/GPL on Debian systems. diff --git a/debian/rules b/debian/rules index 10f0e79..5964448 100755 --- a/debian/rules +++ b/debian/rules @@ -21,7 +21,7 @@ binary-arch: build dh_testroot dh_clean -k dh_installdirs - $(MAKE) PREFIX=debian/moreutils install + $(MAKE) PREFIX=debian/moreutils INSTALL_BIN=install install dh_installdocs README dh_installchangelogs dh_perl diff --git a/lckdo.c b/lckdo.c new file mode 100644 index 0000000..39b7f17 --- /dev/null +++ b/lckdo.c @@ -0,0 +1,227 @@ +/* lckdo.c: run a program with a lock held, + * to prevent multiple processes running in parallel. + * Use just like `nice' or `nohup'. + * Written by Michael Tokarev + * Public domain. + */ + +#define _GNU_SOURCE +#define _BSD_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* compile with -DUSE_FLOCK to use flock() instead of fcntl() */ + +#if !defined(USE_FLOCK) && !defined(F_SETLKW) +# define USE_FLOCK +#endif + +#ifndef __GNUC__ +# ifndef __attribute__ +# define __attribute__(x) +# endif +#endif + +static char *progname; +static void +__attribute__((format(printf,3,4))) +__attribute__((noreturn)) +error(int errnum, int exitcode, const char *fmt, ...) { + va_list ap; + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); + if (errnum) fprintf(stderr, ": %s\n", strerror(errnum)); + else fputs("\n", stderr); + exit(exitcode); +} + +static const char *lckfile; +static int quiet; + +static void sigalarm(int sig) { + if (quiet) + _exit(EX_TEMPFAIL); + error(0, EX_TEMPFAIL, + "lock file `%s' is already locked (timeout waiting)", lckfile); + sig = sig; +} + +int main(int argc, char **argv) { + int fd; + int c; + int create = O_CREAT; + int dofork = 1; + int waittime = 0; + int shared = 0; + int test = 0; + int fdn = -1; +#ifndef USE_FLOCK + struct flock fl; +#endif + + if ((progname = strrchr(argv[0], '/')) == NULL) progname = argv[0]; + else argv[0] = ++progname; + + if (argc == 1) { + printf( +"%s: execute a program with a lock set.\n" +"Usage: %s [options] lockfile program [arguments]\n" +"where options are:\n" +" -w - if the lock is already held by another process,\n" +" wait for it to complete instead of failing immediately\n" +" -W sec - the same as -w but wait not more than sec seconds\n" +" -e - execute the program directly, no fork/wait\n" +" (keeps extra open file descriptor)\n" +" -E nnn - set the fd# to keep open in -e case (implies -e)\n" +" -n - do not create the lock file if it does not exist\n" +" -q - produce no output if lock is already held\n" +" -s - lock in shared (read) mode\n" +" -x - lock in exclusive (write) mode (default)\n" +" -t - test for lock existence" +#ifndef USE_FLOCK + " (just prints pid if any with -q)\n" +#endif +" (implies -n)\n" + , progname, progname); + return 0; + } + + while((c = getopt(argc, argv, "+wW:neE:sxtq")) != EOF) + switch(c) { + case 'w': + if (!waittime) + waittime = -1; + break; + case 'W': + if ((waittime = atoi(optarg)) < 1) + error(0, EX_USAGE, "invalid wait time `%s'", optarg); + break; + case 't': + test = 1; + /* fall */ + case 'n': + create = 0; + break; + case 'E': + if ((fdn = atoi(optarg)) < 0 || fdn == 2) + error(0, EX_USAGE, "invalid fd# `%s'", optarg); + /* fall */ + case 'e': + dofork = 0; + break; + case 's': + shared = 1; + break; + case 'x': + shared = 0; + break; + case 'q': + quiet = 1; + break; + default: + return EX_USAGE; + } + + argc -= optind; argv += optind; + if (!argc || (!test && argc < 2)) + error(0, EX_USAGE, "too few arguments given"); + + lckfile = *argv++; + +#ifdef USE_FLOCK + create |= O_RDONLY; +#else + if (!test) + create |= shared ? O_RDONLY : O_WRONLY; +#endif + fd = open(lckfile, create, 0666); + if (fd < 0) { + if (test && errno == ENOENT) { + if (!quiet) + printf("lockfile `%s' is not locked\n", lckfile); + return 0; + } + error(errno, EX_CANTCREAT, "unable to open `%s'", lckfile); + } + + if (!test && fdn >= 0) { + /* dup it early to comply with stupid POSIX fcntl locking semantics */ + if (dup2(fd, fdn) < 0) + error(errno, EX_OSERR, "dup2(%d,%d) failed", fd, fdn); + close(fd); + fd = fdn; + } + + if (test) + waittime = 0; + else if (waittime > 0) { + alarm(waittime); + signal(SIGALRM, sigalarm); + } +#ifdef USE_FLOCK + c = flock(fd, (shared ? LOCK_SH : LOCK_EX) | (waittime ? 0 : LOCK_NB)); + if (test && c < 0 && + (errno == EWOULDBLOCK || errno == EAGAIN || errno == EACCES)) { + if (!quiet) + printf("lockfile `%s' is locked\n", lckfile); + else + printf("locked\n"); + return EX_TEMPFAIL; + } +#else + memset(&fl, 0, sizeof(fl)); + fl.l_type = shared ? F_RDLCK : F_WRLCK; + c = fcntl(fd, test ? F_GETLK : waittime ? F_SETLKW : F_SETLK, &fl); + if (test && c == 0) { + if (fl.l_type == F_UNLCK) { + if (!quiet) + printf("lockfile `%s' is not locked\n", lckfile); + return 0; + } + if (!quiet) + printf("lockfile `%s' is locked by process %d\n", lckfile, fl.l_pid); + else + printf("%d\n", fl.l_pid); + return EX_TEMPFAIL; + } +#endif + if (waittime > 0) + alarm(0); + if (c < 0) { + if (errno != EWOULDBLOCK && errno != EAGAIN && errno != EACCES) + error(errno, EX_OSERR, "unable to lock `%s'", lckfile); + else if (quiet) + return EX_TEMPFAIL; + else + error(0, EX_TEMPFAIL, "lockfile `%s' is already locked", lckfile); + } + + if (dofork) { + pid_t pid; + int flags = fcntl(fd, F_GETFD, 0); + if (flags < 0) + error(errno, EX_OSERR, "fcntl() failed"); + fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + pid = fork(); + if (pid < 0) + error(errno, EX_OSERR, "unable to fork"); + else if (pid) { + if (wait(&c) < 0) + error(errno, EX_OSERR, "wait() failed"); + if (WIFSIGNALED(c)) + error(0, EX_SOFTWARE, "%s: %s", *argv, strsignal(WTERMSIG(c))); + return WEXITSTATUS(c); + } + } + execvp(*argv, argv); + error(errno, EX_OSERR, "unable to execute %s", *argv); +} diff --git a/lckdo.docbook b/lckdo.docbook new file mode 100644 index 0000000..8a0a4a8 --- /dev/null +++ b/lckdo.docbook @@ -0,0 +1,145 @@ + + + + + + + + +
+ mjt@tls.msk.ru +
+ + Michael + Tokarev + + 2007-08-15 +
+ + + lckdo + 1 + + + + lckdo + run a program with a lock held + + + + + lckdo + options + lockfile + program + arguments + + + + + DESCRIPTION + + lckdo runs a program with a lock + held, in order to prevent multiple processes from running in + parallel. Use just like nice or + nohup. + + + + + OPTIONS + + + + + + + If the lock is already held by another process, + wait for it to complete instead of failing + immediately. + + + + + + + The same as -w but wait not more than sec + seconds. + + + + + + + Execute the program directly without forking and + waiting (keeps an extra file descriptor open). + + + + + + + Set the file descriptor number to keep open when + exec()ing (implies -e). + + + + + + + Do not create the lock file if it does not + exist. + + + + + + + Produce no output if lock is already held. + + + + + + + Lock in shared (read) mode. + + + + + + + Lock in exclusive (write) mode (default). + + + + + + + Test for lock existence. + + + + + + + + + EXIT STATUS + + If the lock was successfully acquired, the return value is that + of the program invoked by lckdo. If the lock + couldn't be acquired, EX_TEMPFAIL is returned. If there was a problem + opening/creating or locking the lock file, EX_CANTCREAT or EX_OSERR + will be returned. + + + +