chiark / gitweb /
Debianization and various other fixes.
[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