qmail-qmqpc.c
changeset 0 068428edee47
equal deleted inserted replaced
-1:000000000000 0:068428edee47
       
     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 }