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