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