]> mj.ucw.cz Git - umpf.git/commitdiff
started work on locking mailboxes
authorAnicka Bernathova <anicka@anicka.net>
Fri, 29 Aug 2008 15:55:35 +0000 (17:55 +0200)
committerAnicka Bernathova <anicka@anicka.net>
Fri, 29 Aug 2008 15:55:35 +0000 (17:55 +0200)
Makefile
lock.c [new file with mode: 0644]

index beb1a6ec5ba7bc627dece8d5edc0193c72099f1e..35976424351e3a090ef809505359cda66f6688be 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,8 @@ LDLIBS=-lpcre
 brum: brum.c cond.tab.o int.o lex.o ham.o lists.o
        gcc -o $@ $^ $(LDLIBS)
 
+lock: lex.o cond.tab.o
+
 cond.tab.o: cond.tab.c lex.o
 
 lex.o: lex.c cond.tab.c
@@ -21,4 +23,4 @@ cond.tab.c: cond.y
        bison -dvt cond.y
 
 clean:
-       rm -rf cond.tab.[ch] cond.output cond brum *.o
+       rm -rf cond.tab.[ch] cond.output cond brum *.o core
diff --git a/lock.c b/lock.c
new file mode 100644 (file)
index 0000000..b7e3ef4
--- /dev/null
+++ b/lock.c
@@ -0,0 +1,159 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "brum.h"
+
+#define LOCK_MAX_TRIES 30
+
+static void
+random_sleep(unsigned int about, unsigned int offset)
+{
+       int myrand;
+
+       if (about == 0 || offset > about)
+               die("random sleep: Bad input data: %d +- %d", about, offset);
+
+       myrand = random() % offset * (random()%2?1:-1);
+
+       usleep(about * 1000000 + myrand * 500000);
+}
+
+static char*
+cat(char* l, char* r)
+{
+       char* res = xmalloc(strlen(l) + strlen (r) + 1);
+       strcpy(res, l);
+       strcat(res, r);
+
+       return res;     
+}
+
+/* FIXME: what about privileges? */
+static int
+dot_lock(char* path)
+{
+       int i;
+       int fd;
+       int res = -1;
+       char* lockfile = cat(path, ".lock");
+       
+       for (i = 0; i < LOCK_MAX_TRIES; i++){
+               if ((fd = open(lockfile, O_WRONLY | O_EXCL | O_CREAT, 0)) 
+                       >= 0) {
+                       close(fd);
+                       break;
+               }
+
+               if (errno != EEXIST)
+                       break;
+
+               /* FIXME: deal with old locks */
+
+               random_sleep(1, 1);
+       }
+
+       free(lockfile);
+       return res;
+}
+
+static void
+dot_unlock(char* path)
+{
+       char* lockfile = cat(path, ".lock");
+
+       unlink(lockfile);
+
+       free(lockfile);
+}
+
+int
+open_mailbox(char* path, int use_default_mailbox)
+{
+       int fd;
+
+       /* attempt to dot_lock first */
+       if (dot_lock(path))
+               return -1;
+
+       /* if OK, try to open the file:
+               either we are saving to default mailbox (no problem here)
+               or we are saving somewhere else (no need to be privileged)
+       */      
+       if (use_default_mailbox){
+               /* get our preciousss out of pocket */
+               gid_t ruid, euid, suid;
+               getresgid(&ruid, &euid, &suid);
+               setresgid(ruid, suid, suid);
+
+               /* we are not going to create default mailbox */
+               fd = open(path, O_RDWR);
+               if (fd < 0)
+                       return -1;      
+
+               /* hide it again */
+               setresgid(ruid, ruid, suid);
+       } else {
+               fd = open(path, O_RDWR);
+               if (fd < 0 && errno == ENOENT){
+                       fd = open(path, O_RDWR | O_CREAT | O_EXCL,
+                               S_IRUSR | S_IWUSR);
+                       if (fd < 0)
+                               return -1;      
+
+               } else if (fd < 0)
+                       return -1;      
+       }       
+
+       /* fcntl then */
+       struct flock mb_lock;
+       memset(&mb_lock, 0, sizeof(struct flock));
+       mb_lock.l_type = F_WRLCK;
+       mb_lock.l_whence = SEEK_SET;
+
+       if (fcntl(fd, F_GETLK, &mb_lock) < 0){
+               close(fd);
+               dot_unlock(path);
+               return -1;
+       }
+
+       return fd; 
+}
+
+void
+close_mailbox(int fd, char* path)
+{
+       struct flock mb_lock;
+       memset(&mb_lock, 0, sizeof(struct flock));
+       mb_lock.l_type = F_UNLCK; 
+       fcntl(fd, F_SETLK, &mb_lock);
+       close(fd);
+       dot_unlock(path);
+}
+
+int
+main(int argc, char** argv)
+{
+       /* FIXME: move somewhere */
+       int fd;
+       gid_t ruid, euid, suid;
+       if (argc < 2)
+               return 1;
+       char* mb = argv[1]; 
+       getresgid(&ruid, &euid, &suid);
+       setresgid(ruid, ruid, euid);
+       fd = open_mailbox(mb, 1);
+       printf("%d\n", fd); 
+       if (fd < 0)
+               return 1;       
+
+       close_mailbox(fd, mb);
+
+       return 0;
+}