+macro editor ALT-w: wrap text (subject line) to " [WAS: &]"
[nethome.git] / src / flock.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/time.h>
4 #include <sys/types.h>
5 #include <sys/wait.h>
6 #include <signal.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <string.h>
10 #include <limits.h>
11 #include <getopt.h>
12 #include <sys/file.h>
13
14 #define failf(name) do { fprintf(stderr,"%s: ",pname); perror(name"()"); exit(EXIT_FAILURE); } while (0)
15 const char version[]="This is FLock, version 1.0\n";
16
17 int verbose;
18
19 char *pname;
20
21 static void usage(void) __attribute__((noreturn));
22 static void usage(void)
23 {
24         fprintf(stderr,"\
25 %s\
26 This command acts as an interface to flock(2):\n\
27 \n\
28 Usage: flock [{-s|--shared}|{-x|--exclusive}] [-n|--nonblock]\n\
29              [-v|--verbose] [-h|--help] [-V|--version]\n\
30              <lockname> <command>\n\
31 \n\
32   -s, --shared\tCreate shared lock (LOCK_SH) - DEFAULT\n\
33   -x, --exclusive\tCreate exclusive lock (LOCK_EX)\n\
34   -n, --nonblock\tFail immediately if req. lock is busy\n\
35   -v, --verbose\tDisplay progress during locking\n\
36   -h, --help\tPrint a summary of the options\n\
37   -V, --version\tPrint the version number\n\
38 ",version);
39         exit(EXIT_FAILURE);
40 }
41
42 const struct option longopts[]={
43 {"shared"   ,0,0,'s'},
44 {"exclusive",0,0,'x'},
45 {"nonblock" ,0,0,'n'},
46 {"verbose"  ,0,0,'v'},
47 {"help"     ,0,0,'h'},
48 {"version"  ,0,0,'V'}};
49
50 int main(int argc,char **argv)
51 {
52 char *fn,*cmd;
53 int locktype=LOCK_SH,nonblock=0,fd,optc;
54
55         pname=*argv;
56         while ((optc=getopt_long(argc,argv,"sxnvhV",longopts,NULL))!=EOF) switch (optc) {
57                 case 's':
58                         locktype=LOCK_SH;
59                         break;
60                 case 'x':
61                         locktype=LOCK_EX;
62                         break;
63                 case 'n':
64                         nonblock=LOCK_NB;
65                         break;
66                 case 'v':
67                         verbose=1;
68                         break;
69                 case 'V':
70                         fprintf(stderr,version);
71                         exit(EXIT_FAILURE);
72                 default: /* also 'h' */
73                         usage();
74                         break;
75                 }
76         if (optind+2!=argc) {
77                 fprintf(stderr,"%s: Incorrect number of parameters (command needs quoting?)!\n",pname);
78                 exit(EXIT_FAILURE);
79                 }
80         fn=argv[optind];
81         cmd=argv[optind+1];
82         if (verbose) { fprintf(stderr,"%s: Opening \"%s\"...",pname,fn); fflush(stderr); }
83         if ((fd=open(fn,O_RDONLY|(nonblock?O_NONBLOCK:0)))==-1) failf("open");
84         if (verbose) { fprintf(stderr,"done\n%s: Locking \"%s\"...",pname,fn); fflush(stderr); }
85         if (flock(fd,locktype|nonblock)) failf("flock");
86         if (verbose) { fprintf(stderr,"done\n%s: Running \"%s\"...",pname,cmd); fflush(stderr); }
87         if (system(cmd)==-1) failf("system");
88         if (verbose) { fprintf(stderr,"done\n%s: Finishing - removing lock.\n",pname); }
89         return(EXIT_SUCCESS);
90 }