qmail-qmqpc.c (3778B)
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 GEN_SAFE_TIMEOUTREAD(saferead,60,qmqpfd,die_conn()) 38 GEN_SAFE_TIMEOUTWRITE(safewrite,60,qmqpfd,die_conn()) 39 40 char buf[1024]; 41 substdio to = SUBSTDIO_FDBUF(safewrite,-1,buf,sizeof(buf)); 42 substdio from = SUBSTDIO_FDBUF(saferead,-1,buf,sizeof(buf)); 43 substdio envelope = SUBSTDIO_FDBUF(read,1,buf,sizeof(buf)); 44 /* WARNING: can use only one of these at a time! */ 45 46 stralloc beforemessage = {0}; 47 stralloc message = {0}; 48 stralloc aftermessage = {0}; 49 50 char strnum[FMT_ULONG]; 51 stralloc line = {0}; 52 53 void getmess() 54 { 55 int match; 56 57 if (slurpclose(0,&message,1024) == -1) die_read(); 58 59 strnum[fmt_ulong(strnum,(unsigned long) message.len)] = 0; 60 if (!stralloc_copys(&beforemessage,strnum)) nomem(); 61 if (!stralloc_cats(&beforemessage,":")) nomem(); 62 if (!stralloc_copys(&aftermessage,",")) nomem(); 63 64 if (getln(&envelope,&line,&match,'\0') == -1) die_read(); 65 if (!match) die_format(); 66 if (line.len < 2) die_format(); 67 if (line.s[0] != 'F') die_format(); 68 69 strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0; 70 if (!stralloc_cats(&aftermessage,strnum)) nomem(); 71 if (!stralloc_cats(&aftermessage,":")) nomem(); 72 if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem(); 73 if (!stralloc_cats(&aftermessage,",")) nomem(); 74 75 for (;;) { 76 if (getln(&envelope,&line,&match,'\0') == -1) die_read(); 77 if (!match) die_format(); 78 if (line.len < 2) break; 79 if (line.s[0] != 'T') 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 } 88 89 void doit(server) 90 char *server; 91 { 92 struct ip_address ip; 93 char ch; 94 95 if (!ip_scan(server,&ip)) return; 96 97 qmqpfd = socket(AF_INET,SOCK_STREAM,0); 98 if (qmqpfd == -1) die_socket(); 99 100 if (timeoutconn(qmqpfd,&ip,PORT_QMQP,10) != 0) { 101 lasterror = 73; 102 if (errno == error_timeout) lasterror = 72; 103 close(qmqpfd); 104 return; 105 } 106 107 strnum[fmt_ulong(strnum,(unsigned long) (beforemessage.len + message.len + aftermessage.len))] = 0; 108 substdio_puts(&to,strnum); 109 substdio_puts(&to,":"); 110 substdio_put(&to,beforemessage.s,beforemessage.len); 111 substdio_put(&to,message.s,message.len); 112 substdio_put(&to,aftermessage.s,aftermessage.len); 113 substdio_puts(&to,","); 114 substdio_flush(&to); 115 116 for (;;) { 117 substdio_get(&from,&ch,1); 118 if (ch == 'K') die_success(); 119 if (ch == 'Z') die_temp(); 120 if (ch == 'D') die_perm(); 121 } 122 } 123 124 stralloc servers = {0}; 125 126 int 127 main() 128 { 129 int i; 130 int j; 131 132 sig_pipeignore(); 133 134 if (chdir(auto_qmail) == -1) die_home(); 135 if (control_init() == -1) die_control(); 136 if (control_readfile(&servers,"control/qmqpservers",0) != 1) die_control(); 137 138 getmess(); 139 140 i = 0; 141 for (j = 0;j < servers.len;++j) 142 if (!servers.s[j]) { 143 doit(servers.s + i); 144 i = j + 1; 145 } 146 147 return lasterror; 148 }