sbase

suckless unix tools
git clone git@git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

flock.c (1358B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <sys/file.h>
      3 #include <sys/wait.h>
      4 
      5 #include <errno.h>
      6 #include <fcntl.h>
      7 #include <stdio.h>
      8 #include <unistd.h>
      9 
     10 #include "util.h"
     11 
     12 static void
     13 usage(void)
     14 {
     15 	eprintf("usage: %s [-nosux] file cmd [arg ...]\n", argv0);
     16 }
     17 
     18 int
     19 main(int argc, char *argv[])
     20 {
     21 	int fd, status, savederrno, flags = LOCK_EX, nonblk = 0, oflag = 0;
     22 	pid_t pid;
     23 
     24 	ARGBEGIN {
     25 	case 'n':
     26 		nonblk = LOCK_NB;
     27 		break;
     28 	case 'o':
     29 		oflag = 1;
     30 		break;
     31 	case 's':
     32 		flags = LOCK_SH;
     33 		break;
     34 	case 'u':
     35 		flags = LOCK_UN;
     36 		break;
     37 	case 'x':
     38 		flags = LOCK_EX;
     39 		break;
     40 	default:
     41 		usage();
     42 	} ARGEND
     43 
     44 	if (argc < 2)
     45 		usage();
     46 
     47 	if ((fd = open(*argv, O_RDONLY | O_CREAT, 0644)) < 0)
     48 		eprintf("open %s:", *argv);
     49 
     50 	if (flock(fd, flags | nonblk)) {
     51 		if (nonblk && errno == EWOULDBLOCK)
     52 			return 1;
     53 		eprintf("flock:");
     54 	}
     55 
     56 	switch ((pid = fork())) {
     57 	case -1:
     58 		eprintf("fork:");
     59 	case 0:
     60 		if (oflag && close(fd) < 0)
     61 			eprintf("close:");
     62 		argv++;
     63 		execvp(*argv, argv);
     64 		savederrno = errno;
     65 		weprintf("execvp %s:", *argv);
     66 		_exit(126 + (savederrno == ENOENT));
     67 	default:
     68 		break;
     69 	}
     70 	if (waitpid(pid, &status, 0) < 0)
     71 		eprintf("waitpid:");
     72 
     73 	if (close(fd) < 0)
     74 		eprintf("close:");
     75 
     76 	if (WIFSIGNALED(status))
     77 		return 128 + WTERMSIG(status);
     78 	if (WIFEXITED(status))
     79 		return WEXITSTATUS(status);
     80 
     81 	return 0;
     82 }