1 #include <stdlib.h>
2 #include <string.h>
3 #include <unistd.h>
4 
5 #include <bglibs/systime.h>
6 #include <bglibs/iobuf.h>
7 #include <bglibs/msg.h>
8 #include <bglibs/str.h>
9 
10 #include "mailfront.h"
11 #include "qmtp.h"
12 
13 static const response* resp;
14 
15 static char buf[8192];
16 static str line;
17 
18 static void die(const char* msg) __NORETURN__;
die(const char * msg)19 static void die(const char* msg)
20 {
21   response r = { 451, msg };
22   respond(&r);
23   exit(111);
24 }
25 
get_wrapper(ibuf * in)26 static void get_wrapper(ibuf* in)
27 {
28   unsigned long wraplen;
29   switch (get_netstring_len(in, &wraplen)) {
30   case -1: exit(0);
31   case 0: die("Invalid wrapper netstring");
32   }
33 }
34 
get_body(ibuf * in)35 static void get_body(ibuf* in)
36 {
37   unsigned long bodylen;
38   char nl;
39   switch (get_netstring_len(in, &bodylen)) {
40   case -1: exit(0);
41   case 0: die("Invalid message body netstring");
42   }
43   if (bodylen == 0) die("Zero length message");
44   if (response_ok(resp))
45     resp = handle_data_start();
46   while (bodylen > 0) {
47     unsigned long len = sizeof buf;
48     if (len > bodylen) len = bodylen;
49     if (!ibuf_read(in, buf, len) && in->count == 0)
50       die("EOF while reading body");
51     if (response_ok(resp))
52       handle_data_bytes(buf, in->count);
53     bodylen -= in->count;
54   }
55   if (!ibuf_getc(in, &nl)) die("EOF while reading comma");
56   if (nl != ',') die("Invalid netstring terminator");
57 }
58 
get_sender(ibuf * in)59 static void get_sender(ibuf* in)
60 {
61   switch (get_netstring(in, &line)) {
62   case -1: die("EOF while reading sender address");
63   case 0: die("Invalid sender netstring");
64   }
65   msg3("sender <", line.s, ">");
66   if (response_ok(resp))
67     resp = handle_sender(&line, 0);
68 }
69 
get_recips(ibuf * in)70 static void get_recips(ibuf* in)
71 {
72   char ch;
73   while (ibuf_peek(in, &ch)) {
74     if (ch == ',') return;
75     switch (get_netstring(in, &line)) {
76     case -1: die("EOF while reading recipient list");
77     case 0: die("Invalid recipient netstring");
78     }
79     msg3("recipient <", line.s, ">");
80     if (response_ok(resp))
81       resp = handle_recipient(&line, 0);
82   }
83   die("EOF before end of recipient list");
84 }
85 
get_package(ibuf * in)86 static void get_package(ibuf* in)
87 {
88   resp = handle_reset();
89   get_wrapper(in);
90   get_body(in);
91   get_sender(in);
92   get_recips(in);
93   if (response_ok(resp))
94     resp = handle_message_end();
95   if (!resp) resp = &resp_accepted_message;
96   if (!respond(resp)) die("EOF while sending response");
97 }
98 
mainloop(const struct command * commands)99 static int mainloop(const struct command* commands)
100 {
101   alarm(3600);
102   get_package(&inbuf);
103   return 0;
104   (void)commands;
105 }
106 
107 struct protocol protocol = {
108   .version = PROTOCOL_VERSION,
109   .name = "QMQP",
110   .respond_line = qmtp_respond_line,
111   .mainloop = mainloop,
112 };
113