init.c

Go to the documentation of this file.
00001 /* Initalization and related routines.
00002  *
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  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church. 
00010  * 
00011  *
00012  */
00013 
00014 #include "services.h"
00015 #include "pseudo.h"
00016 int servernum = 0;
00017 
00018 extern void moduleAddMsgs(void);
00019 extern void moduleAddIRCDMsgs(void);
00020 
00021 /*************************************************************************/
00022 
00023 void introduce_user(const char *user)
00024 {
00025 
00026     /* Watch out for infinite loops... */
00027 #define LTSIZE 20
00028     static int lasttimes[LTSIZE];
00029     if (lasttimes[0] >= time(NULL) - 3)
00030         fatal("introduce_user() loop detected");
00031     memmove(lasttimes, lasttimes + 1, sizeof(lasttimes) - sizeof(int));
00032     lasttimes[LTSIZE - 1] = time(NULL);
00033 #undef LTSIZE
00034 
00035     /* Introduce OperServ first because on some IRCd's send
00036      * we send data from OperServ before introduction completes.
00037      * Patch fixing ratbox RESV support provided by Jobe. */
00038     if (!user || stricmp(user, s_OperServ) == 0) {
00039         anope_cmd_nick(s_OperServ, desc_OperServ, ircd->operservmode);
00040     }
00041 
00042     /* NickServ */
00043     if (!user || stricmp(user, s_NickServ) == 0) {
00044         anope_cmd_nick(s_NickServ, desc_NickServ, ircd->nickservmode);
00045     }
00046 
00047     /* ChanServ */
00048     if (!user || stricmp(user, s_ChanServ) == 0) {
00049         anope_cmd_nick(s_ChanServ, desc_ChanServ, ircd->chanservmode);
00050     }
00051     if (s_HostServ && ircd->vhost
00052         && (!user || stricmp(user, s_HostServ) == 0)) {
00053         anope_cmd_nick(s_HostServ, desc_HostServ, ircd->hostservmode);
00054     }
00055 
00056     if (!user || stricmp(user, s_MemoServ) == 0) {
00057         anope_cmd_nick(s_MemoServ, desc_MemoServ, ircd->memoservmode);
00058     }
00059 
00060     if (s_BotServ && (!user || stricmp(user, s_BotServ) == 0)) {
00061         anope_cmd_nick(s_BotServ, desc_BotServ, ircd->botservmode);
00062     }
00063 
00064     if (!user || stricmp(user, s_HelpServ) == 0) {
00065         anope_cmd_nick(s_HelpServ, desc_HelpServ, ircd->helpservmode);
00066     }
00067 
00068     if (s_DevNull && (!user || stricmp(user, s_DevNull) == 0)) {
00069         anope_cmd_nick(s_DevNull, desc_DevNull, ircd->devnullmode);
00070     }
00071 
00072     if (!user || stricmp(user, s_GlobalNoticer) == 0) {
00073         anope_cmd_nick(s_GlobalNoticer, desc_GlobalNoticer,
00074                        ircd->globalmode);
00075     }
00076 
00077     /* We make aliases go online */
00078     if (s_NickServAlias && (!user || stricmp(user, s_NickServAlias) == 0)) {
00079         anope_cmd_nick(s_NickServAlias, desc_NickServAlias,
00080                        ircd->nickservaliasmode);
00081     }
00082 
00083     if (s_ChanServAlias && (!user || stricmp(user, s_ChanServAlias) == 0)) {
00084         anope_cmd_nick(s_ChanServAlias, desc_ChanServAlias,
00085                        ircd->chanservaliasmode);
00086     }
00087 
00088     if (s_MemoServAlias && (!user || stricmp(user, s_MemoServAlias) == 0)) {
00089         anope_cmd_nick(s_MemoServAlias, desc_MemoServAlias,
00090                        ircd->memoservaliasmode);
00091     }
00092 
00093     if (s_BotServAlias && (!user || stricmp(user, s_BotServAlias) == 0)) {
00094         anope_cmd_nick(s_BotServAlias, desc_BotServAlias,
00095                        ircd->botservaliasmode);
00096     }
00097 
00098     if (s_HelpServAlias && (!user || stricmp(user, s_HelpServAlias) == 0)) {
00099         anope_cmd_nick(s_HelpServAlias, desc_HelpServAlias,
00100                        ircd->helpservaliasmode);
00101     }
00102 
00103     if (s_OperServAlias && (!user || stricmp(user, s_OperServAlias) == 0)) {
00104         anope_cmd_nick(s_OperServAlias, desc_OperServAlias,
00105                        ircd->operservaliasmode);
00106     }
00107 
00108     if (s_DevNullAlias && (!user || stricmp(user, s_DevNullAlias) == 0)) {
00109         anope_cmd_nick(s_DevNullAlias, desc_DevNullAlias,
00110                        ircd->devnullvaliasmode);
00111     }
00112     if (s_HostServAlias && ircd->vhost
00113         && (!user || stricmp(user, s_HostServAlias) == 0)) {
00114         anope_cmd_nick(s_HostServAlias, desc_HostServAlias,
00115                        ircd->hostservaliasmode);
00116     }
00117     if (s_GlobalNoticerAlias
00118         && (!user || stricmp(user, s_GlobalNoticerAlias) == 0)) {
00119         anope_cmd_nick(s_GlobalNoticerAlias, desc_GlobalNoticerAlias,
00120                        ircd->globalaliasmode);
00121     }
00122 
00123     /* We make the bots go online */
00124     if (s_BotServ) {
00125         BotInfo *bi;
00126         int i;
00127 
00128         for (i = 0; i < 256; i++)
00129             for (bi = botlists[i]; bi; bi = bi->next) {
00130 
00131                 if (!user || !stricmp(user, bi->nick))
00132                     anope_cmd_bot_nick(bi->nick, bi->user, bi->host,
00133                                        bi->real, ircd->botserv_bot_mode);
00134             }
00135     }
00136 }
00137 
00138 /*************************************************************************/
00139 
00140 /* Set GID if necessary.  Return 0 if successful (or if RUNGROUP not
00141  * defined), else print an error message to logfile and return -1.
00142  */
00143 
00144 static int set_group(void)
00145 {
00146 #if defined(RUNGROUP) && defined(HAVE_SETGRENT)
00147     struct group *gr;
00148 
00149     setgrent();
00150     while ((gr = getgrent()) != NULL) {
00151         if (strcmp(gr->gr_name, RUNGROUP) == 0)
00152             break;
00153     }
00154     endgrent();
00155     if (gr) {
00156         setgid(gr->gr_gid);
00157         return 0;
00158     } else {
00159         alog("Unknown group `%s'\n", RUNGROUP);
00160         return -1;
00161     }
00162 #else
00163     return 0;
00164 #endif
00165 }
00166 
00167 /*************************************************************************/
00168 
00169 /* Parse command-line options for the "-dir" option only.  Return 0 if all
00170  * went well or -1 for a syntax error.
00171  */
00172 
00173 /* XXX this could fail if we have "-some-option-taking-an-argument -dir" */
00174 
00175 static int parse_dir_options(int ac, char **av)
00176 {
00177     int i;
00178     char *s;
00179 
00180     for (i = 1; i < ac; i++) {
00181         s = av[i];
00182         if (*s == '-') {
00183             s++;
00184             if (strcmp(s, "dir") == 0) {
00185                 if (++i >= ac) {
00186                     fprintf(stderr, "-dir requires a parameter\n");
00187                     return -1;
00188                 }
00189                 services_dir = av[i];
00190             } else if (strcmp(s, "log") == 0) {
00191                 if (++i >= ac) {
00192                     fprintf(stderr, "-log requires a parameter\n");
00193                     return -1;
00194                 }
00195                 log_filename = av[i];
00196             } else if (strcmp(s, "version") == 0) {
00197                 fprintf(stdout, "Anope-%s %s -- %s\n", version_number,
00198                         version_flags, version_build);
00199                 exit(EXIT_SUCCESS);
00200             }
00201         }
00202     }
00203     return 0;
00204 }
00205 
00206 /*************************************************************************/
00207 
00208 /* Parse command-line options.  Return 0 if all went well, -1 for an error
00209  * with an option, or 1 for -help.
00210  */
00211 
00212 static int parse_options(int ac, char **av)
00213 {
00214     int i;
00215     char *s, *t;
00216 
00217     for (i = 1; i < ac; i++) {
00218         s = av[i];
00219         if (*s == '-') {
00220             s++;
00221             if (strcmp(s, "remote") == 0) {
00222                 if (++i >= ac) {
00223                     fprintf(stderr, "-remote requires hostname[:port]\n");
00224                     return -1;
00225                 }
00226                 s = av[i];
00227                 t = strchr(s, ':');
00228                 if (t) {
00229                     int portnum;
00230                     *t++ = 0;
00231                     portnum = atoi(t);
00232                     if ((portnum > 0) && (portnum < 65535))
00233                         RemotePort = portnum;
00234                     else {
00235                         fprintf(stderr,
00236                                 "-remote: Port numbers must be in the range 1..65535. Using default.\n");
00237                         return -1;
00238                     }
00239                 }
00240                 RemoteServer = s;
00241             } else if (strcmp(s, "local") == 0) {
00242                 if (++i >= ac) {
00243                     fprintf(stderr,
00244                             "-local requires hostname or [hostname]:[port]\n");
00245                     return -1;
00246                 }
00247                 s = av[i];
00248                 t = strchr(s, ':');
00249                 if (t) {
00250                     int portnum;
00251                     *t++ = 0;
00252                     portnum = atoi(t);
00253                     if ((portnum >= 0) && (portnum < 65535))
00254                         LocalPort = portnum;
00255                     else {
00256                         fprintf(stderr,
00257                                 "-local: Port numbers must be in the range 1..65535 or 0. Using default.\n");
00258                         return -1;
00259                     }
00260                 }
00261                 LocalHost = s;
00262             } else if (strcmp(s, "name") == 0) {
00263                 if (++i >= ac) {
00264                     fprintf(stderr, "-name requires a parameter\n");
00265                     return -1;
00266                 }
00267                 ServerName = av[i];
00268             } else if (strcmp(s, "desc") == 0) {
00269                 if (++i >= ac) {
00270                     fprintf(stderr, "-desc requires a parameter\n");
00271                     return -1;
00272                 }
00273                 ServerDesc = av[i];
00274             } else if (strcmp(s, "user") == 0) {
00275                 if (++i >= ac) {
00276                     fprintf(stderr, "-user requires a parameter\n");
00277                     return -1;
00278                 }
00279                 ServiceUser = av[i];
00280             } else if (strcmp(s, "host") == 0) {
00281                 if (++i >= ac) {
00282                     fprintf(stderr, "-host requires a parameter\n");
00283                     return -1;
00284                 }
00285                 ServiceHost = av[i];
00286             } else if (strcmp(s, "dir") == 0) {
00287                 /* Handled by parse_dir_options() */
00288                 i++;            /* Skip parameter */
00289             } else if (strcmp(s, "log") == 0) {
00290                 /* Handled by parse_dir_options(), too */
00291                 i++;            /* Skip parameter */
00292             } else if (strcmp(s, "update") == 0) {
00293                 if (++i >= ac) {
00294                     fprintf(stderr, "-update requires a parameter\n");
00295                     return -1;
00296                 }
00297                 s = av[i];
00298                 if (atoi(s) <= 0) {
00299                     fprintf(stderr,
00300                             "-update: number of seconds must be positive");
00301                     return -1;
00302                 } else
00303                     UpdateTimeout = atol(s);
00304             } else if (strcmp(s, "expire") == 0) {
00305                 if (++i >= ac) {
00306                     fprintf(stderr, "-expire requires a parameter\n");
00307                     return -1;
00308                 }
00309                 s = av[i];
00310                 if (atoi(s) <= 0) {
00311                     fprintf(stderr,
00312                             "-expire: number of seconds must be positive\n");
00313                     return -1;
00314                 } else
00315                     ExpireTimeout = atol(s);
00316             } else if (strcmp(s, "debug") == 0) {
00317                 debug++;
00318             } else if (strcmp(s, "readonly") == 0) {
00319                 readonly = 1;
00320                 skeleton = 0;
00321             } else if (strcmp(s, "skeleton") == 0) {
00322                 readonly = 0;
00323                 skeleton = 1;
00324             } else if (strcmp(s, "nofork") == 0) {
00325                 nofork = 1;
00326             } else if (strcmp(s, "logchan") == 0) {
00327                 if (!LogChannel) {
00328                     fprintf(stderr,
00329                             "-logchan: LogChannel must be defined in services.conf\n");
00330                 } else {        /* LogChannel */
00331 
00332                     logchan = 1;
00333                 }
00334             } else if (strcmp(s, "forceload") == 0) {
00335                 forceload = 1;
00336             } else if (strcmp(s, "nothird") == 0) {
00337                 nothird = 1;
00338             } else if (strcmp(s, "protocoldebug") == 0) {
00339                 protocoldebug = 1;
00340             } else if (strcmp(s, "support") == 0) {
00341                 nofork = 1;
00342                 debug++;
00343                 nothird = 1;
00344             } else if (!strcmp(s, "noexpire")) {
00345                 noexpire = 1;
00346             } else if (!strcmp(s, "help")) {
00347                 fprintf(stdout, "Anope-%s %s -- %s\n", version_number,
00348                         version_flags, version_build);
00349                 fprintf(stdout,
00350                         "Anope IRC Services (http://www.anope.org)\n");
00351                 fprintf(stdout, "Usage ./services [options] ...\n");
00352                 fprintf(stdout,
00353                         "-remote        -remote hostname[:port]\n");
00354                 fprintf(stdout, "-local         -local hostname[:port]\n");
00355                 fprintf(stdout, "-name          -name servername\n");
00356                 fprintf(stdout, "-desc          -desc serverdesc\n");
00357                 fprintf(stdout, "-user          -user serviceuser\n");
00358                 fprintf(stdout, "-host          -host servicehost\n");
00359                 fprintf(stdout,
00360                         "-update        -update updatetime(secs)\n");
00361                 fprintf(stdout,
00362                         "-expire        -expire expiretime(secs)\n");
00363                 fprintf(stdout, "-debug         -debug\n");
00364                 fprintf(stdout, "-protocoldebug -protocoldebug\n");
00365                 fprintf(stdout, "-nofork        -nofork\n");
00366                 fprintf(stdout, "-logchan       -logchan channelname\n");
00367                 fprintf(stdout, "-skeleton      -skeleton\n");
00368                 fprintf(stdout, "-forceload     -forceload\n");
00369                 fprintf(stdout, "-nothird       -nothird\n");
00370                 fprintf(stdout, "-support       -support\n");
00371                 fprintf(stdout, "-readonly      -readonly\n");
00372                 fprintf(stdout, "-noexpire      -noexpire\n");
00373                 fprintf(stdout, "-version       -version\n");
00374                 fprintf(stdout, "-help          -help\n");
00375                 fprintf(stdout, "-log           -log logfilename\n");
00376                 fprintf(stdout,
00377                         "-dir           -dir servicesdirectory\n\n");
00378                 fprintf(stdout,
00379                         "Further support is available from http://www.anope.org\n");
00380                 fprintf(stdout,
00381                         "Or visit US on IRC at irc.anope.org #anope\n");
00382                 exit(EXIT_SUCCESS);
00383             } else {
00384                 fprintf(stderr, "Unknown option -%s\n", s);
00385                 return -1;
00386             }
00387         } else {
00388             fprintf(stderr, "Non-option arguments not allowed\n");
00389             return -1;
00390         }
00391     }
00392     return 0;
00393 }
00394 
00395 /*************************************************************************/
00396 
00397 /* Remove our PID file.  Done at exit. */
00398 
00399 static void remove_pidfile(void)
00400 {
00401     remove(PIDFilename);
00402 }
00403 
00404 /*************************************************************************/
00405 
00406 /* Create our PID file and write the PID to it. */
00407 
00408 static void write_pidfile(void)
00409 {
00410     FILE *pidfile;
00411 
00412     pidfile = fopen(PIDFilename, "w");
00413     if (pidfile) {
00414         fprintf(pidfile, "%d\n", (int) getpid());
00415         fclose(pidfile);
00416         atexit(remove_pidfile);
00417     } else {
00418         log_perror("Warning: cannot write to PID file %s", PIDFilename);
00419     }
00420 }
00421 
00422 /*************************************************************************/
00423 
00424 /* Overall initialization routines.  Return 0 on success, -1 on failure. */
00425 
00426 int openlog_failed = 0, openlog_errno = 0;
00427 
00428 int init_primary(int ac, char **av)
00429 {
00430     int started_from_term = isatty(0) && isatty(1) && isatty(2);
00431 
00432     /* Set file creation mask and group ID. */
00433 #if defined(DEFUMASK) && HAVE_UMASK
00434     umask(DEFUMASK);
00435 #endif
00436     if (set_group() < 0)
00437         return -1;
00438 
00439     /* Parse command line for -dir and -version options. */
00440     parse_dir_options(ac, av);
00441 
00442     /* Chdir to Services data directory. */
00443     if (chdir(services_dir) < 0) {
00444         fprintf(stderr, "chdir(%s): %s\n", services_dir, strerror(errno));
00445         return -1;
00446     }
00447 
00448     /* Open logfile, and complain if we didn't. */
00449     if (open_log() < 0) {
00450         openlog_errno = errno;
00451         if (started_from_term) {
00452             fprintf(stderr, "Warning: unable to open log file %s: %s\n",
00453                     log_filename, strerror(errno));
00454         } else {
00455             openlog_failed = 1;
00456         }
00457     }
00458 
00459     /* Read configuration file; exit if there are problems. */
00460     if (!read_config(0)) {
00461         return -1;
00462     }
00463 
00464     /* Add IRCD Protocol Module; exit if there are errors */
00465     if (protocol_module_init()) {
00466         return -1;
00467     }
00468 
00469     /* Add Encryption Module; exit if there are errors */
00470     if (encryption_module_init()) {
00471         return -1;
00472     }
00473     return 0;
00474 }
00475 
00476 int init_secondary(int ac, char **av)
00477 {
00478     int i;
00479     int started_from_term = isatty(0) && isatty(1) && isatty(2);
00480 
00481     /* Add Core MSG handles */
00482     moduleAddMsgs();
00483 
00484     /* Parse all remaining command-line options. */
00485     parse_options(ac, av);
00486 
00487     /* Parse the defcon mode string if needed */
00488     if (DefConLevel && !ircd->delay_cl_intro) {
00489         if (!defconParseModeString(DefConChanModes)) {
00490             fprintf(stderr,
00491                     "services.conf: The given DefConChanModes mode string was incorrect (see log for exact errors)\n");
00492             return -1;
00493         }
00494     }
00495 #ifndef _WIN32
00496     if (!nofork) {
00497         if ((i = fork()) < 0) {
00498             perror("fork()");
00499             return -1;
00500         } else if (i != 0) {
00501             exit(0);
00502         }
00503         if (started_from_term) {
00504             close(0);
00505             close(1);
00506             close(2);
00507         }
00508         if (setpgid(0, 0) < 0) {
00509             perror("setpgid()");
00510             return -1;
00511         }
00512     }
00513 #else
00514     /* Initialize winsocks -- codemastr */
00515     {
00516         WSADATA wsa;
00517         if (WSAStartup(MAKEWORD(1, 1), &wsa)) {
00518             alog("Failed to initialized WinSock library");
00519             return -1;
00520         }
00521     }
00522     if (!SupportedWindowsVersion()) {
00523 
00524         char *winver = GetWindowsVersion();
00525 
00526         alog("%s is not a supported version of Windows", winver);
00527 
00528         free(winver);
00529 
00530         return -1;
00531 
00532     }
00533     if (!nofork) {
00534         alog("Launching Anope into the background");
00535         FreeConsole();
00536     }
00537 #endif
00538 
00539     /* Write our PID to the PID file. */
00540     write_pidfile();
00541 
00542     /* Announce ourselves to the logfile. */
00543     if (debug || readonly || skeleton) {
00544         alog("Anope %s (ircd protocol: %s) starting up (options:%s%s%s)",
00545              version_number, version_protocol,
00546              debug ? " debug" : "", readonly ? " readonly" : "",
00547              skeleton ? " skeleton" : "");
00548     } else {
00549         alog("Anope %s (ircd protocol: %s) starting up",
00550              version_number, version_protocol);
00551     }
00552     start_time = time(NULL);
00553 
00554 
00555 
00556     /* If in read-only mode, close the logfile again. */
00557     if (readonly)
00558         close_log();
00559 
00560     /* Set signal handlers.  Catch certain signals to let us do things or
00561      * panic as necessary, and ignore all others.
00562      */
00563 
00564 #ifndef _WIN32
00565 #if defined(NSIG)
00566     for (i = 1; i <= NSIG - 1; i++) {
00567 #else
00568     for (i = 1; i <= 31; i++) {
00569 #endif
00570         signal(i, SIG_IGN);
00571     }
00572 #else
00573     /* work around to bug #527 */
00574     signal(SIGILL, SIG_IGN);
00575     signal(SIGBREAK, SIG_IGN);
00576     signal(SIGABRT, SIG_IGN);
00577 #endif
00578 
00579     signal(SIGINT, sighandler);
00580     signal(SIGTERM, sighandler);
00581 #ifndef _WIN32
00582     signal(SIGQUIT, sighandler);
00583 #endif
00584     if (!DumpCore) {
00585         signal(SIGSEGV, sighandler);
00586 #ifndef _WIN32
00587         signal(SIGBUS, sighandler);
00588         signal(SIGTRAP, sighandler);
00589 #endif
00590     } else {
00591         signal(SIGSEGV, SIG_DFL);
00592 #ifndef _WIN32
00593         signal(SIGBUS, sighandler);
00594         signal(SIGTRAP, sighandler);
00595 #endif
00596     }
00597 #ifndef _WIN32
00598     signal(SIGQUIT, sighandler);
00599     signal(SIGHUP, sighandler);
00600     signal(SIGUSR2, sighandler);
00601 #endif
00602 
00603 #ifdef SIGIOT
00604     signal(SIGIOT, sighandler);
00605 #endif
00606     signal(SIGFPE, sighandler);
00607 
00608 #ifndef _WIN32
00609     signal(SIGUSR1, sighandler);        /* This is our "out-of-memory" panic switch */
00610 #endif
00611 
00612     /* Initialize multi-language support */
00613     lang_init();
00614     if (debug)
00615         alog("debug: Loaded languages");
00616 
00617 
00618     /* Initialize subservices */
00619     ns_init();
00620     cs_init();
00621     ms_init();
00622     bs_init();
00623     os_init();
00624     hostserv_init();
00625     helpserv_init();
00626 
00627 #ifdef USE_RDB
00628     if (!rdb_init()) {
00629         if (UseRDB) {
00630             UseRDB = 0;
00631             alog("Error: Disabling UseRDB due to errors with SQL");
00632         }
00633     } else {
00634         if (MysqlSecure && UseRDB) {
00635             UseRDB = 0;
00636             alog("Error: MySQL password are encrypted using method in MysqlSecure disabling UseRDB");
00637         }
00638     }
00639 #endif
00640 
00641     /* load any custom modules */
00642     modules_init();
00643 
00644     /* Initialize random number generator */
00645     rand_init();
00646     add_entropy_userkeys();
00647 
00648     /* Load up databases */
00649 #ifdef USE_RDB
00650     if (UseRDB)
00651         rdb_load_dbases();
00652     /* Need a better way to handle this -dane */
00653     if (!UseRDB) {
00654 #endif
00655         if (!skeleton) {
00656             load_ns_dbase();
00657             if (debug)
00658                 alog("debug: Loaded %s database (1/%d)", s_NickServ,
00659                      (PreNickDBName ? 8 : 7));
00660             if (s_HostServ) {
00661                 load_hs_dbase();
00662                 if (debug)
00663                     alog("debug: Loaded %s database (2/%d)", s_HostServ,
00664                          (PreNickDBName ? 8 : 7));
00665             } else if (debug) {
00666                 alog("debug: HostServ database (2/%d) not loaded because HostServ is disabled", (PreNickDBName ? 8 : 7));
00667             }
00668             if (s_BotServ) {
00669                 load_bs_dbase();
00670                 if (debug)
00671                     alog("debug: Loaded %s database (3/%d)", s_BotServ,
00672                          (PreNickDBName ? 8 : 7));
00673             } else if (debug) {
00674                 alog("debug: BotServ database (3/%d) not loaded because BotServ is disabled", (PreNickDBName ? 8 : 7));
00675             }
00676             load_cs_dbase();
00677             if (debug)
00678                 alog("debug: Loaded %s database (4/%d)", s_ChanServ,
00679                      (PreNickDBName ? 8 : 7));
00680         }
00681         load_os_dbase();
00682         if (debug)
00683             alog("debug: Loaded %s database (5/%d)", s_OperServ,
00684                  (PreNickDBName ? 8 : 7));
00685         load_news();
00686         if (debug)
00687             alog("debug: Loaded news database (6/%d)",
00688                  (PreNickDBName ? 8 : 7));
00689         load_exceptions();
00690         if (debug)
00691             alog("debug: Loaded exception database (7/%d)",
00692                  (PreNickDBName ? 8 : 7));
00693         if (PreNickDBName) {
00694             load_ns_req_db();
00695             if (debug)
00696                 alog("debug: Loaded PreNick database (8/8)");
00697         }
00698 #ifdef USE_RDB
00699     }
00700 #endif
00701     alog("Databases loaded");
00702 
00703     /* Save the databases back to file/mysql to reflect any changes */
00704 #ifdef USE_RDB
00705     if (!UseRDB) {              /* Only save if we are not using remote databases
00706                                  * to avoid floods. As a side effects our nice
00707                                  * FFF databases won't get overwritten if the
00708                                  * mysql db is broken (empty etc.) */
00709 #endif
00710         alog("Info: Reflecting database records.");
00711         save_databases();
00712 #ifdef USE_RDB
00713     } else {
00714         alog("Info: Not reflecting database records.");
00715     }
00716 #endif
00717     send_event(EVENT_CONNECT, 1, EVENT_START);
00718 
00719     /* Connect to the remote server */
00720     servsock = conn(RemoteServer, RemotePort, LocalHost, LocalPort);
00721     if (servsock < 0 && RemoteServer2) {
00722         servsock = conn(RemoteServer2, RemotePort2, LocalHost, LocalPort);
00723         if (servsock < 0 && RemoteServer3) {
00724             servsock =
00725                 conn(RemoteServer3, RemotePort3, LocalHost, LocalPort);
00726             if (servsock < 0) {
00727                 fatal_perror("Can't connect to server");
00728             } else {
00729                 servernum = 3;
00730                 alog("Connected to Server %d (%s:%d)", servernum,
00731                      RemoteServer3, RemotePort3);
00732             }
00733         } else {
00734             if (servsock < 0) {
00735                 fatal_perror("Can't connect to server");
00736             }
00737             servernum = 2;
00738             alog("Connected to Server %d (%s:%d)", servernum,
00739                  RemoteServer2, RemotePort2);
00740         }
00741     } else {
00742         if (servsock < 0) {
00743             fatal_perror("Can't connect to server");
00744         }
00745         servernum = 1;
00746         alog("Connected to Server %d (%s:%d)", servernum, RemoteServer,
00747              RemotePort);
00748     }
00749 
00750     anope_cmd_connect(servernum);
00751     send_event(EVENT_CONNECT, 1, EVENT_STOP);
00752 
00753     sgets2(inbuf, sizeof(inbuf), servsock);
00754     if (strnicmp(inbuf, "ERROR", 5) == 0) {
00755         /* Close server socket first to stop wallops, since the other
00756          * server doesn't want to listen to us anyway */
00757         disconn(servsock);
00758         servsock = -1;
00759         fatal("Remote server returned: %s", inbuf);
00760     }
00761 
00762     /* Announce a logfile error if there was one */
00763     if (openlog_failed) {
00764         anope_cmd_global(NULL, "Warning: couldn't open logfile: %s",
00765                          strerror(openlog_errno));
00766     }
00767 
00768     if (!ircd->delay_cl_intro)
00769         init_tertiary();
00770 
00771     /* Success! */
00772     return 0;
00773 }
00774 
00775 /*************************************************************************/
00776 
00777 void init_tertiary()
00778 {
00779     /* Begin our burst..*/
00780     anope_cmd_bob();
00781 
00782     /* Bring in our pseudo-clients */
00783     introduce_user(NULL);
00784 
00785     /* And hybrid needs Global joined in the logchan */
00786     if (logchan && ircd->join2msg) {
00787         /* XXX might desync */
00788         anope_cmd_join(s_GlobalNoticer, LogChannel, time(NULL));
00789     }
00790 
00791     /* End our burst.. */
00792     anope_cmd_eob();
00793 
00798     modules_delayed_init();
00799 }
00800 
00801 /*************************************************************************/