epona2anope.c

Go to the documentation of this file.
00001 /*
00002  *   IRC - Internet Relay Chat, epona2anope.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 convert epona-1.4.15+ dbs to anope standard dbs.
00018  *   At the moment this only affects chanserv dbs.
00019  *
00020  *   - Certus
00021  *      February 26, 2005
00022  *
00023  *   Added win32 fix. Who needs that anyways? :P
00024  *   - Certus
00025  *     July 20, 2006
00026  */
00027 
00028 
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <stdio.h>
00032 #include <fcntl.h>
00033 #include <ctype.h>
00034 #include <time.h>
00035 
00036 #ifndef _WIN32
00037 #include <unistd.h>
00038 #else
00039 #include "sysconf.h"
00040 #include <windows.h>
00041 #endif
00042 
00043 /* Some SUN fixs */
00044 #ifdef __sun
00045 /* Solaris specific code, types that do not exist in Solaris'
00046  *  * sys/types.h
00047  *   **/
00048 #undef u_int8_t
00049 #undef u_int16_t
00050 #undef u_int32_t
00051 #undef u_int_64_t
00052 #define u_int8_t uint8_t
00053 #define u_int16_t uint16_t
00054 #define u_int32_t uint32_t
00055 #define u_int64_t uint64_t
00056 
00057 #ifndef INADDR_NONE
00058 #define INADDR_NONE (-1)
00059 #endif
00060 
00061 #endif
00062 
00063 
00064 /* CONFIGURATION BLOCK */
00065 
00066 #define CHAN_DB_EPONA      "chan1.db"
00067 #define CHAN_DB_ANOPE      "chan.db"
00068 
00069 /* END OF CONFIGURATION BLOCK */
00070 
00071 #ifndef _WIN32
00072 #define C_LBLUE "\033[1;34m"
00073 #define C_NONE "\033[m"
00074 #else
00075 #define C_LBLUE ""
00076 #define C_NONE ""
00077 #endif
00078 
00079 #define getc_db(f)      (fgetc((f)->fp))
00080 #define HASH(nick)  ((tolower((nick)[0])&31)<<5 | (tolower((nick)[1])&31))
00081 #define HASH2(chan) ((chan)[1] ? ((chan)[1]&31)<<5 | ((chan)[2]&31) : 0)
00082 #define read_buffer(buf,f)  (read_db((f),(buf),sizeof(buf)) == sizeof(buf))
00083 #define write_buffer(buf,f) (write_db((f),(buf),sizeof(buf)) == sizeof(buf))
00084 #define read_db(f,buf,len)  (fread((buf),1,(len),(f)->fp))
00085 #define write_db(f,buf,len) (fwrite((buf),1,(len),(f)->fp))
00086 #define read_int8(ret,f)    ((*(ret)=fgetc((f)->fp))==EOF ? -1 : 0)
00087 #define write_int8(val,f)   (fputc((val),(f)->fp)==EOF ? -1 : 0)
00088 #define SAFE(x) do { \
00089     if ((x) < 0) { \
00090     printf("Error, the database is broken, trying to continue... no guarantee.\n"); \
00091     } \
00092 } while (0)
00093 #define READ(x) do { \
00094     if ((x) < 0) { \
00095         printf("Error, the database is broken, trying to continue... no guarantee.\n"); \
00096         exit(0); \
00097     } \
00098 } while (0)
00099 
00100 typedef int16_t int16;
00101 typedef u_int16_t uint16;
00102 typedef int32_t int32;
00103 typedef u_int32_t uint32;
00104 typedef struct memo_ Memo;
00105 typedef struct dbFILE_ dbFILE;
00106 typedef struct nickalias_ NickAlias;
00107 typedef struct nickcore_ NickCore;
00108 typedef struct chaninfo_ ChannelInfo;
00109 typedef struct botinfo_ BotInfo;
00110 typedef struct badword_ BadWord;
00111 typedef struct hostcore_ HostCore;
00112 
00113 struct memo_ {
00114     uint32 number;      /* Index number -- not necessarily array position! */
00115     int16 flags;            /* Flags */
00116     time_t time;          /* When was it sent? */
00117     char sender[32];   /* Name of the sender */
00118     char *text;
00119 };
00120 
00121 struct dbFILE_ {
00122     int mode;                   /* 'r' for reading, 'w' for writing */
00123     FILE *fp;                    /* The normal file descriptor */
00124     char filename[1024];  /* Name of the database file */
00125 };
00126 
00127 typedef struct {
00128     int16 memocount;  /* Current # of memos */
00129     int16 memomax;    /* Max # of memos one can hold*/
00130     Memo *memos;     /* Pointer to original memos */
00131 } MemoInfo;
00132 
00133 typedef struct {
00134     int16 in_use;         /* 1 if this entry is in use, else 0 */
00135     int16 level;
00136     NickCore *nc;       /* Guaranteed to be non-NULL if in use, NULL if not */
00137     time_t last_seen;
00138 } ChanAccess;
00139 
00140 typedef struct {
00141     int16 in_use;         /* Always 0 if not in use */
00142     int16 is_nick;         /* 1 if a regged nickname, 0 if a nick!user@host mask */
00143     int16 flags;
00144     union {
00145         char *mask;      /* Guaranteed to be non-NULL if in use, NULL if not */
00146         NickCore *nc;   /* Same */
00147     } u;
00148     char *reason;
00149     char *creator;
00150     time_t addtime;
00151 } AutoKick;
00152 
00153 struct nickcore_ {
00154     NickCore *next, *prev;
00155 
00156     char *display;            /* How the nick is displayed */
00157     int unused;                /* Used for nick collisions */
00158 };
00159 
00160 struct chaninfo_ {
00161     ChannelInfo *next, *prev;
00162 
00163     char name[64];                     /* Channel name */
00164     char *founder;                      /* Who registered the channel */
00165     char *successor;                   /* Who gets the channel if the founder nick is dropped or expires */
00166     char founderpass[32];            /* Channel password */
00167     char *desc;                           /* Description */
00168     char *url;                              /* URL */
00169     char *email;                          /* Email address */
00170     time_t time_registered;          /* When was it registered */
00171     time_t last_used;                   /* When was it used hte last time */
00172     char *last_topic;                       /* Last topic on the channel */
00173     char last_topic_setter[32];      /* Who set the last topic */
00174     time_t last_topic_time;           /* When the last topic was set */
00175     uint32 flags;                          /* Flags */
00176     char *forbidby;                      /* if forbidden: who did it */
00177     char *forbidreason;                /* if forbidden: why */
00178     int16 bantype;                       /* Bantype */
00179     int16 *levels;                        /* Access levels for commands */
00180     int16 accesscount;                 /* # of pple with access */
00181     ChanAccess *access;             /* List of authorized users */
00182     int16 akickcount;                    /* # of akicked pple */
00183     AutoKick *akick;                    /* List of users to kickban */
00184     uint32 mlock_on, mlock_off;   /* See channel modes below */
00185     uint32 mlock_limit;                /* 0 if no limit */
00186     char *mlock_key;                  /* NULL if no key */
00187     char *mlock_flood;                  /* NULL if no +f */
00188     char *mlock_joinrate;               /* NULL if no +j */
00189     char *mlock_redirect;            /* NULL if no +L */
00190     char *entry_message;           /* Notice sent on entering channel */
00191     MemoInfo memos;                 /* Memos */
00192     char *bi;                               /* Bot used on this channel */
00193     uint32 botflags;                      /* BS_* below */
00194     int16 *ttb;                             /* Times to ban for each kicker */
00195     int16 bwcount;                       /* Badword count */
00196     BadWord *badwords;             /* For BADWORDS kicker */
00197     int16 capsmin, capspercent;    /* For CAPS kicker */
00198     int16 floodlines, floodsecs;      /* For FLOOD kicker */
00199     int16 repeattimes;                 /* For REPEAT kicker */
00200 };
00201 
00202 struct botinfo_ {
00203     BotInfo *next, *prev;
00204     char *nick;            /* Nickname of the bot */
00205     char *user;            /* Its user name */
00206     char *host;            /* Its hostname */
00207     char *real;            /* Its real name */
00208     int16 flags;            /* Bot flags */
00209     time_t created;      /* Birth date */
00210     int16 chancount;        /* Number of channels that use the bot. */
00211 };
00212 
00213 struct badword_ {
00214     int16 in_use;
00215     char *word;
00216     int16 type; 
00217 };
00218 
00219 dbFILE *open_db_write(const char *service, const char *filename, int version);
00220 dbFILE *open_db_read(const char *service, const char *filename, int version);
00221 NickCore *findcore(const char *nick, int version);
00222 ChannelInfo *cs_findchan(const char *chan);
00223 char *strscpy(char *d, const char *s, size_t len);
00224 int write_file_version(dbFILE * f, uint32 version);
00225 int mystricmp(const char *s1, const char *s2);
00226 int write_string(const char *s, dbFILE * f);
00227 int write_ptr(const void *ptr, dbFILE * f);
00228 int read_int16(int16 * ret, dbFILE * f);
00229 int read_uint16(uint16 * ret, dbFILE * f);
00230 int read_int32(int32 * ret, dbFILE * f);
00231 int read_uint32(uint32 * ret, dbFILE * f);
00232 int read_string(char **ret, dbFILE * f);
00233 int write_int16(uint16 val, dbFILE * f);
00234 int write_int32(uint32 val, dbFILE * f);
00235 int read_ptr(void **ret, dbFILE * f);
00236 void alpha_insert_chan(ChannelInfo * ci);
00237 void close_db(dbFILE * f);
00238 
00239 ChannelInfo *chanlists[256];
00240 NickCore *nclists[1024];
00241 
00242 int main(int argc, char *argv[])
00243 {
00244     dbFILE *f;
00245     int i;
00246     long countr = 0, countw = 0;
00247     /* Unused variables - why? -GD
00248     NickCore *nc, *ncnext;
00249     */
00250 
00251     printf("\n"C_LBLUE"Epona to Anope DB converter by Certus"C_NONE"\n\n");
00252 
00253     /* Section I: Reading */
00254     if ((f = open_db_read("ChanServ", CHAN_DB_EPONA, 17))) {
00255         ChannelInfo *ci, **last, *prev;
00256         int c;
00257 
00258         printf("Trying to convert channel database...\n");
00259 
00260         for (i = 0; i < 256; i++) {
00261             int16 tmp16;
00262             int32 tmp32;
00263             int n_levels;
00264             char *s;
00265             int n_ttb;
00266             /* Unused variable - why? -GD
00267             int J;
00268             */
00269 
00270             last = &chanlists[i];
00271             prev = NULL;
00272         
00273             while ((c = getc_db(f)) == 1) {
00274                 int j;
00275 
00276                 if (c != 1) {
00277                     printf("Invalid format in %s.\n", CHAN_DB_EPONA);
00278                     exit(0);
00279                 }
00280 
00281                 ci = calloc(sizeof(ChannelInfo), 1);
00282                 *last = ci;
00283                 last = &ci->next;
00284                 ci->prev = prev;
00285                 prev = ci;
00286                 READ(read_buffer(ci->name, f));
00287                 READ(read_string(&ci->founder, f));
00288                 READ(read_string(&ci->successor, f));
00289                 READ(read_buffer(ci->founderpass, f));
00290                 READ(read_string(&ci->desc, f));
00291                 if (!ci->desc)
00292                     ci->desc = strdup("");
00293                 READ(read_string(&ci->url, f));
00294                 READ(read_string(&ci->email, f));
00295                 READ(read_int32(&tmp32, f));
00296                 ci->time_registered = tmp32;
00297                 READ(read_int32(&tmp32, f));
00298                 ci->last_used = tmp32;
00299                 READ(read_string(&ci->last_topic, f));
00300                 READ(read_buffer(ci->last_topic_setter, f));
00301                 READ(read_int32(&tmp32, f));
00302                 ci->last_topic_time = tmp32;
00303                 READ(read_uint32(&ci->flags, f));
00304                 /* Temporary flags cleanup */
00305                 ci->flags &= ~0x80000000;
00306                 READ(read_string(&ci->forbidby, f));
00307                 READ(read_string(&ci->forbidreason, f));
00308                 READ(read_int16(&tmp16, f));
00309                 ci->bantype = tmp16;
00310                 READ(read_int16(&tmp16, f));
00311                 n_levels = tmp16;
00312                 ci->levels = calloc(36 * sizeof(*ci->levels), 1);
00313                 for (j = 0; j < n_levels; j++) {
00314                     if (j < 36)
00315                         READ(read_int16(&ci->levels[j], f));
00316                     else
00317                         READ(read_int16(&tmp16, f));
00318                 }
00319                 READ(read_int16(&ci->accesscount, f));
00320                 if (ci->accesscount) {
00321                     ci->access = calloc(ci->accesscount, sizeof(ChanAccess));
00322                     for (j = 0; j < ci->accesscount; j++) {
00323                         READ(read_int16(&ci->access[j].in_use, f));
00324                         if (ci->access[j].in_use) {
00325                             READ(read_int16(&ci->access[j].level, f));
00326                             READ(read_string(&s, f));
00327                             if (s) {
00328                                 ci->access[j].nc = findcore(s, 0);
00329                                 free(s);
00330                             }
00331                             if (ci->access[j].nc == NULL)
00332                                 ci->access[j].in_use = 0;
00333                             READ(read_int32(&tmp32, f));
00334                             ci->access[j].last_seen = tmp32;
00335                         }
00336                     }
00337                 } else {
00338                     ci->access = NULL;
00339                 }
00340                 READ(read_int16(&ci->akickcount, f));
00341                 if (ci->akickcount) {
00342                     ci->akick = calloc(ci->akickcount, sizeof(AutoKick));
00343                     for (j = 0; j < ci->akickcount; j++) {
00344                         SAFE(read_int16(&ci->akick[j].flags, f));
00345                         if (ci->akick[j].flags & 0x0001) {
00346                             SAFE(read_string(&s, f));
00347                             if (ci->akick[j].flags & 0x0002) {
00348                                 ci->akick[j].u.nc = findcore(s, 0);
00349                                 if (!ci->akick[j].u.nc)
00350                                     ci->akick[j].flags &= ~0x0001;
00351                                 free(s);
00352                             } else {
00353                                 ci->akick[j].u.mask = s;
00354                             }
00355                             SAFE(read_string(&s, f));
00356                             if (ci->akick[j].flags & 0x0001)
00357                                 ci->akick[j].reason = s;
00358                             else if (s)
00359                                 free(s);
00360                             SAFE(read_string(&s, f));
00361                             if (ci->akick[j].flags & 0x0001) {
00362                                 ci->akick[j].creator = s;
00363                             } else if (s) {
00364                                 free(s);
00365                             }
00366                             SAFE(read_int32(&tmp32, f));
00367                             if (ci->akick[j].flags & 0x0001)
00368                                 ci->akick[j].addtime = tmp32;
00369                         }
00370                     }
00371                 } else {
00372                     ci->akick = NULL;
00373                 }
00374                 READ(read_uint32(&ci->mlock_on, f));
00375                 READ(read_uint32(&ci->mlock_off, f));
00376                 READ(read_uint32(&ci->mlock_limit, f));
00377                 READ(read_string(&ci->mlock_key, f));
00378                 READ(read_string(&ci->mlock_flood, f));
00379                 READ(read_string(&ci->mlock_joinrate, f));
00380                 READ(read_string(&ci->mlock_redirect, f));
00381                 READ(read_int16(&ci->memos.memocount, f));
00382                 READ(read_int16(&ci->memos.memomax, f));
00383                 if (ci->memos.memocount) {
00384                     Memo *memos;
00385                     memos = calloc(sizeof(Memo) * ci->memos.memocount, 1);
00386                     ci->memos.memos = memos;
00387                     for (j = 0; j < ci->memos.memocount; j++, memos++) {
00388                         READ(read_uint32(&memos->number, f));
00389                         READ(read_int16(&memos->flags, f));
00390                         READ(read_int32(&tmp32, f));
00391                         memos->time = tmp32;
00392                         READ(read_buffer(memos->sender, f));
00393                         READ(read_string(&memos->text, f));
00394                     }
00395                 }
00396                 READ(read_string(&ci->entry_message, f));
00397 
00398                 /* BotServ options */
00399                 READ(read_string(&ci->bi, f));
00400                 READ(read_int32(&tmp32, f));
00401                 ci->botflags = tmp32;
00402                 READ(read_int16(&tmp16, f));
00403                 n_ttb = tmp16;
00404                 ci->ttb = calloc(2 * 8, 1);
00405                 for (j = 0; j < n_ttb; j++) {
00406                     if (j < 8)
00407                         READ(read_int16(&ci->ttb[j], f));
00408                     else
00409                         READ(read_int16(&tmp16, f));
00410                 }
00411                 for (j = n_ttb; j < 8; j++)
00412                     ci->ttb[j] = 0;
00413                 READ(read_int16(&tmp16, f));
00414                 ci->capsmin = tmp16;
00415                 READ(read_int16(&tmp16, f));
00416                 ci->capspercent = tmp16;
00417                 READ(read_int16(&tmp16, f));
00418                 ci->floodlines = tmp16;
00419                 READ(read_int16(&tmp16, f));
00420                 ci->floodsecs = tmp16;
00421                 READ(read_int16(&tmp16, f));
00422                 ci->repeattimes = tmp16;
00423 
00424                 READ(read_int16(&ci->bwcount, f));
00425                 if (ci->bwcount) {
00426                     ci->badwords = calloc(ci->bwcount, sizeof(BadWord));
00427                     for (j = 0; j < ci->bwcount; j++) {
00428                         SAFE(read_int16(&ci->badwords[j].in_use, f));
00429                         if (ci->badwords[j].in_use) {
00430                             SAFE(read_string(&ci->badwords[j].word, f));
00431                             SAFE(read_int16(&ci->badwords[j].type, f));
00432                         }
00433                     }
00434                 } else {
00435                     ci->badwords = NULL;
00436                 }
00437                 countr++;
00438             } /* getc_db() */
00439             *last = NULL;
00440         } /* for() loop */
00441         close_db(f);
00442     }
00443 
00444     /* II: Saving */
00445     {
00446         if ((f = open_db_write("ChanServ", CHAN_DB_ANOPE, 16))) {
00447             ChannelInfo *ci;
00448             Memo *memos;
00449             /* Unused variable - why? -GD
00450             static time_t lastwarn = 0;
00451             */
00452 
00453             for (i = 0; i < 256; i++) {
00454                 int16 tmp16;
00455                 for (ci = chanlists[i]; ci; ci = ci->next) {
00456                     int j;
00457                     SAFE(write_int8(1, f));
00458                     SAFE(write_buffer(ci->name, f));
00459                     if (ci->founder)
00460                         SAFE(write_string(ci->founder, f));
00461                     else
00462                         SAFE(write_string(NULL, f));
00463                     if (ci->successor)
00464                         SAFE(write_string(ci->successor, f));
00465                     else
00466                         SAFE(write_string(NULL, f));
00467                     SAFE(write_buffer(ci->founderpass, f));
00468                     SAFE(write_string(ci->desc, f));
00469                     SAFE(write_string(ci->url, f));
00470                     SAFE(write_string(ci->email, f));
00471                     SAFE(write_int32(ci->time_registered, f));
00472                     SAFE(write_int32(ci->last_used, f));
00473                     SAFE(write_string(ci->last_topic, f));
00474                     SAFE(write_buffer(ci->last_topic_setter, f));
00475                     SAFE(write_int32(ci->last_topic_time, f));
00476                     SAFE(write_int32(ci->flags, f));
00477                     SAFE(write_string(ci->forbidby, f));
00478                     SAFE(write_string(ci->forbidreason, f));
00479                     SAFE(write_int16(ci->bantype, f));
00480                     tmp16 = 36;
00481                     SAFE(write_int16(tmp16, f));
00482                     for (j = 0; j < 36; j++)
00483                         SAFE(write_int16(ci->levels[j], f));
00484 
00485                     SAFE(write_int16(ci->accesscount, f));
00486                     for (j = 0; j < ci->accesscount; j++) {
00487                         SAFE(write_int16(ci->access[j].in_use, f));
00488                         if (ci->access[j].in_use) {
00489                             SAFE(write_int16(ci->access[j].level, f));
00490                             SAFE(write_string(ci->access[j].nc->display, f));
00491                             SAFE(write_int32(ci->access[j].last_seen, f));
00492                         }
00493                     }
00494                     SAFE(write_int16(ci->akickcount, f));
00495                     for (j = 0; j < ci->akickcount; j++) {
00496                         SAFE(write_int16(ci->akick[j].flags, f));
00497                         if (ci->akick[j].flags & 0x0001) {
00498                             if (ci->akick[j].flags & 0x0002)
00499                                 SAFE(write_string(ci->akick[j].u.nc->display, f));
00500                             else
00501                                 SAFE(write_string(ci->akick[j].u.mask, f));
00502                             SAFE(write_string(ci->akick[j].reason, f));
00503                             SAFE(write_string(ci->akick[j].creator, f));
00504                             SAFE(write_int32(ci->akick[j].addtime, f));
00505                         }
00506                     }
00507 
00508                     SAFE(write_int32(ci->mlock_on, f));
00509                     SAFE(write_int32(ci->mlock_off, f));
00510                     SAFE(write_int32(ci->mlock_limit, f));
00511                     SAFE(write_string(ci->mlock_key, f));
00512                     SAFE(write_string(ci->mlock_flood, f));
00513                     SAFE(write_string(ci->mlock_redirect, f));
00514                     SAFE(write_int16(ci->memos.memocount, f));
00515                     SAFE(write_int16(ci->memos.memomax, f));
00516                     memos = ci->memos.memos;
00517                     for (j = 0; j < ci->memos.memocount; j++, memos++) {
00518                         SAFE(write_int32(memos->number, f));
00519                         SAFE(write_int16(memos->flags, f));
00520                         SAFE(write_int32(memos->time, f));
00521                         SAFE(write_buffer(memos->sender, f));
00522                         SAFE(write_string(memos->text, f));
00523                     }
00524                     SAFE(write_string(ci->entry_message, f));
00525                     if (ci->bi)
00526                         SAFE(write_string(ci->bi, f));
00527                     else
00528                         SAFE(write_string(NULL, f));
00529                     SAFE(write_int32(ci->botflags, f));
00530                     tmp16 = 8;
00531                     SAFE(write_int16(tmp16, f));
00532                     for (j = 0; j < 8; j++)
00533                         SAFE(write_int16(ci->ttb[j], f));
00534                     SAFE(write_int16(ci->capsmin, f));
00535                     SAFE(write_int16(ci->capspercent, f));
00536                     SAFE(write_int16(ci->floodlines, f));
00537                     SAFE(write_int16(ci->floodsecs, f));
00538                     SAFE(write_int16(ci->repeattimes, f));
00539 
00540                     SAFE(write_int16(ci->bwcount, f));
00541                     for (j = 0; j < ci->bwcount; j++) {
00542                         SAFE(write_int16(ci->badwords[j].in_use, f));
00543                         if (ci->badwords[j].in_use) {
00544                             SAFE(write_string(ci->badwords[j].word, f));
00545                             SAFE(write_int16(ci->badwords[j].type, f));
00546                         }
00547                     }
00548                     countw++;
00549                 } /* for (chanlists[i]) */
00550                 SAFE(write_int8(0, f));
00551             } /* for (i) */
00552             close_db(f);
00553             printf("%ld channels read, %ld channels written. New database saved as %s.\n", countr, countw, CHAN_DB_ANOPE);
00554         }
00555     }
00556 
00557     printf("\n\nConverting is now done.\n");
00558     return 0;
00559 } /* End of main() */
00560 
00561 /* Open a database file for reading and check for the version */
00562 dbFILE *open_db_read(const char *service, const char *filename, int version)
00563 {
00564     dbFILE *f;
00565     FILE *fp;
00566     int myversion;
00567 
00568     f = calloc(sizeof(*f), 1);
00569     if (!f) {
00570         printf("Can't allocate memory for %s database %s.\n", service, filename);
00571         exit(0);
00572     }
00573     strscpy(f->filename, filename, sizeof(f->filename));
00574     f->mode = 'r';
00575     fp = fopen(f->filename, "rb");
00576     if (!fp) {
00577         printf("Can't read %s database %s.\n", service, f->filename);
00578         free(f);
00579         return NULL;
00580     }
00581     f->fp = fp;
00582     myversion = fgetc(fp) << 24 | fgetc(fp) << 16 | fgetc(fp) << 8 | fgetc(fp);
00583     if (feof(fp)) {
00584         printf("Error reading version number on %s: End of file detected.\n", f->filename);
00585         exit(0);
00586     } else if (myversion < version) {
00587         printf("Unsuported database version (%d) on %s.\n", myversion, f->filename);
00588         exit(0);
00589     }
00590     return f;
00591 }
00592 
00593 /* Open a database file for reading and check for the version */
00594 dbFILE *open_db_write(const char *service, const char *filename, int version)
00595 {
00596     dbFILE *f;
00597     int fd;
00598 
00599     f = calloc(sizeof(*f), 1);
00600     if (!f) {
00601         printf("Can't allocate memory for %s database %s.\n", service, filename);
00602         exit(0);
00603     }
00604     strscpy(f->filename, filename, sizeof(f->filename));
00605     filename = f->filename;
00606 #ifndef _WIN32
00607     unlink(filename);
00608 #else
00609     DeleteFile(filename);
00610 #endif
00611     f->mode = 'w';
00612 #ifndef _WIN32
00613     fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
00614 #else
00615     fd = open(filename, O_WRONLY | O_CREAT | O_EXCL | _O_BINARY, 0666);
00616 #endif
00617     f->fp = fdopen(fd, "wb");   /* will fail and return NULL if fd < 0 */
00618     if (!f->fp || !write_file_version(f, version)) {
00619         printf("Can't write to %s database %s.\n", service, filename);
00620         if (f->fp) {
00621             fclose(f->fp);
00622 #ifndef _WIN32
00623             unlink(filename);
00624 #else
00625             DeleteFile(filename);
00626 #endif
00627         }
00628         free(f);
00629         return NULL;
00630     }
00631     return f;
00632 }
00633 
00634 /* Close it */
00635 void close_db(dbFILE * f)
00636 {
00637     fclose(f->fp);
00638     free(f);
00639 }
00640 
00641 int read_int16(int16 * ret, dbFILE * f)
00642 {
00643     int c1, c2;
00644 
00645     c1 = fgetc(f->fp);
00646     c2 = fgetc(f->fp);
00647     if (c1 == EOF || c2 == EOF)
00648         return -1;
00649     *ret = c1 << 8 | c2;
00650     return 0;
00651 }
00652 
00653 int read_uint16(uint16 * ret, dbFILE * f)
00654 {
00655     int c1, c2;
00656 
00657     c1 = fgetc(f->fp);
00658     c2 = fgetc(f->fp);
00659     if (c1 == EOF || c2 == EOF)
00660         return -1;
00661     *ret = c1 << 8 | c2;
00662     return 0;
00663 }
00664 
00665 int write_int16(uint16 val, dbFILE * f)
00666 {
00667     if (fputc((val >> 8) & 0xFF, f->fp) == EOF
00668         || fputc(val & 0xFF, f->fp) == EOF)
00669         return -1;
00670     return 0;
00671 }
00672 
00673 
00674 int read_int32(int32 * ret, dbFILE * f)
00675 {
00676     int c1, c2, c3, c4;
00677 
00678     c1 = fgetc(f->fp);
00679     c2 = fgetc(f->fp);
00680     c3 = fgetc(f->fp);
00681     c4 = fgetc(f->fp);
00682     if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF)
00683         return -1;
00684     *ret = c1 << 24 | c2 << 16 | c3 << 8 | c4;
00685     return 0;
00686 }
00687 
00688 int read_uint32(uint32 * ret, dbFILE * f)
00689 {
00690     int c1, c2, c3, c4;
00691 
00692     c1 = fgetc(f->fp);
00693     c2 = fgetc(f->fp);
00694     c3 = fgetc(f->fp);
00695     c4 = fgetc(f->fp);
00696     if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF)
00697         return -1;
00698     *ret = c1 << 24 | c2 << 16 | c3 << 8 | c4;
00699     return 0;
00700 }
00701 
00702 int write_int32(uint32 val, dbFILE * f)
00703 {
00704     if (fputc((val >> 24) & 0xFF, f->fp) == EOF)
00705         return -1;
00706     if (fputc((val >> 16) & 0xFF, f->fp) == EOF)
00707         return -1;
00708     if (fputc((val >> 8) & 0xFF, f->fp) == EOF)
00709         return -1;
00710     if (fputc((val) & 0xFF, f->fp) == EOF)
00711         return -1;
00712     return 0;
00713 }
00714 
00715 
00716 int read_ptr(void **ret, dbFILE * f)
00717 {
00718     int c;
00719 
00720     c = fgetc(f->fp);
00721     if (c == EOF)
00722         return -1;
00723     *ret = (c ? (void *) 1 : (void *) 0);
00724     return 0;
00725 }
00726 
00727 int write_ptr(const void *ptr, dbFILE * f)
00728 {
00729     if (fputc(ptr ? 1 : 0, f->fp) == EOF)
00730         return -1;
00731     return 0;
00732 }
00733 
00734 
00735 int read_string(char **ret, dbFILE * f)
00736 {
00737     char *s;
00738     uint16 len;
00739 
00740     if (read_uint16(&len, f) < 0)
00741         return -1;
00742     if (len == 0) {
00743         *ret = NULL;
00744         return 0;
00745     }
00746     s = calloc(len, 1);
00747     if (len != fread(s, 1, len, f->fp)) {
00748         free(s);
00749         return -1;
00750     }
00751     *ret = s;
00752     return 0;
00753 }
00754 
00755 int write_string(const char *s, dbFILE * f)
00756 {
00757     uint32 len;
00758 
00759     if (!s)
00760         return write_int16(0, f);
00761     len = strlen(s);
00762     if (len > 65534)
00763         len = 65534;
00764     if (write_int16((uint16) (len + 1), f) < 0)
00765         return -1;
00766     if (len > 0 && fwrite(s, 1, len, f->fp) != len)
00767         return -1;
00768     if (fputc(0, f->fp) == EOF)
00769         return -1;
00770     return 0;
00771 }
00772 
00773 NickCore *findcore(const char *nick, int unused)
00774 {
00775     NickCore *nc;
00776 
00777     for (nc = nclists[HASH(nick)]; nc; nc = nc->next) {
00778         if (!mystricmp(nc->display, nick))
00779             if ((nc->unused && unused) || (!nc->unused && !unused))
00780                 return nc;
00781     }
00782 
00783     return NULL;
00