xref: /minix3/usr.bin/flock/flock.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: flock.c,v 1.11 2014/08/18 09:16:35 christos Exp $	*/
29488aa4cSDavid van Moolenbroek 
39488aa4cSDavid van Moolenbroek /*-
49488aa4cSDavid van Moolenbroek  * Copyright (c) 2012 The NetBSD Foundation, Inc.
59488aa4cSDavid van Moolenbroek  * All rights reserved.
69488aa4cSDavid van Moolenbroek  *
79488aa4cSDavid van Moolenbroek  * This code is derived from software contributed to The NetBSD Foundation
89488aa4cSDavid van Moolenbroek  * by Christos Zoulas.
99488aa4cSDavid van Moolenbroek  *
109488aa4cSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
119488aa4cSDavid van Moolenbroek  * modification, are permitted provided that the following conditions
129488aa4cSDavid van Moolenbroek  * are met:
139488aa4cSDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
149488aa4cSDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
159488aa4cSDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
169488aa4cSDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
179488aa4cSDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
189488aa4cSDavid van Moolenbroek  *    from this software without specific prior written permission.
199488aa4cSDavid van Moolenbroek  *
209488aa4cSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
219488aa4cSDavid van Moolenbroek  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
229488aa4cSDavid van Moolenbroek  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
239488aa4cSDavid van Moolenbroek  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
249488aa4cSDavid van Moolenbroek  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
259488aa4cSDavid van Moolenbroek  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
269488aa4cSDavid van Moolenbroek  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
279488aa4cSDavid van Moolenbroek  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
289488aa4cSDavid van Moolenbroek  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
299488aa4cSDavid van Moolenbroek  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
309488aa4cSDavid van Moolenbroek  * POSSIBILITY OF SUCH DAMAGE.
319488aa4cSDavid van Moolenbroek  */
329488aa4cSDavid van Moolenbroek 
339488aa4cSDavid van Moolenbroek #include <sys/cdefs.h>
34*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: flock.c,v 1.11 2014/08/18 09:16:35 christos Exp $");
359488aa4cSDavid van Moolenbroek 
369488aa4cSDavid van Moolenbroek #include <stdio.h>
379488aa4cSDavid van Moolenbroek #include <string.h>
389488aa4cSDavid van Moolenbroek #include <fcntl.h>
399488aa4cSDavid van Moolenbroek #include <stdlib.h>
409488aa4cSDavid van Moolenbroek #include <signal.h>
419488aa4cSDavid van Moolenbroek #include <unistd.h>
429488aa4cSDavid van Moolenbroek #include <err.h>
439488aa4cSDavid van Moolenbroek #include <errno.h>
449488aa4cSDavid van Moolenbroek #include <getopt.h>
459488aa4cSDavid van Moolenbroek #include <paths.h>
46*0a6a1f1dSLionel Sambuc #include <limits.h>
479488aa4cSDavid van Moolenbroek #include <time.h>
489488aa4cSDavid van Moolenbroek 
499488aa4cSDavid van Moolenbroek static struct option flock_longopts[] = {
509488aa4cSDavid van Moolenbroek 	{ "debug",		no_argument,		0, 'd' },
519488aa4cSDavid van Moolenbroek 	{ "help",		no_argument,		0, 'h' },
529488aa4cSDavid van Moolenbroek 	{ "nonblock",		no_argument,		0, 'n' },
539488aa4cSDavid van Moolenbroek 	{ "nb",			no_argument,		0, 'n' },
549488aa4cSDavid van Moolenbroek 	{ "close",		no_argument,		0, 'o' },
559488aa4cSDavid van Moolenbroek 	{ "shared",		no_argument,		0, 's' },
569488aa4cSDavid van Moolenbroek 	{ "exclusive",		no_argument,		0, 'x' },
579488aa4cSDavid van Moolenbroek 	{ "unlock",		no_argument,		0, 'u' },
589488aa4cSDavid van Moolenbroek 	{ "verbose",		no_argument,		0, 'v' },
599488aa4cSDavid van Moolenbroek 	{ "command",		required_argument,	0, 'c' },
609488aa4cSDavid van Moolenbroek 	{ "wait",		required_argument,	0, 'w' },
619488aa4cSDavid van Moolenbroek 	{ "timeout",		required_argument,	0, 'w' },
629488aa4cSDavid van Moolenbroek 	{ NULL,			0,			0, 0   },
639488aa4cSDavid van Moolenbroek };
649488aa4cSDavid van Moolenbroek 
659488aa4cSDavid van Moolenbroek static sig_atomic_t timeout_expired;
669488aa4cSDavid van Moolenbroek 
67*0a6a1f1dSLionel Sambuc static __dead __printflike(1, 2) void
usage(const char * fmt,...)689488aa4cSDavid van Moolenbroek usage(const char *fmt, ...)
699488aa4cSDavid van Moolenbroek {
709488aa4cSDavid van Moolenbroek 	if (fmt) {
719488aa4cSDavid van Moolenbroek 		va_list ap;
729488aa4cSDavid van Moolenbroek 		va_start(ap, fmt);
739488aa4cSDavid van Moolenbroek 		fprintf(stderr, "%s: ", getprogname());
749488aa4cSDavid van Moolenbroek 		vfprintf(stderr, fmt, ap);
759488aa4cSDavid van Moolenbroek 		fputc('\n', stderr);
769488aa4cSDavid van Moolenbroek 		va_end(ap);
779488aa4cSDavid van Moolenbroek 	}
789488aa4cSDavid van Moolenbroek 
799488aa4cSDavid van Moolenbroek 	fprintf(stderr, "Usage: %s [-dnosvx] [-w timeout] lockfile|lockdir "
809488aa4cSDavid van Moolenbroek 	    "[-c command]|command ...\n\t%s [-dnsuvx] [-w timeout] lockfd\n",
819488aa4cSDavid van Moolenbroek 	    getprogname(), getprogname());
829488aa4cSDavid van Moolenbroek 	exit(EXIT_FAILURE);
839488aa4cSDavid van Moolenbroek }
849488aa4cSDavid van Moolenbroek 
859488aa4cSDavid van Moolenbroek static void
sigalrm(int sig)869488aa4cSDavid van Moolenbroek sigalrm(int sig)
879488aa4cSDavid van Moolenbroek {
889488aa4cSDavid van Moolenbroek 	timeout_expired++;
899488aa4cSDavid van Moolenbroek }
909488aa4cSDavid van Moolenbroek 
919488aa4cSDavid van Moolenbroek static const char *
lock2name(int l)929488aa4cSDavid van Moolenbroek lock2name(int l)
939488aa4cSDavid van Moolenbroek {
949488aa4cSDavid van Moolenbroek 	static char buf[1024];
959488aa4cSDavid van Moolenbroek 	int nb = l & LOCK_NB;
969488aa4cSDavid van Moolenbroek 
979488aa4cSDavid van Moolenbroek 	l &= ~LOCK_NB;
989488aa4cSDavid van Moolenbroek 	if (nb)
999488aa4cSDavid van Moolenbroek 		strlcpy(buf, "LOCK_NB|", sizeof(buf));
1009488aa4cSDavid van Moolenbroek 	else
1019488aa4cSDavid van Moolenbroek 		buf[0] = '\0';
1029488aa4cSDavid van Moolenbroek 
1039488aa4cSDavid van Moolenbroek 	switch (l) {
1049488aa4cSDavid van Moolenbroek 	case LOCK_SH:
1059488aa4cSDavid van Moolenbroek 		strlcat(buf, "LOCK_SH", sizeof(buf));
1069488aa4cSDavid van Moolenbroek 		return buf;
1079488aa4cSDavid van Moolenbroek 	case LOCK_EX:
1089488aa4cSDavid van Moolenbroek 		strlcat(buf, "LOCK_EX", sizeof(buf));
1099488aa4cSDavid van Moolenbroek 		return buf;
1109488aa4cSDavid van Moolenbroek 	case LOCK_UN:
1119488aa4cSDavid van Moolenbroek 		strlcat(buf, "LOCK_UN", sizeof(buf));
1129488aa4cSDavid van Moolenbroek 		return buf;
1139488aa4cSDavid van Moolenbroek 	default:
1149488aa4cSDavid van Moolenbroek 		snprintf(buf, sizeof(buf), "*%d*", l | nb);
1159488aa4cSDavid van Moolenbroek 		return buf;
1169488aa4cSDavid van Moolenbroek 	}
1179488aa4cSDavid van Moolenbroek }
1189488aa4cSDavid van Moolenbroek 
1199488aa4cSDavid van Moolenbroek static char
lockchar(int l)1209488aa4cSDavid van Moolenbroek lockchar(int l)
1219488aa4cSDavid van Moolenbroek {
1229488aa4cSDavid van Moolenbroek 	switch (l & ~LOCK_NB) {
1239488aa4cSDavid van Moolenbroek 	case LOCK_SH:
1249488aa4cSDavid van Moolenbroek 		return 's';
1259488aa4cSDavid van Moolenbroek 	case LOCK_EX:
1269488aa4cSDavid van Moolenbroek 		return 'x';
1279488aa4cSDavid van Moolenbroek 	case LOCK_UN:
1289488aa4cSDavid van Moolenbroek 		return 'u';
1299488aa4cSDavid van Moolenbroek 	default:
1309488aa4cSDavid van Moolenbroek 		return '*';
1319488aa4cSDavid van Moolenbroek 	}
1329488aa4cSDavid van Moolenbroek }
1339488aa4cSDavid van Moolenbroek 
1349488aa4cSDavid van Moolenbroek static char *
cmdline(char ** av)1359488aa4cSDavid van Moolenbroek cmdline(char **av)
1369488aa4cSDavid van Moolenbroek {
1379488aa4cSDavid van Moolenbroek 	char *v = NULL;
1389488aa4cSDavid van Moolenbroek 	while (*av)
1399488aa4cSDavid van Moolenbroek 		if (v) {
1409488aa4cSDavid van Moolenbroek 			if (asprintf(&v, "%s %s", v, *av++) < 0)
1419488aa4cSDavid van Moolenbroek 				err(EXIT_FAILURE, "malloc");
1429488aa4cSDavid van Moolenbroek 		} else {
1439488aa4cSDavid van Moolenbroek 			if ((v = strdup(*av++)) == NULL)
1449488aa4cSDavid van Moolenbroek 				err(EXIT_FAILURE, "strdup");
1459488aa4cSDavid van Moolenbroek 		}
1469488aa4cSDavid van Moolenbroek 	return v;
1479488aa4cSDavid van Moolenbroek }
1489488aa4cSDavid van Moolenbroek 
1499488aa4cSDavid van Moolenbroek int
main(int argc,char * argv[])1509488aa4cSDavid van Moolenbroek main(int argc, char *argv[])
1519488aa4cSDavid van Moolenbroek {
1529488aa4cSDavid van Moolenbroek 	int c;
1539488aa4cSDavid van Moolenbroek 	int lock = 0;
1549488aa4cSDavid van Moolenbroek 	double timeout = 0;
1559488aa4cSDavid van Moolenbroek 	int cls = 0;
1569488aa4cSDavid van Moolenbroek 	int fd = -1;
1579488aa4cSDavid van Moolenbroek 	int debug = 0;
1589488aa4cSDavid van Moolenbroek 	int verbose = 0;
159*0a6a1f1dSLionel Sambuc 	long l;
1609488aa4cSDavid van Moolenbroek 	char *mcargv[] = {
1619488aa4cSDavid van Moolenbroek 	    __UNCONST(_PATH_BSHELL), __UNCONST("-c"), NULL, NULL
1629488aa4cSDavid van Moolenbroek 	};
1639488aa4cSDavid van Moolenbroek 	char **cmdargv = NULL, *v;
164*0a6a1f1dSLionel Sambuc #if !defined(__minix)
1659488aa4cSDavid van Moolenbroek 	timer_t tm;
166*0a6a1f1dSLionel Sambuc #else
1679488aa4cSDavid van Moolenbroek 	struct itimerval it;
168*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
1699488aa4cSDavid van Moolenbroek 
1709488aa4cSDavid van Moolenbroek 	setprogname(argv[0]);
1719488aa4cSDavid van Moolenbroek 
1729488aa4cSDavid van Moolenbroek 	while ((c = getopt_long(argc, argv, "+dnosuvw:x", flock_longopts, NULL))
1739488aa4cSDavid van Moolenbroek 	    != -1)
1749488aa4cSDavid van Moolenbroek 		switch (c) {
1759488aa4cSDavid van Moolenbroek 		case 'd':
1769488aa4cSDavid van Moolenbroek 			debug++;
1779488aa4cSDavid van Moolenbroek 			break;
1789488aa4cSDavid van Moolenbroek 		case 'x':
1799488aa4cSDavid van Moolenbroek #define T(l)	(lock & ~LOCK_NB) != (l) && (lock & ~LOCK_NB) != 0
1809488aa4cSDavid van Moolenbroek 			if (T(LOCK_EX))
1819488aa4cSDavid van Moolenbroek 				goto badlock;
1829488aa4cSDavid van Moolenbroek 			lock |= LOCK_EX;
1839488aa4cSDavid van Moolenbroek 			break;
1849488aa4cSDavid van Moolenbroek 		case 'n':
1859488aa4cSDavid van Moolenbroek 			lock |= LOCK_NB;
1869488aa4cSDavid van Moolenbroek 			break;
1879488aa4cSDavid van Moolenbroek 		case 's':
1889488aa4cSDavid van Moolenbroek 			if (T(LOCK_SH))
1899488aa4cSDavid van Moolenbroek 				goto badlock;
1909488aa4cSDavid van Moolenbroek 			lock |= LOCK_SH;
1919488aa4cSDavid van Moolenbroek 			break;
1929488aa4cSDavid van Moolenbroek 		case 'u':
1939488aa4cSDavid van Moolenbroek 			if (T(LOCK_UN))
1949488aa4cSDavid van Moolenbroek 				goto badlock;
1959488aa4cSDavid van Moolenbroek 			lock |= LOCK_UN;
1969488aa4cSDavid van Moolenbroek 			break;
1979488aa4cSDavid van Moolenbroek 		case 'w':
1989488aa4cSDavid van Moolenbroek 			timeout = strtod(optarg, NULL);
1999488aa4cSDavid van Moolenbroek 			break;
2009488aa4cSDavid van Moolenbroek 		case 'v':
2019488aa4cSDavid van Moolenbroek 			verbose = 1;
2029488aa4cSDavid van Moolenbroek 			break;
2039488aa4cSDavid van Moolenbroek 		case 'o':
2049488aa4cSDavid van Moolenbroek 			cls = 1;
2059488aa4cSDavid van Moolenbroek 			break;
2069488aa4cSDavid van Moolenbroek 		default:
2079488aa4cSDavid van Moolenbroek 			usage("Invalid option '%c'", c);
2089488aa4cSDavid van Moolenbroek 		badlock:
2099488aa4cSDavid van Moolenbroek 			usage("-%c can't be used with -%c", c, lockchar(lock));
2109488aa4cSDavid van Moolenbroek 		}
2119488aa4cSDavid van Moolenbroek 
2129488aa4cSDavid van Moolenbroek 	argc -= optind;
2139488aa4cSDavid van Moolenbroek 	argv += optind;
2149488aa4cSDavid van Moolenbroek 
2159488aa4cSDavid van Moolenbroek 	if ((lock & ~LOCK_NB) == 0)
216*0a6a1f1dSLionel Sambuc 		lock |= LOCK_EX;	/* default to exclusive like linux */
2179488aa4cSDavid van Moolenbroek 
2189488aa4cSDavid van Moolenbroek 	switch (argc) {
2199488aa4cSDavid van Moolenbroek 	case 0:
2209488aa4cSDavid van Moolenbroek 		usage("Missing lock file argument");
2219488aa4cSDavid van Moolenbroek 	case 1:
2229488aa4cSDavid van Moolenbroek 		if (cls)
223*0a6a1f1dSLionel Sambuc 			usage("Close is not valid for descriptors");
224*0a6a1f1dSLionel Sambuc 		errno = 0;
225*0a6a1f1dSLionel Sambuc 		l = strtol(argv[0], &v, 0);
226*0a6a1f1dSLionel Sambuc 		if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE)
227*0a6a1f1dSLionel Sambuc 			err(EXIT_FAILURE, "Bad file descriptor `%s'", argv[0]);
228*0a6a1f1dSLionel Sambuc 		if (l > INT_MAX || l < 0 || *v)
229*0a6a1f1dSLionel Sambuc 			errx(EXIT_FAILURE, "Bad file descriptor `%s'", argv[0]);
230*0a6a1f1dSLionel Sambuc 		fd = (int)l;
2319488aa4cSDavid van Moolenbroek 		if (debug) {
2329488aa4cSDavid van Moolenbroek 			fprintf(stderr, "descriptor %s lock %s\n",
2339488aa4cSDavid van Moolenbroek 			    argv[0], lock2name(lock));
2349488aa4cSDavid van Moolenbroek 		}
2359488aa4cSDavid van Moolenbroek 		break;
2369488aa4cSDavid van Moolenbroek 
2379488aa4cSDavid van Moolenbroek 	default:
2389488aa4cSDavid van Moolenbroek 		if ((lock & LOCK_NB) == LOCK_UN)
2399488aa4cSDavid van Moolenbroek 			usage("Unlock is only valid for descriptors");
2409488aa4cSDavid van Moolenbroek 		if (strcmp(argv[1], "-c") == 0 ||
2419488aa4cSDavid van Moolenbroek 		    strcmp(argv[1], "--command") == 0) {
2429488aa4cSDavid van Moolenbroek 			if (argc == 2)
2439488aa4cSDavid van Moolenbroek 				usage("Missing argument to %s", strcmp(argv[1],
2449488aa4cSDavid van Moolenbroek 				    "-c") == 0 ? "-c" : "--command");
2459488aa4cSDavid van Moolenbroek 			mcargv[2] = argv[2];
2469488aa4cSDavid van Moolenbroek 			cmdargv = mcargv;
2479488aa4cSDavid van Moolenbroek 		} else
2489488aa4cSDavid van Moolenbroek 			cmdargv = argv + 1;
2499488aa4cSDavid van Moolenbroek 
2509488aa4cSDavid van Moolenbroek 		if ((fd = open(argv[0], O_RDONLY)) == -1) {
2519488aa4cSDavid van Moolenbroek 			if (errno != ENOENT ||
2529488aa4cSDavid van Moolenbroek 			    (fd = open(argv[0], O_RDWR|O_CREAT, 0600)) == -1)
2539488aa4cSDavid van Moolenbroek 				err(EXIT_FAILURE, "Cannot open `%s'", argv[0]);
2549488aa4cSDavid van Moolenbroek 		}
2559488aa4cSDavid van Moolenbroek 		if (debug) {
2569488aa4cSDavid van Moolenbroek 			fprintf(stderr, "file %s lock %s command %s ...\n",
2579488aa4cSDavid van Moolenbroek 			    argv[0], lock2name(lock), v = cmdline(cmdargv));
2589488aa4cSDavid van Moolenbroek 			free(v);
2599488aa4cSDavid van Moolenbroek 		}
2609488aa4cSDavid van Moolenbroek 		break;
2619488aa4cSDavid van Moolenbroek 	}
2629488aa4cSDavid van Moolenbroek 
2639488aa4cSDavid van Moolenbroek 	if (timeout) {
264*0a6a1f1dSLionel Sambuc #if !defined(__minix)
2659488aa4cSDavid van Moolenbroek 		struct sigevent ev;
2669488aa4cSDavid van Moolenbroek 		struct itimerspec it;
267*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
2689488aa4cSDavid van Moolenbroek 		struct sigaction sa;
2699488aa4cSDavid van Moolenbroek 
270*0a6a1f1dSLionel Sambuc #if !defined(__minix)
2719488aa4cSDavid van Moolenbroek 		timespecclear(&it.it_interval);
2729488aa4cSDavid van Moolenbroek 		it.it_value.tv_sec = timeout;
2739488aa4cSDavid van Moolenbroek 		it.it_value.tv_nsec = (timeout - it.it_value.tv_sec) *
2749488aa4cSDavid van Moolenbroek 			1000000000;
2759488aa4cSDavid van Moolenbroek 
2769488aa4cSDavid van Moolenbroek 		memset(&ev, 0, sizeof(ev));
2779488aa4cSDavid van Moolenbroek 		ev.sigev_notify = SIGEV_SIGNAL;
2789488aa4cSDavid van Moolenbroek 		ev.sigev_signo = SIGALRM;
2799488aa4cSDavid van Moolenbroek 
2809488aa4cSDavid van Moolenbroek 		if (timer_create(CLOCK_REALTIME, &ev, &tm) == -1)
2819488aa4cSDavid van Moolenbroek 			err(EXIT_FAILURE, "timer_create");
2829488aa4cSDavid van Moolenbroek 
2839488aa4cSDavid van Moolenbroek 		if (timer_settime(tm, TIMER_RELTIME, &it, NULL) == -1)
2849488aa4cSDavid van Moolenbroek 			err(EXIT_FAILURE, "timer_settime");
285*0a6a1f1dSLionel Sambuc #else
2869488aa4cSDavid van Moolenbroek 		memset(&it.it_interval, 0, sizeof(it.it_interval));
2879488aa4cSDavid van Moolenbroek 		it.it_value.tv_sec = timeout;
2889488aa4cSDavid van Moolenbroek 		it.it_value.tv_usec = (timeout - it.it_value.tv_sec) * 1000000;
2899488aa4cSDavid van Moolenbroek 
2909488aa4cSDavid van Moolenbroek 		if (setitimer(ITIMER_REAL, &it, NULL) == -1)
2919488aa4cSDavid van Moolenbroek 			err(EXIT_FAILURE, "setitimer");
2929488aa4cSDavid van Moolenbroek 
2939488aa4cSDavid van Moolenbroek 		memset(&it, 0, sizeof(it)); /* for the reset later */
294*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
2959488aa4cSDavid van Moolenbroek 
2969488aa4cSDavid van Moolenbroek 		memset(&sa, 0, sizeof(sa));
2979488aa4cSDavid van Moolenbroek 		sa.sa_handler = sigalrm;
2989488aa4cSDavid van Moolenbroek 		sigemptyset(&sa.sa_mask);
2999488aa4cSDavid van Moolenbroek 		sa.sa_flags = 0;
3009488aa4cSDavid van Moolenbroek 		if (sigaction(SIGALRM, &sa, NULL) == -1)
3019488aa4cSDavid van Moolenbroek 			err(EXIT_FAILURE, "sigaction");
3029488aa4cSDavid van Moolenbroek 
3039488aa4cSDavid van Moolenbroek 		if (debug)
3049488aa4cSDavid van Moolenbroek 			fprintf(stderr, "alarm %g\n", timeout);
3059488aa4cSDavid van Moolenbroek 	}
3069488aa4cSDavid van Moolenbroek 
3079488aa4cSDavid van Moolenbroek 	while (flock(fd, lock) == -1) {
3089488aa4cSDavid van Moolenbroek 		if (errno == EINTR && timeout_expired == 0)
3099488aa4cSDavid van Moolenbroek 			continue;
3109488aa4cSDavid van Moolenbroek 		if (verbose)
3119488aa4cSDavid van Moolenbroek 			err(EXIT_FAILURE, "flock(%d, %s)", fd, lock2name(lock));
3129488aa4cSDavid van Moolenbroek 		else
3139488aa4cSDavid van Moolenbroek 			return EXIT_FAILURE;
3149488aa4cSDavid van Moolenbroek 	}
3159488aa4cSDavid van Moolenbroek 
3169488aa4cSDavid van Moolenbroek 	if (timeout)
317*0a6a1f1dSLionel Sambuc #if !defined(__minix)
3189488aa4cSDavid van Moolenbroek 		timer_delete(tm);
319*0a6a1f1dSLionel Sambuc #else
3209488aa4cSDavid van Moolenbroek 		setitimer(ITIMER_REAL, &it, NULL);
321*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
3229488aa4cSDavid van Moolenbroek 
3239488aa4cSDavid van Moolenbroek 	if (cls)
3249488aa4cSDavid van Moolenbroek 		(void)close(fd);
3259488aa4cSDavid van Moolenbroek 
3269488aa4cSDavid van Moolenbroek 	if (cmdargv != NULL) {
3279488aa4cSDavid van Moolenbroek 		execvp(cmdargv[0], cmdargv);
3289488aa4cSDavid van Moolenbroek 		err(EXIT_FAILURE, "execvp '%s'", v = cmdline(cmdargv));
3299488aa4cSDavid van Moolenbroek 		free(v);
3309488aa4cSDavid van Moolenbroek 	}
3319488aa4cSDavid van Moolenbroek 	return 0;
3329488aa4cSDavid van Moolenbroek }
333