summaryrefslogtreecommitdiff
path: root/src/spawn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/spawn.c')
-rw-r--r--src/spawn.c297
1 files changed, 179 insertions, 118 deletions
diff --git a/src/spawn.c b/src/spawn.c
index effcb26..5315637 100644
--- a/src/spawn.c
+++ b/src/spawn.c
@@ -1,37 +1,37 @@
-#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
+
#include "alloc.h"
-#include "sig.h"
-#include "wait.h"
#include "buffer.h"
#include "byte.h"
-#include "str.h"
-#include "stralloc.h"
-#include "select.h"
+#include "error.h"
#include "exit.h"
#include "fd.h"
#include "open.h"
-#include "error.h"
+#include "select.h"
+#include "sig.h"
+#include "str.h"
+#include "stralloc.h"
+#include "wait.h"
+
#include "auto_qmail.h"
-#include "auto_uids.h"
#include "auto_spawn.h"
+#include "auto_uids.h"
extern int truncreport;
extern int spawn();
extern void report();
extern void initialize();
-struct delivery
- {
+struct delivery {
int used;
- int fdin; /* pipe input */
- int pid; /* zero if child is dead */
+ int fdin; /* pipe input */
+ int pid; /* zero if child is dead */
int wstat; /* if !pid: status of child */
int fdout; /* pipe output, -1 if !pid; delays eof until after death */
stralloc output;
- }
-;
+};
struct delivery *d;
@@ -42,32 +42,35 @@ void sigchld()
int i;
while ((pid = wait_nohang(&wstat)) > 0)
- for (i = 0; i < auto_spawn; ++i)
+ for (i = 0; i < auto_spawn; ++i)
if (d[i].used)
if (d[i].pid == pid) {
- close(d[i].fdout); d[i].fdout = -1;
- d[i].wstat = wstat; d[i].pid = 0;
+ close(d[i].fdout);
+ d[i].fdout = -1;
+ d[i].wstat = wstat;
+ d[i].pid = 0;
}
-}
+}
int flagwriting = 1;
-ssize_t okwrite(int fd,char *buf,int n)
+ssize_t okwrite(int fd, char *buf, int n)
{
int w;
if (!flagwriting) return n;
- w = write(fd,buf,n);
+ w = write(fd, buf, n);
if (w != -1) return w;
if (errno == EINTR) return -1;
- flagwriting = 0; close(fd);
+ flagwriting = 0;
+ close(fd);
return n;
}
int flagreading = 1;
-char outbuf[1024];
+char outbuf[1024];
buffer bo;
-int stage = 0; /* reading 0:delnum 1:messid 2:sender 3:recip */
+int stage = 0; /* reading 0:delnum 1:messid 2:sender 3:recip */
int flagabort = 0; /* if 1, everything except delnum is garbage */
int delnum;
stralloc messid = {0};
@@ -76,12 +79,12 @@ stralloc recip = {0};
void err(char *s)
{
- char ch;
-
- ch = delnum;
- buffer_put(&bo,&ch,1);
- buffer_puts(&bo,s);
- buffer_putflush(&bo,"",1);
+ char ch;
+
+ ch = delnum;
+ buffer_put(&bo, &ch, 1);
+ buffer_puts(&bo, s);
+ buffer_putflush(&bo, "", 1);
}
void docmd()
@@ -93,57 +96,105 @@ void docmd()
int pi[2];
struct stat st;
- if (flagabort) { err("Zqmail-spawn: Out of memory. (#4.3.0)\n"); return; }
- if (delnum < 0) { err("Zqmail-spawn: Internal error: delnum negative. (#4.3.5)\n"); return; }
- if (delnum >= auto_spawn) { err("Zqmail-spawn: Internal error: delnum too big. (#4.3.5)\n"); return; }
- if (d[delnum].used) { err("Zqmail-spawn: Internal error: delnum in use. (#4.3.5)\n"); return; }
-
+ if (flagabort) {
+ err("Zqmail-spawn: Out of memory. (#4.3.0)\n");
+ return;
+ }
+ if (delnum < 0) {
+ err("Zqmail-spawn: Internal error: delnum negative. (#4.3.5)\n");
+ return;
+ }
+ if (delnum >= auto_spawn) {
+ err("Zqmail-spawn: Internal error: delnum too big. (#4.3.5)\n");
+ return;
+ }
+ if (d[delnum].used) {
+ err("Zqmail-spawn: Internal error: delnum in use. (#4.3.5)\n");
+ return;
+ }
+
for (i = 0; i < messid.len; ++i)
if (messid.s[i])
if (!i || (messid.s[i] != '/'))
- if ((unsigned char) (messid.s[i] - '0') > 9)
- { err("Dqmail-spawn: Internal error: messid has nonnumerics. (#5.3.5)\n"); return; }
+ if ((unsigned char)(messid.s[i] - '0') > 9) {
+ err("Dqmail-spawn: Internal error: messid has nonnumerics. (#5.3.5)\n");
+ return;
+ }
- if (messid.len > 100) { err("Dqmail-spawn: Internal error: messid too long. (#5.3.5)\n"); return; }
- if (!messid.s[0]) { err("Dqmail-spawn: Internal error: messid too short. (#5.3.5)\n"); return; }
+ if (messid.len > 100) {
+ err("Dqmail-spawn: Internal error: messid too long. (#5.3.5)\n");
+ return;
+ }
+ if (!messid.s[0]) {
+ err("Dqmail-spawn: Internal error: messid too short. (#5.3.5)\n");
+ return;
+ }
- if (!stralloc_copys(&d[delnum].output,""))
- { err("Zqmail-spawn: Out of memory. (#4.3.0)\n"); return; }
+ if (!stralloc_copys(&d[delnum].output, "")) {
+ err("Zqmail-spawn: Out of memory. (#4.3.0)\n");
+ return;
+ }
- j = byte_rchr(recip.s,recip.len,'@');
- if (j >= recip.len) { err("DSorry, address must include host name. (#5.1.3)\n"); return; }
+ j = byte_rchr(recip.s, recip.len, '@');
+ if (j >= recip.len) {
+ err("DSorry, address must include host name. (#5.1.3)\n");
+ return;
+ }
fdmess = open_read(messid.s);
- if (fdmess == -1) { err("Zqmail-spawn: Unable to open message. (#4.3.0)\n"); return; }
+ if (fdmess == -1) {
+ err("Zqmail-spawn: Unable to open message. (#4.3.0)\n");
+ return;
+ }
- if (fstat(fdmess,&st) == -1)
- { close(fdmess); err("Zqmail-spawn: Unable to fstat message. (#4.3.0)\n"); return; }
- if ((st.st_mode & S_IFMT) != S_IFREG)
- { close(fdmess); err("ZSorry, message has wrong type. (#4.3.5)\n"); return; }
+ if (fstat(fdmess, &st) == -1) {
+ close(fdmess);
+ err("Zqmail-spawn: Unable to fstat message. (#4.3.0)\n");
+ return;
+ }
+ if ((st.st_mode & S_IFMT) != S_IFREG) {
+ close(fdmess);
+ err("ZSorry, message has wrong type. (#4.3.5)\n");
+ return;
+ }
if (st.st_uid != auto_uidq) /* aaack! qmailq has to be trusted! */
- /* your security is already toast at this point. damage control... */
- { close(fdmess); err("ZSorry, message has wrong owner. (#4.3.5)\n"); return; }
+ /* your security is already toast at this point. damage control... */
+ {
+ close(fdmess);
+ err("ZSorry, message has wrong owner. (#4.3.5)\n");
+ return;
+ }
if (pipe(pi) == -1) {
- if (errno == EFAULT) err("Zqmail-spawn: Unable to create pipe (wrong fildes). (#4.3.0)\n");
- else if (errno == EMFILE) err("Zqmail-spawn: Unable to create pipe (too many FDS). (#4.3.0)\n");
- else if (errno == ENFILE) err("Zqmail-spawn: Unable to create pipe (system file table full). (#4.3.0)\n");
- else if (errno == ENOMEM) err("Zqmail-spawn: Unable to create pipe (out of memory). (#4.3.0)\n");
- else err("Zqmail-spawn: Unable to create pipe (unkown reason). (#4.3.0)\n");
- close(fdmess);
- return;
+ if (errno == EFAULT)
+ err("Zqmail-spawn: Unable to create pipe (wrong fildes). (#4.3.0)\n");
+ else if (errno == EMFILE)
+ err("Zqmail-spawn: Unable to create pipe (too many FDS). (#4.3.0)\n");
+ else if (errno == ENFILE)
+ err("Zqmail-spawn: Unable to create pipe (system file table full). (#4.3.0)\n");
+ else if (errno == ENOMEM)
+ err("Zqmail-spawn: Unable to create pipe (out of memory). (#4.3.0)\n");
+ else
+ err("Zqmail-spawn: Unable to create pipe (unkown reason). (#4.3.0)\n");
+ close(fdmess);
+ return;
}
fd_coe(pi[0]);
- f = spawn(fdmess,pi[1],sender.s,recip.s,j);
+ f = spawn(fdmess, pi[1], sender.s, recip.s, j);
close(fdmess);
- if (f == -1)
- { close(pi[0]); close(pi[1]); err("Zqmail-spawn: Unable to fork. (#4.3.0)\n"); return; }
+ if (f == -1) {
+ close(pi[0]);
+ close(pi[1]);
+ err("Zqmail-spawn: Unable to fork. (#4.3.0)\n");
+ return;
+ }
d[delnum].fdin = pi[0];
- d[delnum].fdout = pi[1]; fd_coe(pi[1]);
+ d[delnum].fdout = pi[1];
+ fd_coe(pi[1]);
d[delnum].pid = f;
d[delnum].used = 1;
}
@@ -156,41 +207,50 @@ void getcmd()
int r;
char ch;
- r = read(0,cmdbuf,sizeof(cmdbuf));
- if (r == 0)
- { flagreading = 0; return; }
+ r = read(0, cmdbuf, sizeof(cmdbuf));
+ if (r == 0) {
+ flagreading = 0;
+ return;
+ }
if (r == -1) {
- if (errno != EINTR)
- flagreading = 0;
+ if (errno != EINTR) flagreading = 0;
return;
}
-
+
for (i = 0; i < r; ++i) {
ch = cmdbuf[i];
switch (stage) {
case 0:
- delnum = (unsigned int) (unsigned char) ch;
- messid.len = 0; stage = 1; break;
+ delnum = (unsigned int)(unsigned char)ch;
+ messid.len = 0;
+ stage = 1;
+ break;
case 1:
- if (!stralloc_append(&messid,&ch)) flagabort = 1;
+ if (!stralloc_append(&messid, &ch)) flagabort = 1;
if (ch) break;
- sender.len = 0; stage = 2; break;
+ sender.len = 0;
+ stage = 2;
+ break;
case 2:
- if (!stralloc_append(&sender,&ch)) flagabort = 1;
+ if (!stralloc_append(&sender, &ch)) flagabort = 1;
if (ch) break;
- recip.len = 0; stage = 3; break;
+ recip.len = 0;
+ stage = 3;
+ break;
case 3:
- if (!stralloc_append(&recip,&ch)) flagabort = 1;
+ if (!stralloc_append(&recip, &ch)) flagabort = 1;
if (ch) break;
docmd();
- flagabort = 0; stage = 0; break;
+ flagabort = 0;
+ stage = 0;
+ break;
}
}
}
char inbuf[128];
-int main(int argc,char **argv)
+int main(int argc, char **argv)
{
char ch;
int i;
@@ -200,77 +260,78 @@ int main(int argc,char **argv)
if (chdir(auto_qmail) == -1) _exit(110);
if (chdir("queue/mess") == -1) _exit(110);
- if (!stralloc_copys(&messid,"")) _exit(111);
- if (!stralloc_copys(&sender,"")) _exit(111);
- if (!stralloc_copys(&recip,"")) _exit(111);
+ if (!stralloc_copys(&messid, "")) _exit(111);
+ if (!stralloc_copys(&sender, "")) _exit(111);
+ if (!stralloc_copys(&recip, "")) _exit(111);
- d = (struct delivery *) alloc((auto_spawn + 10) * sizeof(struct delivery));
+ d = (struct delivery *)alloc((auto_spawn + 10) * sizeof(struct delivery));
if (!d) _exit(111);
- buffer_init(&bo,okwrite,1,outbuf,sizeof(outbuf));
+ buffer_init(&bo, okwrite, 1, outbuf, sizeof(outbuf));
sig_pipeignore();
sig_childcatch(sigchld);
- initialize(argc,argv);
+ initialize(argc, argv);
- ch = auto_spawn;
- buffer_putflush(&bo,&ch,1);
+ ch = auto_spawn;
+ buffer_putflush(&bo, &ch, 1);
- for (i = 0; i < auto_spawn; ++i)
- { d[i].used = 0; d[i].output.s = 0; }
+ for (i = 0; i < auto_spawn; ++i) {
+ d[i].used = 0;
+ d[i].output.s = 0;
+ }
for (;;) {
if (!flagreading) {
- for (i = 0; i < auto_spawn; ++i) if (d[i].used) break;
+ for (i = 0; i < auto_spawn; ++i)
+ if (d[i].used) break;
if (i >= auto_spawn) _exit(0);
}
sig_childunblock();
FD_ZERO(&rfds);
- if (flagreading) FD_SET(0,&rfds);
+ if (flagreading) FD_SET(0, &rfds);
nfds = 1;
- for (i = 0; i < auto_spawn; ++i)
- if (d[i].used) {
- FD_SET(d[i].fdin,&rfds);
- if (d[i].fdin >= nfds)
- nfds = d[i].fdin + 1;
+ for (i = 0; i < auto_spawn; ++i)
+ if (d[i].used) {
+ FD_SET(d[i].fdin, &rfds);
+ if (d[i].fdin >= nfds) nfds = d[i].fdin + 1;
}
- r = select(nfds,&rfds,(fd_set *) 0,(fd_set *) 0,(struct timeval *) 0);
+ r = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
sig_childblock();
if (r != -1) {
if (flagreading)
- if (FD_ISSET(0,&rfds)) getcmd();
- for (i = 0; i < auto_spawn; ++i)
+ if (FD_ISSET(0, &rfds)) getcmd();
+ for (i = 0; i < auto_spawn; ++i)
if (d[i].used)
- if (FD_ISSET(d[i].fdin,&rfds)) {
- r = read(d[i].fdin,inbuf,128);
- if (r == -1)
- continue; /* read error on a readable pipe? be serious */
- if (r == 0) {
- ch = i;
- buffer_put(&bo,&ch,1);
- report(&bo,d[i].wstat,d[i].output.s,d[i].output.len);
- buffer_put(&bo,"",1);
- buffer_flush(&bo);
- close(d[i].fdin); d[i].used = 0;
- continue;
- }
- while (!stralloc_readyplus(&d[i].output,r))
- sleep(10); /*XXX*/
- byte_copy(d[i].output.s + d[i].output.len,r,inbuf);
- d[i].output.len += r;
- if (truncreport > 100)
- if (d[i].output.len > truncreport) {
- char *truncmess = "\nError report too long, sorry.\n";
- d[i].output.len = truncreport - str_len(truncmess) - 3;
- stralloc_cats(&d[i].output,truncmess);
+ if (FD_ISSET(d[i].fdin, &rfds)) {
+ r = read(d[i].fdin, inbuf, 128);
+ if (r == -1) continue; /* read error on a readable pipe? be serious */
+ if (r == 0) {
+ ch = i;
+ buffer_put(&bo, &ch, 1);
+ report(&bo, d[i].wstat, d[i].output.s, d[i].output.len);
+ buffer_put(&bo, "", 1);
+ buffer_flush(&bo);
+ close(d[i].fdin);
+ d[i].used = 0;
+ continue;
+ }
+ while (!stralloc_readyplus(&d[i].output, r)) sleep(10); /*XXX*/
+ byte_copy(d[i].output.s + d[i].output.len, r, inbuf);
+ d[i].output.len += r;
+ if (truncreport > 100)
+ if (d[i].output.len > truncreport) {
+ char *truncmess = "\nError report too long, sorry.\n";
+ d[i].output.len = truncreport - str_len(truncmess) - 3;
+ stralloc_cats(&d[i].output, truncmess);
+ }
}
- }
}
}
}