|
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 |
|
138 main() |
|
139 { |
|
140 int i; |
|
141 int j; |
|
142 |
|
143 sig_pipeignore(); |
|
144 |
|
145 if (chdir(auto_qmail) == -1) die_home(); |
|
146 if (control_init() == -1) die_control(); |
|
147 if (control_readfile(&servers,"control/qmqpservers",0) != 1) die_control(); |
|
148 |
|
149 getmess(); |
|
150 |
|
151 i = 0; |
|
152 for (j = 0;j < servers.len;++j) |
|
153 if (!servers.s[j]) { |
|
154 doit(servers.s + i); |
|
155 i = j + 1; |
|
156 } |
|
157 |
|
158 _exit(lasterror); |
|
159 } |