7de5c419f68b4bd57fb2d29055b7eca7481c8621
[citadel.git] / citadel / netmailer.c
1 /*
2  * netmailer for Citadel/UX
3  * see copyright.doc for copyright information
4  *
5  * netproc calls this to export Citadel mail to RFC822-compliant mailers.
6  * $Id$
7  */
8
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <stdio.h>
12 #include <fcntl.h>
13 #include <time.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <limits.h>
17 #include <syslog.h>
18 #include "citadel.h"
19 #include "genstamp.h"
20
21 void LoadInternetConfig(void);
22 void get_config(void);
23 struct config config;
24
25 char temp[PATH_MAX];
26
27 char ALIASES[128];
28 char CIT86NET[128];
29 char SENDMAIL[128];
30 char FALLBACK[128];
31 char GW_DOMAIN[128];
32 char TABLEFILE[128];
33 int RUN_NETPROC = 1;
34
35 int haschar(char *st, int ch)
36 {
37         int a, b;
38         b = 0;
39         for (a = 0; a < strlen(st); ++a)
40                 if (st[a] == ch)
41                         ++b;
42         return (b);
43 }
44
45
46
47 void fpgetfield(FILE * fp, char *string)
48 {
49         int a, b;
50         strcpy(string, "");
51         a = 0;
52         do {
53                 b = getc(fp);
54                 if (b < 1) {
55                         string[a] = 0;
56                         return;
57                 }
58                 string[a] = b;
59                 ++a;
60         } while (b != 0);
61 }
62
63
64 /* This is NOT the same msgform() found in the main program. It has been
65  * modified to format 80 columns into a temporary file, and extract the
66  * sender and recipient names for use within the main() loop.
67  */
68 void msgform(char *msgfile, FILE * mfout, char *sbuf, char *rbuf, char *nbuf,
69                 char *pbuf, time_t * mid_buf, char *rmname, char *subj)
70                         /* sender */
71                         /* recipient (in this case, an Internet address) */
72                         /* source node */
73                         /* path */
74                         /* message ID */
75                         /* room name */
76                         /* subject */
77 {
78         int a, b, c, e, old, mtype, aflag;
79         int real = 0;
80         char aaa[128], bbb[128];
81         FILE *fp;
82         int width;
83         int generate_subject = 1;
84
85         strcpy(subj, "");
86         strcpy(pbuf, "");
87         strcpy(nbuf, NODENAME);
88         strcpy(rmname, "");
89         time(mid_buf);
90         width = 80;
91         fp = fopen(msgfile, "rb");
92         if (fp == NULL) {
93                 fprintf(stderr, "netmailer: can't open message file\n");
94                 return;
95         }
96         strcpy(aaa, "");
97         old = 255;
98         c = 1;                  /* c is the current pos */
99         e = getc(fp);
100         if (e != 255) {
101                 fprintf(stderr, "netmailer: This is not a Citadel message.\n");
102                 goto END;
103         }
104         mtype = getc(fp);
105         aflag = getc(fp);
106         goto BONFGM;
107
108 A:      if (aflag == 1)
109                 goto AFLAG;
110         old = real;
111         a = getc(fp);
112         real = a;
113         if (a == 0)
114                 goto END;
115         if (a < 0)
116                 goto END;
117
118         /* generate subject... */
119         if ((generate_subject == 1) && (strlen(subj) < 60)) {
120                 subj[strlen(subj) + 1] = 0;
121                 subj[strlen(subj)] = (((a > 31) && (a < 127)) ? a : 32);
122         }
123         if (((a == 13) || (a == 10)) && (old != 13) && (old != 10))
124                 a = 32;
125         if (((old == 13) || (old == 10)) && ((real == 32) || (real == 13) || (real == 10))) {
126                 fprintf(mfout, "\n");
127                 c = 1;
128         }
129         if (a != 32) {
130                 if (((strlen(aaa) + c) > (width - 5)) && (strlen(aaa) > (width - 5))) {
131                         fprintf(mfout, "\n%s", aaa);
132                         c = strlen(aaa);
133                         aaa[0] = 0;
134                 }
135                 b = strlen(aaa);
136                 aaa[b] = a;
137                 aaa[b + 1] = 0;
138         }
139         if (a == 32) {
140                 if ((strlen(aaa) + c) > (width - 5)) {
141                         fprintf(mfout, "\n");
142                         c = 1;
143                 }
144                 fprintf(mfout, "%s ", aaa);
145                 ++c;
146                 c = c + strlen(aaa);
147                 strcpy(aaa, "");
148                 goto A;
149         }
150         if ((a == 13) || (a == 10)) {
151                 fprintf(mfout, "%s\n", aaa);
152                 c = 1;
153                 strcpy(aaa, "");
154                 goto A;
155         }
156         goto A;
157
158 AFLAG:  a = getc(fp);
159         if (a == 0)
160                 goto END;
161         if (a == 13) {
162                 putc(10, mfout);
163         } else {
164                 putc(a, mfout);
165         }
166         goto AFLAG;
167
168 END:    fclose(fp);
169         return;
170
171 BONFGM: b = getc(fp);
172         if (b < 0)
173                 goto END;
174         if (b == 'M')
175                 goto A;
176         fpgetfield(fp, bbb);
177         if (b == 'A')
178                 strcpy(sbuf, bbb);
179         if (b == 'R')
180                 strcpy(rbuf, bbb);
181         if (b == 'N')
182                 strcpy(nbuf, bbb);
183         if (b == 'P')
184                 strcpy(pbuf, bbb);
185         if (b == 'I')
186                 *mid_buf = atol(bbb);
187         if (b == 'O')
188                 strcpy(rmname, bbb);
189         if (b == 'U') {
190                 strcpy(subj, bbb);
191                 generate_subject = 0;   /* have a real subj so don't gen one */
192         }
193         goto BONFGM;
194 }
195
196 int main(int argc, char **argv)
197 {
198         int a;
199         FILE *fp, *rmail;
200         char sbuf[200], rbuf[200], cstr[100], fstr[128];
201         char nbuf[64], pbuf[128], rmname[128], buf[128];
202         char datestamp[256];
203         char subject[256];
204         time_t mid_buf;
205         time_t now;
206         int mlist = 0;
207
208         openlog("netmailer", LOG_PID, LOG_USER);
209         get_config();
210         LoadInternetConfig();
211         sprintf(temp, tmpnam(NULL));    /* temp file name */
212
213         if ((argc < 2) || (argc > 3)) {
214                 fprintf(stderr, "netmailer: usage: "
215                         "netmailer <filename> [mlist]\n");
216                 exit(1);
217         }
218         /*
219          * If we are running in mailing list mode, the room is being two-way
220          * gatewayed to an Internet mailing list.  Since many listprocs only
221          * accept postings from subscribed addresses, we must always use the
222          * room's address as the originating user.
223          */
224         if ((argc == 3) && (!strcasecmp(argv[2], "mlist"))) {
225                 mlist = 1;
226         }
227         /* convert to ASCII & get info */
228         fp = fopen(temp, "w");
229         msgform(argv[1], fp, sbuf, rbuf, nbuf, pbuf, &mid_buf, rmname, subject);
230         fclose(fp);
231
232         strcpy(buf, rmname);
233         strcpy(rmname, "room_");
234         strcat(rmname, buf);
235         for (a = 0; a < strlen(rmname); ++a) {
236                 if (rmname[a] == ' ')
237                         rmname[a] = '_';
238                 rmname[a] = tolower(rmname[a]);
239         }
240
241         sprintf(cstr, SENDMAIL, rbuf);
242         rmail = (FILE *) popen(cstr, "w");
243
244         strcpy(fstr, sbuf);
245         for (a = 0; a < strlen(sbuf); ++a)
246                 if (sbuf[a] == 32)
247                         sbuf[a] = '_';
248         for (a = 0; a < strlen(rbuf); ++a)
249                 if (rbuf[a] == 32)
250                         rbuf[a] = '_';
251
252         /*
253          * This logic attempts to compose From and From: lines that are
254          * as RFC822-compliant as possible.  The return addresses are correct
255          * if you're using Citadel's 'citmail' delivery agent to allow BBS
256          * users to receive Internet mail.
257          */
258         fprintf(rmail, "From ");
259         if (strcasecmp(nbuf, NODENAME))
260                 fprintf(rmail, "%s!", nbuf);
261
262         if (!strcasecmp(nbuf, NODENAME))
263                 strcpy(nbuf, FQDN);
264
265         if (mlist) {
266                 fprintf(rmail, "%s\n", rmname);
267                 fprintf(rmail, "From: %s@%s (%s)\n", rmname, FQDN, fstr);
268         } else {
269
270                 if (!strcasecmp(nbuf, NODENAME)) {      /* from this system */
271                         fprintf(rmail, "%s\n", pbuf);
272                         fprintf(rmail, "From: %s@%s (%s)\n",
273                                 sbuf, FQDN, fstr);
274                 } else if (haschar(nbuf, '.')) {        /* from an FQDN */
275                         fprintf(rmail, "%s\n", sbuf);
276                         fprintf(rmail, "From: %s@%s (%s)\n",
277                                 sbuf, nbuf, fstr);
278                 } else {        /* from another Cit */
279                         fprintf(rmail, "%s\n", sbuf);
280                         fprintf(rmail, "From: %s@%s.%s (%s)\n",
281                                 sbuf, nbuf, GW_DOMAIN, fstr);
282                 }
283
284         }
285
286         /*
287          * Everything else is pretty straightforward.
288          */
289         fprintf(rmail, "To: %s\n", rbuf);
290         time(&now);
291         generate_rfc822_datestamp(datestamp, now);
292         fprintf(rmail, "Date: %s\n", datestamp);
293         fprintf(rmail, "Message-Id: <%ld@%s>\n", (long) mid_buf, nbuf);
294         fprintf(rmail, "X-Mailer: %s\n", CITADEL);
295         fprintf(rmail, "Subject: %s\n", subject);
296         fprintf(rmail, "\n");
297         fp = fopen(temp, "r");
298         if (fp != NULL) {
299                 do {
300                         a = getc(fp);
301                         if (a >= 0)
302                                 putc(a, rmail);
303                 } while (a >= 0);
304                 fclose(fp);
305         }
306         fprintf(rmail, "\n");
307         pclose(rmail);
308
309         unlink(temp);           /* get rid of the ASCII file */
310         execlp("./netproc", "netproc", "-i", NULL);
311         exit(0);                /* go back to the main program */
312 }