Started implementing global room numbers.
[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         int roomnum = 0;
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, "qrpasswd"))
161                                         strcpy(qr.QRpasswd, tval);
162                                 if (!strcasecmp(tag, "qrroomaide"))
163                                         qr.QRroomaide = atol(tval);
164                                 if (!strcasecmp(tag, "qrhighest"))
165                                         qr.QRhighest = atol(tval);
166                                 if (!strcasecmp(tag, "qrgen"))
167                                         qr.QRgen = atol(tval);
168                                 if (!strcasecmp(tag, "qrflags"))
169                                         qr.QRflags = atoi(tval);
170                                 if (!strcasecmp(tag, "qrdirname"))
171                                         strcpy(qr.QRdirname, tval);
172                                 if (!strcasecmp(tag, "qrinfo"))
173                                         qr.QRinfo = atol(tval);
174                                 if (!strcasecmp(tag, "qrfloor"))
175                                         qr.QRfloor = atoi(tval);
176                                 if (!strcasecmp(tag, "qrmtime"))
177                                         qr.QRmtime = atol(tval);
178                                 if (!strcasecmp(tag, "qrepmode"))
179                                         qr.QRep.expire_mode = atoi(tval);
180                                 if (!strcasecmp(tag, "qrepvalue"))
181                                         qr.QRep.expire_value = atoi(tval);
182                                 if (!strcasecmp(tag, "message")) {
183                                         fpgetfield(imfp, tval);
184                                         msgnum = atol(tval);
185                                         fpgetfield(imfp, tval);
186                                         msglen = atol(tval);
187                                         import_message(msgnum, msglen);
188                                         ++num_msgs;
189                                         msglist = realloc(msglist,
190                                                 (sizeof(long)*num_msgs) );
191                                         msglist[num_msgs - 1] = msgnum;
192                                         }
193
194                                 }
195
196                         lprintf(9, "(%d messages)\n", num_msgs);
197                         if ((roomnum!=1)&&(qr.QRflags&QR_INUSE)) {
198                                 putroom(&qr, qr.QRname);
199                                 }
200
201                         if (num_msgs > 0) {
202                                 if ((roomnum!=1)&&(qr.QRflags&QR_INUSE)) {
203                                         CC->msglist = msglist;
204                                         CC->num_msgs = num_msgs;
205                                         put_msglist(&qr);
206                                         }
207                                 free(msglist);
208                                 }
209
210                         ++roomnum;
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         char vkey[256], vvalue[256];
227         struct usersupp us;
228         struct quickroom qr;
229         struct visit vbuf;
230         int visits = 0;
231
232         bzero(&us, sizeof(struct usersupp));    
233         while(fpgetfield(imfp, key), strcasecmp(key, "enduser")) {
234                 if ((strcasecmp(key, "mail"))
235                    &&(strcasecmp(key, "visit")) ) {
236                         fpgetfield(imfp, value);
237                         }
238                 else {
239                         strcpy(value, "");
240                         }
241
242                 if (!strcasecmp(key, "usuid"))
243                         us.USuid = atoi(value);
244                 if (!strcasecmp(key, "password")) {
245                         strcpy(us.password, value);
246                         }
247
248                 if (!strcasecmp(key, "flags"))
249                         us.flags = atoi(value);
250                 if (!strcasecmp(key, "timescalled"))
251                         us.timescalled = atoi(value);
252                 if (!strcasecmp(key, "posted"))
253                         us.posted = atoi(value);
254                 if (!strcasecmp(key, "fullname")) {
255                         strcpy(us.fullname, value);
256                         lprintf(9, "User <%s> ", us.fullname);
257                         }
258                 if (!strcasecmp(key, "axlevel"))
259                         us.axlevel = atoi(value);
260                 if (!strcasecmp(key, "usscreenwidth"))
261                         us.USscreenwidth = atoi(value);
262                 if (!strcasecmp(key, "usscreenheight"))
263                         us.USscreenheight = atoi(value);
264                 if (!strcasecmp(key, "usernum")) {
265                         us.usernum = atol(value);
266                         lprintf(9, "<#%ld> ", us.usernum);
267                         }
268                 if (!strcasecmp(key, "lastcall"))
269                         us.lastcall = atol(value);
270                 if (!strcasecmp(key, "usname"))
271                         strcpy(us.USname, value);
272                 if (!strcasecmp(key, "usaddr"))
273                         strcpy(us.USaddr, value);
274                 if (!strcasecmp(key, "uscity"))
275                         strcpy(us.UScity, value);
276                 if (!strcasecmp(key, "usstate"))
277                         strcpy(us.USstate, value);
278                 if (!strcasecmp(key, "uszip"))
279                         strcpy(us.USzip, value);
280                 if (!strcasecmp(key, "usphone"))
281                         strcpy(us.USphone, value);
282                 if (!strcasecmp(key, "usemail"))
283                         strcpy(us.USemail, value);
284                 if (!strcasecmp(key, "ususerpurge"))
285                         us.USuserpurge = atoi(value);
286                 if (!strcasecmp(key, "visit")) {
287                         ++visits;
288                         bzero(&vbuf, sizeof(struct visit));
289                         bzero(&qr, sizeof(struct quickroom));
290                         while(fpgetfield(imfp, vkey),
291                           strcasecmp(vkey, "endvisit")) {
292                                 fpgetfield(imfp, vvalue);
293                                 if (!strcasecmp(vkey, "vname")) 
294                                         strcpy(qr.QRname, vvalue);
295                                 if (!strcasecmp(vkey, "vgen"))  {
296                                         qr.QRgen = atol(vvalue);
297                                         CtdlGetRelationship(&vbuf, &us, &qr);
298                                         }
299                                 if (!strcasecmp(vkey, "lastseen"))      
300                                         vbuf.v_lastseen = atol(vvalue);
301                                 if (!strcasecmp(vkey, "flags"))
302                                         vbuf.v_flags = atoi(vvalue);
303                                 }
304                         CtdlSetRelationship(&vbuf, &us, &qr);
305                         }
306                 }
307         
308         putuser(&us, us.fullname);
309
310         lprintf(9, "(%d rooms)\n", visits);
311         }
312
313
314 void imp_usersupp(void) {
315         char key[256], value[256];
316         
317         while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
318                 if (strcasecmp(key, "user")) {
319                         fpgetfield(imfp, value);
320                         }
321                 else {
322                         strcpy(value, "");
323                         }
324
325                 if (!strcasecmp(key, "user")) {
326                         import_a_user();
327                         }
328                 }               
329         }
330
331
332 void imp_globals(void) {
333         char key[256], value[256];
334
335         get_control();
336         while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
337                 fpgetfield(imfp, value);
338                 lprintf(9, " %s = %s\n", key, value);
339
340                 if (!strcasecmp(key, "mmhighest"))
341                         CitControl.MMhighest = atol(value);
342                 if (!strcasecmp(key, "mmnextuser"))
343                         CitControl.MMnextuser = atol(value);
344                 if (!strcasecmp(key, "mmnextroom"))
345                         CitControl.MMnextroom = atol(value);
346
347                 }
348         put_control();
349         }
350
351
352
353 void imp_config(void) { 
354         char key[256], value[256];
355         FILE *fp;
356
357         while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
358                 fpgetfield(imfp, value);
359                 lprintf(9, " %s = %s\n", key, value);
360
361                 if (!strcasecmp(key, "c_nodename"))
362                         strcpy(config.c_nodename, value);
363                 if (!strcasecmp(key, "c_fqdn"))
364                         strcpy(config.c_fqdn, value);
365                 if (!strcasecmp(key, "c_humannode"))
366                         strcpy(config.c_humannode, value);
367                 if (!strcasecmp(key, "c_phonenum"))
368                         strcpy(config.c_phonenum, value);
369                 if (!strcasecmp(key, "c_phonenum"))
370                         strcpy(config.c_phonenum, value);
371                 if (!strcasecmp(key, "c_bbsuid"))
372                         config.c_bbsuid = atoi(value);
373                 if (!strcasecmp(key, "c_creataide"))
374                         config.c_creataide = atoi(value);
375                 if (!strcasecmp(key, "c_sleeping"))
376                         config.c_sleeping = atoi(value);
377                 if (!strcasecmp(key, "c_initax"))
378                         config.c_initax = atoi(value);
379                 if (!strcasecmp(key, "c_regiscall"))
380                         config.c_regiscall = atoi(value);
381                 if (!strcasecmp(key, "c_twitdetect"))
382                         config.c_twitdetect = atoi(value);
383                 if (!strcasecmp(key, "c_twitroom"))
384                         strcpy(config.c_twitroom, value);
385                 if (!strcasecmp(key, "c_moreprompt"))
386                         strcpy(config.c_moreprompt, value);
387                 if (!strcasecmp(key, "c_restrict"))
388                         config.c_restrict = atoi(value);
389                 if (!strcasecmp(key, "c_bbs_city"))
390                         strcpy(config.c_bbs_city, value);
391                 if (!strcasecmp(key, "c_sysadm"))
392                         strcpy(config.c_sysadm, value);
393                 if (!strcasecmp(key, "c_bucket_dir"))
394                         strcpy(config.c_bucket_dir, value);
395                 if (!strcasecmp(key, "c_setup_level"))
396                         config.c_setup_level = atoi(value);
397                 if (!strcasecmp(key, "c_maxsessions"))
398                         config.c_maxsessions = atoi(value);
399                 if (!strcasecmp(key, "c_net_password"))
400                         strcpy(config.c_net_password, value);
401                 if (!strcasecmp(key, "c_port_number"))
402                         config.c_port_number = atoi(value);
403                 if (!strcasecmp(key, "c_expire_policy"))
404                         config.c_ep.expire_mode = atoi(value);
405                 if (!strcasecmp(key, "c_expire_value"))
406                         config.c_ep.expire_value = atoi(value);
407                 if (!strcasecmp(key, "c_userpurge"))
408                         config.c_userpurge = atoi(value);
409                 }
410
411         fp = fopen("citadel.config", "wb");
412         fwrite(&config, sizeof(struct config), 1, fp);
413         fclose(fp);
414         }
415                 
416                 
417
418
419
420 void imp_ssv(void) {
421         char key[256], value[256];
422         int ssv_maxfloors = MAXFLOORS;
423         
424         while(fpgetfield(imfp, key), strcasecmp(key, "endsection")) {
425                 fpgetfield(imfp, value);
426                 lprintf(9, " %s = %s\n", key, value);
427                 
428                 if (!strcasecmp(key, "maxfloors")) {
429                         ssv_maxfloors = atol(value);
430                         if (ssv_maxfloors > MAXFLOORS) {
431                                 lprintf(3, "ERROR: maxfloors is %d, need %d\n",
432                                         ssv_maxfloors, MAXFLOORS);
433                                 fclose(imfp);
434                                 return;
435                                 }
436                         }
437                 }
438         }
439
440
441
442
443
444
445
446 void import_databases(void) {
447         char section[256];
448
449         lprintf(9, " ** IMPORTING ** \n");
450         while (fpgetfield(imfp, section), strcasecmp(section, "endfile")) {
451                 lprintf(9, "Section: <%s>\n", section);
452
453                 if (!strcasecmp(section, "ssv"))                imp_ssv();
454                 else if (!strcasecmp(section, "config"))        imp_config();
455                 else if (!strcasecmp(section, "globals"))       imp_globals();
456                 else if (!strcasecmp(section, "usersupp"))      imp_usersupp();
457                 else if (!strcasecmp(section, "rooms"))         imp_rooms();
458                 else if (!strcasecmp(section, "floors"))        imp_floors();
459                 else {
460                         lprintf(3, "ERROR: invalid import section.\n");
461                         lprintf(3, "Your data files are now corrupt.\n");
462                         fclose(imfp);
463                         return;
464                         }
465
466                 }
467
468         }
469
470
471
472 void do_import(char *argbuf) {
473         char import_filename[PATH_MAX];
474         
475         extract(import_filename, argbuf, 0);
476         imfp = fopen(import_filename, "rb");
477         if (imfp == NULL) {
478                 lprintf(9, "Cannot open %s: %s\n",
479                         import_filename, strerror(errno));
480                 cprintf("%d Cannot open file\n", ERROR);
481                 return;
482                 }
483
484         import_databases();
485         lprintf(9, "Defragmenting databases (this may take a while)...\n");
486         defrag_databases();
487         lprintf(1, "Import is finished.  Shutting down Citadel...\n");
488         cprintf("%d Import finished.  Shutting down Citadel...\n", OK);
489         master_cleanup();
490         }
491
492
493 void dump_message(long msg_num) {
494         struct cdbdata *dmsgtext;
495
496         dmsgtext = cdb_fetch(CDB_MSGMAIN, &msg_num, sizeof(long));
497         
498         if (dmsgtext == NULL) {
499                 lprintf(9, "%d Can't find message %ld\n", msg_num);
500                 return;
501                 }
502
503         fprintf(exfp, "message%c%ld%c", 0, msg_num, 0);
504         fprintf(exfp, "%ld%c", (long)dmsgtext->len, 0);
505         fwrite(dmsgtext->ptr, dmsgtext->len, 1, exfp);
506
507         cdb_free(dmsgtext);
508         }
509
510
511 void export_a_room(struct quickroom *qr) {
512         int b = 0;
513         int msgcount = 0;
514
515         lprintf(9,"<%s>\n", qr->QRname);
516         fprintf(exfp, "room%c", 0);
517         fprintf(exfp, "qrname%c%s%c", 0, qr->QRname, 0);
518         fprintf(exfp, "qrpasswd%c%s%c", 0, qr->QRpasswd, 0);
519         fprintf(exfp, "qrroomaide%c%ld%c", 0, qr->QRroomaide, 0);
520         fprintf(exfp, "qrhighest%c%ld%c", 0, qr->QRhighest, 0);
521         fprintf(exfp, "qrgen%c%ld%c", 0, qr->QRgen, 0);
522         fprintf(exfp, "qrflags%c%d%c", 0, qr->QRflags, 0);
523         fprintf(exfp, "qrdirname%c%s%c", 0, qr->QRdirname, 0);
524         fprintf(exfp, "qrinfo%c%ld%c", 0, qr->QRinfo, 0);
525         fprintf(exfp, "qrfloor%c%d%c", 0, qr->QRfloor, 0);
526         fprintf(exfp, "qrmtime%c%ld%c", 0, qr->QRmtime, 0);
527         fprintf(exfp, "qrepmode%c%d%c", 0, qr->QRep.expire_mode, 0);
528         fprintf(exfp, "qrepvalue%c%d%c", 0, qr->QRep.expire_value, 0);
529
530         get_msglist(qr);
531         if (CC->num_msgs > 0) for (b=0; b<(CC->num_msgs); ++b) {
532                 ++msgcount;
533                 lprintf(9, "Message #%ld\n", MessageFromList(b));
534                 dump_message(MessageFromList(b));
535                 }
536
537         fprintf(exfp, "endroom%c", 0);
538         }
539
540
541 void export_rooms(void) {
542         lprintf(9,"Rooms\n");
543         fprintf(exfp, "rooms%c", 0);
544         ForEachRoom(export_a_room);
545         fprintf(exfp, "endsection%c", 0);
546         }
547
548
549
550 void export_floors(void) {
551         int floornum;
552         struct floor fl;
553
554         fprintf(exfp, "floors%c", 0);
555         for (floornum=0; floornum<MAXFLOORS; ++floornum) {
556                 getfloor(&fl, floornum);
557                 fprintf(exfp, "floor%c", 0);
558                 fprintf(exfp, "f_flags%c%d%c", 0, fl.f_flags, 0);
559                 fprintf(exfp, "f_name%c%s%c", 0, fl.f_name, 0);
560                 fprintf(exfp, "f_ref_count%c%d%c", 0, fl.f_ref_count, 0);
561                 fprintf(exfp, "f_expire_mode%c%d%c", 0, fl.f_ep.expire_mode, 0);
562                 fprintf(exfp, "f_expire_value%c%d%c", 0,
563                                 fl.f_ep.expire_value, 0);
564                 fprintf(exfp, "endfloor%c", 0);
565                 }
566         fprintf(exfp, "endsection%c", 0);
567         }
568
569
570
571
572 void export_a_user(struct usersupp *us) {
573         struct cdbdata *cdbvisit;
574         struct visit *visits;
575         int num_visits = 0;
576         int a;
577
578         lprintf(9, "User <%s> ", us->fullname);
579
580         fprintf(exfp, "user%c", 0);
581         fprintf(exfp, "usuid%c%d%c", 0, us->USuid, 0);
582         fprintf(exfp, "password%c%s%c", 0, us->password, 0);
583         fprintf(exfp, "flags%c%d%c", 0, us->flags, 0);
584         fprintf(exfp, "timescalled%c%d%c", 0, us->timescalled, 0);
585         fprintf(exfp, "posted%c%d%c", 0, us->posted, 0);
586         fprintf(exfp, "fullname%c%s%c", 0, us->fullname, 0);
587         fprintf(exfp, "axlevel%c%d%c", 0, us->axlevel, 0);
588         fprintf(exfp, "usscreenwidth%c%d%c", 0, us->USscreenwidth, 0);
589         fprintf(exfp, "usscreenheight%c%d%c", 0, us->USscreenheight, 0);
590         fprintf(exfp, "usernum%c%ld%c", 0, us->usernum, 0);
591         fprintf(exfp, "lastcall%c%ld%c", 0, us->lastcall, 0);
592         fprintf(exfp, "usname%c%s%c", 0, us->USname, 0);
593         fprintf(exfp, "usaddr%c%s%c", 0, us->USaddr, 0);
594         fprintf(exfp, "uscity%c%s%c", 0, us->UScity, 0);
595         fprintf(exfp, "usstate%c%s%c", 0, us->USstate, 0);
596         fprintf(exfp, "uszip%c%s%c", 0, us->USzip, 0);
597         fprintf(exfp, "usphone%c%s%c", 0, us->USphone, 0);
598         fprintf(exfp, "usemail%c%s%c", 0, us->USemail, 0);
599         fprintf(exfp, "ususerpurge%c%d%c", 0, us->USuserpurge, 0);
600
601
602         cdbvisit = cdb_fetch(CDB_VISIT, &us->usernum, sizeof(long));
603         if (cdbvisit != NULL) {
604                 num_visits = cdbvisit->len / sizeof(struct visit);
605                 if (num_visits == 0) {
606                         cdb_free(cdbvisit);
607                         goto VISITS_DONE;
608                         }
609                 visits = (struct visit *)
610                         malloc(num_visits * sizeof(struct visit));
611                 memcpy(visits, cdbvisit->ptr,
612                         (num_visits * sizeof(struct visit)));
613                 cdb_free(cdbvisit);
614
615                 if (num_visits > 0) for (a=0; a<num_visits; ++a) {
616                         fprintf(exfp, "visit%c", 0);
617                         fprintf(exfp, "vname%c%s%c", 0,
618                                         visits[a].v_roomname, 0);
619                         fprintf(exfp, "vgen%c%ld%c", 0,
620                                         visits[a].v_generation, 0);
621                         fprintf(exfp, "lastseen%c%ld%c", 0,
622                                         visits[a].v_lastseen, 0);
623                         fprintf(exfp, "flags%c%d%c", 0,
624                                         visits[a].v_flags, 0);
625                         fprintf(exfp, "endvisit%c", 0);
626                         }
627                 free(visits);
628                 }
629
630 VISITS_DONE:
631         lprintf(9, "(%d rooms)\n", num_visits);
632         fprintf(exfp, "enduser%c", 0);
633         }
634
635
636 void export_usersupp(void) {
637         lprintf(9, "Users\n");
638         fprintf(exfp, "usersupp%c", 0);
639
640         ForEachUser(export_a_user);
641
642         fprintf(exfp, "endsection%c", 0);
643         }
644         
645
646 void do_export(char *argbuf) {
647         char export_filename[PATH_MAX];
648         
649         extract(export_filename, argbuf, 0);
650         exfp = fopen(export_filename, "wb");
651         if (exfp == NULL) {
652                 lprintf(9, "Cannot open %s: %s\n",
653                         export_filename, strerror(errno));
654                 cprintf("%d Cannot open file\n", ERROR);
655                 return;
656                 }
657
658         /* structure size variables */
659         lprintf(9, "Structure size variables\n");
660         fprintf(exfp, "ssv%c", 0);
661         fprintf(exfp, "maxfloors%c%d%c", 0, MAXFLOORS, 0);
662         fprintf(exfp, "endsection%c", 0);
663
664         /* Write out the server config */
665         lprintf(9,"Server config\n");
666         fprintf(exfp, "config%c", 0);
667         fprintf(exfp, "c_nodename%c%s%c", 0, config.c_nodename, 0);
668         fprintf(exfp, "c_fqdn%c%s%c", 0, config.c_fqdn, 0);
669         fprintf(exfp, "c_humannode%c%s%c", 0, config.c_humannode, 0);
670         fprintf(exfp, "c_phonenum%c%s%c", 0, config.c_phonenum, 0);
671         fprintf(exfp, "c_bbsuid%c%d%c", 0, config.c_bbsuid, 0);
672         fprintf(exfp, "c_creataide%c%d%c", 0, config.c_creataide, 0);
673         fprintf(exfp, "c_sleeping%c%d%c", 0, config.c_sleeping, 0);
674         fprintf(exfp, "c_initax%c%d%c", 0, config.c_initax, 0);
675         fprintf(exfp, "c_regiscall%c%d%c", 0, config.c_regiscall, 0);
676         fprintf(exfp, "c_twitdetect%c%d%c", 0, config.c_twitdetect, 0);
677         fprintf(exfp, "c_twitroom%c%s%c", 0, config.c_twitroom, 0);
678         fprintf(exfp, "c_moreprompt%c%s%c", 0, config.c_moreprompt, 0);
679         fprintf(exfp, "c_restrict%c%d%c", 0, config.c_restrict, 0);
680         fprintf(exfp, "c_bbs_city%c%s%c", 0, config.c_bbs_city, 0);
681         fprintf(exfp, "c_sysadm%c%s%c", 0, config.c_sysadm, 0);
682         fprintf(exfp, "c_bucket_dir%c%s%c", 0, config.c_bucket_dir, 0);
683         fprintf(exfp, "c_setup_level%c%d%c", 0, config.c_setup_level, 0);
684         fprintf(exfp, "c_maxsessions%c%d%c", 0, config.c_maxsessions, 0);
685         fprintf(exfp, "c_net_password%c%s%c", 0, config.c_net_password, 0);
686         fprintf(exfp, "c_port_number%c%d%c", 0, config.c_port_number, 0);
687         fprintf(exfp, "c_expire_policy%c%d%c", 0, config.c_ep.expire_mode, 0);
688         fprintf(exfp, "c_expire_value%c%d%c", 0, config.c_ep.expire_value, 0);
689         fprintf(exfp, "c_userpurge%c%d%c", 0, config.c_userpurge, 0);
690         fprintf(exfp, "endsection%c", 0);
691
692         /* Now some global stuff */
693         lprintf(9, "Globals\n");
694         get_control();
695         fprintf(exfp, "globals%c", 0);
696         fprintf(exfp, "mmhighest%c%ld%c", 0, CitControl.MMhighest, 0);
697         fprintf(exfp, "mmnextuser%c%ld%c", 0, CitControl.MMnextuser, 0);
698         fprintf(exfp, "mmnextroom%c%ld%c", 0, CitControl.MMnextroom, 0);
699         fprintf(exfp, "mmflags%c%d%c", 0, CitControl.MMflags, 0);
700         fprintf(exfp, "endsection%c", 0);
701
702         /* Export all of the databases */
703         export_rooms();
704         export_floors();
705         export_usersupp();
706
707         fprintf(exfp, "endfile%c", 0);
708         fclose(exfp);
709         lprintf(1, "Export is finished.\n");
710         cprintf("%d Export is finished.\n", OK);
711         }
712
713
714
715 struct DLModule_Info *Dynamic_Module_Init(void) {
716         CtdlRegisterProtoHook(do_import,
717                                 "IMPO",
718                                 "Import an unpacked system");
719         CtdlRegisterProtoHook(do_export,
720                                 "EXPO",
721                                 "Export the system");
722         return &info;
723         }