]> code.citadel.org Git - citadel.git/blob - citadel/serv_network.c
aef3fdca829a7a3b10a2f9483bf46d4628e3f8e1
[citadel.git] / citadel / serv_network.c
1 /*
2  * $Id$ 
3  *
4  * This module will eventually replace netproc and some of its utilities.
5  * Copyright (C) 2000 by Art Cancro and others.
6  * This code is released under the terms of the GNU General Public License.
7  *
8  */
9
10
11 /* FIXME
12
13 there's stuff in here that makes the assumption that /tmp is on the same
14 filesystem as Citadel, and makes calls to link() on that basis.  fix this.
15
16 */
17
18 #include "sysdep.h"
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <stdio.h>
22 #include <fcntl.h>
23 #include <signal.h>
24 #include <pwd.h>
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <sys/time.h>
28 #include <sys/wait.h>
29 #include <string.h>
30 #include <limits.h>
31 #include "citadel.h"
32 #include "server.h"
33 #include <time.h>
34 #include "sysdep_decls.h"
35 #include "citserver.h"
36 #include "support.h"
37 #include "config.h"
38 #include "dynloader.h"
39 #include "room_ops.h"
40 #include "user_ops.h"
41 #include "policy.h"
42 #include "database.h"
43 #include "msgbase.h"
44 #include "tools.h"
45 #include "internet_addressing.h"
46 #include "serv_network.h"
47
48
49 void cmd_gnet(char *argbuf) {
50         char filename[256];
51         char buf[256];
52         FILE *fp;
53
54         if (CtdlAccessCheck(ac_room_aide)) return;
55         assoc_file_name(filename, &CC->quickroom, "netconfigs");
56         cprintf("%d Network settings for room #%ld <%s>\n",
57                 LISTING_FOLLOWS,
58                 CC->quickroom.QRnumber, CC->quickroom.QRname);
59
60         fp = fopen(filename, "r");
61         if (fp != NULL) {
62                 while (fgets(buf, sizeof buf, fp) != NULL) {
63                         buf[strlen(buf)-1] = 0;
64                         cprintf("%s\n", buf);
65                 }
66                 fclose(fp);
67         }
68
69         cprintf("000\n");
70 }
71
72
73 void cmd_snet(char *argbuf) {
74         char tempfilename[256];
75         char filename[256];
76         char buf[256];
77         FILE *fp;
78
79         if (CtdlAccessCheck(ac_room_aide)) return;
80         safestrncpy(tempfilename, tmpnam(NULL), sizeof tempfilename);
81         assoc_file_name(filename, &CC->quickroom, "netconfigs");
82
83         fp = fopen(tempfilename, "w");
84         if (fp == NULL) {
85                 cprintf("%d Cannot open %s: %s\n",
86                         ERROR+INTERNAL_ERROR,
87                         tempfilename,
88                         strerror(errno));
89         }
90
91         cprintf("%d %s\n", SEND_LISTING, tempfilename);
92         while (client_gets(buf), strcmp(buf, "000")) {
93                 fprintf(fp, "%s\n", buf);
94         }
95         fclose(fp);
96
97         /* Now that we've got the whole file, put it in place */
98         unlink(filename);
99         link(tempfilename, filename);
100         unlink(tempfilename);
101 }
102
103
104
105 /*
106  * Spools out one message from the list.
107  */
108 void network_spool_msg(long msgnum, void *userdata) {
109         struct SpoolControl *sc;
110         struct namelist *nptr;
111         int err;
112         char *instr = NULL;
113         int instr_len = 0;
114         struct CtdlMessage *imsg;
115
116         sc = (struct SpoolControl *)userdata;
117
118         /* If no recipients, bail out now.
119          * (May need to tweak this when we add other types of targets)
120          */
121         if (sc->listrecps == NULL) return;
122         
123         /* First, copy it to the spoolout room */
124         err = CtdlSaveMsgPointerInRoom(SMTP_SPOOLOUT_ROOM, msgnum, 0);
125         if (err != 0) return;
126
127         lprintf(9, "Generating delivery instructions\n");
128         instr_len = 4096;
129         instr = mallok(instr_len);
130         sprintf(instr,
131                 "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n"
132                 "bounceto|postmaster@%s\n" ,
133                 SPOOLMIME, msgnum, time(NULL), config.c_fqdn );
134
135         imsg = mallok(sizeof(struct CtdlMessage));
136         memset(imsg, 0, sizeof(struct CtdlMessage));
137         imsg->cm_magic = CTDLMESSAGE_MAGIC;
138         imsg->cm_anon_type = MES_NORMAL;
139         imsg->cm_format_type = FMT_RFC822;
140         imsg->cm_fields['A'] = strdoop("Citadel");
141         imsg->cm_fields['M'] = instr;
142
143         /* Generate delivery instructions for each recipient */
144         for (nptr = sc->listrecps; nptr != NULL; nptr = nptr->next) {
145                 if (instr_len - strlen(instr) < 256) {
146                         instr_len = instr_len * 2;
147                         instr = reallok(instr, instr_len);
148                 }
149                 sprintf(&instr[strlen(instr)], "remote|%s|0||\n",
150                         nptr->name);
151         }
152
153         /* Save delivery instructions in spoolout room */
154         CtdlSaveMsg(imsg, "", SMTP_SPOOLOUT_ROOM, MES_LOCAL);
155         CtdlFreeMessage(imsg);
156
157         /* update lastsent */
158         sc->lastsent = msgnum;
159 }
160
161
162
163
164 /*
165  * Batch up and send all outbound traffic from the current room
166  */
167 void network_spoolout_current_room(void) {
168         char filename[256];
169         char buf[256];
170         char instr[256];
171         FILE *fp;
172         struct SpoolControl sc;
173         /* struct namelist *digestrecps = NULL; */
174         struct namelist *nptr;
175
176         memset(&sc, 0, sizeof(struct SpoolControl));
177         assoc_file_name(filename, &CC->quickroom, "netconfigs");
178
179         fp = fopen(filename, "r");
180         if (fp == NULL) {
181                 lprintf(7, "Outbound batch processing skipped for <%s>\n",
182                         CC->quickroom.QRname);
183                 return;
184         }
185
186         lprintf(5, "Outbound batch processing started for <%s>\n",
187                 CC->quickroom.QRname);
188
189         while (fgets(buf, sizeof buf, fp) != NULL) {
190                 buf[strlen(buf)-1] = 0;
191
192                 extract(instr, buf, 0);
193                 if (!strcasecmp(instr, "lastsent")) {
194                         sc.lastsent = extract_long(buf, 1);
195                 }
196                 else if (!strcasecmp(instr, "listrecp")) {
197                         nptr = (struct namelist *)
198                                 mallok(sizeof(struct namelist));
199                         nptr->next = sc.listrecps;
200                         extract(nptr->name, buf, 1);
201                         sc.listrecps = nptr;
202                 }
203
204
205         }
206         fclose(fp);
207
208
209         /* Do something useful */
210         CtdlForEachMessage(MSGS_ALL, 0L, (-63), NULL, NULL,
211                 network_spool_msg, &sc);
212
213
214         /* Now rewrite the config file */
215         fp = fopen(filename, "w");
216         if (fp == NULL) {
217                 lprintf(1, "ERROR: cannot open %s: %s\n",
218                         filename, strerror(errno));
219         }
220         else {
221                 fprintf(fp, "lastsent|%ld\n", sc.lastsent);
222
223                 /* Write out the listrecps while freeing from memory at the
224                  * same time.  Am I clever or what?  :)
225                  */
226                 while (sc.listrecps != NULL) {
227                         fprintf(fp, "listrecp|%s\n", sc.listrecps->name);
228                         nptr = sc.listrecps->next;
229                         phree(sc.listrecps);
230                         sc.listrecps = nptr;
231                 }
232
233                 fclose(fp);
234         }
235
236         lprintf(5, "Outbound batch processing finished for <%s>\n",
237                 CC->quickroom.QRname);
238 }
239
240
241
242 /* FIXME temporary server command for batch send */
243 void cmd_batc(char *argbuf) {
244         if (CtdlAccessCheck(ac_aide)) return;
245
246         network_spoolout_current_room();
247
248         cprintf("%d FIXME cmd_batc() ok\n", OK);
249 }
250
251
252
253 char *Dynamic_Module_Init(void)
254 {
255         CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config");
256         CtdlRegisterProtoHook(cmd_snet, "SNET", "Get network config");
257
258         /* FIXME
259            temporary server command for batch send
260          */
261         CtdlRegisterProtoHook(cmd_batc, "BATC", "send out batch (temp)");
262
263         return "$Id$";
264 }