db-merger.c

Go to the documentation of this file.
00001 /*
00002  *   IRC - Internet Relay Chat, db-merger.c
00003  *   (C) Copyright 2005-2006, Florian Schulze (Certus)
00004  *
00005  *   Based on the original code of Anope, (C) 2003-2005 Anope Team
00006  *
00007  *   This program is free software; you can redistribute it and/or modify
00008  *   it under the terms of the GNU General Public License (see it online
00009  *   at http://www.gnu.org/copyleft/gpl.html) as published by the Free
00010  *   Software Foundation;
00011  *
00012  *   This program is distributed in the hope that it will be useful,
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *   GNU General Public License for more details.
00016  *
00017  *   This program tries to merge two standard anope-1.7.7+ database sets,
00018  *   that includes chanserv, nickserv, botserv and memoserv databases.
00019  *
00020  *   - Certus
00021  *      February 11, 2005
00022  *
00023  *
00024  *   0.2 beta:
00025  *   Fixed some overflows in the ->flags and the ->status fields. Use db-fix
00026  *   to fix your broken nick dbs.
00027  *
00028  *   - Certus
00029  *      August 04, 2005
00030  *
00031  *
00032  *   0.3 beta:
00033  *   Fixed win32 stuff. Merging should now work fine under windows.
00034  *
00035  *   - Certus
00036  *      July 20, 2006
00037  *
00038  *
00039  *   0.4 beta:
00040  *   Fixed some compiler warnings about signed/unsigned ints.
00041  *
00042  *   - Certus
00043  *      August 8, 2006
00044 
00045  */
00046 
00047 
00048 #include <stdlib.h>
00049 #include <string.h>
00050 #include <stdio.h>
00051 #include <fcntl.h>
00052 #include <ctype.h>
00053 #include <time.h>
00054 
00055 #ifndef _WIN32
00056 #include <unistd.h>
00057 #else
00058 #include "sysconf.h"
00059 #include <windows.h>
00060 #endif
00061 
00062 /* Some SUN fixs */
00063 #ifdef __sun
00064 /* Solaris specific code, types that do not exist in Solaris'
00065  * sys/types.h
00066  **/
00067 #undef u_int8_t
00068 #undef u_int16_t
00069 #undef u_int32_t
00070 #undef u_int_64_t
00071 #define u_int8_t uint8_t
00072 #define u_int16_t uint16_t
00073 #define u_int32_t uint32_t
00074 #define u_int64_t uint64_t
00075 
00076 #ifndef INADDR_NONE
00077 #define INADDR_NONE (-1)
00078 #endif
00079 
00080 #endif
00081 
00082 
00083 /* CONFIGURATION BLOCK */
00084 
00085 #define NICK_DB_1      "nick1.db"
00086 #define NICK_DB_2      "nick2.db"
00087 #define NICK_DB_NEW "nick.db"
00088 
00089 #define CHAN_DB_1      "chan1.db"
00090 #define CHAN_DB_2      "chan2.db"
00091 #define CHAN_DB_NEW "chan.db"
00092 
00093 #define BOT_DB_1        "bot1.db"
00094 #define BOT_DB_2        "bot2.db"
00095 #define BOT_DB_NEW   "bot.db"
00096 
00097 #define HOST_DB_1      "hosts1.db"
00098 #define HOST_DB_2      "hosts2.db"
00099 #define HOST_DB_NEW "hosts.db"
00100 
00101 /* END OF CONFIGURATION BLOCK */
00102 
00103 #ifndef _WIN32
00104 #define C_LBLUE "\033[1;34m"
00105 #define C_NONE "\033[m"
00106 #else
00107 #define C_LBLUE ""
00108 #define C_NONE ""
00109 #endif
00110 
00111 #define getc_db(f)              (fgetc((f)->fp))
00112 #define HASH(nick)      ((tolower((nick)[0])&31)<<5 | (tolower((nick)[1])&31))
00113 #define HASH2(chan)     ((chan)[1] ? ((chan)[1]&31)<<5 | ((chan)[2]&31) : 0)
00114 #define read_buffer(buf,f)      (read_db((f),(buf),sizeof(buf)) == sizeof(buf))
00115 #define write_buffer(buf,f)     (write_db((f),(buf),sizeof(buf)) == sizeof(buf))
00116 #define read_db(f,buf,len)      (fread((buf),1,(len),(f)->fp))
00117 #define write_db(f,buf,len)     (fwrite((buf),1,(len),(f)->fp))
00118 #define read_int8(ret,f)        ((*(ret)=fgetc((f)->fp))==EOF ? -1 : 0)
00119 #define write_int8(val,f)       (fputc((val),(f)->fp)==EOF ? -1 : 0)
00120 #define SAFE(x) do { \
00121     if ((x) < 0) { \
00122         printf("Error, the database is broken, trying to continue... no guarantee.\n"); \
00123     } \
00124 } while (0)
00125 #define READ(x) do { \
00126     if ((x) < 0) { \
00127             printf("Error, the database is broken, trying to continue... no guarantee.\n"); \
00128         exit(0); \
00129     } \
00130 } while (0)
00131 
00132 typedef int16_t int16;
00133 typedef u_int16_t uint16;
00134 typedef int32_t int32;
00135 typedef u_int32_t uint32;
00136 typedef struct memo_ Memo;
00137 typedef struct dbFILE_ dbFILE;
00138 typedef struct nickalias_ NickAlias;
00139 typedef struct nickcore_ NickCore;
00140 typedef struct chaninfo_ ChannelInfo;
00141 typedef struct botinfo_ BotInfo;
00142 typedef struct badword_ BadWord;
00143 typedef struct hostcore_ HostCore;
00144 
00145 struct memo_ {
00146     uint32 number;      /* Index number -- not necessarily array position! */
00147     uint16 flags;            /* Flags */
00148     time_t time;          /* When was it sent? */
00149     char sender[32];   /* Name of the sender */
00150     char *text;
00151 };
00152 
00153 struct dbFILE_ {
00154     int mode;                   /* 'r' for reading, 'w' for writing */
00155     FILE *fp;                    /* The normal file descriptor */
00156     char filename[1024];  /* Name of the database file */
00157 };
00158 
00159 typedef struct {
00160     int16 memocount;  /* Current # of memos */
00161     int16 memomax;    /* Max # of memos one can hold*/
00162     Memo *memos;     /* Pointer to original memos */
00163 } MemoInfo;
00164 
00165 typedef struct {
00166     uint16 in_use;         /* 1 if this entry is in use, else 0 */
00167     int16 level;
00168     NickCore *nc;       /* Guaranteed to be non-NULL if in use, NULL if not */
00169     time_t last_seen;
00170 } ChanAccess;
00171 
00172 typedef struct {
00173     int16 in_use;         /* Always 0 if not in use */
00174     int16 is_nick;         /* 1 if a regged nickname, 0 if a nick!user@host mask */
00175         uint16 flags;
00176     union {
00177                 char *mask;      /* Guaranteed to be non-NULL if in use, NULL if not */
00178                 NickCore *nc;   /* Same */
00179     } u;
00180     char *reason;
00181     char *creator;
00182     time_t addtime;
00183 } AutoKick;
00184 
00185 struct nickalias_ {
00186     NickAlias *next, *prev;
00187     char *nick;                    /* Nickname */
00188     char *last_quit;             /* Last quit message */
00189     char *last_realname;     /* Last realname */
00190     char *last_usermask;     /* Last usermask */
00191     time_t time_registered;  /* When the nick was registered */
00192     time_t last_seen;           /* When it was seen online for the last time */
00193     uint16 status;                  /* See NS_* below */
00194     NickCore *nc;               /* I'm an alias of this */
00195 };
00196 
00197 struct nickcore_ {
00198         NickCore *next, *prev;
00199 
00200     char *display;           /* How the nick is displayed */
00201     char *pass;               /* Password of the nicks */
00202     char *email;              /* E-mail associated to the nick */
00203     char *greet;              /* Greet associated to the nick */
00204     uint32 icq;                 /* ICQ # associated to the nick */
00205     char *url;                  /* URL associated to the nick */
00206     uint32 flags;                /* See NI_* below */
00207     uint16 language;        /* Language selected by nickname owner (LANG_*) */
00208     uint16 accesscount;     /* # of entries */
00209     char **access;          /* Array of strings */
00210     MemoInfo memos;     /* Memo information */
00211     uint16 channelcount;  /* Number of channels currently registered */
00212     uint16 channelmax;   /* Maximum number of channels allowed */
00213     int unused;                /* Used for nick collisions */
00214     int aliascount;            /* How many aliases link to us? Remove the core if 0 */
00215 };
00216 
00217 struct chaninfo_ {
00218     ChannelInfo *next, *prev;
00219 
00220     char name[64];                     /* Channel name */
00221     char *founder;                      /* Who registered the channel */
00222     char *successor;                   /* Who gets the channel if the founder nick is dropped or expires */
00223     char founderpass[32];            /* Channel password */
00224     char *desc;                           /* Description */
00225     char *url;                              /* URL */
00226     char *email;                          /* Email address */
00227     time_t time_registered;          /* When was it registered */
00228     time_t last_used;                   /* When was it used hte last time */
00229     char *last_topic;                       /* Last topic on the channel */
00230     char last_topic_setter[32];      /* Who set the last topic */
00231     time_t last_topic_time;           /* When the last topic was set */
00232     uint32 flags;                          /* Flags */
00233     char *forbidby;                      /* if forbidden: who did it */
00234     char *forbidreason;                /* if forbidden: why */
00235     int16 bantype;                       /* Bantype */
00236     int16 *levels;                        /* Access levels for commands */
00237     uint16 accesscount;                 /* # of pple with access */
00238     ChanAccess *access;             /* List of authorized users */
00239     uint16 akickcount;                    /* # of akicked pple */
00240     AutoKick *akick;                    /* List of users to kickban */
00241     uint32 mlock_on, mlock_off;   /* See channel modes below */
00242     uint32 mlock_limit;                /* 0 if no limit */
00243     char *mlock_key;                  /* NULL if no key */
00244     char *mlock_flood;                  /* NULL if no +f */
00245     char *mlock_redirect;            /* NULL if no +L */
00246     char *entry_message;           /* Notice sent on entering channel */
00247     MemoInfo memos;                 /* Memos */
00248     char *bi;                               /* Bot used on this channel */
00249     uint32 botflags;                      /* BS_* below */
00250     int16 *ttb;                             /* Times to ban for each kicker */
00251     uint16 bwcount;                       /* Badword count */
00252     BadWord *badwords;             /* For BADWORDS kicker */
00253     int16 capsmin, capspercent;    /* For CAPS kicker */
00254     int16 floodlines, floodsecs;      /* For FLOOD kicker */
00255     int16 repeattimes;                 /* For REPEAT kicker */
00256 };
00257 
00258 struct botinfo_ {
00259         BotInfo *next, *prev;
00260         char *nick;            /* Nickname of the bot */
00261         char *user;            /* Its user name */
00262         char *host;            /* Its hostname */
00263         char *real;            /* Its real name */
00264         int16 flags;            /* Bot flags */
00265         time_t created;      /* Birth date */
00266         int16 chancount;            /* Number of channels that use the bot. */
00267 };
00268 
00269 struct badword_ {
00270         uint16 in_use;
00271         char *word;
00272         uint16 type;    
00273 };
00274 
00275 struct hostcore_ {
00276     HostCore *next, *last;
00277     char *nick;        /* Owner of the vHost */
00278     char *vIdent;    /* vIdent for the user */
00279     char *vHost;     /* Vhost for this user */
00280     char *creator;   /* Oper Nick of the oper who set the vhost */
00281     time_t time;      /* Date/Time vHost was set */
00282 };
00283 
00284 dbFILE *open_db_write(const char *service, const char *filename, int version);
00285 dbFILE *open_db_read(const char *service, const char *filename, int version);
00286 NickCore *findcore(const char *nick, int version);
00287 NickAlias *findnick(const char *nick);
00288 BotInfo *findbot(char *nick);
00289 ChannelInfo *cs_findchan(const char *chan);
00290 char *strscpy(char *d, const char *s, size_t len);
00291 int write_file_version(dbFILE * f, uint32 version);
00292 int mystricmp(const char *s1, const char *s2);
00293 int delnick(NickAlias *na, int donttouchthelist);
00294 int write_string(const char *s, dbFILE * f);
00295 int write_ptr(const void *ptr, dbFILE * f);
00296 int read_int16(int16 * ret, dbFILE * f);
00297 int read_int32(int32 * ret, dbFILE * f);
00298 int read_uint16(uint16 * ret, dbFILE * f);
00299 int read_uint32(uint32 * ret, dbFILE * f);
00300 int read_string(char **ret, dbFILE * f);
00301 int write_int16(uint16 val, dbFILE * f);
00302 int write_int32(uint32 val, dbFILE * f);
00303 int read_ptr(void **ret, dbFILE * f);
00304 int delcore(NickCore *nc);
00305 void alpha_insert_chan(ChannelInfo * ci);
00306 void insert_bot(BotInfo * bi);
00307 void close_db(dbFILE * f);
00308 
00309 ChannelInfo *chanlists[256];
00310 NickAlias *nalists[1024];
00311 NickCore *nclists[1024];
00312 BotInfo *botlists[256];
00313 
00314 int preferfirst = 0, prefersecond = 0, preferoldest = 0, prefernewest = 0;
00315 int nonick = 0, nochan = 0, nobot = 0, nohost = 0;
00316 
00317 int main(int argc, char *argv[])
00318 {
00319     dbFILE *f;
00320     int i;
00321     NickCore *nc, *ncnext;
00322     HostCore *firsthc = NULL;
00323 
00324     printf("\n"C_LBLUE"DB Merger v0.4 beta for Anope IRC Services by Certus"C_NONE"\n\n");
00325 
00326     if (argc >= 2) {
00327         if (!mystricmp(argv[1], "--PREFEROLDEST")) {
00328             printf("Preferring oldest database entries on collision.\n");
00329             preferoldest = 1;
00330         } else if (!mystricmp(argv[1], "--PREFERFIRST")) {
00331             printf("Preferring first database's entries on collision .\n");
00332             preferfirst = 1;
00333         } else if (!mystricmp(argv[1], "--PREFERSECOND")) {
00334             printf("Preferring second database's entries on collision.\n");
00335             prefersecond = 1;
00336         } else if (!mystricmp(argv[1], "--PREFERNEWEST")) {
00337             printf("Preferring newest database entries on collision.\n");
00338             prefernewest = 1;
00339         }
00340     }
00341 
00342     /* Section I: Nicks */
00343     /* Ia: First database */
00344     if ((f = open_db_read("NickServ", NICK_DB_1, 13))) {
00345 
00346         NickAlias *na, **nalast, *naprev;
00347         NickCore *nc, **nclast, *ncprev;
00348         int16 tmp16;
00349         int32 tmp32;
00350         int i, j, c;
00351 
00352         printf("Trying to merge nicks...\n");
00353 
00354         /* Nick cores */
00355         for (i = 0; i < 1024; i++) {
00356             nclast = &nclists[i];
00357             ncprev = NULL;
00358 
00359             while ((c = getc_db(f)) == 1) {
00360                 if (c != 1) {
00361                     printf("Invalid format in %s.\n", NICK_DB_1);
00362                     exit(0);
00363                 }
00364 
00365                 nc = calloc(1, sizeof(NickCore));
00366                 nc->aliascount = 0;
00367                 nc->unused = 0;
00368 
00369                 *nclast = nc;
00370                 nclast = &nc->next;
00371                 nc->prev = ncprev;
00372                 ncprev = nc;
00373 
00374                 READ(read_string(&nc->display, f));
00375                 READ(read_string(&nc->pass, f));
00376                 READ(read_string(&nc->email, f));
00377                 READ(read_string(&nc->greet, f));
00378                 READ(read_uint32(&nc->icq, f));
00379                 READ(read_string(&nc->url, f));
00380                 READ(read_uint32(&nc->flags, f));
00381                 READ(read_uint16(&nc->language, f));
00382                 READ(read_uint16(&nc->accesscount, f));
00383                 if (nc->accesscount) {
00384                     char **access;
00385                     access = calloc(sizeof(char *) * nc->accesscount, 1);
00386                     nc->access = access;
00387                     for (j = 0; j < nc->accesscount; j++, access++)
00388                         READ(read_string(access, f));
00389                 }
00390                 READ(read_int16(&nc->memos.memocount, f));
00391                 READ(read_int16(&nc->memos.memomax, f));
00392                 if (nc->memos.memocount) {
00393                     Memo *memos;
00394                     memos = calloc(sizeof(Memo) * nc->memos.memocount, 1);
00395                     nc->memos.memos = memos;
00396                     for (j = 0; j < nc->memos.memocount; j++, memos++) {
00397                         READ(read_uint32(&memos->number, f));
00398                         READ(read_uint16(&memos->flags, f));
00399                         READ(read_int32(&tmp32, f));
00400                         memos->time = tmp32;
00401                         READ(read_buffer(memos->sender, f));
00402                         READ(read_string(&memos->text, f));
00403                     }
00404                 }
00405                 READ(read_uint16(&nc->channelcount, f));
00406                 READ(read_int16(&tmp16, f));
00407             } /* getc_db() */
00408             *nclast = NULL;
00409         } /* for() loop */
00410 
00411         /* Nick aliases */
00412         for (i = 0; i < 1024; i++) {
00413             char *s = NULL;
00414 
00415             nalast = &nalists[i];
00416             naprev = NULL;
00417 
00418             while ((c = getc_db(f)) == 1) {
00419                 if (c != 1) {
00420                     printf("Invalid format in %s.\n", NICK_DB_1);
00421                     exit(0);
00422                 }
00423 
00424                 na = calloc(1, sizeof(NickAlias));
00425 
00426                 READ(read_string(&na->nick, f));
00427                 READ(read_string(&na->last_usermask, f));
00428                 READ(read_string(&na->last_realname, f));
00429                 READ(read_string(&na->last_quit, f));
00430 
00431                 READ(read_int32(&tmp32, f));
00432                 na->time_registered = tmp32;
00433                 READ(read_int32(&tmp32, f));
00434                 na->last_seen = tmp32;
00435                 READ(read_uint16(&na->status, f));
00436                 READ(read_string(&s, f));
00437                 na->nc = findcore(s, 0);
00438                 na->nc->aliascount++;
00439                 free(s);
00440 
00441                 *nalast = na;
00442                 nalast = &na->next;
00443                 na->prev = naprev;
00444                 naprev = na;
00445             } /* getc_db() */
00446             *nalast = NULL;
00447         } /* for() loop */
00448         close_db(f); /* End of section Ia */
00449     } else
00450         nonick = 1;
00451 
00452     /* Ib: Second database */
00453     if (!nonick) {
00454         if ((f = open_db_read("NickServ", NICK_DB_2, 13))) {
00455 
00456             NickAlias *na, *naptr;
00457             NickCore *nc;
00458             int16 tmp16;
00459             int32 tmp32;
00460             int i, j, index, c;
00461 
00462             /* Nick cores */
00463             for (i = 0; i < 1024; i++) {
00464 
00465                 while ((c = getc_db(f)) == 1) {
00466                     if (c != 1) {
00467                         printf("Invalid format in %s.\n", NICK_DB_2);
00468                         exit(0);
00469                     }
00470 
00471                     nc = calloc(1, sizeof(NickCore));
00472                     READ(read_string(&nc->display, f));
00473                     READ(read_string(&nc->pass, f));
00474                     READ(read_string(&nc->email, f));
00475 
00476                     naptr = findnick(nc->display);
00477                     if (naptr)
00478                         nc->unused = 1;
00479                     else
00480                         nc->unused = 0;
00481 
00482                     nc->aliascount = 0;
00483 
00484                     index = HASH(nc->display);
00485                     nc->prev = NULL;
00486                     nc->next = nclists[index];
00487                     if (nc->next)
00488                         nc->next->prev = nc;
00489                     nclists[index] = nc;
00490 
00491                     READ(read_string(&nc->greet, f));
00492                     READ(read_uint32(&nc->icq, f));
00493                     READ(read_string(&nc->url, f));
00494                     READ(read_uint32(&nc->flags, f));
00495                     READ(read_uint16(&nc->language, f));
00496                     READ(read_uint16(&nc->accesscount, f));
00497                     if (nc->accesscount) {
00498                         char **access;
00499                         access = calloc(sizeof(char *) * nc->accesscount, 1);
00500                         nc->access = access;
00501                         for (j = 0; j < nc->accesscount; j++, access++)
00502                             READ(read_string(access, f));
00503                     }
00504                     READ(read_int16(&nc->memos.memocount, f));
00505                     READ(read_int16(&nc->memos.memomax, f));
00506                     if (nc->memos.memocount) {
00507                         Memo *memos;
00508                         memos = calloc(sizeof(Memo) * nc->memos.memocount, 1);
00509                         nc->memos.memos = memos;
00510                         for (j = 0; j < nc->memos.memocount; j++, memos++) {
00511                             READ(read_uint32(&memos->number, f));
00512                             READ(read_uint16(&memos->flags, f));
00513                             READ(read_int32(&tmp32, f));
00514                             memos->time = tmp32;
00515                             READ(read_buffer(memos->sender, f));
00516                             READ(read_string(&memos->text, f));
00517                         }
00518                     }
00519                     READ(read_uint16(&nc->channelcount, f));
00520                     READ(read_int16(&tmp16, f));
00521                 } /* getc_db() */
00522             } /* for() loop */
00523 
00524             /* Nick aliases */
00525             for (i = 0; i < 1024; i++) {
00526                 char *s = NULL;
00527                 NickAlias *ptr, *prev, *naptr;
00528 
00529                 while ((c = getc_db(f)) == 1) {
00530                     if (c != 1) {
00531                         printf("Invalid format in %s.\n", NICK_DB_1);
00532                         exit(0);
00533                     }
00534 
00535                     na = calloc(1, sizeof(NickAlias));
00536 
00537                     READ(read_string(&na->nick, f));
00538                     READ(read_string(&na->last_usermask, f));
00539                     READ(read_string(&na->last_realname, f));
00540                     READ(read_string(&na->last_quit, f));
00541                     READ(read_int32(&tmp32, f));
00542                     na->time_registered = tmp32;
00543                     READ(read_int32(&tmp32, f));
00544                     na->last_seen = tmp32;
00545                     READ(read_uint16(&na->status, f));
00546                     READ(read_string(&s, f));
00547 
00548                     naptr = findnick(na->nick);
00549                     if (naptr) { /* COLLISION! na = collision #1 (na->nc doesn't exist yet), naptr = collision #2 (naptr->nc exists) */
00550                         char input[1024];
00551                         NickCore *ncptr = findcore(na->nick, 1); /* Find core for #1, ncptr MUST exist since we've read all cores, if it doesn't eixst, we have a malformed db */;
00552 
00553                         if (!ncptr) { /* malformed */
00554                             printf("\n\n     WARNING! Malformed database. No nickcore for nick %s, droping it.\n\n\n", na->nick);
00555                             delnick(na, 1);
00556                         } else { /* not malformed */
00557                             if (!preferoldest && !preferfirst && !prefersecond && !prefernewest) {
00558                                 printf("Nick collision for nick %s:\n\n", na->nick);
00559                                 printf("Group 1: %s (%s)\n", ncptr->display, ncptr->email);
00560                                 printf("Time registered: %s\n", ctime(&na->time_registered));
00561                                 printf("Group 2: %s (%s)\n", naptr->nc->display, naptr->nc->email);
00562                                 printf("Time registered: %s\n", ctime(&naptr->time_registered));
00563                                 printf("What group do you want to keep? Enter the related group number \"1\" or \"2\".\n");
00564                             }
00565 
00566                             if (preferoldest) {
00567                                 input[0] = (na->time_registered > naptr->time_registered) ? '1' : '2';
00568                             } else if (prefernewest) {
00569                                 input[0] = (na->time_registered > naptr->time_registered) ? '2' : '1';
00570                             } else if (preferfirst) {
00571                                 input[0] = '2';
00572                             } else if (prefersecond) {
00573                                 input[0] = '1';
00574                             } else {
00575                                 waiting_for_input:
00576                                 scanf("%s", input);
00577                             }
00578                             if (input[0] == '1') { /* get alias #2 out of the list, then free() it, then add #1 to the list */
00579                                 printf("Deleting nick alias %s (#2).\n", naptr->nick); 
00580                                 naptr->nc->aliascount--; /* tell the core it has one alias less */
00581                                 delnick(naptr, 0); /* removes the alias from the list and free()s it */
00582                                 na->nc = ncptr;
00583                                 na->nc->aliascount++;
00584                                 index = HASH(na->nick);
00585                                 for (prev = NULL, ptr = nalists[index]; ptr && mystricmp(ptr->nick, na->nick) < 0; prev = ptr, ptr = ptr->next);
00586                                 na->prev = prev;
00587                                 na->next = ptr;
00588                                 if (!prev)
00589                                     nalists[index] = na;
00590                                 else
00591                                     prev->next = na;
00592                                 if (ptr)
00593                                     ptr->prev = na;
00594                             } else if (input[0] == '2') { /* free() #1 alias */
00595                                 printf("Deleting nick alias %s (#1).\n", na->nick);
00596                                 delnick(na, 1); /* free()s the alias without touching the list since na isn't in the list */
00597                             } else {
00598                                 printf("Invalid number, give us a valid one (1 or 2).\n");
00599                                 goto waiting_for_input;
00600                             }
00601                         } /* not malformed */
00602                     } else { /* No collision, add the core pointer and put the alias in the list */
00603                         na->nc = findcore(s, 0);
00604                         if (!na->nc) {
00605                             printf("\n\n     WARNING! Malformed database. No nickcore for nick %s, droping it.\n\n\n", na->nick);
00606                             delnick(na, 1);
00607                         } else {
00608                             na->nc->aliascount++;
00609                             index = HASH(na->nick);
00610                             for (prev = NULL, ptr = nalists[index]; ptr && mystricmp(ptr->nick, na->nick) < 0; prev = ptr, ptr = ptr->next);
00611                             na->prev = prev;
00612                             na->next = ptr;
00613                             if (!prev)
00614                                 nalists[index] = na;
00615                             else
00616                                 prev->next = na;
00617                             if (ptr)
00618                                 ptr->prev = na;
00619                         }
00620                     }
00621                     free(s);
00622                 } /* getc_db() */
00623             } /* for() loop */
00624             close_db(f); /* End of section Ib */   
00625         } else
00626             nonick = 1;
00627     }
00628 
00629     /* CLEAN THE CORES */
00630 
00631     for (i = 0; i < 1024; i++) {
00632         for (nc = nclists[i]; nc; nc = ncnext) {
00633             ncnext = nc->next;
00634             if (nc->aliascount < 1) {
00635                 printf("Deleting core %s (%s).\n", nc->display, nc->email); 
00636                 delcore(nc);
00637             }
00638         }
00639     }
00640 
00641     /* Ic: Saving */
00642     if (!nonick) {
00643         if ((f = open_db_write("NickServ", NICK_DB_NEW, 13))) {
00644 
00645             NickAlias *na;
00646             NickCore *nc;
00647             char **access;
00648             Memo *memos;
00649             int i, j;
00650 
00651             /* Nick cores */
00652             for (i = 0; i < 1024; i++) {
00653                 for (nc = nclists[i]; nc; nc = nc->next) {
00654                     SAFE(write_int8(1, f));
00655                     SAFE(write_string(nc->display, f));
00656                     SAFE(write_string(nc->pass, f));
00657                     SAFE(write_string(nc->email, f));
00658                     SAFE(write_string(nc->greet, f));
00659                     SAFE(write_int32(nc->icq, f));
00660                     SAFE(write_string(nc->url, f));
00661                     SAFE(write_int32(nc->flags, f));
00662                     SAFE(write_int16(nc->language, f));
00663                     SAFE(write_int16(nc->accesscount, f));
00664                     for (j = 0, access = nc->access; j < nc->accesscount; j++, access++)
00665                         SAFE(write_string(*access, f));
00666 
00667                     SAFE(write_int16(nc->memos.memocount, f));
00668                     SAFE(write_int16(nc->memos.memomax, f));
00669                     memos = nc->memos.memos;
00670                     for (j = 0; j < nc->memos.memocount; j++, memos++) {
00671                         SAFE(write_int32(memos->number, f));
00672                         SAFE(write_int16(memos->flags, f));
00673                         SAFE(write_int32(memos->time, f));
00674                         SAFE(write_buffer(memos->sender, f));
00675                         SAFE(write_string(memos->text, f));
00676                     }
00677                     SAFE(write_int16(nc->channelcount, f));
00678                     SAFE(write_int16(nc->channelmax, f));
00679                 } /* for (nc) */
00680                 SAFE(write_int8(0, f));
00681             } /* for (i) */
00682 
00683             /* Nick aliases */
00684             for (i = 0; i < 1024; i++) {
00685                 for (na = nalists[i]; na; na = na->next) {
00686                     SAFE(write_int8(1, f));
00687                     SAFE(write_string(na->nick, f));
00688                     SAFE(write_string(na->last_usermask, f));
00689                     SAFE(write_string(na->last_realname, f));
00690                     SAFE(write_string(na->last_quit, f));
00691                     SAFE(write_int32(na->time_registered, f));
00692                     SAFE(write_int32(na->last_seen, f));
00693                     SAFE(write_int16(na->status, f));
00694                     SAFE(write_string(na->nc->display, f));
00695 
00696                 } /* for (na) */
00697                 SAFE(write_int8(0, f));
00698             } /* for (i) */
00699                 close_db(f); /* End of section Ic */
00700                 printf("Nick merging done. New database saved as %s.\n", NICK_DB_NEW);
00701         }
00702     } /* End of section I */
00703 
00704     /* Section II: Chans */
00705     /* IIa: First database */
00706     if ((f = open_db_read("ChanServ", CHAN_DB_1, 16))) {
00707         ChannelInfo *ci, **last, *prev;
00708         int c;
00709 
00710         printf("Trying to merge channels...\n");
00711 
00712         for (i = 0; i < 256; i++) {
00713             int16 tmp16;
00714             int32 tmp32;
00715             int n_levels;
00716             char *s;
00717             int n_ttb;
00718                         /* Unused variable - why? -GD
00719             int J;
00720                         */
00721 
00722             last = &chanlists[i];
00723             prev = NULL;
00724         
00725             while ((c = getc_db(f)) == 1) {
00726                 int j;
00727 
00728                 if (c != 1) {
00729                     printf("Invalid format in %s.\n", CHAN_DB_1);
00730                     exit(0);
00731                 }
00732 
00733                 ci = calloc(sizeof(ChannelInfo), 1);
00734                 *last = ci;
00735                 last = &ci->next;
00736                 ci->prev = prev;
00737                 prev = ci;
00738                 READ(read_buffer(ci->name, f));
00739                 READ(read_string(&ci->founder, f));
00740                 READ(read_string(&ci->successor, f));
00741                 READ(read_buffer(ci->founderpass, f));
00742                 READ(read_string(&ci->desc, f));
00743                 if (!ci->desc)
00744                     ci->desc = strdup("");
00745                 READ(read_string(&ci->url, f));
00746                 READ(read_string(&ci->email, f));
00747                 READ(read_int32(&tmp32, f));
00748                 ci->time_registered = tmp32;
00749                 READ(read_int32(&tmp32, f));
00750                 ci->last_used = tmp32;
00751                 READ(read_string(&ci->last_topic, f));
00752                 READ(read_buffer(ci->last_topic_setter, f));
00753                 READ(read_int32(&tmp32, f));
00754                 ci->last_topic_time = tmp32;
00755                 READ(read_uint32(&ci->flags, f));
00756                 /* Temporary flags cleanup */
00757                 ci->flags &= ~0x80000000;
00758                 READ(read_string(&ci->forbidby, f));
00759                 READ(read_string(&ci->forbidreason, f));
00760