Import ezmlm-idx 0.40
[ezmlm] / ezmlm-gate.c
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