]> err.no Git - moreutils/commitdiff
* Don't strip binaries for debian package if built with
authorjoeyh <joeyh>
Thu, 6 Sep 2007 01:28:28 +0000 (01:28 +0000)
committerjoeyh <joeyh>
Thu, 6 Sep 2007 01:28:28 +0000 (01:28 +0000)
  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.

Makefile
README
debian/changelog
debian/control
debian/copyright
debian/rules
lckdo.c [new file with mode: 0644]
lckdo.docbook [new file with mode: 0644]

index 8f9db54f0831cdd86de5ee4134837277abcf8a71..a15226e8a6fe773f7d1c8d0722860ef4d3081f53 100644 (file)
--- 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 c07e5652f5b13834e1e45565d4e20fc0bdbcff9b..702bb0d800a712028fd3f4664e7f8a9c04fe415e 100644 (file)
--- 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
index 52e97b501dec238d0f76ffad9a01fddcc8da55b9..a87665bd17404ab46ac97e99ba2dd6478fc0ca18 100644 (file)
@@ -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 <joeyh@debian.org>  Wed, 01 Aug 2007 13:45:23 -0400
+ -- Joey Hess <joeyh@debian.org>  Wed, 05 Sep 2007 21:21:29 -0400
 
 moreutils (0.22) unstable; urgency=low
 
index 7fb0cb9b1d6979dda6fa3774916e40c91926924e..06b7339bb93a4e5da615eb9d753f14ed877d676a 100644 (file)
@@ -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
index 22e443e9335603a16ec945518cd82d206d32c8a5..6b65c168d8074b66a66199bfc36bbbec21c6f43a 100644 (file)
@@ -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.
index 10f0e79119375a3da808b95129e9887a80039ef4..596444863f6e7b9d7afc707133adac72cd2eb807 100755 (executable)
@@ -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 (file)
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 <mjt@tls.msk.ru>
+ * Public domain.
+ */
+
+#define _GNU_SOURCE
+#define _BSD_SOURCE
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sysexits.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+/* 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 (file)
index 0000000..8a0a4a8
--- /dev/null
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+
+Written by Michael Tokarev <mjt@tls.msk.ru>
+Public domain.
+
+-->
+
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.4//EN"
+"file:///usr/share/xml/docbook/schema/dtd/4.4/docbookx.dtd"
+[]>
+
+<refentry>
+       <refentryinfo>
+               <address>
+                       <email>mjt@tls.msk.ru</email>
+               </address>
+               <author>
+                       <firstname>Michael</firstname>
+                       <surname>Tokarev</surname>
+               </author>
+               <date>2007-08-15</date>
+       </refentryinfo>
+
+       <refmeta>
+               <refentrytitle>lckdo</refentrytitle>
+               <manvolnum>1</manvolnum>
+       </refmeta>
+
+       <refnamediv>
+               <refname>lckdo</refname> 
+               <refpurpose>run a program with a lock held</refpurpose>
+       </refnamediv>
+
+       <refsynopsisdiv>
+               <cmdsynopsis>
+                       <command>lckdo</command>
+                       <arg>options</arg>
+                       <arg choice="req">lockfile</arg>
+                       <arg choice="req">program</arg>
+                       <arg>arguments</arg>
+               </cmdsynopsis>
+       </refsynopsisdiv>
+       
+       <refsect1>
+               <title>DESCRIPTION</title>
+               
+               <para><command>lckdo</command> runs a program with a lock
+               held, in order to prevent multiple processes from running in
+               parallel. Use just like <command>nice</command> or
+               <command>nohup</command>.</para>
+
+       </refsect1>
+       
+       <refsect1>
+               <title>OPTIONS</title>
+               
+               <variablelist>
+               
+               <varlistentry>
+                       <term><option>-w</option></term>
+                       <listitem>
+                               <para>If the lock is already held by another process,
+                               wait for it to complete instead of failing
+                               immediately.</para>
+                       </listitem>
+               </varlistentry>
+               
+               <varlistentry>
+                       <term><option>-W {sec}</option></term>
+                       <listitem>
+                               <para>The same as -w but wait not more than sec
+                               seconds.</para>
+                       </listitem>
+               </varlistentry>
+
+               <varlistentry>
+                       <term><option>-e</option></term>
+                       <listitem>
+                               <para>Execute the program directly without forking and
+                               waiting (keeps an extra file descriptor open).</para>
+                       </listitem>
+               </varlistentry>
+
+               <varlistentry>
+                       <term><option>-E {nnn}</option></term>
+                       <listitem>
+                               <para>Set the file descriptor number to keep open when
+                               exec()ing (implies -e).</para>
+                       </listitem>
+               </varlistentry>
+
+               <varlistentry>
+                       <term><option>-n</option></term>
+                       <listitem>
+                               <para>Do not create the lock file if it does not
+                               exist.</para>
+                       </listitem>
+               </varlistentry>
+
+               <varlistentry>
+                       <term><option>-q</option></term>
+                       <listitem>
+                               <para>Produce no output if lock is already held.</para>
+                       </listitem>
+               </varlistentry>
+
+               <varlistentry>
+                       <term><option>-s</option></term>
+                       <listitem>
+                               <para>Lock in shared (read) mode.</para>
+                       </listitem>
+               </varlistentry>
+
+               <varlistentry>
+                       <term><option>-x</option></term>
+                       <listitem>
+                               <para>Lock in exclusive (write) mode (default).</para>
+                       </listitem>
+               </varlistentry>
+
+               <varlistentry>
+                       <term><option>-t</option></term>
+                       <listitem>
+                               <para>Test for lock existence.</para>
+                       </listitem>
+               </varlistentry>
+
+               </variablelist>
+               
+       </refsect1>
+       
+       <refsect1>
+               <title>EXIT STATUS</title>
+
+        <para>If the lock was successfully acquired, the return value is that
+        of the program invoked by <command>lckdo</command>. 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.</para>
+               
+       </refsect1>
+
+</refentry>