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