| 1 | /*$Id: ezmlm-gate.c,v 1.18 1999/10/09 16:49:56 lindberg Exp $*/ |
| 2 | /*$Name: ezmlm-idx-040 $*/ |
| 3 | |
| 4 | #include "stralloc.h" |
| 5 | #include "strerr.h" |
| 6 | #include "error.h" |
| 7 | #include "env.h" |
| 8 | #include "sig.h" |
| 9 | #include "str.h" |
| 10 | #include "seek.h" |
| 11 | #include "fork.h" |
| 12 | #include "wait.h" |
| 13 | #include "exit.h" |
| 14 | #include "getconf.h" |
| 15 | #include "auto_bin.h" |
| 16 | #include "sgetopt.h" |
| 17 | #include "errtxt.h" |
| 18 | #include "idx.h" |
| 19 | #include "subscribe.h" |
| 20 | |
| 21 | #define FATAL "ezmlm-gate: fatal: " |
| 22 | |
| 23 | void die_usage() |
| 24 | { |
| 25 | strerr_die1x(100,"ezmlm-gate: usage: ezmlm-gate [-cCmMpPqrRsSvV] " |
| 26 | "dir [moddir [...]]"); |
| 27 | } |
| 28 | void die_nomem() { strerr_die2x(111,FATAL,ERR_NOMEM); } |
| 29 | |
| 30 | stralloc line = {0}; |
| 31 | stralloc cmds = {0}; |
| 32 | stralloc send = {0}; |
| 33 | stralloc sendopt = {0}; |
| 34 | stralloc storeopt = {0}; |
| 35 | void *psql = (void *) 0; |
| 36 | |
| 37 | char szchar[2] = "-"; |
| 38 | char *sendargs[4]; |
| 39 | int child; |
| 40 | int wstat; |
| 41 | char *pmod; |
| 42 | |
| 43 | int mailprog(s) |
| 44 | char *s; |
| 45 | { |
| 46 | int r; |
| 47 | |
| 48 | sendargs[0] = "/bin/sh"; /* 100 perm error, 111 temp, 99 dom ok */ |
| 49 | sendargs[1] = "-c"; /* 0 rec ok, others bounce */ |
| 50 | sendargs[2] = s; |
| 51 | sendargs[3] = (char *)0; |
| 52 | switch(child = fork()) { |
| 53 | case -1: |
| 54 | strerr_die2sys(111,FATAL,ERR_FORK); |
| 55 | case 0: |
| 56 | execv(*sendargs,sendargs); |
| 57 | if (errno == error_txtbsy || errno == error_nomem || |
| 58 | errno == error_io) |
| 59 | strerr_die5sys(111,FATAL,ERR_EXECUTE, |
| 60 | "/bin/sh -c ",sendargs[2],": "); |
| 61 | else |
| 62 | strerr_die5sys(100,FATAL,ERR_EXECUTE, |
| 63 | "/bin/sh -c ",sendargs[2],": "); |
| 64 | } |
| 65 | /* parent */ |
| 66 | wait_pid(&wstat,child); |
| 67 | if (wait_crashed(wstat)) |
| 68 | strerr_die2x(111,FATAL,ERR_CHILD_CRASHED); |
| 69 | switch((r = wait_exitcode(wstat))) { |
| 70 | case 0: case 99: case 100: break; |
| 71 | case 111: /* temp error */ |
| 72 | strerr_die2x(111,FATAL,ERR_CHILD_TEMP); |
| 73 | default: |
| 74 | strerr_die2x(100,FATAL,ERR_REJECT); /* other errors => bounce */ |
| 75 | } |
| 76 | if (seek_begin(0) == -1) /* rewind */ |
| 77 | strerr_die2sys(111,FATAL,ERR_SEEK_INPUT); |
| 78 | return r; |
| 79 | } |
| 80 | |
| 81 | void main(argc,argv) |
| 82 | int argc; |
| 83 | char **argv; |
| 84 | { |
| 85 | char *dir; |
| 86 | char *sender; |
| 87 | char *moddir; |
| 88 | char *queryext = (char *) 0; |
| 89 | int opt; |
| 90 | int ret = 0; |
| 91 | unsigned int i,j,k; |
| 92 | |
| 93 | umask(022); |
| 94 | sig_pipeignore(); |
| 95 | /* storeopts to ezmlm-store only. Others to both (ezmlm-store may */ |
| 96 | /* pass them on to ezmlm-send. */ |
| 97 | if (!stralloc_copys(&sendopt," -")) die_nomem(); |
| 98 | if (!stralloc_copys(&storeopt," -")) die_nomem(); |
| 99 | |
| 100 | while ((opt = getopt(argc,argv, |
| 101 | "cCmMpPq:Q:sSrRt:T:vV")) != opteof) |
| 102 | switch(opt) { /* pass on unrecognized options */ |
| 103 | case 'c': /* ezmlm-send flags */ |
| 104 | case 'C': |
| 105 | case 'r': |
| 106 | case 'R': |
| 107 | szchar[0] = opt; |
| 108 | if (!stralloc_append(&sendopt,szchar)) die_nomem(); |
| 109 | break; |
| 110 | case 'm': /* ezmlm-store flags */ |
| 111 | case 'M': |
| 112 | case 'p': |
| 113 | case 'P': |
| 114 | case 's': |
| 115 | case 'S': |
| 116 | szchar[0] = opt; |
| 117 | if (!stralloc_append(&storeopt,szchar)) die_nomem(); |
| 118 | break; |
| 119 | case 'q': /* allow both qQ to be nice */ |
| 120 | case 'Q': if (optarg) queryext = optarg; break; |
| 121 | case 'v': |
| 122 | case 'V': strerr_die2x(0,"ezmlm-gate version: ",EZIDX_VERSION); |
| 123 | default: /* ezmlm-store flags */ |
| 124 | die_usage(); |
| 125 | } |
| 126 | |
| 127 | dir = argv[optind++]; |
| 128 | if (!dir) die_usage(); |
| 129 | if (chdir(dir) == -1) |
| 130 | strerr_die4sys(111,FATAL,ERR_SWITCH,dir,": "); |
| 131 | |
| 132 | sender = env_get("SENDER"); |
| 133 | |
| 134 | pmod = (char *) 0; |
| 135 | |
| 136 | if (queryext) { |
| 137 | getconf(&cmds,queryext,1,FATAL,dir); |
| 138 | i = 0; |
| 139 | for (j = 0;j < cmds.len; ++j) |
| 140 | if (!cmds.s[j]) { |
| 141 | switch (cmds.s[i]) { |
| 142 | case '\0': case '#': break; /* ignore blank/comment */ |
| 143 | case '|': |
| 144 | ret = mailprog(cmds.s + i + 1); break; |
| 145 | default: |
| 146 | ret = mailprog(cmds.s + i); break; |
| 147 | } |
| 148 | if (ret) break; |
| 149 | i = j + 1; |
| 150 | } |
| 151 | if (!ret || ret == 99) /* 111 => temp error */ |
| 152 | pmod = ""; /* 0, 99 => post */ |
| 153 | /* other => moderate */ |
| 154 | } |
| 155 | moddir = argv[optind++]; |
| 156 | if (moddir && !ret) { /* if exit 0 and moddir, add issub */ |
| 157 | pmod = (char *) 0; |
| 158 | while (moddir && !pmod && sender) { |
| 159 | pmod = issub(moddir,sender,(char *) 0,FATAL); |
| 160 | closesql(); |
| 161 | moddir = argv[optind++]; |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | sendargs[0] = "sh"; |
| 166 | sendargs[1] = "-c"; |
| 167 | if (!stralloc_copys(&send,auto_bin)) die_nomem(); |
| 168 | if (pmod) { |
| 169 | if (!stralloc_cats(&send,"/ezmlm-send")) die_nomem(); |
| 170 | if (sendopt.len > 2) |
| 171 | if (!stralloc_cat(&send,&sendopt)) die_nomem(); |
| 172 | |
| 173 | } else { |
| 174 | if (!stralloc_cats(&send,"/ezmlm-store")) die_nomem(); |
| 175 | if (storeopt.len > 2) |
| 176 | if (!stralloc_cat(&send,&storeopt)) die_nomem(); |
| 177 | if (sendopt.len > 2) |
| 178 | if (!stralloc_cat(&send,&sendopt)) die_nomem(); |
| 179 | } |
| 180 | if (!stralloc_cats(&send," '")) die_nomem(); |
| 181 | if (!stralloc_cats(&send,dir)) die_nomem(); |
| 182 | if (!stralloc_cats(&send,"'")) die_nomem(); |
| 183 | if (!stralloc_0(&send)) die_nomem(); |
| 184 | sendargs[2] = send.s; |
| 185 | sendargs[3] = 0; |
| 186 | |
| 187 | switch(child = fork()) { |
| 188 | case -1: |
| 189 | strerr_die2sys(111,FATAL,ERR_FORK); |
| 190 | case 0: |
| 191 | execvp(*sendargs,sendargs); |
| 192 | if (errno == error_txtbsy || errno == error_nomem || |
| 193 | errno == error_io) |
| 194 | strerr_die4sys(111,FATAL,ERR_EXECUTE,sendargs[2],": "); |
| 195 | else |
| 196 | strerr_die4sys(100,FATAL,ERR_EXECUTE,sendargs[2],": "); |
| 197 | } |
| 198 | /* parent */ |
| 199 | wait_pid(&wstat,child); |
| 200 | if (wait_crashed(wstat)) |
| 201 | strerr_die2x(111,FATAL,ERR_CHILD_CRASHED); |
| 202 | switch(wait_exitcode(wstat)) { |
| 203 | case 100: |
| 204 | strerr_die2x(100,FATAL,ERR_CHILD_FATAL); |
| 205 | case 111: |
| 206 | strerr_die2x(111,FATAL,ERR_CHILD_TEMP); |
| 207 | case 0: |
| 208 | _exit(0); |
| 209 | default: |
| 210 | strerr_die2x(111,FATAL,ERR_CHILD_UNKNOWN); |
| 211 | } |
| 212 | } |
| 213 | |