+#define _GNU_SOURCE
+
#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 <time.h>
+
+#include "umpf.h"
+
+#define LOCK_MAX_TRIES 3
+gid_t rgid, egid, sgid;
+
+void
+save_gids(void)
+{
+ getresgid(&rgid, &egid, &sgid);
+}
-#include "brum.h"
+static void
+drop_gid(void)
+{
+ setresgid(rgid, rgid, egid);
+}
-#define LOCK_MAX_TRIES 30
+static void
+raise_gid(void)
+{
+ setresgid(rgid, sgid, sgid);
+}
static void
random_sleep(unsigned int about, unsigned int offset)
usleep(about * 1000000 + myrand * 500000);
}
-static char*
+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 fd;
int res = -1;
char* lockfile = cat(path, ".lock");
-
+
+ raise_gid();
for (i = 0; i < LOCK_MAX_TRIES; i++){
+ struct stat buf;
+
if ((fd = open(lockfile, O_WRONLY | O_EXCL | O_CREAT, 0))
>= 0) {
close(fd);
+ res = 0;
break;
}
if (errno != EEXIST)
break;
-
- /* FIXME: deal with old locks */
-
+ /* deal with old locks */
+ stat(lockfile, &buf);
+ if ((time(NULL) - buf.st_mtime) > 3600)
+ unlink(lockfile);
random_sleep(1, 1);
}
+ drop_gid();
free(lockfile);
return res;
{
char* lockfile = cat(path, ".lock");
+ raise_gid();
unlink(lockfile);
-
+ drop_gid();
free(lockfile);
}
-int
-open_mailbox(char* path, int use_default_mailbox)
+static int
+do_open_mailbox(char* path, int is_default_mailbox)
{
int fd;
/* 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;
+ */
+ int perms = S_IRUSR | S_IWUSR;
+ if (is_default_mailbox)
+ perms |= (S_IRGRP | S_IWGRP);
+
+ mode_t oldmask = umask(0);
+ fd = open(path, O_RDWR | O_CREAT, perms);
+ umask(oldmask);
+ if (fd < 0){
+ dot_unlock(path);
+ return -1;
}
/* fcntl then */
return fd;
}
-void
-close_mailbox(int fd, char* path)
+static void
+do_close_mailbox(int fd, char* path)
{
struct flock mb_lock;
memset(&mb_lock, 0, sizeof(struct flock));
dot_unlock(path);
}
+void
+close_mailbox(int fd, char* path, int is_default_mailbox)
+{
+ if (is_default_mailbox)
+ raise_gid();
+ do_close_mailbox(fd, path);
+ if (is_default_mailbox)
+ drop_gid();
+}
+
int
-main(int argc, char** argv)
+open_mailbox(char* path, int is_default_mailbox)
{
- /* 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;
+
+ if (is_default_mailbox)
+ raise_gid();
+ fd = do_open_mailbox(path, is_default_mailbox);
+ if (is_default_mailbox)
+ drop_gid();
+
+ return fd;
}