]> code.citadel.org Git - citadel.git/blob - citadel/serv_upgrade.c
* Fixed serv_upgrade.c and export5.c (found elsewhere) to use a new
[citadel.git] / citadel / serv_upgrade.c
1 /*
2  * This module imports an "unpacked" system.  The unpacked data may come from
3  * an older version of Citadel, or a different hardware architecture, or
4  * whatever.  You should only run an import when your installed system is
5  * brand new and _empty_ !!
6  *
7  * $Id$
8  */
9
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <stdio.h>
13 #include <fcntl.h>
14 #include <signal.h>
15 #include <pwd.h>
16 #include <errno.h>
17 #include <sys/types.h>
18 #include <sys/time.h>
19 #include <sys/wait.h>
20 #include <string.h>
21 #include <limits.h>
22 #include <pthread.h>
23 #include "citadel.h"
24 #include "server.h"
25 #include <syslog.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 "database.h"
34 #include "control.h"
35
36 extern struct CitContext *ContextList;
37 FILE *imfp, *exfp;
38
39 #define MODULE_NAME     "Import an unpacked system"
40 #define MODULE_AUTHOR   "Art Cancro"
41 #define MODULE_EMAIL    "ajc@uncnsrd.mt-kisco.ny.us"
42 #define MAJOR_VERSION   0
43 #define MINOR_VERSION   3
44
45 static struct DLModule_Info info = {
46         MODULE_NAME,
47         MODULE_AUTHOR,
48         MODULE_EMAIL,
49         MAJOR_VERSION,
50         MINOR_VERSION
51         };
52
53
54
55 void fpgetfield(FILE *fp, char *string)
56 {
57         int a,b;
58         strcpy(string,"");
59         a=0;
60         do {
61                 b=getc(fp);
62                 if (b<1) {
63                         string[a]=0;
64                         return;
65                         }
66                 string[a]=b;
67                 ++a;
68                 } while (b!=0);
69         }
70
71
72 void import_message(long msgnum, long msglen) {
73         char *msgtext;
74
75         msgtext = malloc(msglen);
76         if (msgtext == NULL) {
77                 lprintf(3, "ERROR: cannot allocate memory\n");
78                 lprintf(3, "Your data files are now corrupt.\n");
79                 fclose(imfp);
80                 exit(1);
81                 }
82
83         fread(msgtext, msglen, 1, imfp);
84         cdb_store(CDB_MSGMAIN, &msgnum, sizeof(long), msgtext, msglen);
85         free(msgtext);
86         }
87
88 void imp_floors(void) {
89         char key[256], tag[256], tval[256];
90         struct floor fl;
91         int floornum = 0;
92
93
94         while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
95
96                 if (!strcasecmp(key, "floor")) {
97                         bzero(&fl, sizeof(struct floor));
98
99                         while(fpgetfield(imfp, tag),
100                              strcasecmp(tag, "endfloor")) {
101                                 fpgetfield(imfp, tval);
102
103                                 if (!strcasecmp(tag, "f_flags")) 
104                                         fl.f_flags = atoi(tval);
105                                 if (!strcasecmp(tag, "f_name")) {
106                                         lprintf(9, "Floor <%s>\n", tval);
107                                         strcpy(fl.f_name, tval);        
108                                         }
109                                 if (!strcasecmp(tag, "f_ref_count")) 
110                                         fl.f_ref_count = atoi(tval);
111                                 if (!strcasecmp(tag, "f_expire_mode")) 
112                                         fl.f_ep.expire_mode = atoi(tval);
113                                 if (!strcasecmp(tag, "f_expire_value")) 
114                                         fl.f_ep.expire_value = atoi(tval);
115                                 }
116
117                         putfloor(&fl, floornum);
118                         ++floornum;
119                         }
120                 else {
121                         lprintf(3, "ERROR: invalid floor section.\n");
122                         lprintf(3, "Your data files are now corrupt.\n");
123                         fclose(imfp);
124                         return;
125                         }
126                 }
127         }
128
129
130
131 void imp_rooms(void) {
132         char key[256];
133         char tag[256], tval[256];
134         struct quickroom qr;
135         long *msglist;
136         int num_msgs = 0;
137         long msgnum, msglen;
138         
139         while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
140                 if (!strcasecmp(key, "room")) {
141                         bzero(&qr, sizeof(struct quickroom));
142                         msglist = NULL;
143                         num_msgs = 0;
144                         lprintf(9, "Room ");
145
146                         while(fpgetfield(imfp, tag),
147                              strcasecmp(tag, "endroom")) {
148                                 if (strcasecmp(tag, "message")) {
149                                         fpgetfield(imfp, tval);
150                                         }
151                                 else {
152                                         strcpy(tval, "");
153                                         }
154
155                                 if (!strcasecmp(tag, "qrname")) {
156                                         strcpy(qr.QRname, tval);
157                                         lprintf(9, "<%s> ", qr.QRname);
158                                         }
159                                 if (!strcasecmp(tag, "qrnumber"))
160                                         qr.QRnumber = atol(tval);
161                                 if (!strcasecmp(tag, "qrpasswd"))
162                                         strcpy(qr.QRpasswd, tval);
163                                 if (!strcasecmp(tag, "qrroomaide"))
164                                         qr.QRroomaide = atol(tval);
165                                 if (!strcasecmp(tag, "qrhighest"))
166                                         qr.QRhighest = atol(tval);
167                                 if (!strcasecmp(tag, "qrgen"))
168                                         qr.QRgen = atol(tval);
169                                 if (!strcasecmp(tag, "qrflags"))
170                                         qr.QRflags = atoi(tval);
171                                 if (!strcasecmp(tag, "qrdirname"))
172                                         strcpy(qr.QRdirname, tval);
173                                 if (!strcasecmp(tag, "qrinfo"))
174                                         qr.QRinfo = atol(tval);
175                                 if (!strcasecmp(tag, "qrfloor"))
176                                         qr.QRfloor = atoi(tval);
177                                 if (!strcasecmp(tag, "qrmtime"))
178                                         qr.QRmtime = atol(tval);
179                                 if (!strcasecmp(tag, "qrepmode"))
180                                         qr.QRep.expire_mode = atoi(tval);
181                                 if (!strcasecmp(tag, "qrepvalue"))
182                                         qr.QRep.expire_value = atoi(tval);
183                                 if (!strcasecmp(tag, "message")) {
184                                         fpgetfield(imfp, tval);
185                                         msgnum = atol(tval);
186                                         fpgetfield(imfp, tval);
187                                         msglen = atol(tval);
188                                         import_message(msgnum, msglen);
189                                         ++num_msgs;
190                                         msglist = realloc(msglist,
191                                                 (sizeof(long)*num_msgs) );
192                                         msglist[num_msgs - 1] = msgnum;
193                                         }
194
195                                 }
196
197                         lprintf(9, "(%d messages)\n", num_msgs);
198                         if (qr.QRflags&QR_INUSE) {
199                                 putroom(&qr, qr.QRname);
200                                 }
201
202                         if (num_msgs > 0) {
203                                 if (qr.QRflags&QR_INUSE) {
204                                         CC->msglist = msglist;
205                                         CC->num_msgs = num_msgs;
206                                         put_msglist(&qr);
207                                         }
208                                 free(msglist);
209                                 }
210
211                         }
212                 else {
213                         lprintf(3, "ERROR: invalid room section.\n");
214                         lprintf(3, "Your data files are now corrupt.\n");
215                         fclose(imfp);
216                         return;
217                         }
218                 }
219         }
220
221
222
223 void import_a_user(void) {
224         char key[256], value[256];
225         struct usersupp us;
226
227         bzero(&us, sizeof(struct usersupp));    
228         while(fpgetfield(imfp, key), strcasecmp(key, "enduser")) {
229                 if (strcasecmp(key, "mail")) {
230                         fpgetfield(imfp, value);
231                         }
232                 else {
233                         strcpy(value, "");
234                         }
235
236                 if (!strcasecmp(key, "usuid"))
237                         us.USuid = atoi(value);
238                 if (!strcasecmp(key, "password")) {
239                         strcpy(us.password, value);
240                         }
241
242                 if (!strcasecmp(key, "flags"))
243                         us.flags = atoi(value);
244                 if (!strcasecmp(key, "timescalled"))
245                         us.timescalled = atoi(value);
246                 if (!strcasecmp(key, "posted"))
247                         us.posted = atoi(value);
248                 if (!strcasecmp(key, "fullname")) {
249                         strcpy(us.fullname, value);
250                         lprintf(9, "User <%s> ", us.fullname);
251                         }
252                 if (!strcasecmp(key, "axlevel"))
253                         us.axlevel = atoi(value);
254                 if (!strcasecmp(key, "usscreenwidth"))
255                         us.USscreenwidth = atoi(value);
256                 if (!strcasecmp(key, "usscreenheight"))
257                         us.USscreenheight = atoi(value);
258                 if (!strcasecmp(key, "usernum")) {
259                         us.usernum = atol(value);
260                         lprintf(9, "<#%ld> ", us.usernum);
261                         }
262                 if (!strcasecmp(key, "lastcall"))
263                         us.lastcall = atol(value);
264                 if (!strcasecmp(key, "usname"))
265                         strcpy(us.USname, value);
266                 if (!strcasecmp(key, "usaddr"))
267                         strcpy(us.USaddr, value);
268                 if (!strcasecmp(key, "uscity"))
269                         strcpy(us.UScity, value);
270                 if (!strcasecmp(key, "usstate"))
271                         strcpy(us.USstate, value);
272                 if (!strcasecmp(key, "uszip"))
273                         strcpy(us.USzip, value);
274                 if (!strcasecmp(key, "usphone"))
275                         strcpy(us.USphone, value);
276                 if (!strcasecmp(key, "usemail"))
277                         strcpy(us.USemail, value);
278                 if (!strcasecmp(key, "ususerpurge")) {
279                         us.USuserpurge = atoi(value);
280                         }
281                 }
282         
283         putuser(&us, us.fullname);
284
285         lprintf(9, "\n");
286         }
287
288
289 void imp_usersupp(void) {
290         char key[256], value[256];
291         
292         while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
293                 if (strcasecmp(key, "user")) {
294                         fpgetfield(imfp, value);
295                         }
296                 else {
297                         strcpy(value, "");
298                         }
299
300                 if (!strcasecmp(key, "user")) {
301                         import_a_user();
302                         }
303                 }               
304         }
305
306
307 void imp_globals(void) {
308         char key[256], value[256];
309
310         get_control();
311         while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
312                 fpgetfield(imfp, value);
313                 lprintf(9, " %s = %s\n", key, value);
314
315                 if (!strcasecmp(key, "mmhighest"))
316                         CitControl.MMhighest = atol(value);
317                 if (!strcasecmp(key, "mmnextuser"))
318                         CitControl.MMnextuser = atol(value);
319                 if (!strcasecmp(key, "mmnextroom"))
320                         CitControl.MMnextroom = atol(value);
321
322                 }
323         put_control();
324         }
325
326
327
328 void imp_config(void) { 
329         char key[256], value[256];
330         FILE *fp;
331
332         while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
333                 fpgetfield(imfp, value);
334                 lprintf(9, " %s = %s\n", key, value);
335
336                 if (!strcasecmp(key, "c_nodename"))
337                         strcpy(config.c_nodename, value);
338                 if (!strcasecmp(key, "c_fqdn"))
339                         strcpy(config.c_fqdn, value);
340                 if (!strcasecmp(key, "c_humannode"))
341                         strcpy(config.c_humannode, value);
342                 if (!strcasecmp(key, "c_phonenum"))
343                         strcpy(config.c_phonenum, value);
344                 if (!strcasecmp(key, "c_phonenum"))
345                         strcpy(config.c_phonenum, value);
346                 if (!strcasecmp(key, "c_bbsuid"))
347                         config.c_bbsuid = atoi(value);
348                 if (!strcasecmp(key, "c_creataide"))
349                         config.c_creataide = atoi(value);
350                 if (!strcasecmp(key, "c_sleeping"))
351                         config.c_sleeping = atoi(value);
352                 if (!strcasecmp(key, "c_initax"))
353                         config.c_initax = atoi(value);
354                 if (!strcasecmp(key, "c_regiscall"))
355                         config.c_regiscall = atoi(value);
356                 if (!strcasecmp(key, "c_twitdetect"))
357                         config.c_twitdetect = atoi(value);
358                 if (!strcasecmp(key, "c_twitroom"))
359                         strcpy(config.c_twitroom, value);
360                 if (!strcasecmp(key, "c_moreprompt"))
361                         strcpy(config.c_moreprompt, value);
362                 if (!strcasecmp(key, "c_restrict"))
363                         config.c_restrict = atoi(value);
364                 if (!strcasecmp(key, "c_bbs_city"))
365                         strcpy(config.c_bbs_city, value);
366                 if (!strcasecmp(key, "c_sysadm"))
367                         strcpy(config.c_sysadm, value);
368                 if (!strcasecmp(key, "c_bucket_dir"))
369                         strcpy(config.c_bucket_dir, value);
370                 if (!strcasecmp(key, "c_setup_level"))
371                         config.c_setup_level = atoi(value);
372                 if (!strcasecmp(key, "c_maxsessions"))
373                         config.c_maxsessions = atoi(value);
374                 if (!strcasecmp(key, "c_net_password"))
375                         strcpy(config.c_net_password, value);
376                 if (!strcasecmp(key, "c_port_number"))
377                         config.c_port_number = atoi(value);
378                 if (!strcasecmp(key, "c_expire_policy"))
379                         config.c_ep.expire_mode = atoi(value);
380                 if (!strcasecmp(key, "c_expire_value"))
381                         config.c_ep.expire_value = atoi(value);
382                 if (!strcasecmp(key, "c_userpurge"))
383                         config.c_userpurge = atoi(value);
384                 }
385
386         fp = fopen("citadel.config", "wb");
387         fwrite(&config, sizeof(struct config), 1, fp);
388         fclose(fp);
389         }
390                 
391                 
392
393
394
395 void imp_ssv(void) {
396         char key[256], value[256];
397         int ssv_maxfloors = MAXFLOORS;
398         
399         while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
400                 fpgetfield(imfp, value);
401                 lprintf(9, " %s = %s\n", key, value);
402                 
403                 if (!strcasecmp(key, "maxfloors")) {
404                         ssv_maxfloors = atol(value);
405                         if (ssv_maxfloors > MAXFLOORS) {
406                                 lprintf(3, "ERROR: maxfloors is %d, need %d\n",
407                                         ssv_maxfloors, MAXFLOORS);
408                                 fclose(imfp);
409                                 return;
410                                 }
411                         }
412                 }
413         }
414
415 void imp_visits(void) {
416         char key[256], value[256];
417         struct usersupp us;
418         struct quickroom qr;
419         struct visit visit;
420
421         while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
422                 lprintf(9, "%s: ", key);
423                 while(fpgetfield(imfp, key),
424                     strcasecmp(key, "endvisit")) {
425                         fpgetfield(imfp, value);
426                         if (!strcasecmp(key, "vrnum")) {
427                                 qr.QRnumber = atol(value);
428                                 visit.v_roomnum = atol(value);
429                                 }
430                         else if (!strcasecmp(key, "vgen")) {
431                                 qr.QRgen = atol(value);
432                                 visit.v_roomgen = atol(value);
433                                 }
434                         else if (!strcasecmp(key, "vunum")) {
435                                 us.usernum = atol(value);
436                                 visit.v_usernum = atol(value);
437                                 }
438                         else if (!strcasecmp(key, "lastseen")) {
439                                 visit.v_lastseen = atol(value);
440                                 }
441                         else if (!strcasecmp(key, "flags")) {
442                                 visit.v_flags = atol(value);
443                                 }
444                         }
445                 lprintf(9, "<%ld><%ld><%ld> <%d> <%ld>\n",
446                         visit.v_roomnum, visit.v_roomgen,
447                         visit.v_usernum,
448                         visit.v_flags, visit.v_lastseen);
449                 CtdlSetRelationship(&visit, &us, &qr);
450                 }
451
452         }
453
454
455 void import_databases(void) {
456         char section[256];
457
458         lprintf(9, " ** IMPORTING ** \n");
459         while (fpgetfield(imfp, section), strcasecmp(section, "endfile")) {
460                 lprintf(9, "Section: <%s>\n", section);
461
462                 if (!strcasecmp(section, "ssv"))                imp_ssv();
463                 else if (!strcasecmp(section, "config"))        imp_config();
464                 else if (!strcasecmp(section, "globals"))       imp_globals();
465                 else if (!strcasecmp(section, "usersupp"))      imp_usersupp();
466                 else if (!strcasecmp(section, "rooms"))         imp_rooms();
467                 else if (!strcasecmp(section, "floors"))        imp_floors();
468                 else if (!strcasecmp(section, "visits"))        imp_visits();
469                 else {
470                         lprintf(3, "ERROR: invalid import section.\n");
471                         lprintf(3, "Your data files are now corrupt.\n");
472                         fclose(imfp);
473                         return;
474                         }
475
476                 }
477
478         }
479
480
481
482 void do_import(char *argbuf) {
483         char import_filename[PATH_MAX];
484         
485         extract(import_filename, argbuf, 0);
486         imfp = fopen(import_filename, "rb");
487         if (imfp == NULL) {
488                 lprintf(9, "Cannot open %s: %s\n",
489                         import_filename, strerror(errno));
490                 cprintf("%d Cannot open file\n", ERROR);
491                 return;
492                 }
493
494         import_databases();
495         lprintf(9, "Defragmenting databases (this may take a while)...\n");
496         defrag_databases();
497         lprintf(1, "Import is finished.  Shutting down Citadel...\n");
498         cprintf("%d Import finished.  Shutting down Citadel...\n", OK);
499         master_cleanup();
500         }
501
502
503 void dump_message(long msg_num) {
504         struct cdbdata *dmsgtext;
505
506         dmsgtext = cdb_fetch(CDB_MSGMAIN, &msg_num, sizeof(long));
507         
508         if (dmsgtext == NULL) {
509                 lprintf(9, "%d Can't find message %ld\n", msg_num);
510                 return;
511                 }
512
513         fprintf(exfp, "message%c%ld%c", 0, msg_num, 0);
514         fprintf(exfp, "%ld%c", (long)dmsgtext->len, 0);
515         fwrite(dmsgtext->ptr, dmsgtext->len, 1, exfp);
516
517         cdb_free(dmsgtext);
518         }
519
520
521 void export_a_room(struct quickroom *qr) {
522         int b = 0;
523         int msgcount = 0;
524
525         lprintf(9,"<%s>\n", qr->QRname);
526         fprintf(exfp, "room%c", 0);
527         fprintf(exfp, "qrname%c%s%c", 0, qr->QRname, 0);
528         fprintf(exfp, "qrnumber%c%ld%c", 0, qr->QRnumber, 0);
529         fprintf(exfp, "qrpasswd%c%s%c", 0, qr->QRpasswd, 0);
530         fprintf(exfp, "qrroomaide%c%ld%c", 0, qr->QRroomaide, 0);
531         fprintf(exfp, "qrhighest%c%ld%c", 0, qr->QRhighest, 0);
532         fprintf(exfp, "qrgen%c%ld%c", 0, qr->QRgen, 0);
533         fprintf(exfp, "qrflags%c%d%c", 0, qr->QRflags, 0);
534         fprintf(exfp, "qrdirname%c%s%c", 0, qr->QRdirname, 0);
535         fprintf(exfp, "qrinfo%c%ld%c", 0, qr->QRinfo, 0);
536         fprintf(exfp, "qrfloor%c%d%c", 0, qr->QRfloor, 0);
537         fprintf(exfp, "qrmtime%c%ld%c", 0, qr->QRmtime, 0);
538         fprintf(exfp, "qrepmode%c%d%c", 0, qr->QRep.expire_mode, 0);
539         fprintf(exfp, "qrepvalue%c%d%c", 0, qr->QRep.expire_value, 0);
540
541         get_msglist(qr);
542         if (CC->num_msgs > 0) for (b=0; b<(CC->num_msgs); ++b) {
543                 ++msgcount;
544                 lprintf(9, "Message #%ld\n", MessageFromList(b));
545                 dump_message(MessageFromList(b));
546                 }
547
548         fprintf(exfp, "endroom%c", 0);
549         }
550
551
552 void export_rooms(void) {
553         lprintf(9,"Rooms\n");
554         fprintf(exfp, "rooms%c", 0);
555         ForEachRoom(export_a_room);
556         fprintf(exfp, "endsection%c", 0);
557         }
558
559
560
561 void export_floors(void) {
562         int floornum;
563         struct floor fl;
564
565         fprintf(exfp, "floors%c", 0);
566         for (floornum=0; floornum<MAXFLOORS; ++floornum) {
567                 getfloor(&fl, floornum);
568                 fprintf(exfp, "floor%c", 0);
569                 fprintf(exfp, "f_flags%c%d%c", 0, fl.f_flags, 0);
570                 fprintf(exfp, "f_name%c%s%c", 0, fl.f_name, 0);
571                 fprintf(exfp, "f_ref_count%c%d%c", 0, fl.f_ref_count, 0);
572                 fprintf(exfp, "f_expire_mode%c%d%c", 0, fl.f_ep.expire_mode, 0);
573                 fprintf(exfp, "f_expire_value%c%d%c", 0,
574                                 fl.f_ep.expire_value, 0);
575                 fprintf(exfp, "endfloor%c", 0);
576                 }
577         fprintf(exfp, "endsection%c", 0);
578         }
579
580
581
582
583 void export_a_user(struct usersupp *us) {
584
585         lprintf(9, "User <%s> ", us->fullname);
586
587         fprintf(exfp, "user%c", 0);
588         fprintf(exfp, "usuid%c%d%c", 0, us->USuid, 0);
589         fprintf(exfp, "password%c%s%c", 0, us->password, 0);
590         fprintf(exfp, "flags%c%d%c", 0, us->flags, 0);
591         fprintf(exfp, "timescalled%c%d%c", 0, us->timescalled, 0);
592         fprintf(exfp, "posted%c%d%c", 0, us->posted, 0);
593         fprintf(exfp, "fullname%c%s%c", 0, us->fullname, 0);
594         fprintf(exfp, "axlevel%c%d%c", 0, us->axlevel, 0);
595         fprintf(exfp, "usscreenwidth%c%d%c", 0, us->USscreenwidth, 0);
596         fprintf(exfp, "usscreenheight%c%d%c", 0, us->USscreenheight, 0);
597         fprintf(exfp, "usernum%c%ld%c", 0, us->usernum, 0);
598         fprintf(exfp, "lastcall%c%ld%c", 0, us->lastcall, 0);
599         fprintf(exfp, "usname%c%s%c", 0, us->USname, 0);
600         fprintf(exfp, "usaddr%c%s%c", 0, us->USaddr, 0);
601         fprintf(exfp, "uscity%c%s%c", 0, us->UScity, 0);
602         fprintf(exfp, "usstate%c%s%c", 0, us->USstate, 0);
603         fprintf(exfp, "uszip%c%s%c", 0, us->USzip, 0);
604         fprintf(exfp, "usphone%c%s%c", 0, us->USphone, 0);
605         fprintf(exfp, "usemail%c%s%c", 0, us->USemail, 0);
606         fprintf(exfp, "ususerpurge%c%d%c", 0, us->USuserpurge, 0);
607
608         lprintf(9, "\n");
609         fprintf(exfp, "enduser%c", 0);
610         }
611
612
613 void export_usersupp(void) {
614         lprintf(9, "Users\n");
615         fprintf(exfp, "usersupp%c", 0);
616
617         ForEachUser(export_a_user);
618
619         fprintf(exfp, "endsection%c", 0);
620         }
621
622
623 void export_visits(void) {
624         struct cdbdata *cdbvisit;
625         struct visit vbuf;
626
627         lprintf(9, "Visits\n");
628         fprintf(exfp, "visits%c", 0);
629
630         cdb_rewind(CDB_VISIT);
631         while(cdbvisit = cdb_next_item(CDB_VISIT), cdbvisit != NULL) {
632                 memset(&vbuf, 0, sizeof(struct visit));
633                 memcpy(&vbuf, cdbvisit->ptr,
634                         ( (cdbvisit->len > sizeof(struct visit)) ?
635                         sizeof(struct visit) : cdbvisit->len) );
636                 cdb_free(cdbvisit);
637
638                 fprintf(exfp, "visit%c", 0);
639                 fprintf(exfp, "vrnum%c%ld%c", 0, vbuf.v_roomnum, 0);
640                 fprintf(exfp, "vgen%c%ld%c", 0, vbuf.v_roomgen, 0);
641                 fprintf(exfp, "vunum%c%ld%c", 0, vbuf.v_usernum, 0);
642                 fprintf(exfp, "flags%c%d%c", 0, vbuf.v_flags, 0);
643                 fprintf(exfp, "lastseen%c%ld%c", 0, vbuf.v_lastseen, 0);
644                 fprintf(exfp, "endvisit%c", 0);
645                 }
646
647         fprintf(exfp, "endsection%c", 0);
648         }       
649
650 void do_export(char *argbuf) {
651         char export_filename[PATH_MAX];
652         
653         extract(export_filename, argbuf, 0);
654         exfp = fopen(export_filename, "wb");
655         if (exfp == NULL) {
656                 lprintf(9, "Cannot open %s: %s\n",
657                         export_filename, strerror(errno));
658                 cprintf("%d Cannot open file\n", ERROR);
659                 return;
660                 }
661
662         /* structure size variables */
663         lprintf(9, "Structure size variables\n");
664         fprintf(exfp, "ssv%c", 0);
665         fprintf(exfp, "maxfloors%c%d%c", 0, MAXFLOORS, 0);
666         fprintf(exfp, "endsection%c", 0);
667
668         /* Write out the server config */
669         lprintf(9,"Server config\n");
670         fprintf(exfp, "config%c", 0);
671         fprintf(exfp, "c_nodename%c%s%c", 0, config.c_nodename, 0);
672         fprintf(exfp, "c_fqdn%c%s%c", 0, config.c_fqdn, 0);
673         fprintf(exfp, "c_humannode%c%s%c", 0, config.c_humannode, 0);
674         fprintf(exfp, "c_phonenum%c%s%c", 0, config.c_phonenum, 0);
675         fprintf(exfp, "c_bbsuid%c%d%c", 0, config.c_bbsuid, 0);
676         fprintf(exfp, "c_creataide%c%d%c", 0, config.c_creataide, 0);
677         fprintf(exfp, "c_sleeping%c%d%c", 0, config.c_sleeping, 0);
678         fprintf(exfp, "c_initax%c%d%c", 0, config.c_initax, 0);
679         fprintf(exfp, "c_regiscall%c%d%c", 0, config.c_regiscall, 0);
680         fprintf(exfp, "c_twitdetect%c%d%c", 0, config.c_twitdetect, 0);
681         fprintf(exfp, "c_twitroom%c%s%c", 0, config.c_twitroom, 0);
682         fprintf(exfp, "c_moreprompt%c%s%c", 0, config.c_moreprompt, 0);
683         fprintf(exfp, "c_restrict%c%d%c", 0, config.c_restrict, 0);
684         fprintf(exfp, "c_bbs_city%c%s%c", 0, config.c_bbs_city, 0);
685         fprintf(exfp, "c_sysadm%c%s%c", 0, config.c_sysadm, 0);
686         fprintf(exfp, "c_bucket_dir%c%s%c", 0, config.c_bucket_dir, 0);
687         fprintf(exfp, "c_setup_level%c%d%c", 0, config.c_setup_level, 0);
688         fprintf(exfp, "c_maxsessions%c%d%c", 0, config.c_maxsessions, 0);
689         fprintf(exfp, "c_net_password%c%s%c", 0, config.c_net_password, 0);
690         fprintf(exfp, "c_port_number%c%d%c", 0, config.c_port_number, 0);
691         fprintf(exfp, "c_expire_policy%c%d%c", 0, config.c_ep.expire_mode, 0);
692         fprintf(exfp, "c_expire_value%c%d%c", 0, config.c_ep.expire_value, 0);
693         fprintf(exfp, "c_userpurge%c%d%c", 0, config.c_userpurge, 0);
694         fprintf(exfp, "endsection%c", 0);
695
696         /* Now some global stuff */
697         lprintf(9, "Globals\n");
698         get_control();
699         fprintf(exfp, "globals%c", 0);
700         fprintf(exfp, "mmhighest%c%ld%c", 0, CitControl.MMhighest, 0);
701         fprintf(exfp, "mmnextuser%c%ld%c", 0, CitControl.MMnextuser, 0);
702         fprintf(exfp, "mmnextroom%c%ld%c", 0, CitControl.MMnextroom, 0);
703         fprintf(exfp, "mmflags%c%d%c", 0, CitControl.MMflags, 0);
704         fprintf(exfp, "endsection%c", 0);
705
706         /* Export all of the databases */
707         export_rooms();
708         export_floors();
709         export_usersupp();
710         export_visits();
711
712         fprintf(exfp, "endfile%c", 0);
713         fclose(exfp);
714         lprintf(1, "Export is finished.\n");
715         cprintf("%d Export is finished.\n", OK);
716         }
717
718
719
720
721 struct DLModule_Info *Dynamic_Module_Init(void) {
722         CtdlRegisterProtoHook(do_import,
723                                 "IMPO",
724                                 "Import an unpacked system");
725         CtdlRegisterProtoHook(do_export,
726                                 "EXPO",
727                                 "Export the system");
728         return &info;
729         }