diff options
Diffstat (limited to 'src/spawn.c')
-rw-r--r-- | src/spawn.c | 297 |
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); + } } - } } } } |