Commit | Line | Data |
---|---|---|
f8beb284 MW |
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 |