Import NetBSD flock(1)
Also fix the MINIX3 libc flock(3) implementation. Change-Id: Ia80280029968786d7f029940ec02e942057701bd
This commit is contained in:
		
							parent
							
								
									875abb8724
								
							
						
					
					
						commit
						9488aa4c04
					
				@ -331,6 +331,7 @@
 | 
			
		||||
./usr/bin/fix				minix-sys
 | 
			
		||||
./usr/bin/flex++			minix-sys
 | 
			
		||||
./usr/bin/flex				minix-sys
 | 
			
		||||
./usr/bin/flock				minix-sys
 | 
			
		||||
./usr/bin/fold				minix-sys
 | 
			
		||||
./usr/bin/format			minix-sys
 | 
			
		||||
./usr/bin/fpr				minix-sys
 | 
			
		||||
@ -2405,6 +2406,7 @@
 | 
			
		||||
./usr/man/man1/finger.1			minix-sys
 | 
			
		||||
./usr/man/man1/flex.1			minix-sys
 | 
			
		||||
./usr/man/man1/flexdoc.1		minix-sys
 | 
			
		||||
./usr/man/man1/flock.1			minix-sys
 | 
			
		||||
./usr/man/man1/fold.1			minix-sys
 | 
			
		||||
./usr/man/man1/for.1			minix-sys	obsolete
 | 
			
		||||
./usr/man/man1/format.1			minix-sys
 | 
			
		||||
 | 
			
		||||
@ -21,14 +21,15 @@
 | 
			
		||||
