|
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 } |