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