xref: /freebsd/contrib/sendmail/libsmutil/t-lockfile.c (revision d39bd2c1388b520fcba9abed1932acacead60fba)
12fb4f839SGregory Neil Shapiro /*
22fb4f839SGregory Neil Shapiro  * Copyright (c) 2005 Proofpoint, Inc. and its suppliers.
32fb4f839SGregory Neil Shapiro  *	All rights reserved.
42fb4f839SGregory Neil Shapiro  *
52fb4f839SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
62fb4f839SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
72fb4f839SGregory Neil Shapiro  * the sendmail distribution.
82fb4f839SGregory Neil Shapiro  *
92fb4f839SGregory Neil Shapiro  */
102fb4f839SGregory Neil Shapiro 
112fb4f839SGregory Neil Shapiro #include <sm/gen.h>
122fb4f839SGregory Neil Shapiro SM_IDSTR(id, "@(#)$Id: t-lockfile.c,v 1.2 2013-11-22 20:51:50 ca Exp $")
132fb4f839SGregory Neil Shapiro #include <stdlib.h>
142fb4f839SGregory Neil Shapiro #include <stdio.h>
152fb4f839SGregory Neil Shapiro #include <sendmail.h>
162fb4f839SGregory Neil Shapiro 
172fb4f839SGregory Neil Shapiro #define IOBUFSZ	64
182fb4f839SGregory Neil Shapiro char iobuf[IOBUFSZ];
192fb4f839SGregory Neil Shapiro #define FIRSTLINE	"first line\n"
202fb4f839SGregory Neil Shapiro #define LASTLINE	"last line\n"
212fb4f839SGregory Neil Shapiro static int noio, chk;
222fb4f839SGregory Neil Shapiro static pid_t pid;
232fb4f839SGregory Neil Shapiro 
24*d39bd2c1SGregory Neil Shapiro /*
25*d39bd2c1SGregory Neil Shapiro **  OPENFILE -- open a file
26*d39bd2c1SGregory Neil Shapiro **
27*d39bd2c1SGregory Neil Shapiro **	Parameters:
28*d39bd2c1SGregory Neil Shapiro **		owner -- create file?
29*d39bd2c1SGregory Neil Shapiro **		filename -- name of file.
30*d39bd2c1SGregory Neil Shapiro **		flags -- flags for open(2)
31*d39bd2c1SGregory Neil Shapiro **
32*d39bd2c1SGregory Neil Shapiro **	Returns:
33*d39bd2c1SGregory Neil Shapiro **		>=0 fd
34*d39bd2c1SGregory Neil Shapiro **		<0 on failure.
35*d39bd2c1SGregory Neil Shapiro */
36*d39bd2c1SGregory Neil Shapiro 
37*d39bd2c1SGregory Neil Shapiro static int
openfile(owner,filename,flags)382fb4f839SGregory Neil Shapiro openfile(owner, filename, flags)
392fb4f839SGregory Neil Shapiro 	int owner;
402fb4f839SGregory Neil Shapiro 	char *filename;
412fb4f839SGregory Neil Shapiro 	int flags;
422fb4f839SGregory Neil Shapiro {
432fb4f839SGregory Neil Shapiro 	int fd;
442fb4f839SGregory Neil Shapiro 
452fb4f839SGregory Neil Shapiro 	if (owner)
462fb4f839SGregory Neil Shapiro 		flags |= O_CREAT;
472fb4f839SGregory Neil Shapiro 	fd = open(filename, flags, 0640);
482fb4f839SGregory Neil Shapiro 	if (fd >= 0)
492fb4f839SGregory Neil Shapiro 		return fd;
502fb4f839SGregory Neil Shapiro 	fprintf(stderr, "%d: %ld: owner=%d, open(%s) failed\n",
512fb4f839SGregory Neil Shapiro 		(int) pid, (long) time(NULL), owner, filename);
52*d39bd2c1SGregory Neil Shapiro 	return -1;
532fb4f839SGregory Neil Shapiro }
542fb4f839SGregory Neil Shapiro 
55*d39bd2c1SGregory Neil Shapiro /*
56*d39bd2c1SGregory Neil Shapiro **  WRBUF -- write iobuf to fd
57*d39bd2c1SGregory Neil Shapiro **
58*d39bd2c1SGregory Neil Shapiro **	Parameters:
59*d39bd2c1SGregory Neil Shapiro **		fd -- file descriptor.
60*d39bd2c1SGregory Neil Shapiro **
61*d39bd2c1SGregory Neil Shapiro **	Returns:
62*d39bd2c1SGregory Neil Shapiro **		==0 write was ok
63*d39bd2c1SGregory Neil Shapiro **		!=0 on failure.
64*d39bd2c1SGregory Neil Shapiro */
65*d39bd2c1SGregory Neil Shapiro 
66*d39bd2c1SGregory Neil Shapiro static int
wrbuf(fd)672fb4f839SGregory Neil Shapiro wrbuf(fd)
682fb4f839SGregory Neil Shapiro 	int fd;
692fb4f839SGregory Neil Shapiro {
702fb4f839SGregory Neil Shapiro 	int r;
712fb4f839SGregory Neil Shapiro 
722fb4f839SGregory Neil Shapiro 	if (noio)
732fb4f839SGregory Neil Shapiro 		return 0;
742fb4f839SGregory Neil Shapiro 	r = write(fd, iobuf, sizeof(iobuf));
752fb4f839SGregory Neil Shapiro 	if (sizeof(iobuf) == r)
762fb4f839SGregory Neil Shapiro 		return 0;
772fb4f839SGregory Neil Shapiro 	fprintf(stderr, "%d: %ld: owner=1, write(%s)=fail\n",
782fb4f839SGregory Neil Shapiro 		(int) pid, (long) time(NULL), iobuf);
792fb4f839SGregory Neil Shapiro 	return 1;
802fb4f839SGregory Neil Shapiro }
812fb4f839SGregory Neil Shapiro 
82*d39bd2c1SGregory Neil Shapiro /*
83*d39bd2c1SGregory Neil Shapiro **  RDBUF -- read from fd
84*d39bd2c1SGregory Neil Shapiro **
85*d39bd2c1SGregory Neil Shapiro **	Parameters:
86*d39bd2c1SGregory Neil Shapiro **		fd -- file descriptor.
87*d39bd2c1SGregory Neil Shapiro **		xbuf -- expected content.
88*d39bd2c1SGregory Neil Shapiro **
89*d39bd2c1SGregory Neil Shapiro **	Returns:
90*d39bd2c1SGregory Neil Shapiro **		==0 read was ok and content matches
91*d39bd2c1SGregory Neil Shapiro **		!=0 otherwise
92*d39bd2c1SGregory Neil Shapiro */
93*d39bd2c1SGregory Neil Shapiro 
94*d39bd2c1SGregory Neil Shapiro static int
rdbuf(fd,xbuf)952fb4f839SGregory Neil Shapiro rdbuf(fd, xbuf)
962fb4f839SGregory Neil Shapiro 	int fd;
972fb4f839SGregory Neil Shapiro 	const char *xbuf;
982fb4f839SGregory Neil Shapiro {
992fb4f839SGregory Neil Shapiro 	int r;
1002fb4f839SGregory Neil Shapiro 
1012fb4f839SGregory Neil Shapiro 	if (noio)
1022fb4f839SGregory Neil Shapiro 		return 0;
1032fb4f839SGregory Neil Shapiro 	r = read(fd, iobuf, sizeof(iobuf));
1042fb4f839SGregory Neil Shapiro 	if (sizeof(iobuf) != r)
1052fb4f839SGregory Neil Shapiro 	{
1062fb4f839SGregory Neil Shapiro 		fprintf(stderr, "%d: %ld: owner=0, read()=fail\n",
1072fb4f839SGregory Neil Shapiro 			(int) pid, (long) time(NULL));
1082fb4f839SGregory Neil Shapiro 		return 1;
1092fb4f839SGregory Neil Shapiro 	}
1102fb4f839SGregory Neil Shapiro 	if (strncmp(iobuf, xbuf, strlen(xbuf)))
1112fb4f839SGregory Neil Shapiro 	{
1122fb4f839SGregory Neil Shapiro 		fprintf(stderr, "%d: %ld: owner=0, read=%s expected=%s\n",
1132fb4f839SGregory Neil Shapiro 			(int) pid, (long) time(NULL), iobuf, xbuf);
1142fb4f839SGregory Neil Shapiro 		return 1;
1152fb4f839SGregory Neil Shapiro 	}
1162fb4f839SGregory Neil Shapiro 	return 0;
1172fb4f839SGregory Neil Shapiro }
1182fb4f839SGregory Neil Shapiro 
1192fb4f839SGregory Neil Shapiro /*
120*d39bd2c1SGregory Neil Shapiro **  LOCKTESTWR -- test WR/EX file locking
1212fb4f839SGregory Neil Shapiro **
1222fb4f839SGregory Neil Shapiro **	Parameters:
1232fb4f839SGregory Neil Shapiro **		owner -- create file?
1242fb4f839SGregory Neil Shapiro **		filename -- name of file.
1252fb4f839SGregory Neil Shapiro **		flags -- flags for open(2)
1262fb4f839SGregory Neil Shapiro **		delay -- how long to keep file locked?
1272fb4f839SGregory Neil Shapiro **
1282fb4f839SGregory Neil Shapiro **	Returns:
1292fb4f839SGregory Neil Shapiro **		0 on success
1302fb4f839SGregory Neil Shapiro **		!= 0 on failure.
1312fb4f839SGregory Neil Shapiro */
1322fb4f839SGregory Neil Shapiro 
1332fb4f839SGregory Neil Shapiro #define DBGPRINTR(str)	\
1342fb4f839SGregory Neil Shapiro 	do	\
1352fb4f839SGregory Neil Shapiro 	{	\
1362fb4f839SGregory Neil Shapiro 		fprintf(stderr, "%d: %ld: owner=0, ", (int) pid,	\
1372fb4f839SGregory Neil Shapiro 			(long) time(NULL));	\
1382fb4f839SGregory Neil Shapiro 		fprintf(stderr, str, filename, shared ? "RD" : "EX");	\
1392fb4f839SGregory Neil Shapiro 	} while (0)
1402fb4f839SGregory Neil Shapiro 
141*d39bd2c1SGregory Neil Shapiro static int
locktestwr(filename,flags,delay)1422fb4f839SGregory Neil Shapiro locktestwr(filename, flags, delay)
1432fb4f839SGregory Neil Shapiro 	char *filename;
1442fb4f839SGregory Neil Shapiro 	int flags;
1452fb4f839SGregory Neil Shapiro 	int delay;
1462fb4f839SGregory Neil Shapiro {
1472fb4f839SGregory Neil Shapiro 	int fd;
1482fb4f839SGregory Neil Shapiro 	bool locked;
1492fb4f839SGregory Neil Shapiro 
1502fb4f839SGregory Neil Shapiro 	fd = openfile(1, filename, flags);
1512fb4f839SGregory Neil Shapiro 	if (fd < 0)
1522fb4f839SGregory Neil Shapiro 		return errno;
1532fb4f839SGregory Neil Shapiro 	locked = lockfile(fd, filename, "[owner]", LOCK_EX);
1542fb4f839SGregory Neil Shapiro 	if (!locked)
1552fb4f839SGregory Neil Shapiro 	{
1562fb4f839SGregory Neil Shapiro 		fprintf(stderr, "%d: %ld: owner=1, lock(%s) failed\n",
1572fb4f839SGregory Neil Shapiro 			(int) pid, (long) time(NULL), filename);
1582fb4f839SGregory Neil Shapiro 		return 1;
1592fb4f839SGregory Neil Shapiro 	}
1602fb4f839SGregory Neil Shapiro 	else
1612fb4f839SGregory Neil Shapiro 		fprintf(stderr, "%d: %ld: owner=1, lock(%s) ok\n",
1622fb4f839SGregory Neil Shapiro 			(int) pid, (long) time(NULL), filename);
1632fb4f839SGregory Neil Shapiro 
1642fb4f839SGregory Neil Shapiro 	sm_strlcpy(iobuf, FIRSTLINE, sizeof(iobuf));
1652fb4f839SGregory Neil Shapiro 	if (wrbuf(fd))
1662fb4f839SGregory Neil Shapiro 		return 1;
167*d39bd2c1SGregory Neil Shapiro 	if (delay > 0)
1682fb4f839SGregory Neil Shapiro 		sleep(delay);
1692fb4f839SGregory Neil Shapiro 	sm_strlcpy(iobuf, LASTLINE, sizeof(iobuf));
1702fb4f839SGregory Neil Shapiro 	if (wrbuf(fd))
1712fb4f839SGregory Neil Shapiro 		return 1;
1722fb4f839SGregory Neil Shapiro 	locked = lockfile(fd, filename, "[owner]", LOCK_UN);
1732fb4f839SGregory Neil Shapiro 	if (!locked)
1742fb4f839SGregory Neil Shapiro 	{
1752fb4f839SGregory Neil Shapiro 		fprintf(stderr, "%d: %ld: owner=1, unlock(%s) failed\n",
1762fb4f839SGregory Neil Shapiro 			(int) pid, (long) time(NULL), filename);
1772fb4f839SGregory Neil Shapiro 		return 1;
1782fb4f839SGregory Neil Shapiro 	}
1792fb4f839SGregory Neil Shapiro 	fprintf(stderr, "%d: %ld: owner=1, unlock(%s) done\n",
1802fb4f839SGregory Neil Shapiro 		(int) pid, (long) time(NULL), filename);
1812fb4f839SGregory Neil Shapiro 	if (fd > 0)
1822fb4f839SGregory Neil Shapiro 	{
1832fb4f839SGregory Neil Shapiro 		close(fd);
1842fb4f839SGregory Neil Shapiro 		fd = -1;
1852fb4f839SGregory Neil Shapiro 	}
1862fb4f839SGregory Neil Shapiro 	return 0;
1872fb4f839SGregory Neil Shapiro }
1882fb4f839SGregory Neil Shapiro 
189*d39bd2c1SGregory Neil Shapiro /*
190*d39bd2c1SGregory Neil Shapiro **  CHKLCK -- check whether fd is locked (only for fcntl())
191*d39bd2c1SGregory Neil Shapiro **
192*d39bd2c1SGregory Neil Shapiro **	Parameters:
193*d39bd2c1SGregory Neil Shapiro **		owner -- create file?
194*d39bd2c1SGregory Neil Shapiro **		filename -- name of file.
195*d39bd2c1SGregory Neil Shapiro **		flags -- flags for open(2)
196*d39bd2c1SGregory Neil Shapiro **		delay -- how long to keep file locked?
197*d39bd2c1SGregory Neil Shapiro **
198*d39bd2c1SGregory Neil Shapiro **	Returns:
199*d39bd2c1SGregory Neil Shapiro **		0 if not locked
200*d39bd2c1SGregory Neil Shapiro **		>0 pid of process which holds a WR lock
201*d39bd2c1SGregory Neil Shapiro **		<0 error
202*d39bd2c1SGregory Neil Shapiro */
203*d39bd2c1SGregory Neil Shapiro 
204*d39bd2c1SGregory Neil Shapiro static long
chklck(fd)2052fb4f839SGregory Neil Shapiro chklck(fd)
2062fb4f839SGregory Neil Shapiro 	int fd;
2072fb4f839SGregory Neil Shapiro {
2082fb4f839SGregory Neil Shapiro #if !HASFLOCK
2092fb4f839SGregory Neil Shapiro 	int action, i;
2102fb4f839SGregory Neil Shapiro 	struct flock lfd;
2112fb4f839SGregory Neil Shapiro 
2122fb4f839SGregory Neil Shapiro 	(void) memset(&lfd, '\0', sizeof lfd);
2132fb4f839SGregory Neil Shapiro 	lfd.l_type = F_RDLCK;
2142fb4f839SGregory Neil Shapiro 	action = F_GETLK;
2152fb4f839SGregory Neil Shapiro 	while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR)
2162fb4f839SGregory Neil Shapiro 		continue;
2172fb4f839SGregory Neil Shapiro 	if (i < 0)
2182fb4f839SGregory Neil Shapiro 		return (long)i;
2192fb4f839SGregory Neil Shapiro 	if (F_WRLCK == lfd.l_type)
2202fb4f839SGregory Neil Shapiro 		return (long)lfd.l_pid;
2212fb4f839SGregory Neil Shapiro 	return 0L;
2222fb4f839SGregory Neil Shapiro #else /* !HASFLOCK */
223*d39bd2c1SGregory Neil Shapiro 	fprintf(stderr, "%d: %ld: flock(): no lock test\n",
2242fb4f839SGregory Neil Shapiro 		(int) pid, (long) time(NULL));
2252fb4f839SGregory Neil Shapiro 	return -1L;
2262fb4f839SGregory Neil Shapiro #endif /* !HASFLOCK */
2272fb4f839SGregory Neil Shapiro }
2282fb4f839SGregory Neil Shapiro 
229*d39bd2c1SGregory Neil Shapiro /*
230*d39bd2c1SGregory Neil Shapiro **  LOCKTESTRD -- test file locking for reading
231*d39bd2c1SGregory Neil Shapiro **
232*d39bd2c1SGregory Neil Shapiro **	Parameters:
233*d39bd2c1SGregory Neil Shapiro **		filename -- name of file.
234*d39bd2c1SGregory Neil Shapiro **		flags -- flags for open(2)
235*d39bd2c1SGregory Neil Shapiro **		delay -- how long is file locked by owner?
236*d39bd2c1SGregory Neil Shapiro **		shared -- LOCK_{EX/SH}
237*d39bd2c1SGregory Neil Shapiro **
238*d39bd2c1SGregory Neil Shapiro **	Returns:
239*d39bd2c1SGregory Neil Shapiro **		0 on success
240*d39bd2c1SGregory Neil Shapiro **		!= 0 on failure.
241*d39bd2c1SGregory Neil Shapiro */
242*d39bd2c1SGregory Neil Shapiro 
243*d39bd2c1SGregory Neil Shapiro static int
locktestrd(filename,flags,delay,shared)2442fb4f839SGregory Neil Shapiro locktestrd(filename, flags, delay, shared)
2452fb4f839SGregory Neil Shapiro 	char *filename;
2462fb4f839SGregory Neil Shapiro 	int flags;
2472fb4f839SGregory Neil Shapiro 	int delay;
2482fb4f839SGregory Neil Shapiro 	int shared;
2492fb4f839SGregory Neil Shapiro {
2502fb4f839SGregory Neil Shapiro 	int fd, cnt;
2512fb4f839SGregory Neil Shapiro 	int lt;
2522fb4f839SGregory Neil Shapiro 	bool locked;
2532fb4f839SGregory Neil Shapiro 
2542fb4f839SGregory Neil Shapiro 	fd = openfile(0, filename, flags);
2552fb4f839SGregory Neil Shapiro 	if (fd < 0)
2562fb4f839SGregory Neil Shapiro 		return errno;
2572fb4f839SGregory Neil Shapiro 	if (chk)
2582fb4f839SGregory Neil Shapiro 	{
2592fb4f839SGregory Neil Shapiro 		long locked;
2602fb4f839SGregory Neil Shapiro 
2612fb4f839SGregory Neil Shapiro 		locked = chklck(fd);
2622fb4f839SGregory Neil Shapiro 		if (locked > 0)
2632fb4f839SGregory Neil Shapiro 			fprintf(stderr, "%d: %ld: file=%s status=locked pid=%ld\n",
2642fb4f839SGregory Neil Shapiro 				 (int) pid, (long) time(NULL), filename, locked);
2652fb4f839SGregory Neil Shapiro 		else if (0 == locked)
2662fb4f839SGregory Neil Shapiro 			fprintf(stderr, "%d: %ld: file=%s status=not_locked\n",
2672fb4f839SGregory Neil Shapiro 				 (int) pid, (long) time(NULL), filename);
2682fb4f839SGregory Neil Shapiro 		else
2692fb4f839SGregory Neil Shapiro 			fprintf(stderr, "%d: %ld: file=%s status=unknown\n",
2702fb4f839SGregory Neil Shapiro 				 (int) pid, (long) time(NULL), filename);
2712fb4f839SGregory Neil Shapiro 		goto end;
2722fb4f839SGregory Neil Shapiro 	}
2732fb4f839SGregory Neil Shapiro 
2742fb4f839SGregory Neil Shapiro 	if (shared)
2752fb4f839SGregory Neil Shapiro 		lt = LOCK_SH;
2762fb4f839SGregory Neil Shapiro 	else
2772fb4f839SGregory Neil Shapiro 		lt = LOCK_EX;
2782fb4f839SGregory Neil Shapiro 
2792fb4f839SGregory Neil Shapiro 	for (cnt = 0; cnt < delay - 2; cnt++)
2802fb4f839SGregory Neil Shapiro 	{
2812fb4f839SGregory Neil Shapiro 		/* try to get lock: should fail (nonblocking) */
2822fb4f839SGregory Neil Shapiro 		locked = lockfile(fd, filename, "[client]", lt|LOCK_NB);
2832fb4f839SGregory Neil Shapiro 		if (locked)
2842fb4f839SGregory Neil Shapiro 		{
2852fb4f839SGregory Neil Shapiro 			DBGPRINTR("lock(%s)=%s succeeded\n");
2862fb4f839SGregory Neil Shapiro 			return 1;
2872fb4f839SGregory Neil Shapiro 		}
2882fb4f839SGregory Neil Shapiro 		sleep(1);
2892fb4f839SGregory Neil Shapiro 	}
2902fb4f839SGregory Neil Shapiro 	if (delay > 0)
2912fb4f839SGregory Neil Shapiro 		sleep(2);
2922fb4f839SGregory Neil Shapiro 	locked = lockfile(fd, filename, "[client]", lt);
2932fb4f839SGregory Neil Shapiro 	if (!locked)
2942fb4f839SGregory Neil Shapiro 	{
2952fb4f839SGregory Neil Shapiro 		DBGPRINTR("lock(%s)=%s failed\n");
2962fb4f839SGregory Neil Shapiro 		return 1;
2972fb4f839SGregory Neil Shapiro 	}
2982fb4f839SGregory Neil Shapiro 	DBGPRINTR("lock(%s)=%s ok\n");
2992fb4f839SGregory Neil Shapiro 	if (rdbuf(fd, FIRSTLINE))
3002fb4f839SGregory Neil Shapiro 		return 1;
3012fb4f839SGregory Neil Shapiro 	if (rdbuf(fd, LASTLINE))
3022fb4f839SGregory Neil Shapiro 		return 1;
3032fb4f839SGregory Neil Shapiro 	sleep(1);
3042fb4f839SGregory Neil Shapiro 	locked = lockfile(fd, filename, "[client]", LOCK_UN);
3052fb4f839SGregory Neil Shapiro 	if (!locked)
3062fb4f839SGregory Neil Shapiro 	{
3072fb4f839SGregory Neil Shapiro 		DBGPRINTR("unlock(%s)=%s failed\n");
3082fb4f839SGregory Neil Shapiro 		return 1;
3092fb4f839SGregory Neil Shapiro 	}
3102fb4f839SGregory Neil Shapiro 	DBGPRINTR("unlock(%s)=%s done\n");
3112fb4f839SGregory Neil Shapiro 
3122fb4f839SGregory Neil Shapiro   end:
3132fb4f839SGregory Neil Shapiro 	if (fd > 0)
3142fb4f839SGregory Neil Shapiro 	{
3152fb4f839SGregory Neil Shapiro 		close(fd);
3162fb4f839SGregory Neil Shapiro 		fd = -1;
3172fb4f839SGregory Neil Shapiro 	}
3182fb4f839SGregory Neil Shapiro 	return 0;
3192fb4f839SGregory Neil Shapiro }
3202fb4f839SGregory Neil Shapiro 
321*d39bd2c1SGregory Neil Shapiro /*
322*d39bd2c1SGregory Neil Shapiro **  USAGE -- show usage
323*d39bd2c1SGregory Neil Shapiro **
324*d39bd2c1SGregory Neil Shapiro **	Parameters:
325*d39bd2c1SGregory Neil Shapiro **		prg -- name of program
326*d39bd2c1SGregory Neil Shapiro **
327*d39bd2c1SGregory Neil Shapiro **	Returns:
328*d39bd2c1SGregory Neil Shapiro **		nothing.
329*d39bd2c1SGregory Neil Shapiro */
330*d39bd2c1SGregory Neil Shapiro 
3312fb4f839SGregory Neil Shapiro static void
usage(prg)3322fb4f839SGregory Neil Shapiro usage(prg)
3332fb4f839SGregory Neil Shapiro 	const char *prg;
3342fb4f839SGregory Neil Shapiro {
3352fb4f839SGregory Neil Shapiro 	fprintf(stderr, "usage: %s [options]\n"
3362fb4f839SGregory Neil Shapiro 		"-f filename	use filename\n"
3372fb4f839SGregory Neil Shapiro 		"-i		do not perform I/O\n"
3382fb4f839SGregory Neil Shapiro 		"-n		do not try non-blocking locking first\n"
3392fb4f839SGregory Neil Shapiro 		"-R		only start reader process\n"
3402fb4f839SGregory Neil Shapiro 		"-r		use shared locking for reader\n"
3412fb4f839SGregory Neil Shapiro 		"-s delay	sleep delay seconds before unlocking\n"
3422fb4f839SGregory Neil Shapiro 		"-W		only start writer process\n"
343*d39bd2c1SGregory Neil Shapiro #if !HASFLOCK
344*d39bd2c1SGregory Neil Shapiro 		"uses fcntl()\n"
345*d39bd2c1SGregory Neil Shapiro #else
346*d39bd2c1SGregory Neil Shapiro 		"uses flock()\n"
347*d39bd2c1SGregory Neil Shapiro #endif
348*d39bd2c1SGregory Neil Shapiro 
3492fb4f839SGregory Neil Shapiro 		, prg);
3502fb4f839SGregory Neil Shapiro }
3512fb4f839SGregory Neil Shapiro 
3522fb4f839SGregory Neil Shapiro int
main(argc,argv)3532fb4f839SGregory Neil Shapiro main(argc, argv)
3542fb4f839SGregory Neil Shapiro 	int argc;
3552fb4f839SGregory Neil Shapiro 	char *argv[];
3562fb4f839SGregory Neil Shapiro {
3572fb4f839SGregory Neil Shapiro 	int ch, delay, r, status, flags, shared, nb, reader, writer;
3582fb4f839SGregory Neil Shapiro 	char *filename;
3592fb4f839SGregory Neil Shapiro 	pid_t fpid;
3602fb4f839SGregory Neil Shapiro 	extern char *optarg;
3612fb4f839SGregory Neil Shapiro 
3622fb4f839SGregory Neil Shapiro 	delay = 5;
3632fb4f839SGregory Neil Shapiro 	filename = "testlock";
3642fb4f839SGregory Neil Shapiro 	flags = O_RDWR;
3652fb4f839SGregory Neil Shapiro 	shared = nb = noio = reader = writer = chk = 0;
3662fb4f839SGregory Neil Shapiro #define OPTIONS	"cf:inRrs:W"
3672fb4f839SGregory Neil Shapiro 	while ((ch = getopt(argc, argv, OPTIONS)) != -1)
3682fb4f839SGregory Neil Shapiro 	{
3692fb4f839SGregory Neil Shapiro 		switch ((char) ch)
3702fb4f839SGregory Neil Shapiro 		{
3712fb4f839SGregory Neil Shapiro 		  case 'c':
3722fb4f839SGregory Neil Shapiro 			chk = 1;
3732fb4f839SGregory Neil Shapiro 			break;
3742fb4f839SGregory Neil Shapiro 
3752fb4f839SGregory Neil Shapiro 		  case 'f':
3762fb4f839SGregory Neil Shapiro 			filename = optarg;
3772fb4f839SGregory Neil Shapiro 			break;
3782fb4f839SGregory Neil Shapiro 
3792fb4f839SGregory Neil Shapiro 		  case 'i':
3802fb4f839SGregory Neil Shapiro 			noio = 1;
3812fb4f839SGregory Neil Shapiro 			break;
3822fb4f839SGregory Neil Shapiro 
3832fb4f839SGregory Neil Shapiro 		  case 'n':
3842fb4f839SGregory Neil Shapiro 			nb = 0;
3852fb4f839SGregory Neil Shapiro 			break;
3862fb4f839SGregory Neil Shapiro 
3872fb4f839SGregory Neil Shapiro 		  case 'R':
3882fb4f839SGregory Neil Shapiro 			reader = 1;
3892fb4f839SGregory Neil Shapiro 			break;
3902fb4f839SGregory Neil Shapiro 
3912fb4f839SGregory Neil Shapiro 		  case 'r':
3922fb4f839SGregory Neil Shapiro 			shared = 1;
3932fb4f839SGregory Neil Shapiro 			break;
3942fb4f839SGregory Neil Shapiro 
3952fb4f839SGregory Neil Shapiro 		  case 's':
3962fb4f839SGregory Neil Shapiro 			delay = atoi(optarg);
3972fb4f839SGregory Neil Shapiro 			break;
3982fb4f839SGregory Neil Shapiro 
3992fb4f839SGregory Neil Shapiro 		  case 'W':
4002fb4f839SGregory Neil Shapiro 			writer = 1;
4012fb4f839SGregory Neil Shapiro 			break;
4022fb4f839SGregory Neil Shapiro 
4032fb4f839SGregory Neil Shapiro 		  default:
4042fb4f839SGregory Neil Shapiro 			usage(argv[0]);
4052fb4f839SGregory Neil Shapiro 			exit(69);
4062fb4f839SGregory Neil Shapiro 			break;
4072fb4f839SGregory Neil Shapiro 		}
4082fb4f839SGregory Neil Shapiro 	}
4092fb4f839SGregory Neil Shapiro 
4102fb4f839SGregory Neil Shapiro 	fpid = -1;
4112fb4f839SGregory Neil Shapiro 	if (0 == reader && 0 == writer && (fpid = fork()) < 0)
4122fb4f839SGregory Neil Shapiro 	{
4132fb4f839SGregory Neil Shapiro 		perror("fork failed\n");
4142fb4f839SGregory Neil Shapiro 		return 1;
4152fb4f839SGregory Neil Shapiro 	}
4162fb4f839SGregory Neil Shapiro 
4172fb4f839SGregory Neil Shapiro 	r = 0;
4182fb4f839SGregory Neil Shapiro 	if (reader || fpid == 0)
4192fb4f839SGregory Neil Shapiro 	{
4202fb4f839SGregory Neil Shapiro 		/* give the parent the chance to set up data */
4212fb4f839SGregory Neil Shapiro 		pid = getpid();
4222fb4f839SGregory Neil Shapiro 		sleep(1);
4232fb4f839SGregory Neil Shapiro 		r = locktestrd(filename, flags, nb ? delay : 0, shared);
4242fb4f839SGregory Neil Shapiro 	}
4252fb4f839SGregory Neil Shapiro 	if (writer || fpid > 0)
4262fb4f839SGregory Neil Shapiro 	{
4272fb4f839SGregory Neil Shapiro 		fpid = getpid();
4282fb4f839SGregory Neil Shapiro 		r = locktestwr(filename, flags, delay);
4292fb4f839SGregory Neil Shapiro 		(void) wait(&status);
4302fb4f839SGregory Neil Shapiro 	}
4312fb4f839SGregory Neil Shapiro 	/* (void) unlink(filename); */
4322fb4f839SGregory Neil Shapiro 	return r;
4332fb4f839SGregory Neil Shapiro }
434