3 * Completely reworked version of "citmail"
4 * This program attempts to act like a local MDA if you're using sendmail or
5 * some other non-Citadel MTA. It basically just forwards the message to
6 * the Citadel SMTP listener on some non-standard port.
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
28 #include "citadel_decls.h"
35 #define INADDR_NONE 0xffffffff
41 void strip_trailing_nonprint(char *buf)
43 while ( (strlen(buf)>0) && (!isprint(buf[strlen(buf) - 1])) )
44 buf[strlen(buf) - 1] = 0;
52 void timeout(int signum)
58 int connectsock(char *host, char *service, char *protocol)
63 struct sockaddr_in sin;
66 memset(&sin, 0, sizeof(sin));
67 sin.sin_family = AF_INET;
69 pse = getservbyname(service, protocol);
71 sin.sin_port = pse->s_port;
72 } else if ((sin.sin_port = htons((u_short) atoi(service))) == 0) {
73 fprintf(stderr, "Can't get %s service entry: %s\n",
74 service, strerror(errno));
77 phe = gethostbyname(host);
79 memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
80 } else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
81 fprintf(stderr, "Can't get %s host entry: %s\n",
82 host, strerror(errno));
85 if ((ppe = getprotobyname(protocol)) == 0) {
86 fprintf(stderr, "Can't get %s protocol entry: %s\n",
87 protocol, strerror(errno));
90 if (!strcmp(protocol, "udp")) {
96 s = socket(PF_INET, type, ppe->p_proto);
98 fprintf(stderr, "Can't create socket: %s\n", strerror(errno));
101 signal(SIGALRM, timeout);
104 if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
105 fprintf(stderr, "can't connect to %s.%s: %s\n",
106 host, service, strerror(errno));
110 signal(SIGALRM, SIG_IGN);
116 * convert service and host entries into a six-byte numeric in the format
117 * expected by a SOCKS v4 server
119 void numericize(char *buf, char *host, char *service, char *protocol)
123 struct sockaddr_in sin;
125 memset(&sin, 0, sizeof(sin));
126 sin.sin_family = AF_INET;
128 pse = getservbyname(service, protocol);
130 sin.sin_port = pse->s_port;
131 } else if ((sin.sin_port = htons((u_short) atoi(service))) == 0) {
132 fprintf(stderr, "Can't get %s service entry: %s\n",
133 service, strerror(errno));
136 buf[1] = (((sin.sin_port) & 0xFF00) >> 8);
137 buf[0] = ((sin.sin_port) & 0x00FF);
139 phe = gethostbyname(host);
141 memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
142 } else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE) {
143 fprintf(stderr, "Can't get %s host entry: %s\n",
144 host, strerror(errno));
147 buf[5] = ((sin.sin_addr.s_addr) & 0xFF000000) >> 24;
148 buf[4] = ((sin.sin_addr.s_addr) & 0x00FF0000) >> 16;
149 buf[3] = ((sin.sin_addr.s_addr) & 0x0000FF00) >> 8;
150 buf[2] = ((sin.sin_addr.s_addr) & 0x000000FF);
154 * input binary data from socket
156 void serv_read(char *buf, int bytes)
161 while (len < bytes) {
162 rlen = read(serv_sock, &buf[len], bytes - len);
172 * send binary to server
174 void serv_write(char *buf, int nbytes)
176 int bytes_written = 0;
178 while (bytes_written < nbytes) {
179 retval = write(serv_sock, &buf[bytes_written],
180 nbytes - bytes_written);
184 bytes_written = bytes_written + retval;
191 * input string from socket - implemented in terms of serv_read()
193 void serv_gets(char *buf)
197 /* Read one character at a time.
200 serv_read(&buf[i], 1);
201 if (buf[i] == '\n' || i == 255)
205 /* If we got a long line, discard characters until the newline.
208 while (buf[i] != '\n')
209 serv_read(&buf[i], 1);
211 /* Strip all trailing nonprintables (crlf)
214 strip_trailing_nonprint(buf);
219 * send line to server - implemented in terms of serv_write()
221 void serv_puts(char *buf)
223 /* printf("< %s\n", buf); */
224 serv_write(buf, strlen(buf));
232 void cleanup(int exitcode) {
237 fprintf(stderr, "%s\n", buf);
243 int main(int argc, char **argv) {
249 if (fp == NULL) return(errno);
250 sprintf(fromline, "From: someone@somewhere.org");
251 while (fgets(buf, 1024, stdin) != NULL) {
252 fprintf(fp, "%s", buf);
253 if (!strncasecmp(buf, "From:", 5)) strcpy(fromline, buf);
255 strip_trailing_nonprint(fromline);
257 sprintf(buf, "%d", SMTP_PORT);
258 serv_sock = connectsock("localhost", buf, "tcp");
260 fprintf(stderr, "%s\n", buf);
261 if (buf[0]!='2') cleanup(1);
263 serv_puts("HELO localhost");
265 fprintf(stderr, "%s\n", buf);
266 if (buf[0]!='2') cleanup(1);
268 sprintf(buf, "MAIL %s", fromline);
271 fprintf(stderr, "%s\n", buf);
272 if (buf[0]!='2') cleanup(1);
274 sprintf(buf, "RCPT To: %s", argv[1]);
277 fprintf(stderr, "%s\n", buf);
278 if (buf[0]!='2') cleanup(1);
282 fprintf(stderr, "%s\n", buf);
283 if (buf[0]!='3') cleanup(1);
286 while (fgets(buf, sizeof buf, fp) != NULL) {
287 strip_trailing_nonprint(buf);
292 fprintf(stderr, "%s\n", buf);
293 if (buf[0]!='2') cleanup(1);