Hi there,
I've came across to the need of a flock(1) utility at work and I've
noticed we don't have any in OpenBSD, it's basically a flock(2)
wrapper that is usefull for running shell commands under a exclusive
and/or shared locks.
I've implemented one that the interface is 90% compatible with the one
found in linux-ng, although the implementation is quite
different. It's not final yet, I've tryed to follow style(9) and I'm
willing to make a port for it. So what do you guys think ? Can it be a
port ?
Any feedback is welcome, here is the code:
==flock.c==
#include <err.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
static int owait, oclose;
static const char *statusfile;
static int getlock(const char *, int, char *[]);
__dead void usage(void);
int
main(int argc, char *argv[])
{
char **cmdargv, *lockfile;
int ch, incmd, locktype, onblock;
ch = incmd = locktype = onblock = owait = oclose = 0;
cmdargv = NULL;
if (argc < 2)
usage();
while (!incmd && (ch = getopt(argc, argv, "cehonr:suxw:?")) != -1) {
switch (ch) {
case 'c':
incmd = 1;
break;
case 'e': /* FALLTROUGH */
case 'x':
if (locktype & LOCK_UN || locktype & LOCK_SH)
usage();
locktype = LOCK_EX;
break;
case 'n':
onblock = LOCK_NB;
break;
case 'o':
oclose = 1;
break;
case 's':
if (locktype & LOCK_UN || locktype & LOCK_EX)
usage();
locktype = LOCK_SH;
break;
case 'u':
if (locktype & LOCK_SH || locktype & LOCK_EX)
usage();
locktype = LOCK_UN;
break;
case 'w':
owait = strtol(optarg, NULL, 10);
break;
case 'r':
statusfile = optarg;
break;
case 'h': /* FALLTROUGH */
default:
usage();
/* NOTREACHED */
}
}
if ((argc - optind) < 3 || strcmp("-c", *(argv + optind + 1)) != 0)
usage();
lockfile = *(argv + optind);
argc -= optind + 2;
argv += optind + 2;
cmdargv = argv;
if (!locktype)
locktype = LOCK_EX;
return getlock(lockfile, locktype | onblock, argv);
}
static int
getlock(const char *lockfile, int type, char *argv[])
{
int mode, fd, fd_status, chstatus, chreturn;
pid_t pid;
mode = type & LOCK_EX ? O_WRONLY | O_CREAT : O_RDONLY | O_CREAT;
if ((fd = open(lockfile, mode, 0644)) < 0)
err(1, "Can't open %s", lockfile);
if (owait)
alarm(owait);
if (flock(fd, type) < 0)
return 1;
/* We should have the lock by now */
if ((pid = fork()) < 0)
err(1, "fork error");
else if(pid > 0) {/* parent */
if (waitpid(pid, &chstatus, 0) < 0)
err(1, "waitpid error");
if (statusfile && WIFEXITED(chstatus)) {
char buf[8];
if ((fd_status = open(statusfile,
O_CREAT | O_WRONLY,
0644)) < 0) {
err(1, "Can't open %s", statusfile);
}
chreturn = WEXITSTATUS(chstatus);
snprintf(buf, sizeof(buf), "%d", chreturn);
if (write(fd_status, buf, strlen(buf)) < 0)
err(1, "write error");
}
}
else {/* child */
if(oclose)
close(fd);
return execvp(*argv, argv);
}
return 0;
}d
__dead void
usage(void)
{
errx(1, "usage: flock [-sexu] [-no] [-r file] [-w seconds] -c command");
/* NOTREACHED */
}
==end flock.c==
--
Christiano Farina HAESBAERT