int flock(int fd, int mode)
 | 
			
		||||
{
 | 
			
		||||
  struct flock lck;
 | 
			
		||||
  register int retcode;
 | 
			
		||||
 | 
			
		||||
  memset((void *) &lck, 0, sizeof(struct flock));
 | 
			
		||||
  lck.l_type = mode & ~LOCK_NB;
 | 
			
		||||
  lck.l_pid = getpid();
 | 
			
		||||
  if ((retcode = fcntl(fd, mode & LOCK_NB ? F_SETLK : F_SETLKW, &lck)) < 0 && errno == EAGAIN)
 | 
			
		||||
	errno = EWOULDBLOCK;
 | 
			
		||||
  return retcode;
 | 
			
		||||
  switch (mode & ~LOCK_NB) {
 | 
			
		||||
  case LOCK_SH: lck.l_type = F_RDLCK; break;
 | 
			
		||||
  case LOCK_EX: lck.l_type = F_WRLCK; break;
 | 
			
		||||
  case LOCK_UN: lck.l_type = F_UNLCK; break;
 | 
			
		||||
  default: errno = EINVAL; return -1;
 | 
			
		||||
  }
 | 
			
		||||
  return fcntl(fd, mode & LOCK_NB ? F_SETLK : F_SETLKW, &lck);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** flock.c **/
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ SUBDIR= asa \
 | 
			
		||||
	column comm csplit ctags cut \
 | 
			
		||||
	deroff dirname du \
 | 
			
		||||
	env expand \
 | 
			
		||||
	false find finger fold fpr from \
 | 
			
		||||
	false find finger flock fold fpr from \
 | 
			
		||||
	fsplit ftp genassym getopt \
 | 
			
		||||
	head hexdump id indent infocmp join jot \
 | 
			
		||||
	lam last ldd leave \
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								usr.bin/flock/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								usr.bin/flock/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
#	$NetBSD: Makefile,v 1.1 2012/11/01 23:30:19 christos Exp $
 | 
			
		||||
#	@(#)Makefile	8.1 (Berkeley) 6/6/93
 | 
			
		||||
 | 
			
		||||
PROG=	flock
 | 
			
		||||
#LDADD+=	-lutil
 | 
			
		||||
#DPADD+=	${LIBUTIL}
 | 
			
		||||
 | 
			
		||||
.include <bsd.prog.mk>
 | 
			
		||||
							
								
								
									
										100
									
								
								usr.bin/flock/flock.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								usr.bin/flock/flock.1
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,100 @@
 | 
			
		||||
.\"	$NetBSD: flock.1,v 1.9 2013/09/21 15:01:14 khorben Exp $
 | 
			
		||||
.\"
 | 
			
		||||
.\" Copyright (c) 2012 The NetBSD Foundation, Inc.
 | 
			
		||||
.\" All rights reserved.
 | 
			
		||||
.\"
 | 
			
		||||
.\" This code is derived from software contributed to The NetBSD Foundation
 | 
			
		||||
.\" by Christos Zoulas.
 | 
			
		||||
.\"
 | 
			
		||||
.\" Redistribution and use in source and binary forms, with or without
 | 
			
		||||
.\" modification, are permitted provided that the following conditions
 | 
			
		||||
.\" are met:
 | 
			
		||||
.\" 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
.\"    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
.\" 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
.\"    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
.\"    documentation and/or other materials provided with the distribution.
 | 
			
		||||
.\"
 | 
			
		||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 | 
			
		||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 | 
			
		||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | 
			
		||||
.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 | 
			
		||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 | 
			
		||||
.\" POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
.\"
 | 
			
		||||
.\"
 | 
			
		||||
.Dd November 2, 2012
 | 
			
		||||
.Dt FLOCK 1
 | 
			
		||||
.Os
 | 
			
		||||
.Sh NAME
 | 
			
		||||
.Nm flock
 | 
			
		||||
.Nd Provide locking API for shell scripts
 | 
			
		||||
.Sh SYNOPSIS
 | 
			
		||||
.Nm
 | 
			
		||||
.Op Fl dnosvx
 | 
			
		||||
.Op Fl w Ar timeout
 | 
			
		||||
.Ar lockfile|lockdir
 | 
			
		||||
.Op Fl c Ar command
 | 
			
		||||
|
 | 
			
		||||
.Op Ar command ...
 | 
			
		||||
.Nm
 | 
			
		||||
.Op Fl dnsuvx
 | 
			
		||||
.Op Fl w Ar timeout
 | 
			
		||||
.Ar lockfd
 | 
			
		||||
.Sh DESCRIPTION
 | 
			
		||||
The
 | 
			
		||||
.Nm
 | 
			
		||||
utility provides
 | 
			
		||||
.Xr flock 2
 | 
			
		||||
access to the command line or scripts.
 | 
			
		||||
The first form locks a file or directory while the command provided is executed.
 | 
			
		||||
If the file or directory does not exist, then a file is created.
 | 
			
		||||
.Pp
 | 
			
		||||
The second form can use an arbitrary file descriptor that is provided from a
 | 
			
		||||
shell script for example:
 | 
			
		||||
.Bd -literal
 | 
			
		||||
(
 | 
			
		||||
	flock -s 100
 | 
			
		||||
	# commands to be executed under the lock
 | 
			
		||||
) 100> /path/to/lockfile
 | 
			
		||||
.Ed
 | 
			
		||||
.Pp
 | 
			
		||||
The following options are available:
 | 
			
		||||
.Bl -tag -width "XXXXXXXXXXXXXXXXX"
 | 
			
		||||
.It Fl c Ar command
 | 
			
		||||
Pass a command to a the shell.
 | 
			
		||||
.It Fl d , Fl Fl debug
 | 
			
		||||
Provide debugging output.
 | 
			
		||||
.It Fl n , Fl Fl nb , Fl Fl nonblock
 | 
			
		||||
Don't block and fail immediately if the lock could not be obtained.
 | 
			
		||||
.It Fl o , Fl Fl close
 | 
			
		||||
Close the file before executing the command.
 | 
			
		||||
This is useful if the child forks and should not be holding the lock.
 | 
			
		||||
.It Fl s , Fl Fl shared
 | 
			
		||||
Obtain a shared lock.
 | 
			
		||||
.It Fl u , Fl Fl unlock
 | 
			
		||||
Unlock an existing lock.
 | 
			
		||||
This is available only for a file descriptor.
 | 
			
		||||
.It Fl v , Fl Fl verbose
 | 
			
		||||
On error print an explanation of the failure.
 | 
			
		||||
.It Fl w , Fl Fl wait , Fl Fl timeout Ar seconds
 | 
			
		||||
Fail if the lock could not be obtained after
 | 
			
		||||
.Ar seconds .
 | 
			
		||||
.It Fl x , Fl Fl exclusive
 | 
			
		||||
Obtain an exclusive lock.
 | 
			
		||||
.El
 | 
			
		||||
.Sh EXIT STATUS
 | 
			
		||||
.Ex -std
 | 
			
		||||
.Sh SEE ALSO
 | 
			
		||||
.Xr shlock 1 ,
 | 
			
		||||
.Xr flock 2
 | 
			
		||||
.Sh HISTORY
 | 
			
		||||
An
 | 
			
		||||
.Nm
 | 
			
		||||
utility appeared in
 | 
			
		||||
.Nx 6.1 .
 | 
			
		||||
							
								
								
									
										324
									
								
								usr.bin/flock/flock.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										324
									
								
								usr.bin/flock/flock.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,324 @@
 | 
			
		||||
/*	$NetBSD: flock.c,v 1.8 2013/10/29 16:02:15 christos Exp $	*/
 | 
			
		||||
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright (c) 2012 The NetBSD Foundation, Inc.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This code is derived from software contributed to The NetBSD Foundation
 | 
			
		||||
 * by Christos Zoulas.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *    from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 | 
			
		||||
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 | 
			
		||||
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | 
			
		||||
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 | 
			
		||||
 * POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/cdefs.h>
 | 
			
		||||
__RCSID("$NetBSD: flock.c,v 1.8 2013/10/29 16:02:15 christos Exp $");
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <err.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
#include <paths.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
static struct option flock_longopts[] = {
 | 
			
		||||
	{ "debug",		no_argument,		0, 'd' },
 | 
			
		||||
	{ "help",		no_argument,		0, 'h' },
 | 
			
		||||
	{ "nonblock",		no_argument,		0, 'n' },
 | 
			
		||||
	{ "nb",			no_argument,		0, 'n' },
 | 
			
		||||
	{ "close",		no_argument,		0, 'o' },
 | 
			
		||||
	{ "shared",		no_argument,		0, 's' },
 | 
			
		||||
	{ "exclusive",		no_argument,		0, 'x' },
 | 
			
		||||
	{ "unlock",		no_argument,		0, 'u' },
 | 
			
		||||
	{ "verbose",		no_argument,		0, 'v' },
 | 
			
		||||
	{ "command",		required_argument,	0, 'c' },
 | 
			
		||||
	{ "wait",		required_argument,	0, 'w' },
 | 
			
		||||
	{ "timeout",		required_argument,	0, 'w' },
 | 
			
		||||
	{ NULL,			0,			0, 0   },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static sig_atomic_t timeout_expired;
 | 
			
		||||
 | 
			
		||||
static __dead void
 | 
			
		||||
usage(const char *fmt, ...) 
 | 
			
		||||
{
 | 
			
		||||
	if (fmt) {
 | 
			
		||||
		va_list ap;
 | 
			
		||||
		va_start(ap, fmt);
 | 
			
		||||
		fprintf(stderr, "%s: ", getprogname());
 | 
			
		||||
		vfprintf(stderr, fmt, ap);
 | 
			
		||||
		fputc('\n', stderr);
 | 
			
		||||
		va_end(ap);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fprintf(stderr, "Usage: %s [-dnosvx] [-w timeout] lockfile|lockdir "
 | 
			
		||||
	    "[-c command]|command ...\n\t%s [-dnsuvx] [-w timeout] lockfd\n",
 | 
			
		||||
	    getprogname(), getprogname());
 | 
			
		||||
	exit(EXIT_FAILURE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
sigalrm(int sig)
 | 
			
		||||
{
 | 
			
		||||
	timeout_expired++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *
 | 
			
		||||
lock2name(int l)
 | 
			
		||||
{
 | 
			
		||||
	static char buf[1024];
 | 
			
		||||
	int nb = l & LOCK_NB;
 | 
			
		||||
 | 
			
		||||
	l &= ~LOCK_NB;
 | 
			
		||||
	if (nb)
 | 
			
		||||
		strlcpy(buf, "LOCK_NB|", sizeof(buf));
 | 
			
		||||
	else
 | 
			
		||||
		buf[0] = '\0';
 | 
			
		||||
 | 
			
		||||
	switch (l) {
 | 
			
		||||
	case LOCK_SH:
 | 
			
		||||
		strlcat(buf, "LOCK_SH", sizeof(buf));
 | 
			
		||||
		return buf;
 | 
			
		||||
	case LOCK_EX:
 | 
			
		||||
		strlcat(buf, "LOCK_EX", sizeof(buf));
 | 
			
		||||
		return buf;
 | 
			
		||||
	case LOCK_UN:
 | 
			
		||||
		strlcat(buf, "LOCK_UN", sizeof(buf));
 | 
			
		||||
		return buf;
 | 
			
		||||
	default:
 | 
			
		||||
		snprintf(buf, sizeof(buf), "*%d*", l | nb);
 | 
			
		||||
		return buf;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char
 | 
			
		||||
lockchar(int l)
 | 
			
		||||
{
 | 
			
		||||
	switch (l & ~LOCK_NB) {
 | 
			
		||||
	case LOCK_SH:
 | 
			
		||||
		return 's';
 | 
			
		||||
	case LOCK_EX:
 | 
			
		||||
		return 'x';
 | 
			
		||||
	case LOCK_UN:
 | 
			
		||||
		return 'u';
 | 
			
		||||
	default:
 | 
			
		||||
		return '*';
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
cmdline(char **av)
 | 
			
		||||
{
 | 
			
		||||
	char *v = NULL;
 | 
			
		||||
	while (*av)
 | 
			
		||||
		if (v) {
 | 
			
		||||
			if (asprintf(&v, "%s %s", v, *av++) < 0)
 | 
			
		||||
				err(EXIT_FAILURE, "malloc");
 | 
			
		||||
		} else {
 | 
			
		||||
			if ((v = strdup(*av++)) == NULL)
 | 
			
		||||
				err(EXIT_FAILURE, "strdup");
 | 
			
		||||
		}
 | 
			
		||||
	return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	int c;
 | 
			
		||||
	int lock = 0;
 | 
			
		||||
	double timeout = 0;
 | 
			
		||||
	int cls = 0;
 | 
			
		||||
	int fd = -1;
 | 
			
		||||
	int debug = 0;
 | 
			
		||||
	int verbose = 0;
 | 
			
		||||
	char *mcargv[] = {
 | 
			
		||||
	    __UNCONST(_PATH_BSHELL), __UNCONST("-c"), NULL, NULL
 | 
			
		||||
	};
 | 
			
		||||
	char **cmdargv = NULL, *v;
 | 
			
		||||
#ifndef __minix
 | 
			
		||||
	timer_t tm;
 | 
			
		||||
#else /* __minix */
 | 
			
		||||
	struct itimerval it;
 | 
			
		||||
#endif /* __minix */
 | 
			
		||||
 | 
			
		||||
	setprogname(argv[0]);
 | 
			
		||||
 | 
			
		||||
	while ((c = getopt_long(argc, argv, "+dnosuvw:x", flock_longopts, NULL))
 | 
			
		||||
	    != -1)
 | 
			
		||||
		switch (c) {
 | 
			
		||||
		case 'd':
 | 
			
		||||
			debug++;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'x':
 | 
			
		||||
#define T(l)	(lock & ~LOCK_NB) != (l) && (lock & ~LOCK_NB) != 0
 | 
			
		||||
			if (T(LOCK_EX))
 | 
			
		||||
				goto badlock;
 | 
			
		||||
			lock |= LOCK_EX;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'n':
 | 
			
		||||
			lock |= LOCK_NB;
 | 
			
		||||
			break;
 | 
			
		||||
		case 's':
 | 
			
		||||
			if (T(LOCK_SH))
 | 
			
		||||
				goto badlock;
 | 
			
		||||
			lock |= LOCK_SH;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'u':
 | 
			
		||||
			if (T(LOCK_UN))
 | 
			
		||||
				goto badlock;
 | 
			
		||||
			lock |= LOCK_UN;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'w':
 | 
			
		||||
			timeout = strtod(optarg, NULL);
 | 
			
		||||
			break;
 | 
			
		||||
		case 'v':
 | 
			
		||||
			verbose = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'o':
 | 
			
		||||
			cls = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			usage("Invalid option '%c'", c);
 | 
			
		||||
		badlock:
 | 
			
		||||
			usage("-%c can't be used with -%c", c, lockchar(lock));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	argc -= optind;
 | 
			
		||||
	argv += optind;
 | 
			
		||||
 | 
			
		||||
	if ((lock & ~LOCK_NB) == 0)
 | 
			
		||||
		usage("Missing lock type flag");
 | 
			
		||||
 | 
			
		||||
	switch (argc) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		usage("Missing lock file argument");
 | 
			
		||||
	case 1:
 | 
			
		||||
		if (cls)
 | 
			
		||||
			usage("Close is valid only for descriptors");
 | 
			
		||||
		fd = strtol(argv[0], NULL, 0);	// XXX: error checking
 | 
			
		||||
		if (debug) {
 | 
			
		||||
			fprintf(stderr, "descriptor %s lock %s\n",
 | 
			
		||||
			    argv[0], lock2name(lock));
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		if ((lock & LOCK_NB) == LOCK_UN)
 | 
			
		||||
			usage("Unlock is only valid for descriptors");
 | 
			
		||||
		if (strcmp(argv[1], "-c") == 0 ||
 | 
			
		||||
		    strcmp(argv[1], "--command") == 0) {
 | 
			
		||||
			if (argc == 2)
 | 
			
		||||
				usage("Missing argument to %s", strcmp(argv[1],
 | 
			
		||||
				    "-c") == 0 ? "-c" : "--command");
 | 
			
		||||
			mcargv[2] = argv[2];
 | 
			
		||||
			cmdargv = mcargv;
 | 
			
		||||
		} else
 | 
			
		||||
			cmdargv = argv + 1;
 | 
			
		||||
			
 | 
			
		||||
		if ((fd = open(argv[0], O_RDONLY)) == -1) {
 | 
			
		||||
			if (errno != ENOENT || 
 | 
			
		||||
			    (fd = open(argv[0], O_RDWR|O_CREAT, 0600)) == -1)
 | 
			
		||||
				err(EXIT_FAILURE, "Cannot open `%s'", argv[0]);
 | 
			
		||||
		}
 | 
			
		||||
		if (debug) {
 | 
			
		||||
			fprintf(stderr, "file %s lock %s command %s ...\n",
 | 
			
		||||
			    argv[0], lock2name(lock), v = cmdline(cmdargv));
 | 
			
		||||
			free(v);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (timeout) {
 | 
			
		||||
#ifndef __minix
 | 
			
		||||
		struct sigevent ev;
 | 
			
		||||
		struct itimerspec it;
 | 
			
		||||
#endif /* !__minix */
 | 
			
		||||
		struct sigaction sa;
 | 
			
		||||
 | 
			
		||||
#ifndef __minix
 | 
			
		||||
		timespecclear(&it.it_interval);
 | 
			
		||||
		it.it_value.tv_sec = timeout;
 | 
			
		||||
		it.it_value.tv_nsec = (timeout - it.it_value.tv_sec) *
 | 
			
		||||
			1000000000;
 | 
			
		||||
 | 
			
		||||
		memset(&ev, 0, sizeof(ev));
 | 
			
		||||
		ev.sigev_notify = SIGEV_SIGNAL;
 | 
			
		||||
		ev.sigev_signo = SIGALRM;
 | 
			
		||||
 | 
			
		||||
		if (timer_create(CLOCK_REALTIME, &ev, &tm) == -1)
 | 
			
		||||
			err(EXIT_FAILURE, "timer_create");
 | 
			
		||||
 | 
			
		||||
		if (timer_settime(tm, TIMER_RELTIME, &it, NULL) == -1)
 | 
			
		||||
			err(EXIT_FAILURE, "timer_settime");
 | 
			
		||||
#else /* __minix */
 | 
			
		||||
		memset(&it.it_interval, 0, sizeof(it.it_interval));
 | 
			
		||||
		it.it_value.tv_sec = timeout;
 | 
			
		||||
		it.it_value.tv_usec = (timeout - it.it_value.tv_sec) * 1000000;
 | 
			
		||||
 | 
			
		||||
		if (setitimer(ITIMER_REAL, &it, NULL) == -1)
 | 
			
		||||
			err(EXIT_FAILURE, "setitimer");
 | 
			
		||||
 | 
			
		||||
		memset(&it, 0, sizeof(it)); /* for the reset later */
 | 
			
		||||
#endif /* __minix */
 | 
			
		||||
 | 
			
		||||
		memset(&sa, 0, sizeof(sa));
 | 
			
		||||
		sa.sa_handler = sigalrm;
 | 
			
		||||
		sigemptyset(&sa.sa_mask);
 | 
			
		||||
		sa.sa_flags = 0;
 | 
			
		||||
		if (sigaction(SIGALRM, &sa, NULL) == -1)
 | 
			
		||||
			err(EXIT_FAILURE, "sigaction");
 | 
			
		||||
 | 
			
		||||
		if (debug)
 | 
			
		||||
			fprintf(stderr, "alarm %g\n", timeout);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while (flock(fd, lock) == -1) {
 | 
			
		||||
		if (errno == EINTR && timeout_expired == 0)
 | 
			
		||||
			continue;
 | 
			
		||||
		if (verbose)
 | 
			
		||||
			err(EXIT_FAILURE, "flock(%d, %s)", fd, lock2name(lock));
 | 
			
		||||
		else
 | 
			
		||||
			return EXIT_FAILURE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (timeout)
 | 
			
		||||
#ifndef __minix
 | 
			
		||||
		timer_delete(tm);
 | 
			
		||||
#else /* __minix */
 | 
			
		||||
		setitimer(ITIMER_REAL, &it, NULL);
 | 
			
		||||
#endif /* __minix */
 | 
			
		||||
 | 
			
		||||
	if (cls)
 | 
			
		||||
		(void)close(fd);
 | 
			
		||||
 | 
			
		||||
	if (cmdargv != NULL) {
 | 
			
		||||
		execvp(cmdargv[0], cmdargv);
 | 
			
		||||
		err(EXIT_FAILURE, "execvp '%s'", v = cmdline(cmdargv));
 | 
			
		||||
		free(v);
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user