--- /dev/null
+#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;
+}