qmaild.c starter

From: v20-qd-1213599553wzknjwd@riemann.fmi.uni-sofia.bg (Nikola Vladov)
Subject: qmaild.c starter
Date: Mon, 9 Jun 2008 10:01:13 +0300
--text follows this line--
Hi, I wrote next small program. It's good for hosts starting qmail
with svc or [mn]init. If your queue is most of the time empty
you can start qmail using it (I use it at home. Qmail delivers 20-30
messages daily). Otherwise srop reading here.

Install:
compile and copy qmaild in /var/qmail/bin

Usage:
Let assume that 'qmail-send' is a soft link to service dir and one
can start qmail-send daemon with: svc -o qmail-start

Then test qmaild with:
1) svc -d qmail-send
2) rm /service/qmail-send # see also bellow
3) /var/qmail/bin/qmaild /path/to/svc /path/to/qmail-send/start/script
It's possible to start also: strace /var/qmail/bin/qmaild ...

qmaild will start/stop qmail-send service by need. Most of the time you
will have one process instead of four.

I tested qmaild with ninit http://riemann.fmi.uni-sofia.bg/ninit/
It should work good also with svc from daemontools package.
I'm not sure if one have to remove the link in 2) above.
This is to prevent SVC system to start qmail-send automatic.

If all works fine and your system has small queue you can
prepare one service (qmaild) to start 3) and make a link
to qmaild service in /service/ dir. Let same-one who start qmail
with daemontools correct me if I made syntax errors.

Russ, if you find qmaild.c usefull make a link on www.qmail.org, please!

Nikola

------------------------------------------------------------
/* qmaild.c
gcc -W -Wall -s -o qmaild qmaild.c
diet -Os gcc -W -Wall -s -o qmaild qmaild.c -Wl,-N
usage: qmaild /path/to/[mn]svc qmail_service
author: Nikola Vladov
http://riemann.fmi.uni-sofia.bg/programs/
*/

#define QQ "/var/qmail/queue/"
#define HASFLOCK

#include <unistd.h>
#define __USE_GNU
#include <fcntl.h>
#include <dirent.h>
#include <sys/file.h>
#include <sys/poll.h>
#include <sys/wait.h>

int mesg;

typedef struct buffer {
char *x; /* actual buffer space */
unsigned int p; /* current position */
unsigned int n; /* string postition */
unsigned int a; /* allocated buffer size */
int fd;
} buffer;

#ifdef __dietlibc__
#define get_de int res = getdents(d->fd, (struct dirent *)d->x, d->a)
#else
#define get_de off_t x; int res = getdirentries(d->fd, d->x, d->a, &x)
#endif

static struct dirent* read_dir(buffer *d) {
struct dirent *de = (struct dirent*)(d->x + d->p);
if (d->p >= d->n || (d->p += de->d_reclen) >= d->n) {
get_de;
if (res<=0) return 0;
d->n=res;
d->p=0;
}
return (struct dirent*)(d->x+d->p);
}

#ifdef HASFLOCK
#define lock_exnb(fd) flock(fd,LOCK_EX | LOCK_NB)
#else
#define lock_exnb(fd) lockf(fd,2,0)
#endif

static int is_started() {
int r,fd;
fd = open(QQ "lock/sendmutex", O_WRONLY | O_NDELAY);
if (fd<0) return -100;
r = lock_exnb(fd);
close(fd);
return r; /* -1 running, 0 stopped */
}

static void scan_dir() {
struct dirent *d;
char buf_space[512];
int fd = open(".", O_RDONLY | O_DIRECTORY);
buffer b = { buf_space, 0, 0, sizeof(buf_space)-1, fd };

if (fd < 0) return;
while (mesg==0 && (d = read_dir(&b))) {
if (d->d_name[0] == '.') continue;
if (chdir(d->d_name)==0) {
scan_dir();
fchdir(fd);
continue;
} else
mesg=1;
}
close(fd);
}

static void ex(char **argv, char *opt) {
char *qm[4] = { argv[1], opt, argv[2], 0 };
int pid;
while ((pid=fork()) == -1) sleep(1);
if (pid == 0) {
execve(*qm, qm, 0);
_exit(127);
}
waitpid(pid, 0, 0);
}

int main (int argc, char **argv) {
struct pollfd pfd[1];
int n;

for (n=0; n<10; n++) close(n);
if (argc < 3 || is_started() == -100) _exit(100);
pfd[0].events = POLLIN;

for (;;) {
if (chdir(QQ "mess")) _exit(111);
mesg = 0;
scan_dir();
if (mesg==0) {
if (is_started())
ex(argv, "-t");

pfd[0].fd = open(QQ "lock/trigger", O_RDWR);
poll(pfd, 1, -1);
close(pfd[0].fd);
goto start;
} else {
start:
if (is_started()==0)
ex(argv, "-o");
}

sleep(127);
}
}

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-admin@muc.de