// $Id: lockfile.c 1447 2004-04-13 08:27:50Z ensc $ --*- c -*-- // Copyright (C) 2004 Enrico Scholz // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef HAVE_CONFIG_H # include #endif #include "util.h" #include #include #include #include #include #include #include #include #include static void showHelp(char const *cmd) { WRITE_MSG(1, "Usage: "); WRITE_STR(1, cmd); WRITE_MSG(1, " [--] []\n\n" "Protocol:\n" " 1. parent (shell) creates a named \n" " 2. 'lockfile' will be called\n" " 3a. 'lockfile' waits until somebody opens the for reading\n" " 3b. parent (shell) opens the pipe for reading and blocks\n" " 4. 'lockfile' calls flock() on the \n" " 5. 'lockfile' closes the \n" " 6. parent (shell) unlocks since is closed\n" " 7. 'lockfile' goes into infinite loop\n" " 8. parent sends SIGHUP (or other signal) to 'lockfile\n" "\n" "Sample code:\n" " tmp=$(mktemp /tmp/lock.XXXXXX)\n" " rm -f $tmp # safe since mknod(2) does not follow symlinks\n" " mkfifo -m700 $tmp || exit 1\n" " lockfile $lock $tmp &\n" " $tmp\n" " ... ...\n" " kill -HUP $! # (implicated by shell-exit)\n" "\n" "Please report bugs to " PACKAGE_BUGREPORT "\n"); exit(0); } static void showVersion() { WRITE_MSG(1, "lockfile " VERSION " -- locks a file" "This program is part of " PACKAGE_STRING "\n\n" "Copyright (C) 2004 Enrico Scholz\n" VERSION_COPYRIGHT_DISCLAIMER); exit(0); } static void alarmFunc(int UNUSED sig) { signal(SIGALRM, alarmFunc); } static void quitFunc(int UNUSED sig) { _exit(0); } int main(int argc, char *argv[]) { int fd, sync_fd = -1; int idx = 1; time_t end_time; pid_t const ppid = getppid(); if (argc>=2) { if (strcmp(argv[1], "--help") ==0) showHelp(argv[0]); if (strcmp(argv[1], "--version")==0) showVersion(); if (strcmp(argv[1], "--") ==0) ++idx; } if (argc)"); else if ((fd=open(argv[idx], O_CREAT|O_RDONLY|O_NOFOLLOW|O_NONBLOCK, 0644))==-1) perror("lockfile: open()"); else if (unlink(argv[idx+1])==-1) perror("lockfile: unlink()"); else if (siginterrupt(SIGALRM, 1)==-1) perror("lockfile: siginterrupt()"); else if (signal(SIGALRM, alarmFunc)==SIG_ERR || signal(SIGHUP, quitFunc) ==SIG_ERR) perror("lockfile: signal()"); else while (time(0)