|
0
|
1 |
#include "fd.h"
|
|
|
2 |
#include "stralloc.h"
|
|
|
3 |
#include "readwrite.h"
|
|
|
4 |
#include "sgetopt.h"
|
|
|
5 |
#include "wait.h"
|
|
|
6 |
#include "env.h"
|
|
|
7 |
#include "byte.h"
|
|
|
8 |
#include "str.h"
|
|
|
9 |
#include "alloc.h"
|
|
|
10 |
#include "exit.h"
|
|
|
11 |
#include "fork.h"
|
|
|
12 |
#include "case.h"
|
|
|
13 |
#include "subfd.h"
|
|
|
14 |
#include "error.h"
|
|
|
15 |
#include "substdio.h"
|
|
|
16 |
#include "sig.h"
|
|
|
17 |
|
|
|
18 |
void die(e,s) int e; char *s; { substdio_putsflush(subfderr,s); _exit(e); }
|
|
|
19 |
void die_usage() { die(100,"qsmhook: fatal: incorrect usage\n"); }
|
|
|
20 |
void die_temp() { die(111,"qsmhook: fatal: temporary problem\n"); }
|
|
|
21 |
void die_read() { die(111,"qsmhook: fatal: unable to read message\n"); }
|
|
|
22 |
void die_badcmd() { die(100,"qsmhook: fatal: command not found\n"); }
|
|
|
23 |
|
|
|
24 |
int flagrpline = 0; char *rpline;
|
|
|
25 |
int flagufline = 1; char *ufline;
|
|
|
26 |
int flagdtline = 0; char *dtline;
|
|
|
27 |
char *host;
|
|
|
28 |
char *sender;
|
|
|
29 |
char *recip;
|
|
|
30 |
|
|
|
31 |
stralloc newarg = {0};
|
|
|
32 |
|
|
|
33 |
substdio ssout;
|
|
|
34 |
char outbuf[SUBSTDIO_OUTSIZE];
|
|
|
35 |
substdio ssin;
|
|
|
36 |
char inbuf[SUBSTDIO_INSIZE];
|
|
|
37 |
|
|
|
38 |
void main(argc,argv)
|
|
|
39 |
int argc;
|
|
|
40 |
char **argv;
|
|
|
41 |
{
|
|
|
42 |
int pid;
|
|
|
43 |
int wstat;
|
|
|
44 |
int pi[2];
|
|
|
45 |
int opt;
|
|
|
46 |
char **arg;
|
|
|
47 |
char *x;
|
|
|
48 |
int i;
|
|
|
49 |
int flagesc;
|
|
|
50 |
|
|
|
51 |
sig_pipeignore();
|
|
|
52 |
|
|
|
53 |
if (!(dtline = env_get("DTLINE"))) die_usage();
|
|
|
54 |
if (!(rpline = env_get("RPLINE"))) die_usage();
|
|
|
55 |
if (!(ufline = env_get("UFLINE"))) die_usage();
|
|
|
56 |
if (!(recip = env_get("LOCAL"))) die_usage();
|
|
|
57 |
if (!(host = env_get("HOST"))) die_usage();
|
|
|
58 |
if (!(sender = env_get("SENDER"))) die_usage();
|
|
|
59 |
|
|
|
60 |
while ((opt = getopt(argc,argv,"DFlMmnPsx:")) != opteof)
|
|
|
61 |
switch(opt)
|
|
|
62 |
{
|
|
|
63 |
case 'D': case 'F': case 'M': break; /* be serious */
|
|
|
64 |
case 'l': flagdtline = 1; break; /* also return-receipt-to? blech */
|
|
|
65 |
case 'm': break; /* we only handle one recipient anyway */
|
|
|
66 |
case 'n': flagufline = 0; break;
|
|
|
67 |
case 's': break; /* could call quote() otherwise, i suppose... */
|
|
|
68 |
case 'P': flagrpline = 1; break;
|
|
|
69 |
case 'x':
|
|
|
70 |
if (case_starts(recip,optarg))
|
|
|
71 |
recip += str_len(optarg);
|
|
|
72 |
break;
|
|
|
73 |
default:
|
|
|
74 |
_exit(100);
|
|
|
75 |
}
|
|
|
76 |
argc -= optind;
|
|
|
77 |
argv += optind;
|
|
|
78 |
|
|
|
79 |
if (!*argv) die_usage();
|
|
|
80 |
|
|
|
81 |
for (arg = argv;x = *arg;++arg)
|
|
|
82 |
{
|
|
|
83 |
if (!stralloc_copys(&newarg,"")) die_temp();
|
|
|
84 |
flagesc = 0;
|
|
|
85 |
for (i = 0;x[i];++i)
|
|
|
86 |
if (flagesc)
|
|
|
87 |
{
|
|
|
88 |
switch(x[i])
|
|
|
89 |
{
|
|
|
90 |
case '%': if (!stralloc_cats(&newarg,"%")) die_temp(); break;
|
|
|
91 |
case 'g': if (!stralloc_cats(&newarg,sender)) die_temp(); break;
|
|
|
92 |
case 'h': if (!stralloc_cats(&newarg,host)) die_temp(); break;
|
|
|
93 |
case 'u': if (!stralloc_cats(&newarg,recip)) die_temp(); break;
|
|
|
94 |
}
|
|
|
95 |
flagesc = 0;
|
|
|
96 |
}
|
|
|
97 |
else
|
|
|
98 |
if (x[i] == '%')
|
|
|
99 |
flagesc = 1;
|
|
|
100 |
else
|
|
|
101 |
if (!stralloc_append(&newarg,&x[i])) die_temp();
|
|
|
102 |
if (!stralloc_0(&newarg)) die_temp();
|
|
|
103 |
i = str_len(newarg.s) + 1;
|
|
|
104 |
if (!(x = alloc(i))) die_temp();
|
|
|
105 |
byte_copy(x,i,newarg.s);
|
|
|
106 |
*arg = x;
|
|
|
107 |
}
|
|
|
108 |
|
|
|
109 |
if (pipe(pi) == -1) die_temp();
|
|
|
110 |
|
|
|
111 |
switch(pid = fork())
|
|
|
112 |
{
|
|
|
113 |
case -1:
|
|
|
114 |
die_temp();
|
|
|
115 |
case 0:
|
|
|
116 |
close(pi[1]);
|
|
|
117 |
if (fd_move(0,pi[0]) == -1) die_temp();
|
|
|
118 |
sig_pipedefault();
|
|
|
119 |
execvp(*argv,argv);
|
|
|
120 |
if (error_temp(errno)) die_temp();
|
|
|
121 |
die_badcmd();
|
|
|
122 |
}
|
|
|
123 |
close(pi[0]);
|
|
|
124 |
|
|
|
125 |
substdio_fdbuf(&ssout,write,pi[1],outbuf,sizeof(outbuf));
|
|
|
126 |
substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
|
|
|
127 |
if (flagufline) substdio_bputs(&ssout,ufline);
|
|
|
128 |
if (flagrpline) substdio_bputs(&ssout,rpline);
|
|
|
129 |
if (flagdtline) substdio_bputs(&ssout,dtline);
|
|
|
130 |
if (substdio_copy(&ssout,&ssin) == -2) die_read();
|
|
|
131 |
substdio_flush(&ssout);
|
|
|
132 |
close(pi[1]);
|
|
|
133 |
|
|
|
134 |
if (wait_pid(&wstat,pid) == -1) die_temp();
|
|
|
135 |
if (wait_crashed(wstat)) die_temp();
|
|
|
136 |
_exit(wait_exitcode(wstat));
|
|
|
137 |
}
|