Commit | Line | Data |
---|---|---|
212b6f5d MW |
1 | #include <sys/types.h> |
2 | #include <sys/socket.h> | |
3 | #include <netinet/in.h> | |
4 | #include <arpa/inet.h> | |
5 | #include "substdio.h" | |
6 | #include "getln.h" | |
7 | #include "readwrite.h" | |
8 | #include "exit.h" | |
9 | #include "stralloc.h" | |
10 | #include "slurpclose.h" | |
11 | #include "error.h" | |
12 | #include "sig.h" | |
13 | #include "ip.h" | |
14 | #include "timeoutconn.h" | |
15 | #include "timeoutread.h" | |
16 | #include "timeoutwrite.h" | |
17 | #include "auto_qmail.h" | |
18 | #include "control.h" | |
19 | #include "fmt.h" | |
20 | ||
21 | #define PORT_QMQP 628 | |
22 | ||
23 | void die_success() { _exit(0); } | |
24 | void die_perm() { _exit(31); } | |
25 | void nomem() { _exit(51); } | |
26 | void die_read() { if (errno == error_nomem) nomem(); _exit(54); } | |
27 | void die_control() { _exit(55); } | |
28 | void die_socket() { _exit(56); } | |
29 | void die_home() { _exit(61); } | |
30 | void die_temp() { _exit(71); } | |
31 | void die_conn() { _exit(74); } | |
32 | void die_format() { _exit(91); } | |
33 | ||
34 | int lasterror = 55; | |
35 | int qmqpfd; | |
36 | ||
37 | int saferead(fd,buf,len) int fd; char *buf; int len; | |
38 | { | |
39 | int r; | |
40 | r = timeoutread(60,qmqpfd,buf,len); | |
41 | if (r <= 0) die_conn(); | |
42 | return r; | |
43 | } | |
44 | int safewrite(fd,buf,len) int fd; char *buf; int len; | |
45 | { | |
46 | int r; | |
47 | r = timeoutwrite(60,qmqpfd,buf,len); | |
48 | if (r <= 0) die_conn(); | |
49 | return r; | |
50 | } | |
51 | ||
52 | char buf[1024]; | |
53 | substdio to = SUBSTDIO_FDBUF(safewrite,-1,buf,sizeof buf); | |
54 | substdio from = SUBSTDIO_FDBUF(saferead,-1,buf,sizeof buf); | |
55 | substdio envelope = SUBSTDIO_FDBUF(read,1,buf,sizeof buf); | |
56 | /* WARNING: can use only one of these at a time! */ | |
57 | ||
58 | stralloc beforemessage = {0}; | |
59 | stralloc message = {0}; | |
60 | stralloc aftermessage = {0}; | |
61 | ||
62 | char strnum[FMT_ULONG]; | |
63 | stralloc line = {0}; | |
64 | ||
65 | void getmess() | |
66 | { | |
67 | int match; | |
68 | ||
69 | if (slurpclose(0,&message,1024) == -1) die_read(); | |
70 | ||
71 | strnum[fmt_ulong(strnum,(unsigned long) message.len)] = 0; | |
72 | if (!stralloc_copys(&beforemessage,strnum)) nomem(); | |
73 | if (!stralloc_cats(&beforemessage,":")) nomem(); | |
74 | if (!stralloc_copys(&aftermessage,",")) nomem(); | |
75 | ||
76 | if (getln(&envelope,&line,&match,'\0') == -1) die_read(); | |
77 | if (!match) die_format(); | |
78 | if (line.len < 2) die_format(); | |
79 | if (line.s[0] != 'F') die_format(); | |
80 | ||
81 | strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0; | |
82 | if (!stralloc_cats(&aftermessage,strnum)) nomem(); | |
83 | if (!stralloc_cats(&aftermessage,":")) nomem(); | |
84 | if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem(); | |
85 | if (!stralloc_cats(&aftermessage,",")) nomem(); | |
86 | ||
87 | for (;;) { | |
88 | if (getln(&envelope,&line,&match,'\0') == -1) die_read(); | |
89 | if (!match) die_format(); | |
90 | if (line.len < 2) break; | |
91 | if (line.s[0] != 'T') die_format(); | |
92 | ||
93 | strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0; | |
94 | if (!stralloc_cats(&aftermessage,strnum)) nomem(); | |
95 | if (!stralloc_cats(&aftermessage,":")) nomem(); | |
96 | if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem(); | |
97 | if (!stralloc_cats(&aftermessage,",")) nomem(); | |
98 | } | |
99 | } | |
100 | ||
101 | void doit(server) | |
102 | char *server; | |
103 | { | |
104 | struct ip_address ip; | |
105 | char ch; | |
106 | ||
107 | if (!ip_scan(server,&ip)) return; | |
108 | ||
109 | qmqpfd = socket(AF_INET,SOCK_STREAM,0); | |
110 | if (qmqpfd == -1) die_socket(); | |
111 | ||
112 | if (timeoutconn(qmqpfd,&ip,PORT_QMQP,10) != 0) { | |
113 | lasterror = 73; | |
114 | if (errno == error_timeout) lasterror = 72; | |
115 | close(qmqpfd); | |
116 | return; | |
117 | } | |
118 | ||
119 | strnum[fmt_ulong(strnum,(unsigned long) (beforemessage.len + message.len + aftermessage.len))] = 0; | |
120 | substdio_puts(&to,strnum); | |
121 | substdio_puts(&to,":"); | |
122 | substdio_put(&to,beforemessage.s,beforemessage.len); | |
123 | substdio_put(&to,message.s,message.len); | |
124 | substdio_put(&to,aftermessage.s,aftermessage.len); | |
125 | substdio_puts(&to,","); | |
126 | substdio_flush(&to); | |
127 | ||
128 | for (;;) { | |
129 | substdio_get(&from,&ch,1); | |
130 | if (ch == 'K') die_success(); | |
131 | if (ch == 'Z') die_temp(); | |
132 | if (ch == 'D') die_perm(); | |
133 | } | |
134 | } | |
135 | ||
136 | stralloc servers = {0}; | |
137 | ||
6d2736c0 MW |
138 | main(argc,argv) |
139 | int argc; | |
140 | char **argv; | |
212b6f5d MW |
141 | { |
142 | int i; | |
143 | int j; | |
144 | ||
145 | sig_pipeignore(); | |
146 | ||
6d2736c0 MW |
147 | if (!argv[1]) { /* std behavior */ |
148 | if (chdir(auto_qmail) == -1) die_home(); | |
149 | if (control_init() == -1) die_control(); | |
150 | if (control_readfile(&servers,"control/qmqpservers",0) != 1) die_control(); | |
212b6f5d | 151 | |
6d2736c0 | 152 | getmess(); |
212b6f5d | 153 | |
6d2736c0 MW |
154 | i = 0; |
155 | for (j = 0;j < servers.len;++j) | |
156 | if (!servers.s[j]) { | |
157 | doit(servers.s + i); | |
158 | i = j + 1; | |
159 | } | |
160 | } else { /* servers on cmd line */ | |
161 | ||
162 | getmess(); | |
163 | ||
164 | i = 1; | |
165 | while (argv[i]) | |
166 | doit(argv[i++]); | |
167 | } | |
212b6f5d MW |
168 | |
169 | _exit(lasterror); | |
170 | } |