db-merger.c

Go to the documentation of this file.
00001 /*
00002  * Anope Database Merger
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  *****
00009  *
00010  *   Based on the original IRC, db-merger.c
00011  *   (C) Copyright 2005-2006, Florian Schulze (Certus)
00012  *   Based on the original code of Anope, (C) 2003-2013 Anope Team
00013  *
00014  */
00015 
00016 /*
00017  * Known issues:
00018  *    - When merging it is possible that ownership of a channel is transferred 
00019  *      to another nickgroup if the founder's main nick is dropped and granted
00020  *      to another user in the other database. This user will then become
00021  *      founder of the channel.
00022  *
00023  *    - The count of channels a nickgroup has registered is not recalculated
00024  *      after the merge. This means that if a channel was dropped, the owner may
00025  *      have an incorrect counter and may sooner reach the maximum number of
00026  *      allowed registered channels.
00027  *
00028  * Ideally, this should be rewritten from scratch to only merge after both
00029  * database sets are fully loaded, however since we will be migrating to
00030  * another database architecture, this is unlikely to be done for the
00031  * current "stable" DB architecture.
00032  *
00033  *  ~ Viper
00034  */
00035 
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <stdio.h>
00039 #include <fcntl.h>
00040 #include <ctype.h>
00041 #include <time.h>
00042 
00043 #ifndef _WIN32
00044 #include <unistd.h>
00045 #else
00046 #include "sysconf.h"
00047 #include <windows.h>
00048 #endif
00049 
00050 /* Some SUN fixs */
00051 #ifdef __sun
00052 /* Solaris specific code, types that do not exist in Solaris'
00053  * sys/types.h
00054  **/
00055 #undef u_int8_t
00056 #undef u_int16_t
00057 #undef u_int32_t
00058 #undef u_int_64_t
00059 #define u_int8_t uint8_t
00060 #define u_int16_t uint16_t
00061 #define u_int32_t uint32_t
00062 #define u_int64_t uint64_t
00063 
00064 #ifndef INADDR_NONE
00065 #define INADDR_NONE (-1)
00066 #endif
00067 
00068 #endif
00069 
00070 
00071 /* CONFIGURATION BLOCK */
00072 
00073 #define NICK_DB_1      "nick1.db"
00074 #define NICK_DB_2      "nick2.db"
00075 #define NICK_DB_NEW "nick.db"
00076 
00077 #define CHAN_DB_1      "chan1.db"
00078 #define CHAN_DB_2      "chan2.db"
00079 #define CHAN_DB_NEW "chan.db"
00080 
00081 #define BOT_DB_1        "bot1.db"
00082 #define BOT_DB_2        "bot2.db"
00083 #define BOT_DB_NEW   "bot.db"
00084 
00085 #define HOST_DB_1      "hosts1.db"
00086 #define HOST_DB_2      "hosts2.db"
00087 #define HOST_DB_NEW "hosts.db"
00088 
00089 /* END OF CONFIGURATION BLOCK */
00090 
00091 #ifndef _WIN32
00092 #define C_LBLUE "\033[1;34m"
00093 #define C_NONE "\033[m"
00094 #else
00095 #define C_LBLUE ""
00096 #define C_NONE ""
00097 #endif
00098 
00099 #define getc_db(f)              (fgetc((f)->fp))
00100 #define HASH(nick)      ((tolower((nick)[0])&31)<<5 | (tolower((nick)[1])&31))
00101 #define HASH2(chan)     ((chan)[1] ? ((chan)[1]&31)<<5 | ((chan)[2]&31) : 0)
00102 #define read_buffer(buf,f)      (read_db((f),(buf),sizeof(buf)) == sizeof(buf))
00103 #define write_buffer(buf,f)     (write_db((f),(buf),sizeof(buf)) == sizeof(buf))
00104 #define read_db(f,buf,len)      (fread((buf),1,(len),(f)->fp))
00105 #define write_db(f,buf,len)     (fwrite((buf),1,(len),(f)->fp))
00106 #define read_int8(ret,f)        ((*(ret)=fgetc((f)->fp))==EOF ? -1 : 0)
00107 #define write_int8(val,f)       (fputc((val),(f)->fp)==EOF ? -1 : 0)
00108 #define SAFE(x) do { \
00109     if ((x) < 0) { \
00110         printf("Error, the database is broken, trying to continue... no guarantee.\n"); \
00111     } \
00112 } while (0)
00113 #define READ(x) do { \
00114     if ((x) < 0) { \
00115         printf("Error, the database is broken, trying to continue... no guarantee.\n"); \
00116         exit(0); \
00117     } \
00118 } while (0)
00119 
00120 typedef int16_t int16;
00121 typedef u_int16_t uint16;
00122 typedef int32_t int32;
00123 typedef u_int32_t uint32;
00124 typedef struct memo_ Memo;
00125 typedef struct dbFILE_ dbFILE;
00126 typedef struct nickalias_ NickAlias;
00127 typedef struct nickcore_ NickCore;
00128 typedef struct chaninfo_ ChannelInfo;
00129 typedef struct botinfo_ BotInfo;
00130 typedef struct badword_ BadWord;
00131 typedef struct hostcore_ HostCore;
00132 
00133 struct memo_ {
00134     uint32 number;      /* Index number -- not necessarily array position! */
00135     uint16 flags;            /* Flags */
00136     time_t time;          /* When was it sent? */
00137     char sender[32];   /* Name of the sender */
00138     char *text;
00139 };
00140 
00141 struct dbFILE_ {
00142     int mode;                   /* 'r' for reading, 'w' for writing */
00143     FILE *fp;                    /* The normal file descriptor */
00144     char filename[1024];  /* Name of the database file */
00145 };
00146 
00147 typedef struct {
00148     int16 memocount;  /* Current # of memos */
00149     int16 memomax;    /* Max # of memos one can hold*/
00150     Memo *memos;     /* Pointer to original memos */
00151 } MemoInfo;
00152 
00153 typedef struct {
00154     uint16 in_use;         /* 1 if this entry is in use, else 0 */
00155     int16 level;
00156     NickCore *nc;       /* Guaranteed to be non-NULL if in use, NULL if not */
00157     time_t last_seen;
00158 } ChanAccess;
00159 
00160 typedef struct {
00161     int16 in_use;         /* Always 0 if not in use */
00162     int16 is_nick;         /* 1 if a regged nickname, 0 if a nick!user@host mask */
00163     uint16 flags;
00164     union {
00165         char *mask;      /* Guaranteed to be non-NULL if in use, NULL if not */
00166         NickCore *nc;   /* Same */
00167     } u;
00168     char *reason;
00169     char *creator;
00170     time_t addtime;
00171 } AutoKick;
00172 
00173 struct nickalias_ {
00174     NickAlias *next, *prev;
00175     char *nick;                    /* Nickname */
00176     char *last_quit;             /* Last quit message */
00177     char *last_realname;     /* Last realname */
00178     char *last_usermask;     /* Last usermask */
00179     time_t time_registered;  /* When the nick was registered */
00180     time_t last_seen;           /* When it was seen online for the last time */
00181     uint16 status;                  /* See NS_* below */
00182     NickCore *nc;               /* I'm an alias of this */
00183 };
00184 
00185 struct nickcore_ {
00186     NickCore *next, *prev;
00187 
00188     char *display;           /* How the nick is displayed */
00189     char pass[32];               /* Password of the nicks */
00190     char *email;              /* E-mail associated to the nick */
00191     char *greet;              /* Greet associated to the nick */
00192     uint32 icq;                 /* ICQ # associated to the nick */
00193     char *url;                  /* URL associated to the nick */
00194     uint32 flags;                /* See NI_* below */
00195     uint16 language;        /* Language selected by nickname owner (LANG_*) */
00196     uint16 accesscount;     /* # of entries */
00197     char **access;          /* Array of strings */
00198     MemoInfo memos;     /* Memo information */
00199     uint16 channelcount;  /* Number of channels currently registered */
00200     uint16 channelmax;   /* Maximum number of channels allowed */
00201     int unused;                /* Used for nick collisions */
00202     int aliascount;            /* How many aliases link to us? Remove the core if 0 */
00203 };
00204 
00205 struct chaninfo_ {
00206     ChannelInfo *next, *prev;
00207 
00208     char name[64];                     /* Channel name */
00209     char *founder;                      /* Who registered the channel */
00210     char *successor;                   /* Who gets the channel if the founder nick is dropped or expires */
00211     char founderpass[32];            /* Channel password */
00212     char *desc;                           /* Description */
00213     char *url;                              /* URL */
00214     char *email;                          /* Email address */
00215     time_t time_registered;          /* When was it registered */
00216     time_t last_used;                   /* When was it used hte last time */
00217     char *last_topic;                       /* Last topic on the channel */
00218     char last_topic_setter[32];      /* Who set the last topic */
00219     time_t last_topic_time;           /* When the last topic was set */
00220     uint32 flags;                          /* Flags */
00221     char *forbidby;                      /* if forbidden: who did it */
00222     char *forbidreason;                /* if forbidden: why */
00223     int16 bantype;                       /* Bantype */
00224     int16 *levels;                        /* Access levels for commands */
00225     uint16 accesscount;                 /* # of pple with access */
00226     ChanAccess *access;             /* List of authorized users */
00227     uint16 akickcount;                    /* # of akicked pple */
00228     AutoKick *akick;                    /* List of users to kickban */
00229     uint32 mlock_on, mlock_off;   /* See channel modes below */
00230     uint32 mlock_limit;                /* 0 if no limit */
00231     char *mlock_key;                  /* NULL if no key */
00232     char *mlock_flood;                /* NULL if no +f */
00233     char *mlock_redirect;            /* NULL if no +L */
00234     char *entry_message;           /* Notice sent on entering channel */
00235     MemoInfo memos;                 /* Memos */
00236     char *bi;                               /* Bot used on this channel */
00237     uint32 botflags;                      /* BS_* below */
00238     int16 *ttb;                             /* Times to ban for each kicker */
00239     uint16 bwcount;                       /* Badword count */
00240     BadWord *badwords;             /* For BADWORDS kicker */
00241     int16 capsmin, capspercent;    /* For CAPS kicker */
00242     int16 floodlines, floodsecs;      /* For FLOOD kicker */
00243     int16 repeattimes;                 /* For REPEAT kicker */
00244 };
00245 
00246 struct botinfo_ {
00247     BotInfo *next, *prev;
00248     char *nick;            /* Nickname of the bot */
00249     char *user;            /* Its user name */
00250     char *host;            /* Its hostname */
00251     char *real;            /* Its real name */
00252     int16 flags;            /* Bot flags */
00253     time_t created;      /* Birth date */
00254     int16 chancount;        /* Number of channels that use the bot. */
00255 };
00256 
00257 struct badword_ {
00258     uint16 in_use;
00259     char *word;
00260     uint16 type;
00261 };
00262 
00263 struct hostcore_ {
00264     HostCore *next, *last;
00265     char *nick;        /* Owner of the vHost */
00266     char *vIdent;    /* vIdent for the user */
00267     char *vHost;     /* Vhost for this user */
00268     char *creator;   /* Oper Nick of the oper who set the vhost */
00269     time_t time;      /* Date/Time vHost was set */
00270 };
00271 
00272 dbFILE *open_db_write(const char *service, const char *filename, int version);
00273 dbFILE *open_db_read(const char *service, const char *filename, int version);
00274 NickCore *findcore(const char *nick, int version);
00275 NickAlias *findnick(const char *nick);
00276 BotInfo *findbot(char *nick);
00277 ChannelInfo *cs_findchan(const char *chan);
00278 char *strscpy(char *d, const char *s, size_t len);
00279 int write_file_version(dbFILE * f, uint32 version);
00280 int mystricmp(const char *s1, const char *s2);
00281 int delnick(NickAlias *na, int donttouchthelist);
00282 int write_string(const char *s, dbFILE * f);
00283 int write_ptr(const void *ptr, dbFILE * f);
00284 int read_int16(int16 * ret, dbFILE * f);
00285 int read_int32(int32 * ret, dbFILE * f);
00286 int read_uint16(uint16 * ret, dbFILE * f);
00287 int read_uint32(uint32 * ret, dbFILE * f);
00288 int read_string(char **ret, dbFILE * f);
00289 int write_int16(uint16 val, dbFILE * f);
00290 int write_int32(uint32 val, dbFILE * f);
00291 int read_ptr(void **ret, dbFILE * f);
00292 int delcore(NickCore *nc);
00293 void alpha_insert_chan(ChannelInfo * ci);
00294 void insert_bot(BotInfo * bi);
00295 void close_db(dbFILE * f);
00296 
00297 ChannelInfo *chanlists[256];
00298 NickAlias *nalists[1024];
00299 NickCore *nclists[1024];
00300 BotInfo *botlists[256];
00301 
00302 int preferfirst = 0, prefersecond = 0, preferoldest = 0, prefernewest = 0;
00303 int nonick = 0, nochan = 0, nobot = 0, nohost = 0;
00304 
00305 int main(int argc, char *argv[])
00306 {
00307     dbFILE *f;
00308     int i;
00309     NickCore *nc, *ncnext;
00310     HostCore *firsthc = NULL;
00311 
00312     printf("\n"C_LBLUE"DB Merger for Anope IRC Services"C_NONE"\n");
00313 
00314     if (argc >= 2) {
00315         if (!mystricmp(argv[1], "--PREFEROLDEST")) {
00316             printf("Preferring oldest database entries on collision.\n");
00317             preferoldest = 1;
00318         } else if (!mystricmp(argv[1], "--PREFERFIRST")) {
00319             printf("Preferring first database's entries on collision .\n");
00320             preferfirst = 1;
00321         } else if (!mystricmp(argv[1], "--PREFERSECOND")) {
00322             printf("Preferring second database's entries on collision.\n");
00323             prefersecond = 1;
00324         } else if (!mystricmp(argv[1], "--PREFERNEWEST")) {
00325             printf("Preferring newest database entries on collision.\n");
00326             prefernewest = 1;
00327         }
00328     }
00329 
00330     /* Section I: Nicks */
00331     /* Ia: First database */
00332     if ((f = open_db_read("NickServ", NICK_DB_1, 14))) {
00333 
00334         NickAlias *na, **nalast, *naprev;
00335         NickCore *nc, **nclast, *ncprev;
00336         int16 tmp16;
00337         int32 tmp32;
00338         int i, j, c;
00339 
00340         printf("Trying to merge nicks...\n");
00341 
00342         /* Nick cores */
00343         for (i = 0; i < 1024; i++) {
00344             nclast = &nclists[i];
00345             ncprev = NULL;
00346 
00347             while ((c = getc_db(f)) == 1) {
00348                 if (c != 1) {
00349                     printf("Invalid format in %s.\n", NICK_DB_1);
00350                     exit(0);
00351                 }
00352 
00353                 nc = calloc(1, sizeof(NickCore));
00354                 nc->aliascount = 0;
00355                 nc->unused = 0;
00356 
00357                 *nclast = nc;
00358                 nclast = &nc->next;
00359                 nc->prev = ncprev;
00360                 ncprev = nc;
00361 
00362                 READ(read_string(&nc->display, f));
00363                 READ(read_buffer(nc->pass, f));
00364                 READ(read_string(&nc->email, f));
00365                 READ(read_string(&nc->greet, f));
00366                 READ(read_uint32(&nc->icq, f));
00367                 READ(read_string(&nc->url, f));
00368                 READ(read_uint32(&nc->flags, f));
00369                 READ(read_uint16(&nc->language, f));
00370                 READ(read_uint16(&nc->accesscount, f));
00371                 if (nc->accesscount) {
00372                     char **access;
00373                     access = calloc(sizeof(char *) * nc->accesscount, 1);
00374                     nc->access = access;
00375                     for (j = 0; j < nc->accesscount; j++, access++)
00376                         READ(read_string(access, f));
00377                 }
00378                 READ(read_int16(&nc->memos.memocount, f));
00379                 READ(read_int16(&nc->memos.memomax, f));
00380                 if (nc->memos.memocount) {
00381                     Memo *memos;
00382                     memos = calloc(sizeof(Memo) * nc->memos.memocount, 1);
00383                     nc->memos.memos = memos;
00384                     for (j = 0; j < nc->memos.memocount; j++, memos++) {
00385                         READ(read_uint32(&memos->number, f));
00386                         READ(read_uint16(&memos->flags, f));
00387                         READ(read_int32(&tmp32, f));
00388                         memos->time = tmp32;
00389                         READ(read_buffer(memos->sender, f));
00390                         READ(read_string(&memos->text, f));
00391                     }
00392                 }
00393                 READ(read_uint16(&nc->channelcount, f));
00394                 READ(read_int16(&tmp16, f));
00395             } /* getc_db() */
00396             *nclast = NULL;
00397         } /* for() loop */
00398 
00399         /* Nick aliases */
00400         for (i = 0; i < 1024; i++) {
00401             char *s = NULL;
00402 
00403             nalast = &nalists[i];
00404             naprev = NULL;
00405 
00406             while ((c = getc_db(f)) == 1) {
00407                 if (c != 1) {
00408                     printf("Invalid format in %s.\n", NICK_DB_1);
00409                     exit(0);
00410                 }
00411 
00412                 na = calloc(1, sizeof(NickAlias));
00413 
00414                 READ(read_string(&na->nick, f));
00415                 READ(read_string(&na->last_usermask, f));
00416                 READ(read_string(&na->last_realname, f));
00417                 READ(read_string(&na->last_quit, f));
00418 
00419                 READ(read_int32(&tmp32, f));
00420                 na->time_registered = tmp32;
00421                 READ(read_int32(&tmp32, f));
00422                 na->last_seen = tmp32;
00423                 READ(read_uint16(&na->status, f));
00424                 READ(read_string(&s, f));
00425                 na->nc = findcore(s, 0);
00426                 na->nc->aliascount++;
00427                 free(s);
00428 
00429                 *nalast = na;
00430                 nalast = &na->next;
00431                 na->prev = naprev;
00432                 naprev = na;
00433             } /* getc_db() */
00434             *nalast = NULL;
00435         } /* for() loop */
00436         close_db(f); /* End of section Ia */
00437     } else
00438         nonick = 1;
00439 
00440     /* Ib: Second database */
00441     if (!nonick) {
00442         if ((f = open_db_read("NickServ", NICK_DB_2, 14))) {
00443 
00444             NickAlias *na, *naptr;
00445             NickCore *nc;
00446             int16 tmp16;
00447             int32 tmp32;
00448             int i, j, index, c;
00449 
00450             /* Nick cores */
00451             for (i = 0; i < 1024; i++) {
00452 
00453                 while ((c = getc_db(f)) == 1) {
00454                     if (c != 1) {
00455                         printf("Invalid format in %s.\n", NICK_DB_2);
00456                         exit(0);
00457                     }
00458 
00459                     nc = calloc(1, sizeof(NickCore));
00460                     READ(read_string(&nc->display, f));
00461                     READ(read_buffer(nc->pass, f));
00462                     READ(read_string(&nc->email, f));
00463 
00464                     naptr = findnick(nc->display);
00465                     if (naptr)
00466                         nc->unused = 1;
00467                     else
00468                         nc->unused = 0;
00469 
00470                     nc->aliascount = 0;
00471 
00472                     index = HASH(nc->display);
00473                     nc->prev = NULL;
00474                     nc->next = nclists[index];
00475                     if (nc->next)
00476                         nc->next->prev = nc;
00477                     nclists[index] = nc;
00478 
00479                     READ(read_string(&nc->greet, f));
00480                     READ(read_uint32(&nc->icq, f));
00481                     READ(read_string(&nc->url, f));
00482                     READ(read_uint32(&nc->flags, f));
00483                     READ(read_uint16(&nc->language, f));
00484                     READ(read_uint16(&nc->accesscount, f));
00485                     if (nc->accesscount) {
00486                         char **access;
00487                         access = calloc(sizeof(char *) * nc->accesscount, 1);
00488                         nc->access = access;
00489                         for (j = 0; j < nc->accesscount; j++, access++)
00490                             READ(read_string(access, f));
00491                     }
00492                     READ(read_int16(&nc->memos.memocount, f));
00493                     READ(read_int16(&nc->memos.memomax, f));
00494                     if (nc->memos.memocount) {
00495                         Memo *memos;
00496                         memos = calloc(sizeof(Memo) * nc->memos.memocount, 1);
00497                         nc->memos.memos = memos;
00498                         for (j = 0; j < nc->memos.memocount; j++, memos++) {
00499                             READ(read_uint32(&memos->number, f));
00500                             READ(read_uint16(&memos->flags, f));
00501                             READ(read_int32(&tmp32, f));
00502                             memos->time = tmp32;
00503                             READ(read_buffer(memos->sender, f));
00504                             READ(read_string(&memos->text, f));
00505                         }
00506                     }
00507                     READ(read_uint16(&nc->channelcount, f));
00508                     READ(read_int16(&tmp16, f));
00509                 } /* getc_db() */
00510             } /* for() loop */
00511 
00512             /* Nick aliases */
00513             for (i = 0; i < 1024; i++) {
00514                 char *s = NULL;
00515                 NickAlias *ptr, *prev, *naptr;
00516 
00517                 while ((c = getc_db(f)) == 1) {
00518                     if (c != 1) {
00519                         printf("Invalid format in %s.\n", NICK_DB_2);
00520                         exit(0);
00521                     }
00522 
00523                     na = calloc(1, sizeof(NickAlias));
00524 
00525                     READ(read_string(&na->nick, f));
00526                     READ(read_string(&na->last_usermask, f));
00527                     READ(read_string(&na->last_realname, f));
00528                     READ(read_string(&na->last_quit, f));
00529                     READ(read_int32(&tmp32, f));
00530                     na->time_registered = tmp32;
00531                     READ(read_int32(&tmp32, f));
00532                     na->last_seen = tmp32;
00533                     READ(read_uint16(&na->status, f));
00534                     READ(read_string(&s, f));
00535 
00536                     naptr = findnick(na->nick);
00537                     if (naptr) { /* COLLISION! na = collision #2 = new (na->nc doesn't exist yet), naptr = collision #1 = old (naptr->nc exists) */
00538                         char input[1024];
00539                         NickCore *ncptr = findcore(na->nick, 1); /* Find core for #2, ncptr MUST exist since we've read all cores, if it doesn't eixst, we have a malformed db */;
00540 
00541                         if (!ncptr) { /* malformed */
00542                             printf("\n\n     WARNING! Malformed database. No nickcore for nick %s, droping it.\n\n\n", na->nick);
00543                             delnick(na, 1);
00544                         } else { /* not malformed */
00545                             if (!preferoldest && !preferfirst && !prefersecond && !prefernewest) {
00546                                 printf("Nick collision for nick %s:\n\n", na->nick);
00547                                 printf("Group 1: %s (%s)\n", naptr->nc->display, naptr->nc->email);
00548                                 printf("Time registered: %s\n", ctime(&naptr->time_registered));
00549                                 printf("Group 2: %s (%s)\n", ncptr->display, ncptr->email);
00550                                 printf("Time registered: %s\n", ctime(&na->time_registered));
00551                                 printf("What group do you want to keep? Enter the related group number \"1\" or \"2\".\n");
00552                             }
00553 
00554                             if (preferoldest) {
00555                                 input[0] = (na->time_registered > naptr->time_registered) ? '1' : '2';
00556                             } else if (prefernewest) {
00557                                 input[0] = (na->time_registered > naptr->time_registered) ? '2' : '1';
00558                             } else if (preferfirst) {
00559                                 input[0] = '1';
00560                             } else if (prefersecond) {
00561                                 input[0] = '2';
00562                             } else {
00563                                 waiting_for_input:
00564                                 scanf("%s", input);
00565                             }
00566                             if (input[0] == '1') { /* #2 isn't in the list yet, #1 is. free #2 alias. */
00567                                 printf("Deleting nick alias %s (#2).\n", na->nick);
00568                                 delnick(na, 1); /* free()s the alias without touching the list since na isn't in the list */
00569                             } else if (input[0] == '2') { /* get alias #1 out of the list, then free() it, then add #2 to the list */
00570                                 printf("Deleting nick alias %s (#1).\n", naptr->nick); 
00571                                 naptr->nc->aliascount--; /* tell the core it has one alias less */
00572                                 delnick(naptr, 0); /* removes the alias from the list and free()s it */
00573                                 na->nc = ncptr;
00574                                 na->nc->aliascount++;
00575                                 index = HASH(na->nick);
00576                                 for (prev = NULL, ptr = nalists[index]; ptr && mystricmp(ptr->nick, na->nick) < 0; prev = ptr, ptr = ptr->next);
00577                                 na->prev = prev;
00578                                 na->next = ptr;
00579                                 if (!prev)
00580                                     nalists[index] = na;
00581                                 else
00582                                     prev->next = na;
00583                                 if (ptr)
00584                                     ptr->prev = na;
00585                             } else {
00586                                 printf("Invalid number, give us a valid one (1 or 2).\n");
00587                                 goto waiting_for_input;
00588                             }
00589                         } /* not malformed */
00590                     } else { /* No collision, add the core pointer and put the alias in the list */
00591                         na->nc = findcore(s, 0);
00592                         if (!na->nc) {
00593                             printf("\n\n     WARNING! Malformed database. No nickcore for nick %s, droping it.\n\n\n", na->nick);
00594                             delnick(na, 1);
00595                         } else {
00596                             na->nc->aliascount++;
00597                             index = HASH(na->nick);
00598                             for (prev = NULL, ptr = nalists[index]; ptr && mystricmp(ptr->nick, na->nick) < 0; prev = ptr, ptr = ptr->next);
00599                             na->prev = prev;
00600                             na->next = ptr;
00601                             if (!prev)
00602                                 nalists[index] = na;
00603                             else
00604                                 prev->next = na;
00605                             if (ptr)
00606                                 ptr->prev = na;
00607                         }
00608                     }
00609                     free(s);
00610                 } /* getc_db() */
00611             } /* for() loop */
00612             close_db(f); /* End of section Ib */   
00613         } else
00614             nonick = 1;
00615     }
00616 
00617     /* CLEAN THE CORES */
00618 
00619     for (i = 0; i < 1024; i++) {
00620         for (nc = nclists[i]; nc; nc = ncnext) {
00621             ncnext = nc->next;
00622             if (nc->aliascount < 1) {
00623                 printf("Deleting core %s (%s).\n", nc->display, nc->email); 
00624                 delcore(nc);
00625             }
00626         }
00627     }
00628 
00629     /* Ic: Saving */
00630     if (!nonick) {
00631         if ((f = open_db_write("NickServ", NICK_DB_NEW, 14))) {
00632 
00633             NickAlias *na;
00634             NickCore *nc;
00635             char **access;
00636             Memo *memos;
00637             int i, j;
00638 
00639             /* Nick cores */
00640             for (i = 0; i < 1024; i++) {
00641                 for (nc = nclists[i]; nc; nc = nc->next) {
00642                     SAFE(write_int8(1, f));
00643                     SAFE(write_string(nc->display, f));
00644                     SAFE(write_buffer(nc->pass, f));
00645                     SAFE(write_string(nc->email, f));
00646                     SAFE(write_string(nc->greet, f));
00647                     SAFE(write_int32(nc->icq, f));
00648                     SAFE(write_string(nc->url, f));
00649                     SAFE(write_int32(nc->flags, f));
00650                     SAFE(write_int16(nc->language, f));
00651                     SAFE(write_int16(nc->accesscount, f));
00652                     for (j = 0, access = nc->access; j < nc->accesscount; j++, access++)
00653                         SAFE(write_string(*access, f));
00654 
00655                     SAFE(write_int16(nc->memos.memocount, f));
00656                     SAFE(write_int16(nc->memos.memomax, f));
00657                     memos = nc->memos.memos;
00658                     for (j = 0; j < nc->memos.memocount; j++, memos++) {
00659                         SAFE(write_int32(memos->number, f));
00660                         SAFE(write_int16(memos->flags, f));
00661                         SAFE(write_int32(memos->time, f));
00662                         SAFE(write_buffer(memos->sender, f));
00663                         SAFE(write_string(memos->text, f));
00664                     }
00665                     SAFE(write_int16(nc->channelcount, f));
00666                     SAFE(write_int16(nc->channelmax, f));
00667                 } /* for (nc) */
00668                 SAFE(write_int8(0, f));
00669             } /* for (i) */
00670 
00671             /* Nick aliases */
00672             for (i = 0; i < 1024; i++) {
00673                 for (na = nalists[i]; na; na = na->next) {
00674                     SAFE(write_int8(1, f));
00675                     SAFE(write_string(na->nick, f));
00676                     SAFE(write_string(na->last_usermask, f));
00677                     SAFE(write_string(na->last_realname, f));
00678                     SAFE(write_string(na->last_quit, f));
00679                     SAFE(write_int32(na->time_registered, f));
00680                     SAFE(write_int32(na->last_seen, f));
00681                     SAFE(write_int16(na->status, f));
00682                     SAFE(write_string(na->nc->display, f));
00683 
00684                 } /* for (na) */
00685                 SAFE(write_int8(0, f));
00686             } /* for (i) */
00687                 close_db(f); /* End of section Ic */
00688                 printf("Nick merging done. New database saved as %s.\n", NICK_DB_NEW);
00689         }
00690     } /* End of section I */
00691 
00692     /* Section II: Chans */
00693     /* IIa: First database */
00694     if ((f = open_db_read("ChanServ", CHAN_DB_1, 16))) {
00695         ChannelInfo *ci, **last, *prev;
00696         int c;
00697 
00698         printf("Trying to merge channels...\n");
00699 
00700         for (i = 0; i < 256; i++) {
00701             int16 tmp16;
00702             int32 tmp32;
00703             int n_levels;
00704             char *s;
00705             int n_ttb;
00706                         /* Unused variable - why? -GD
00707             int J;
00708                         */
00709 
00710             last = &chanlists[i];
00711             prev = NULL;
00712         
00713             while ((c = getc_db(f)) == 1) {
00714                 int j;
00715 
00716                 if (c != 1) {
00717                     printf("Invalid format in %s.\n", CHAN_DB_1);
00718                     exit(0);
00719                 }
00720 
00721                 ci = calloc(sizeof(ChannelInfo), 1);
00722                 *last = ci;
00723                 last = &ci->next;
00724                 ci->prev = prev;
00725                 prev = ci;
00726                 READ(read_buffer(ci->name, f));
00727                 READ(read_string(&ci->founder, f));
00728                 READ(read_string(&ci->successor, f));
00729                 READ(read_buffer(ci->founderpass, f));
00730                 READ(read_string(&ci->desc, f));
00731                 if (!ci->desc)
00732                     ci->desc = strdup("");
00733                 READ(read_string(&ci->url, f));
00734                 READ(read_string(&ci->email, f));
00735                 READ(read_int32(&tmp32, f));
00736                 ci->time_registered = tmp32;
00737                 READ(read_int32(&tmp32, f));
00738                 ci->last_used = tmp32;
00739                 READ(read_string(&ci->last_topic, f));
00740                 READ(read_buffer(ci->last_topic_setter, f));
00741                 READ(read_int32(&tmp32, f));
00742                 ci->last_topic_time = tmp32;
00743                 READ(read_uint32(&ci->flags, f));
00744                 /* Temporary flags cleanup */
00745                 ci->flags &= ~0x80000000;
00746                 READ(read_string(&ci->forbidby, f));
00747                 READ(read_string(&ci->forbidreason, f));
00748                 READ(read_int16(&tmp16, f));
00749                 ci->bantype = tmp16;
00750                 READ(read_int16(&tmp16, f));
00751                 n_levels = tmp16;
00752                 ci->levels = calloc(36 * sizeof(*ci->levels), 1);
00753                 for (j = 0; j < n_levels; j++) {
00754                     if (j < 36)
00755                         READ(read_int16(&ci->levels[j], f));
00756                     else
00757                         READ(read_int16(&tmp16, f));
00758                 }
00759                 READ(read_uint16(&ci->accesscount, f));
00760                 if (ci->accesscount) {
00761                     ci->access = calloc(ci->accesscount, sizeof(ChanAccess));
00762                     for (j = 0; j < ci->accesscount; j++) {
00763                         READ(read_uint16(&ci->access[j].in_use, f));
00764                         if (ci->access[j].in_use) {
00765                             READ(read_int16(&ci->access[j].level, f));
00766                             READ(read_string(&s, f));
00767                             if (s) {
00768                                 ci->access[j].nc = findcore(s, 0);
00769                                 free(s);
00770                             }
00771                             if (ci->access[j].nc == NULL)
00772                                 ci->access[j].in_use = 0;
00773                             READ(read_int32(&tmp32, f));
00774                             ci->access[j].last_seen = tmp32;
00775                         }
00776                     }
00777                 } else {
00778                     ci->access = NULL;
00779                 }
00780                 READ(read_uint16(&ci->akickcount, f));
00781                 if (ci->akickcount) {
00782                     ci->akick = calloc(ci->akickcount, sizeof(AutoKick));
00783                     for (j = 0; j < ci->akickcount; j++) {
00784                         SAFE(read_uint16(&ci->akick[j].flags, f));
00785                         if (ci->akick[j].flags & 0x0001) {
00786                             SAFE(read_string(&s, f));
00787                             if (ci->akick[j].flags & 0x0002) {
00788                                 ci->akick[j].u.nc = findcore(s, 0);
00789                                 if (!ci->akick[j].u.nc)
00790                                     ci->akick[j].flags &= ~0x0001;
00791                                 free(s);
00792                             } else {
00793                                 ci->akick[j].u.mask = s;
00794                             }
00795                             SAFE(read_string(&s, f));
00796                             if (ci->akick[j].flags & 0x0001)
00797                                 ci->akick[j].reason = s;
00798                             else if (s)
00799                                 free(s);
00800                             SAFE(read_string(&s, f));
00801                             if (ci->akick[j].flags & 0x0001) {
00802                                 ci->akick[j].creator = s;
00803                             } else if (s) {
00804                                 free(s);
00805                             }
00806                             SAFE(read_int32(&tmp32, f));
00807                             if (ci->akick[j].flags & 0x0001)
00808                                 ci->akick[j].addtime = tmp32;
00809                         }
00810                     }
00811                 } else {
00812                     ci->akick = NULL;
00813                 }
00814                 READ(read_uint32(&ci->mlock_on, f));
00815                 READ(read_uint32(&ci->mlock_off, f));
00816                 READ(read_uint32(&ci->mlock_limit, f));
00817                 READ(read_string(&ci->mlock_key, f));
00818                 READ(read_string(&ci->mlock_flood, f));
00819                 READ(read_string(&ci->mlock_redirect, f));
00820                 READ(read_int16(&ci->memos.memocount, f));
00821                 READ(read_int16(&ci->memos.memomax, f));
00822                 if (ci->memos.memocount) {
00823                     Memo *memos;
00824                     memos = calloc(sizeof(Memo) * ci->memos.memocount, 1);
00825                     ci->memos.memos = memos;
00826                     for (j = 0; j < ci->memos.memocount; j++, memos++) {
00827                         READ(read_uint32(&memos->number, f));
00828                         READ(read_uint16(&memos->flags, f));
00829                         READ(read_int32(&tmp32, f));
00830                         memos->time = tmp32;
00831                         READ(read_buffer(memos->sender, f));
00832                         READ(read_string(&memos->text, f));
00833                     }
00834                 }
00835                 READ(read_string(&ci->entry_message, f));
00836 
00837                 /* BotServ options */
00838                 READ(read_string(&ci->bi, f));
00839                 READ(read_int32(&tmp32, f));
00840                 ci->botflags = tmp32;
00841                 READ(read_int16(&tmp16, f));
00842                 n_ttb = tmp16;
00843                 ci->ttb = calloc(2 * 8, 1);
00844                 for (j = 0; j < n_ttb; j++) {
00845                     if (j < 8)
00846                         READ(read_int16(&ci->ttb[j], f));
00847                     else
00848                         READ(read_int16(&tmp16, f));
00849                 }
00850                 for (j = n_ttb; j < 8; j++)
00851                     ci->ttb[j] = 0;
00852                 READ(read_int16(&tmp16, f));
00853                 ci->capsmin = tmp16;
00854                 READ(read_int16(&tmp16, f));
00855                 ci->capspercent = tmp16;
00856                 READ(read_int16(&tmp16, f));
00857                 ci->floodlines = tmp16;
00858                 READ(read_int16(&tmp16, f));
00859                 ci->floodsecs = tmp16;
00860                 READ(read_int16(&tmp16, f));
00861                 ci->repeattimes = tmp16;
00862 
00863                 READ(read_uint16(&ci->bwcount, f));
00864                 if (ci->bwcount) {
00865                     ci->badwords = calloc(ci->bwcount, sizeof(BadWord));
00866                     for (j = 0; j < ci->bwcount; j++) {
00867                         SAFE(read_uint16(&ci->badwords[j].in_use, f));
00868                         if (ci->badwords[j].in_use) {
00869                             SAFE(read_string(&ci->badwords[j].word, f));
00870                             SAFE(read_uint16(&ci->badwords[j].type, f));
00871                         }
00872                     }
00873                 } else {
00874                     ci->badwords = NULL;
00875                 }
00876             } /* getc_db() */
00877             *last = NULL;
00878         } /* for() loop */
00879         close_db(f);
00880     } else
00881         nochan = 1;
00882 
00883     /* IIb: Second database */
00884     if (!nochan) {
00885         if ((f = open_db_read("ChanServ", CHAN_DB_2, 16))) {
00886             int c;
00887 
00888             for (i = 0; i < 256; i++) {
00889                 int16 tmp16;
00890                 int32 tmp32;
00891                 int n_levels;
00892                 char *s;
00893                 int n_ttb;
00894                                 /* Unused variables - why? -GD
00895                 char input[1024];
00896                 NickAlias *na;
00897                 int J;
00898                                 */
00899 
00900                 while ((c = getc_db(f)) == 1) {
00901                     ChannelInfo *ci = NULL, *ciptr = NULL;
00902                     int j;
00903 
00904                     if (c != 1) {
00905                         printf("Invalid format in %s.\n", CHAN_DB_2);
00906                         exit(0);
00907                     }
00908 
00909                     ci = calloc(sizeof(ChannelInfo), 1);
00910                     READ(read_buffer(ci->name, f));
00911                     READ(read_string(&ci->founder, f));
00912                     READ(read_string(&ci->successor, f));
00913                     READ(read_buffer(ci->founderpass, f));
00914                     READ(read_string(&ci->desc, f));
00915                     if (!ci->desc)
00916                         ci->desc = strdup("");
00917                     READ(read_string(&ci->url, f));
00918                     READ(read_string(&ci->email, f));
00919                     READ(read_int32(&tmp32, f));
00920                     ci->time_registered = tmp32;
00921                     READ(read_int32(&tmp32, f));
00922                     ci->last_used = tmp32;
00923                     READ(read_string(&ci->last_topic, f));
00924                     READ(read_buffer(ci->last_topic_setter, f));
00925                     READ(read_int32(&tmp32, f));
00926                     ci->last_topic_time = tmp32;
00927                     READ(read_uint32(&ci->flags, f));
00928                     /* Temporary flags cleanup */
00929                     ci->flags &= ~0x80000000;
00930                     READ(read_string(&ci->forbidby, f));
00931                     READ(read_string(&ci->forbidreason, f));
00932                     READ(read_int16(&tmp16, f));
00933                     ci->bantype = tmp16;
00934                     READ(read_int16(&tmp16, f));
00935                     n_levels = tmp16;
00936                     ci->levels = calloc(36 * sizeof(*ci->levels), 1);
00937                     for (j = 0; j < n_levels; j++) {
00938                         if (j < 36)
00939                             READ(read_int16(&ci->levels[j], f));
00940                         else
00941                             READ(read_int16(&tmp16, f));
00942                     }
00943                     READ(read_uint16(&ci->accesscount, f));
00944                     if (ci->accesscount) {
00945                         ci->access = calloc(ci->accesscount, sizeof(ChanAccess));
00946                         for (j = 0; j < ci->accesscount; j++) {
00947                             READ(read_uint16(&ci->access[j].in_use, f));
00948                             if (ci->access[j].in_use) {
00949                                 READ(read_int16(&ci->access[j].level, f));
00950                                 READ(read_string(&s, f));
00951                                 if (s) {
00952                                     ci->access[j].nc = findcore(s, 0);
00953                                     free(s);
00954                                 }
00955                                 if (ci->access[j].nc == NULL)
00956                                     ci->access[j].in_use = 0;
00957                                 READ(read_int32(&tmp32, f));
00958                                 ci->access[j].last_seen = tmp32;
00959                             }
00960                         }
00961                     } else {
00962                         ci->access = NULL;
00963                     }
00964                     READ(read_uint16(&ci->akickcount, f));
00965                     if (ci->akickcount) {
00966                         ci->akick = calloc(ci->akickcount, sizeof(AutoKick));
00967                         for (j = 0; j < ci->akickcount; j++) {
00968                             SAFE(read_uint16(&ci->akick[j].flags, f));
00969                             if (ci->akick[j].flags & 0x0001) {
00970                                 SAFE(read_string(&s, f));
00971                                 if (ci->akick[j].flags & 0x0002) {
00972                                     ci->akick[j].u.nc = findcore(s, 0);
00973                                     if (!ci->akick[j].u.nc)
00974                                         ci->akick[j].flags &= ~0x0001;
00975                                     free(s);
00976                                 } else {
00977                                     ci->akick[j].u.mask = s;
00978                                 }
00979                                 SAFE(read_string(&s, f));
00980                                 if (ci->akick[j].flags & 0x0001)
00981                                     ci->akick[j].reason = s;
00982                                 else if (s)
00983                                     free(s);
00984                                 SAFE(read_string(&s, f));
00985                                 if (ci->akick[j].flags & 0x0001) {
00986                                     ci->akick[j].creator = s;
00987                                 } else if (s) {
00988                                     free(s);
00989                                 }
00990                                 SAFE(read_int32(&tmp32, f));
00991                                 if (ci->akick[j].flags & 0x0001)
00992                                     ci->akick[j].addtime = tmp32;
00993                             }
00994                         }
00995                     } else {
00996                         ci->akick = NULL;
00997                     }
00998                     READ(read_uint32(&ci->mlock_on, f));
00999                     READ(read_uint32(&ci->mlock_off, f));
01000                     READ(read_uint32(&ci->mlock_limit, f));
01001                     READ(read_string(&ci->mlock_key, f));
01002                     READ(read_string(&ci->mlock_flood, f));
01003                     READ(read_string(&ci->mlock_redirect, f));
01004                     READ(read_int16(&ci->memos.memocount, f));
01005                     READ(read_int16(&ci->memos.memomax, f));
01006                     if (ci->memos.memocount) {
01007                         Memo *memos;
01008                         memos = calloc(sizeof(Memo) * ci->memos.memocount, 1);
01009                         ci->memos.memos = memos;
01010                         for (j = 0; j < ci->memos.memocount; j++, memos++) {
01011                             READ(read_uint32(&memos->number, f));
01012                             READ(read_uint16(&memos->flags, f));
01013                             READ(read_int32(&tmp32, f));
01014                             memos->time = tmp32;
01015                             READ(read_buffer(memos->sender, f));
01016                             READ(read_string(&memos->text, f));
01017                         }
01018                     }
01019                     READ(read_string(&ci->entry_message, f));
01020 
01021                     /* BotServ options */
01022                     READ(read_string(&ci->bi, f));
01023                     READ(read_int32(&tmp32, f));
01024                     ci->botflags = tmp32;
01025                     READ(read_int16(&tmp16, f));
01026                     n_ttb = tmp16;
01027                     ci->ttb = calloc(32, 1);
01028                     for (j = 0; j < n_ttb; j++) {
01029                         if (j < 8)
01030                             READ(read_int16(&ci->ttb[j], f));
01031                         else
01032                             READ(read_int16(&tmp16, f));
01033                     }
01034                     for (j = n_ttb; j < 8; j++)
01035                         ci->ttb[j] = 0;
01036                     READ(read_int16(&tmp16, f));
01037                     ci->capsmin = tmp16;
01038                     READ(read_int16(&tmp16, f));
01039                     ci->capspercent = tmp16;
01040                     READ(read_int16(&tmp16, f));
01041                     ci->floodlines = tmp16;
01042                     READ(read_int16(&tmp16, f));
01043                     ci->floodsecs = tmp16;
01044                     READ(read_int16(&tmp16, f));
01045                     ci->repeattimes = tmp16;
01046 
01047                     READ(read_uint16(&ci->bwcount, f));
01048                     if (ci->bwcount) {
01049                         ci->badwords = calloc(ci->bwcount, sizeof(BadWord));
01050                         for (j = 0; j < ci->bwcount; j++) {
01051                             SAFE(read_uint16(&ci->badwords[j].in_use, f));
01052                             if (ci->badwords[j].in_use) {
01053                                 SAFE(read_string(&ci->badwords[j].word, f));
01054                                 SAFE(read_uint16(&ci->badwords[j].type, f));
01055                             }
01056                         }
01057                     } else {
01058                         ci->badwords = NULL;
01059                     }
01060                     /* READING DONE */
01061                     ciptr = cs_findchan(ci->name);
01062                     if (ciptr) { /* COLLISION! ciptr = old = 1; ci = new = 2*/
01063                         char input[1024];
01064 
01065                         if (!preferoldest && !preferfirst && !prefersecond && !prefernewest) {
01066                             printf("Chan collision for channel %s:\n\n", ci->name);
01067 
01068                             printf("Owner of channel 1: %s (%s)\n", (ciptr->founder) ? ciptr->founder : "none", (ciptr->email) ? ciptr->email : "no valid email");
01069                             printf("Accesscount: %u\n", ciptr->accesscount);
01070                             if (ciptr->flags & 0x00000080) {
01071                                 printf("Status: Channel is forbidden");
01072                             } else if (ciptr->flags & 0x00010000) {
01073                                 printf("Status: Channel is suspended");
01074                             }
01075                             printf("Time registered: %s\n", ctime(&ciptr->time_registered));
01076 
01077                             printf("Owner of channel 2: %s (%s)\n", (ci->founder) ? ci->founder : "none", (ci->email) ? ci->email : "no valid email");
01078                             printf("Accesscount: %u\n", ci->accesscount);
01079                             if (ci->flags & 0x00000080) {
01080                                 printf("Status: Channel is forbidden");
01081                             } else if (ci->flags & 0x00010000) {
01082                                 printf("Status: Channel is suspended");
01083                             }
01084                             printf("Time registered: %s\n", ctime(&ci->time_registered));
01085 
01086                             printf("What channel do you want to keep? Enter the related number \"1\" or \"2\".\n");
01087                         }
01088 
01089                         if (preferoldest) {
01090                             input[0] = (ci->time_registered > ciptr->time_registered) ? '1' : '2';
01091                         } else if (prefernewest) {
01092                             input[0] = (ci->time_registered > ciptr->time_registered) ? '2' : '1';
01093                         } else if (preferfirst) {
01094                             input[0] = '1';
01095                         } else if (prefersecond) {
01096                             input[0] = '2';
01097                         } else {
01098                             waiting_for_input4:
01099                             scanf("%s", input);
01100                         }
01101                         if (input[0] == '1') { /* #2 isn't in the list yet, #1 is. -> free() #2 [ci] */
01102                             NickCore *nc = NULL;
01103                             int i;
01104                             printf("Deleting chan %s (#2).\n", ci->name);
01105 
01106                             if (ci->founder) {
01107                                 nc = findcore(ci->founder, 0);
01108                                 if (nc)
01109                                     nc->channelcount--;
01110                             }
01111                             free(ci->desc);
01112                             free(ci->founder);
01113                             free(ci->successor);
01114                             if (ci->url)
01115                                 free(ci->url);
01116                             if (ci->email)
01117                                 free(ci->email);
01118                             if (ci->last_topic)
01119                                 free(ci->last_topic);
01120                             if (ci->forbidby)
01121                                 free(ci->forbidby);
01122                             if (ci->forbidreason)
01123                                 free(ci->forbidreason);
01124                             if (ci->mlock_key)
01125                                 free(ci->mlock_key);
01126                             if (ci->mlock_flood)
01127                                 free(ci->mlock_flood);
01128                             if (ci->mlock_redirect)
01129                                 free(ci->mlock_redirect);
01130                             if (ci->entry_message)
01131                                 free(ci->entry_message);
01132                             if (ci->access)
01133                                 free(ci->access);
01134                             for (i = 0; i < ci->akickcount; i++) {
01135                                 if (!(ci->akick[i].flags & 0x0002) && ci->akick[i].u.mask)
01136                                     free(ci->akick[i].u.mask);
01137                                 if (ci->akick[i].reason)
01138                                     free(ci->akick[i].reason);
01139                                 if (ci->akick[i].creator)
01140                                     free(ci->akick[i].creator);
01141                             }
01142                             if (ci->akick)
01143                                 free(ci->akick);
01144                             if (ci->levels)
01145                                 free(ci->levels);
01146                             if (ci->memos.memos) {
01147                                 for (i = 0; i < ci->memos.memocount; i++) {
01148                                     if (ci->memos.memos[i].text)
01149                                         free(ci->memos.memos[i].text);
01150                                 }
01151                                 free(ci->memos.memos);
01152                             }
01153                             if (ci->ttb)
01154                                 free(ci->ttb);
01155                             for (i = 0; i < ci->bwcount; i++) {
01156                                 if (ci->badwords[i].word)
01157                                     free(ci->badwords[i].word);
01158                             }
01159                             if (ci->badwords)
01160                                 free(ci->badwords);
01161                             if (ci->bi)
01162                                 free(ci->bi);
01163                             free(ci);
01164 
01165                         } else if (input[0] == '2') { /* get #1 out of the list, free() it and add #2 to the list */
01166                             NickCore *nc = NULL;
01167                             printf("Deleting chan %s (#1).\n", ciptr->name);
01168 
01169                             if (ciptr->next)
01170                                 ciptr->next->prev = ciptr->prev;
01171                             if (ciptr->prev)
01172                                 ciptr->prev->next = ciptr->next;
01173                             else
01174                                 chanlists[tolower(ciptr->name[1])] = ciptr->next;
01175 
01176                             if (ciptr->founder) {
01177                                 nc = findcore(ciptr->founder, 0);
01178                                 if (nc)
01179                                     nc->channelcount--;
01180                             }
01181                             free(ciptr->desc);
01182                             if (ciptr->url)
01183                                 free(ciptr->url);
01184                             if (ciptr->email)
01185                                 free(ciptr->email);
01186                             if (ciptr->last_topic)
01187                                 free(ciptr->last_topic);
01188                             if (ciptr->forbidby)
01189                                 free(ciptr->forbidby);
01190                             if (ciptr->forbidreason)
01191                                 free(ciptr->forbidreason);
01192                             if (ciptr->mlock_key)
01193                                 free(ciptr->mlock_key);
01194                             if (ciptr->mlock_flood)
01195                                 free(ciptr->mlock_flood);
01196                             if (ciptr->mlock_redirect)
01197                                 free(ciptr->mlock_redirect);
01198                             if (ciptr->entry_message)
01199                                 free(ciptr->entry_message);
01200                             if (ciptr->access)
01201                                 free(ciptr->access);
01202                             for (i = 0; i < ciptr->akickcount; i++) {
01203                                 if (!(ciptr->akick[i].flags & 0x0002) && ciptr->akick[i].u.mask)
01204                                     free(ciptr->akick[i].u.mask);
01205                                 if (ciptr->akick[i].reason)
01206                                     free(ciptr->akick[i].reason);
01207                                 if (ciptr->akick[i].creator)
01208                                     free(ciptr->akick[i].creator);
01209                             }
01210                             if (ciptr->akick)
01211                                 free(ciptr->akick);
01212                             if (ciptr->levels)
01213                                 free(ciptr->levels);
01214                             if (ciptr->memos.memos) {
01215                                 for (i = 0; i < ciptr->memos.memocount; i++) {
01216                                     if (ciptr->memos.memos[i].text)
01217                                         free(ciptr->memos.memos[i].text);
01218                                 }
01219                                 free(ciptr->memos.memos);
01220                             }
01221                             if (ciptr->ttb)
01222                                 free(ciptr->ttb);
01223                             for (i = 0; i < ciptr->bwcount; i++) {
01224                                 if (ciptr->badwords[i].word)
01225                                     free(ciptr->badwords[i].word);
01226                             }
01227                             if (ciptr->badwords)
01228                                 free(ciptr->badwords);
01229                             free(ciptr);
01230 
01231                             alpha_insert_chan(ci);
01232 
01233                         } else {
01234                             printf("Invalid number, give us a valid one (1 or 2).\n");
01235                             goto waiting_for_input4;
01236                         }
01237                     } else { /* no collision, put the chan into the list */
01238                         alpha_insert_chan(ci);
01239                     }
01240                 } /* getc_db() */
01241             } /* for() loop */
01242             close_db(f);
01243         } else
01244             nochan = 1;
01245     }
01246 
01247     /* IIc: Saving */
01248     if (!nochan) {
01249         if ((f = open_db_write("ChanServ", CHAN_DB_NEW, 16))) {
01250             ChannelInfo *ci;
01251             Memo *memos;
01252                         /* Unused variable - why? -GD
01253             static time_t lastwarn = 0;
01254                         */
01255 
01256             for (i = 0; i < 256; i++) {
01257                 int16 tmp16;
01258                 for (ci = chanlists[i]; ci; ci = ci->next) {
01259                     int j;
01260                     SAFE(write_int8(1, f));
01261                     SAFE(write_buffer(ci->name, f));
01262                     if (ci->founder)
01263                         SAFE(write_string(ci->founder, f));
01264                     else
01265                         SAFE(write_string(NULL, f));
01266                     if (ci->successor)
01267                         SAFE(write_string(ci->successor, f));
01268                     else
01269                         SAFE(write_string(NULL, f));
01270                     SAFE(write_buffer(ci->founderpass, f));
01271                     SAFE(write_string(ci->desc, f));
01272                     SAFE(write_string(ci->url, f));
01273                     SAFE(write_string(ci->email, f));
01274                     SAFE(write_int32(ci->time_registered, f));
01275                     SAFE(write_int32(ci->last_used, f));
01276                     SAFE(write_string(ci->last_topic, f));
01277                     SAFE(write_buffer(ci->last_topic_setter, f));
01278                     SAFE(write_int32(ci->last_topic_time, f));
01279                     SAFE(write_int32(ci->flags, f));
01280                     SAFE(write_string(ci->forbidby, f));
01281                     SAFE(write_string(ci->forbidreason, f));
01282                     SAFE(write_int16(ci->bantype, f));
01283                     tmp16 = 36;
01284                     SAFE(write_int16(tmp16, f));
01285                     for (j = 0; j < 36; j++)
01286                         SAFE(write_int16(ci->levels[j], f));
01287 
01288                     SAFE(write_int16(ci->accesscount, f));
01289                     for (j = 0; j < ci->accesscount; j++) {
01290                         SAFE(write_int16(ci->access[j].in_use, f));
01291                         if (ci->access[j].in_use) {
01292                             SAFE(write_int16(ci->access[j].level, f));
01293                             SAFE(write_string(ci->access[j].nc->display, f));
01294                             SAFE(write_int32(ci->access[j].last_seen, f));
01295                         }
01296                     }
01297                     SAFE(write_int16(ci->akickcount, f));
01298                     for (j = 0; j < ci->akickcount; j++) {
01299                         SAFE(write_int16(ci->akick[j].flags, f));
01300                         if (ci->akick[j].flags & 0x0001) {
01301                             if (ci->akick[j].flags & 0x0002)
01302                                 SAFE(write_string(ci->akick[j].u.nc->display, f));
01303                             else
01304                                 SAFE(write_string(ci->akick[j].u.mask, f));
01305                             SAFE(write_string(ci->akick[j].reason, f));
01306                             SAFE(write_string(ci->akick[j].creator, f));
01307                             SAFE(write_int32(ci->akick[j].addtime, f));
01308                         }
01309                     }
01310 
01311                     SAFE(write_int32(ci->mlock_on, f));
01312                     SAFE(write_int32(ci->mlock_off, f));
01313                     SAFE(write_int32(ci->mlock_limit, f));
01314                     SAFE(write_string(ci->mlock_key, f));
01315                     SAFE(write_string(ci->mlock_flood, f));
01316                     SAFE(write_string(ci->mlock_redirect, f));
01317                     SAFE(write_int16(ci->memos.memocount, f));
01318                     SAFE(write_int16(ci->memos.memomax, f));
01319                     memos = ci->memos.memos;
01320                     for (j = 0; j < ci->memos.memocount; j++, memos++) {
01321                         SAFE(write_int32(memos->number, f));
01322                         SAFE(write_int16(memos->flags, f));
01323                         SAFE(write_int32(memos->time, f));
01324                         SAFE(write_buffer(memos->sender, f));
01325                         SAFE(write_string(memos->text, f));
01326                     }
01327                     SAFE(write_string(ci->entry_message, f));
01328                     if (ci->bi)
01329                         SAFE(write_string(ci->bi, f));
01330                     else
01331                         SAFE(write_string(NULL, f));
01332                     SAFE(write_int32(ci->botflags, f));
01333                     tmp16 = 8;
01334                     SAFE(write_int16(tmp16, f));
01335                     for (j = 0; j < 8; j++)
01336                         SAFE(write_int16(ci->ttb[j], f));
01337                     SAFE(write_int16(ci->capsmin, f));
01338                     SAFE(write_int16(ci->capspercent, f));
01339                     SAFE(write_int16(ci->floodlines, f));
01340                     SAFE(write_int16(ci->floodsecs, f));
01341                     SAFE(write_int16(ci->repeattimes, f));
01342 
01343                     SAFE(write_int16(ci->bwcount, f));
01344                     for (j = 0; j < ci->bwcount; j++) {
01345                         SAFE(write_int16(ci->badwords[j].in_use, f));
01346                         if (ci->badwords[j].in_use) {
01347                             SAFE(write_string(ci->badwords[j].word, f));
01348                             SAFE(write_int16(ci->badwords[j].type, f));
01349                         }
01350                     }
01351                 } /* for (chanlists[i]) */
01352                 SAFE(write_int8(0, f));
01353             } /* for (i) */
01354             close_db(f);
01355             printf("Chan merging done. New database saved as %s.\n", CHAN_DB_NEW);
01356         }
01357     }
01358 
01359     /* Section III: Bots */
01360     /* IIIa: First database */
01361     if ((f = open_db_read("Botserv", BOT_DB_1, 10))) {
01362         BotInfo *bi;
01363         int c;
01364         int32 tmp32;
01365         int16 tmp16;
01366 
01367         printf("Trying to merge bots...\n");
01368 
01369         while ((c = getc_db(f)) == 1) {
01370             if (c != 1) {
01371                 printf("Invalid format in %s.\n", BOT_DB_1);
01372                 exit(0);
01373             }
01374 
01375             bi = calloc(sizeof(BotInfo), 1);
01376             READ(read_string(&bi->nick, f));
01377             READ(read_string(&bi->user, f));
01378             READ(read_string(&bi->host, f));
01379             READ(read_string(&bi->real, f));
01380             SAFE(read_int16(&tmp16, f));
01381             bi->flags = tmp16;
01382             READ(read_int32(&tmp32, f));
01383             bi->created = tmp32;
01384             READ(read_int16(&tmp16, f));
01385             bi->chancount = tmp16;
01386             insert_bot(bi);
01387         }
01388     } else
01389         nobot = 1;
01390 
01391     /* IIIb: Second database */
01392     if (!nobot) {
01393         if ((f = open_db_read("Botserv", BOT_DB_2, 10))) {
01394             BotInfo *bi, *biptr;
01395             int c;
01396             int32 tmp32;
01397             int16 tmp16;
01398             char input[1024];
01399 
01400             while ((c = getc_db(f)) == 1) {
01401                 if (c != 1) {
01402                     printf("Invalid format in %s.\n", BOT_DB_2);
01403                     exit(0);
01404                 }
01405 
01406                 bi = calloc(sizeof(BotInfo), 1);
01407                 READ(read_string(&bi->nick, f));
01408                 READ(read_string(&bi->user, f));
01409                 READ(read_string(&bi->host, f));
01410                 READ(read_string(&bi->real, f));
01411                 SAFE(read_int16(&tmp16, f));
01412                 bi->flags = tmp16;
01413                 READ(read_int32(&tmp32, f));
01414                 bi->created = tmp32;
01415                 READ(read_int16(&tmp16, f));
01416                 bi->chancount = tmp16;
01417                 biptr = findbot(bi->nick);
01418                 if (biptr) { /* BOT COLLISION! #1 is biptr-> (db1), #2 is bi-> (db2) */
01419                     if (!preferoldest && !preferfirst && !prefersecond && !prefernewest) {
01420                         printf("Bot collision for botnick %s:\n\n", biptr->nick);
01421                         printf("Bot 1: %s@%s (%s) is assigned to %d chans\n", biptr->user, biptr->host, biptr->real, biptr->chancount);
01422                         printf("Time registered: %s\n", ctime(&biptr->created));
01423                         printf("Bot 2: %s@%s (%s) is assigned to %d chans\n", bi->user, bi->host, bi->real, bi->chancount);
01424                         printf("Time registered: %s\n", ctime(&bi->created));
01425                         printf("What bot do you want to keep? Enter the related bot number \"1\" or \"2\".\n");
01426                     }
01427 
01428                     if (preferoldest) {
01429                         input[0] = (biptr->created > bi->created) ? '1' : '2';
01430                     } else if (prefernewest) {
01431                         input[0] = (biptr->created > bi->created) ? '2' : '1';
01432                     } else if (preferfirst) {
01433                         input[0] = '2';
01434                     } else if (prefersecond) {
01435                         input[0] = '1';
01436                     } else {
01437                         waiting_for_input3:
01438                         scanf("%s", input);
01439                     }
01440                     if (input[0] == '1') { /* free() bot #2 (bi) */
01441                         printf("Deleting Bot %s!%s@%s (%s) (#2).\n", bi->nick, bi->user, bi->host, bi->real);
01442                         free(bi->nick);
01443                         free(bi->user);
01444                         free(bi->host);
01445                         free(bi->real);
01446                         free(bi);
01447                     } else if (input[0] == '2') { /* get bot #1 (biptr) out of the list, free() it and add #2 to the list */
01448                         printf("Deleting Bot %s!%s@%s (%s) (#1).\n", biptr->nick, biptr->user, biptr->host, biptr->real);
01449                         if (biptr->next)
01450                             biptr->next->prev = biptr->prev;
01451                         if (biptr->prev)
01452                             biptr->prev->next = biptr->next;
01453                         else
01454                             botlists[tolower(*biptr->nick)] = biptr->next;
01455                         free(biptr->nick);
01456                         free(biptr->user);
01457                         free(biptr->host);
01458                         free(biptr->real);
01459                         free(biptr);
01460                         insert_bot(bi);
01461                     } else {
01462                         printf("Invalid number, give us a valid one (1 or 2).\n");
01463                         goto waiting_for_input3;
01464                     }
01465                 } /* NO COLLISION (biptr) */
01466                 else
01467                     insert_bot(bi);
01468             }
01469         } else
01470             nobot = 1;
01471     }
01472 
01473     /* IIIc: Saving */
01474     if (!nobot) {
01475         if ((f = open_db_write("Botserv", BOT_DB_NEW, 10))) {
01476             BotInfo *bi;
01477             for (i = 0; i < 256; i++) {
01478                 for (bi = botlists[i]; bi; bi = bi->next) {
01479                     SAFE(write_int8(1, f));
01480                     SAFE(write_string(bi->nick, f));
01481                     SAFE(write_string(bi->user, f));
01482                     SAFE(write_string(bi->host, f));
01483                     SAFE(write_string(bi->real, f));
01484                     SAFE(write_int16(bi->flags, f));
01485                     SAFE(write_int32(bi->created, f));
01486                     SAFE(write_int16(bi->chancount, f));
01487                 }
01488             }
01489             SAFE(write_int8(0, f));
01490             close_db(f);
01491             printf("Bot merging done. New database saved as %s.\n", BOT_DB_NEW);
01492         }
01493     } /* End of section III */
01494 
01495     /* Section IV: Hosts */
01496     /* IVa: First database */
01497     if ((f = open_db_read("HostServ", HOST_DB_1, 3))) {
01498         HostCore *hc;
01499         int c;
01500         int32 tmp32;
01501 
01502         printf("Trying to merge hosts...\n");
01503 
01504         while ((c = getc_db(f)) == 1) {
01505             if (c != 1) {
01506                 printf("Invalid format in %s.\n", HOST_DB_1);
01507                 exit(0);
01508             }
01509             hc = calloc(1, sizeof(HostCore));
01510             READ(read_string(&hc->nick, f));
01511             READ(read_string(&hc->vIdent, f));
01512             READ(read_string(&hc->vHost, f));
01513             READ(read_string(&hc->creator, f));
01514             READ(read_int32(&tmp32, f));
01515             hc->time = tmp32;
01516             hc->next = firsthc;
01517             if (firsthc)
01518                 firsthc->last = hc;
01519             hc->last = NULL;
01520             firsthc = hc;
01521         }
01522     } else
01523         nohost = 1;
01524 
01525     /* IVb: Second database */
01526     if (!nohost) {
01527         if ((f = open_db_read("HostServ", HOST_DB_2, 3))) {
01528             HostCore *hc, *hcptr;
01529             char input[1024];
01530             int32 tmp32;
01531             int c;
01532             int collision = 0;
01533 
01534             while ((c = getc_db(f)) == 1) {
01535                 if (c != 1) {
01536                     printf("Invalid format in %s.\n", HOST_DB_2);
01537                     exit(0);
01538                 }
01539                 collision = 0;
01540                 hc = calloc(1, sizeof(HostCore));
01541                 READ(read_string(&hc->nick, f));
01542                 READ(read_string(&hc->vIdent, f));
01543                 READ(read_string(&hc->vHost, f));
01544                 READ(read_string(&hc->creator, f));
01545                 READ(read_int32(&tmp32, f));
01546                 hc->time = tmp32;
01547 
01548                 for (hcptr = firsthc; hcptr; hcptr = hcptr->next) {
01549                     if (!mystricmp(hcptr->nick, hc->nick)) { /* COLLISION: #1 is from db1 (hcptr), #2 is from db2 (hc) */
01550                         collision++;
01551                         if (!preferoldest && !preferfirst && !prefersecond && !prefernewest) {
01552                             printf("vHost collision for nick %s:\n\n", hcptr->nick);
01553                             printf("vHost 1: %s (vIdent: %s)\n", hcptr->vHost, (hcptr->vIdent) ? hcptr->vIdent : "none");
01554                             printf("Time set: %s\n", ctime(&hcptr->time));
01555                             printf("vHost 2: %s (vIdent: %s)\n", hc->vHost, (hc->vIdent) ? hc->vIdent : "none");
01556                             printf("Time set: %s\n", ctime(&hc->time));
01557                             printf("What vhost do you want to keep? Enter the related number \"1\" or \"2\".\n");
01558                         }
01559                         if (preferoldest) {
01560                             input[0] = (hcptr->time > hc->time) ? '1' : '2';
01561                         } else if (prefernewest) {
01562                             input[0] = (hcptr->time > hc->time) ? '2' : '1';
01563                         } else if (preferfirst) {
01564                             input[0] = '1';
01565                         } else if (prefersecond) {
01566                             input[0] = '2';
01567                         } else {
01568                             waiting_for_input2:
01569                             scanf("%s", input);
01570                         }
01571                         if (input[0] == '2') { /* free() hcptr and get it out of the list, put hc into the list */
01572                             printf("Deleting vHost %s (vIdent: %s) for nick %s (#1).\n", hcptr->vHost, (hcptr->vIdent) ? hcptr->vIdent : "none", hcptr->nick);
01573                             free(hcptr->nick);
01574                             hcptr->nick = hc->nick;
01575                             free(hcptr->vHost);
01576                             hcptr->vHost = hc->vHost;
01577                             free(hcptr->vIdent);
01578                             hcptr->vIdent = hc->vIdent;
01579                             free(hcptr->creator);
01580                             hcptr->creator = hc->creator;
01581                             hcptr->time = hc->time;
01582                             free(hc);
01583                         } else if (input[0] == '1') { /* free() hc */
01584                             printf("Deleting vHost %s (vIdent: %s) for nick %s (#2).\n", hc->vHost, (hc->vIdent) ? hc->vIdent : "none", hc->nick);
01585                             free(hc->nick);
01586                             free(hc->vHost);
01587                             free(hc->vIdent);
01588                             free(hc->creator);
01589                             free(hc);
01590                         } else {
01591                             printf("Invalid number, give us a valid one (1 or 2).\n");
01592                             goto waiting_for_input2;
01593                         } /* input[0] */
01594                     } /* mystricmp */
01595                 } /* for (hcptr...) */
01596                 if (!collision) { /* No collision */
01597                     hc->next = firsthc;
01598                     if (firsthc)
01599                         firsthc->last = hc;
01600                     hc->last = NULL;
01601                     firsthc = hc;
01602                 }
01603             } /* while */
01604         } else
01605             nohost = 1;
01606     }
01607 
01608     /* IVc: Saving */
01609     if (!nohost) {
01610         if ((f = open_db_write("HostServ", HOST_DB_NEW, 3))) {
01611             HostCore *hcptr;
01612             for (hcptr = firsthc; hcptr; hcptr = hcptr->next) {
01613                 SAFE(write_int8(1, f));
01614                 SAFE(write_string(hcptr->nick, f));
01615                 SAFE(write_string(hcptr->vIdent, f));
01616                 SAFE(write_string(hcptr->vHost, f));
01617                 SAFE(write_string(hcptr->creator, f));
01618                 SAFE(write_int32(hcptr->time, f));
01619             }
01620             SAFE(write_int8(0, f));
01621             close_db(f);
01622             printf("Host merging done. New database saved as %s.\n", HOST_DB_NEW);
01623         }
01624     } /* End of section IV */
01625 
01626     /* MERGING DONE \o/ HURRAY! */
01627 
01628     printf("\n\nMerging is now done. I give NO guarantee for your DBs.\n");
01629         return 0;
01630 } /* End of main() */
01631 
01632 /* Open a database file for reading and check for the version */
01633 dbFILE *open_db_read(const char *service, const char *filename, int version)
01634 {
01635     dbFILE *f;
01636     FILE *fp;
01637     int myversion;
01638 
01639     f = calloc(sizeof(*f), 1);
01640     if (!f) {
01641         printf("Can't allocate memory for %s database %s.\n", service, filename);
01642         exit(0);
01643     }
01644     strscpy(f->filename, filename, sizeof(f->filename));
01645     f->mode = 'r';
01646     fp = fopen(f->filename, "rb");
01647     if (!fp) {
01648         printf("Can't read %s database %s.\n", service, f->filename);
01649         free(f);
01650         return NULL;
01651     }
01652     f->fp = fp;
01653     myversion = fgetc(fp) << 24 | fgetc(fp) << 16 | fgetc(fp) << 8 | fgetc(fp);
01654     if (feof(fp)) {
01655         printf("Error reading version number on %s: End of file detected.\n", f->filename);
01656         exit(0);
01657     } else if (myversion < version) {
01658         printf("Unsuported database version (%d) on %s.\n", myversion, f->filename);
01659         exit(0);
01660     }
01661     return f;
01662 }
01663 
01664 /* Open a database file for reading and check for the version */
01665 dbFILE *open_db_write(const char *service, const char *filename, int version)
01666 {
01667     dbFILE *f;
01668     int fd;
01669 
01670     f = calloc(sizeof(*f), 1);
01671     if (!f) {
01672         printf("Can't allocate memory for %s database %s.\n", service, filename);
01673         exit(0);
01674     }
01675     strscpy(f->filename, filename, sizeof(f->filename));
01676     filename = f->filename;
01677 #ifndef _WIN32
01678     unlink(filename);
01679 #else
01680     DeleteFile(filename);
01681 #endif
01682     f->mode = 'w';
01683 #ifndef _WIN32
01684     fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
01685 #else
01686     fd = open(filename, O_WRONLY | O_CREAT | O_EXCL | _O_BINARY, 0666);
01687 #endif
01688     f->fp = fdopen(fd, "wb");   /* will fail and return NULL if fd < 0 */
01689     if (!f->fp || !write_file_version(f, version)) {
01690         printf("Can't write to %s database %s.\n", service, filename);
01691         if (f->fp) {
01692             fclose(f->fp);
01693 #ifndef _WIN32
01694             unlink(filename);
01695 #else
01696             DeleteFile(filename);
01697 #endif
01698         }
01699         free(f);
01700         return NULL;
01701     }
01702     return f;
01703 }
01704 
01705 /* Close it */
01706 void close_db(dbFILE * f)
01707 {
01708     fclose(f->fp);
01709     free(f);
01710 }
01711 
01712 int read_int16(int16 * ret, dbFILE * f)
01713 {
01714     int c1, c2;
01715 
01716     c1 = fgetc(f->fp);
01717     c2 = fgetc(f->fp);
01718     if (c1 == EOF || c2 == EOF)
01719         return -1;
01720     *ret = c1 << 8 | c2;
01721     return 0;
01722 }
01723 
01724 int read_uint16(uint16 * ret, dbFILE * f)
01725 {
01726     int c1, c2;
01727 
01728     c1 = fgetc(f->fp);
01729     c2 = fgetc(f->fp);
01730     if (c1 == EOF || c2 == EOF)
01731         return -1;
01732     *ret = c1 << 8 | c2;
01733     return 0;
01734 }
01735 
01736 
01737 int write_int16(uint16 val, dbFILE * f)
01738 {
01739     if (fputc((val >> 8) & 0xFF, f->fp) == EOF
01740         || fputc(val & 0xFF, f->fp) == EOF)
01741         return -1;
01742     return 0;
01743 }
01744 
01745 int read_int32(int32 * ret, dbFILE * f)
01746 {
01747     int c1, c2, c3, c4;
01748 
01749     c1 = fgetc(f->fp);
01750     c2 = fgetc(f->fp);
01751     c3 = fgetc(f->fp);
01752     c4 = fgetc(f->fp);
01753     if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF)
01754         return -1;
01755     *ret = c1 << 24 | c2 << 16 | c3 << 8 | c4;
01756     return 0;
01757 }
01758 
01759 int read_uint32(uint32 * ret, dbFILE * f)
01760 {
01761     int c1, c2, c3, c4;
01762 
01763     c1 = fgetc(f->fp);
01764     c2 = fgetc(f->fp);
01765     c3 = fgetc(f->fp);
01766     c4 = fgetc(f->fp);
01767     if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF)
01768         return -1;
01769     *ret = c1 << 24 | c2 << 16 | c3 << 8 | c4;
01770     return 0;
01771 }
01772 
01773 int write_int32(uint32 val, dbFILE * f)
01774 {
01775     if (fputc((val >> 24) & 0xFF, f->fp) == EOF)
01776         return -1;
01777     if (fputc((val >> 16) & 0xFF, f->fp) == EOF)
01778         return -1;
01779     if (fputc((val >> 8) & 0xFF, f->fp) == EOF)
01780         return -1;
01781     if (fputc((val) & 0xFF, f->fp) == EOF)
01782         return -1;
01783     return 0;
01784 }
01785 
01786 
01787 int read_ptr(void **ret, dbFILE * f)
01788 {
01789     int c;
01790 
01791     c = fgetc(f->fp);
01792     if (c == EOF)
01793         return -1;
01794     *ret = (c ? (void *) 1 : (void *) 0);
01795     return 0;
01796 }
01797 
01798 int write_ptr(const void *ptr, dbFILE * f)
01799 {
01800     if (fputc(ptr ? 1 : 0, f->fp) == EOF)
01801         return -1;
01802     return 0;
01803 }
01804 
01805 
01806 int read_string(char **ret, dbFILE * f)
01807 {
01808     char *s;
01809     uint16 len;
01810 
01811     if (read_uint16(&len, f) < 0)
01812         return -1;
01813     if (len == 0) {
01814         *ret = NULL;
01815         return 0;
01816     }
01817     s = calloc(len, 1);
01818     if (len != fread(s, 1, len, f->fp)) {
01819         free(s);
01820         return -1;
01821     }
01822     *ret = s;
01823     return 0;
01824 }
01825 
01826 int write_string(const char *s, dbFILE * f)
01827 {
01828     uint32 len;
01829 
01830     if (!s)
01831         return write_int16(0, f);
01832     len = strlen(s);
01833     if (len > 65534)
01834         len = 65534;
01835     if (write_int16((uint16) (len + 1), f) < 0)
01836         return -1;
01837     if (len > 0 && fwrite(s, 1, len, f->fp) != len)
01838         return -1;
01839     if (fputc(0, f->fp) == EOF)
01840         return -1;
01841     return 0;
01842 }
01843 
01844 NickCore *findcore(const char *nick, int unused)
01845 {
01846     NickCore *nc;
01847 
01848     for (nc = nclists[HASH(nick)]; nc; nc = nc->next) {
01849         if (!mystricmp(nc->display, nick))
01850             if ((nc->unused && unused) || (!nc->unused && !unused))
01851                 return nc;
01852     }
01853 
01854     return NULL;
01855 }
01856 
01857 NickAlias *findnick(const char *nick)
01858 {
01859     NickAlias *na;
01860 
01861     for (na = nalists[HASH(nick)]; na; na = na->next) {
01862         if (!mystricmp(na->nick, nick))
01863             return na;
01864     }
01865 
01866     return NULL;
01867 }
01868 
01869 int write_file_version(dbFILE * f, uint32 version)
01870 {
01871     FILE *fp = f->fp;
01872     if (fputc(version >> 24 & 0xFF, fp) < 0 ||
01873         fputc(version >> 16 & 0xFF, fp) < 0 ||
01874         fputc(version >> 8 & 0xFF, fp) < 0 ||
01875         fputc(version & 0xFF, fp) < 0) {
01876             printf("Error writing version number on %s.\n", f->filename);
01877             exit(0);
01878     }
01879     return 1;
01880 }
01881 
01882 /* strscpy:  Copy at most len-1 characters from a string to a buffer, and
01883  *           add a null terminator after the last character copied.
01884  */
01885 
01886 char *strscpy(char *d, const char *s, size_t len)
01887 {
01888     char *d_orig = d;
01889 
01890     if (!len)
01891         return d;
01892     while (--len && (*d++ = *s++));
01893     *d = '\0';
01894     return d_orig;
01895 }
01896 
01897 int mystricmp(const char *s1, const char *s2)
01898 {
01899     register int c;
01900 
01901     while ((c = tolower(*s1)) == tolower(*s2)) {
01902         if (c == 0)
01903             return 0;
01904         s1++;
01905         s2++;
01906     }
01907     if (c < tolower(*s2))
01908         return -1;
01909     return 1;
01910 }
01911 
01912 int delnick(NickAlias *na, int donttouchthelist)
01913 {
01914     if (!donttouchthelist) {
01915         /* Remove us from the aliases list */
01916         if (na->next)
01917             na->next->prev = na->prev;
01918         if (na->prev)
01919             na->prev->next = na->next;
01920         else
01921             nalists[HASH(na->nick)] = na->next;
01922     }
01923 
01924     /* free() us */
01925     free(na->nick);
01926     if (na->last_usermask)
01927         free(na->last_usermask);
01928     if (na->last_realname)
01929         free(na->last_realname);
01930     if (na->last_quit)
01931         free(na->last_quit);
01932     free(na);
01933     return 1;
01934 }
01935 
01936 int delcore(NickCore *nc)
01937 {
01938     int i;
01939     /* Remove the core from the list */
01940     if (nc->next)
01941         nc->next->prev = nc->prev;
01942     if (nc->prev)
01943         nc->prev->next = nc->next;
01944     else
01945         nclists[HASH(nc->display)] = nc->next;
01946 
01947     free(nc->display);
01948     if (nc->email)
01949         free(nc->email);
01950     if (nc->greet)
01951         free(nc->greet);
01952     if (nc->url)
01953         free(nc->url);
01954     if (nc->access) {
01955         for (i = 0; i < nc->accesscount; i++) {
01956             if (nc->access[i])
01957                 free(nc->access[i]);
01958         }
01959         free(nc->access);
01960     }
01961     if (nc->memos.memos) {
01962         for (i = 0; i < nc->memos.memocount; i++) {
01963             if (nc->memos.memos[i].text)
01964                 free(nc->memos.memos[i].text);
01965         }
01966         free(nc->memos.memos);
01967     }
01968     free(nc);
01969     return 1;
01970 }
01971 
01972 void insert_bot(BotInfo * bi)
01973 {
01974     BotInfo *ptr, *prev;
01975 
01976     for (prev = NULL, ptr = botlists[tolower(*bi->nick)];
01977          ptr != NULL && mystricmp(ptr->nick, bi->nick) < 0;
01978          prev = ptr, ptr = ptr->next);
01979     bi->prev = prev;
01980     bi->next = ptr;
01981     if (!prev)
01982         botlists[tolower(*bi->nick)] = bi;
01983     else
01984         prev->next = bi;
01985     if (ptr)
01986         ptr->prev = bi;
01987 }
01988 
01989 BotInfo *findbot(char *nick)
01990 {
01991     BotInfo *bi;
01992 
01993     for (bi = botlists[tolower(*nick)]; bi; bi = bi->next)
01994         if (!mystricmp(nick, bi->nick))
01995             return bi;
01996 
01997     return NULL;
01998 }
01999 
02000 ChannelInfo *cs_findchan(const char *chan)
02001 {
02002     ChannelInfo *ci;
02003     for (ci = chanlists[tolower(chan[1])]; ci; ci = ci->next) {
02004         if (!mystricmp(ci->name, chan))
02005             return ci;
02006     }
02007     return NULL;
02008 }
02009 
02010 void alpha_insert_chan(ChannelInfo * ci)
02011 {
02012     ChannelInfo *ptr, *prev;
02013     char *chan = ci->name;
02014 
02015     for (prev = NULL, ptr = chanlists[tolower(chan[1])];
02016          ptr != NULL && mystricmp(ptr->name, chan) < 0;
02017          prev = ptr, ptr = ptr->next);
02018     ci->prev = prev;
02019     ci->next = ptr;
02020     if (!prev)
02021         chanlists[tolower(chan[1])] = ci;
02022     else
02023         prev->next = ci;
02024     if (ptr)
02025         ptr->prev = ci;
02026 }
02027