]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/ngircd.c
- Kommandozeilen-Parser implementiert: Debug- und No-Daemon-Modus, Hilfe.
[ngircd-alex.git] / src / ngircd / ngircd.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
4  *
5  * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
6  * der GNU General Public License (GPL), wie von der Free Software Foundation
7  * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
8  * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
9  * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
10  * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
11  *
12  * $Id: ngircd.c,v 1.18 2002/01/11 14:45:18 alex Exp $
13  *
14  * ngircd.c: Hier beginnt alles ;-)
15  *
16  * $Log: ngircd.c,v $
17  * Revision 1.18  2002/01/11 14:45:18  alex
18  * - Kommandozeilen-Parser implementiert: Debug- und No-Daemon-Modus, Hilfe.
19  *
20  * Revision 1.17  2002/01/02 02:51:16  alex
21  * - Signal-Handler fuer SIGCHLD: so sollten Zombies nicht mehr vorkommen.
22  *
23  * Revision 1.15  2001/12/31 02:18:51  alex
24  * - viele neue Befehle (WHOIS, ISON, OPER, DIE, RESTART),
25  * - neuen Header "defines.h" mit (fast) allen Konstanten.
26  * - Code Cleanups und viele "kleine" Aenderungen & Bugfixes.
27  *
28  * Revision 1.14  2001/12/30 19:26:12  alex
29  * - Unterstuetzung fuer die Konfigurationsdatei eingebaut.
30  *
31  * Revision 1.13  2001/12/30 11:42:00  alex
32  * - der Server meldet nun eine ordentliche "Start-Zeit".
33  *
34  * Revision 1.12  2001/12/29 03:07:36  alex
35  * - einige Loglevel geaendert.
36  *
37  * Revision 1.11  2001/12/26 14:45:37  alex
38  * - "Code Cleanups".
39  *
40  * Revision 1.10  2001/12/24 01:34:38  alex
41  * - Signal-Handler aufgeraeumt; u.a. SIGPIPE wird nun korrekt ignoriert.
42  *
43  * Revision 1.9  2001/12/21 22:24:50  alex
44  * - neues Modul "parse" wird initialisiert und abgemeldet.
45  *
46  * Revision 1.8  2001/12/14 08:15:26  alex
47  * - neue Module (irc, client, channel) werden an- und abgemeldet.
48  * - zweiter Listen-Socket wird zu Testzwecken konfiguriert.
49  *
50  * Revision 1.7  2001/12/13 01:31:46  alex
51  * - Conn_Handler() wird nun mit einem Timeout aufgerufen.
52  *
53  * Revision 1.6  2001/12/12 23:30:42  alex
54  * - Log-Meldungen an syslog angepasst.
55  * - NGIRCd_Quit ist nun das Flag zum Beenden des ngircd.
56  *
57  * Revision 1.5  2001/12/12 17:21:21  alex
58  * - mehr Unterfunktionen eingebaut, Modul besser strukturiert & dokumentiert.
59  * - Anpassungen an neue Module.
60  *
61  * Revision 1.4  2001/12/12 01:58:53  alex
62  * - Test auf socklen_t verbessert.
63  *
64  * Revision 1.3  2001/12/12 01:40:39  alex
65  * - ein paar mehr Kommentare; Variablennamen verstaendlicher gemacht.
66  * - fehlenden Header <arpa/inet.h> ergaenz.
67  * - SIGINT und SIGQUIT werden nun ebenfalls behandelt.
68  *
69  * Revision 1.2  2001/12/11 22:04:21  alex
70  * - Test auf stdint.h (HAVE_STDINT_H) hinzugefuegt.
71  *
72  * Revision 1.1.1.1  2001/12/11 21:53:04  alex
73  * - Imported sources to CVS.
74  */
75
76
77 #define PORTAB_CHECK_TYPES              /* Prueffunktion einbinden, s.u. */
78
79
80 #include <portab.h>
81 #include "global.h"
82
83 #include <imp.h>
84
85 #include <assert.h>
86 #include <stdio.h>
87 #include <signal.h>
88 #include <string.h>
89 #include <sys/types.h>
90 #include <sys/wait.h>
91 #include <time.h>
92
93 #include "channel.h"
94 #include "client.h"
95 #include "conf.h"
96 #include "conn.h"
97 #include "irc.h"
98 #include "log.h"
99 #include "parse.h"
100
101 #include <exp.h>
102 #include "ngircd.h"
103
104
105 LOCAL VOID Initialize_Signal_Handler( VOID );
106 LOCAL VOID Signal_Handler( INT Signal );
107
108 LOCAL VOID Initialize_Listen_Ports( VOID );
109
110 LOCAL VOID Show_Version( VOID );
111 LOCAL VOID Show_Help( VOID );
112
113
114 GLOBAL INT main( INT argc, CONST CHAR *argv[] )
115 {
116         BOOLEAN ok;
117         INT i, n;
118
119         /* Datentypen der portab-Library ueberpruefen */
120         portab_check_types( );
121
122         NGIRCd_Restart = FALSE;
123         NGIRCd_Quit = FALSE;
124         NGIRCd_NoDaemon = FALSE;
125 #ifdef DEBUG
126         NGIRCd_Debug = FALSE;
127 #endif
128
129         /* Kommandozeile parsen */
130         for( i = 1; i < argc; i++ )
131         {
132                 ok = FALSE;
133                 if(( argv[i][0] == '-' ) && ( argv[i][1] == '-' ))
134                 {
135                         /* Lange Option */
136
137                         if( strcmp( argv[i], "--help" ) == 0 )
138                         {
139                                 Show_Version( ); puts( "" );
140                                 Show_Help( ); puts( "" );
141                                 exit( 1 );
142                         }
143                         if( strcmp( argv[i], "--version" ) == 0 )
144                         {
145                                 Show_Version( );
146                                 exit( 1 );
147                         }
148 #ifdef DEBUG
149                         if( strcmp( argv[i], "--debug" ) == 0 )
150                         {
151                                 NGIRCd_Debug = TRUE;
152                                 ok = TRUE;
153                         }
154 #endif
155                         if( strcmp( argv[i], "--nodaemon" ) == 0 )
156                         {
157                                 NGIRCd_NoDaemon = TRUE;
158                                 ok = TRUE;
159                         }
160                 }
161                 else if(( argv[i][0] == '-' ) && ( argv[i][1] != '-' ))
162                 {
163                         /* Kurze Option */
164                         
165                         for( n = 1; n < strlen( argv[i] ); n++ )
166                         {
167                                 ok = FALSE;
168 #ifdef DEBUG
169                                 if( argv[i][n] == 'd' )
170                                 {
171                                         NGIRCd_Debug = TRUE;
172                                         ok = TRUE;
173                                 }
174 #endif
175                                 if( argv[i][n] == 'n' )
176                                 {
177                                         NGIRCd_NoDaemon = TRUE;
178                                         ok = TRUE;
179                                 }
180
181                                 if( ! ok )
182                                 {
183                                         printf( PACKAGE": invalid option \"-%c\"!\n", argv[i][n] );
184                                         puts( "Try \""PACKAGE" --help\" for more information." );
185                                         exit( 1 );
186                                 }
187                         }
188
189                 }
190                 if( ! ok )
191                 {
192                         printf( PACKAGE": invalid option \"%s\"!\n", argv[i] );
193                         puts( "Try \""PACKAGE" --help\" for more information." );
194                         exit( 1 );
195                 }
196         }
197
198         while( ! NGIRCd_Quit )
199         {
200                 /* Globale Variablen initialisieren */
201                 NGIRCd_Start = time( NULL );
202                 strftime( NGIRCd_StartStr, 64, "%a %b %d %Y at %H:%M:%S (%Z)", localtime( &NGIRCd_Start ));
203                 NGIRCd_Restart = FALSE;
204                 NGIRCd_Quit = FALSE;
205
206                 /* Module initialisieren */
207                 Log_Init( );
208                 Conf_Init( );
209                 Parse_Init( );
210                 IRC_Init( );
211                 Channel_Init( );
212                 Client_Init( );
213                 Conn_Init( );
214
215                 /* Signal-Handler initialisieren */
216                 Initialize_Signal_Handler( );
217
218                 /* Listen-Ports initialisieren */
219                 Initialize_Listen_Ports( );
220
221                 /* Hauptschleife */
222                 while( TRUE )
223                 {
224                         if( NGIRCd_Quit || NGIRCd_Restart ) break;
225                         Conn_Handler( 5 );
226                 }
227
228                 /* Alles abmelden */
229                 Conn_Exit( );
230                 Client_Exit( );
231                 Channel_Exit( );
232                 IRC_Exit( );
233                 Parse_Exit( );
234                 Conf_Exit( );
235                 Log_Exit( );
236         }
237         return 0;
238 } /* main */
239
240
241 GLOBAL CHAR *NGIRCd_Version( VOID )
242 {
243         STATIC CHAR version[126];
244         CHAR txt[64];
245
246         strcpy( txt, "" );
247
248 #ifdef USE_SYSLOG
249         if( txt[0] ) strcat( txt, "+" );
250         else strcat( txt, "-" );
251         strcat( txt, "SYSLOG" );
252 #endif
253 #ifdef STRICT_RFC
254         if( txt[0] ) strcat( txt, "+" );
255         else strcat( txt, "-" );
256         strcat( txt, "RFC" );
257 #endif
258 #ifdef DEBUG
259         if( txt[0] ) strcat( txt, "+" );
260         else strcat( txt, "-" );
261         strcat( txt, "DEBUG" );
262 #endif
263 #ifdef SNIFFER
264         if( txt[0] ) strcat( txt, "+" );
265         else strcat( txt, "-" );
266         strcat( txt, "SNIFFER" );
267 #endif
268
269         sprintf( version, PACKAGE" version "VERSION"%s-"P_OSNAME"/"P_ARCHNAME, txt );
270         return version;
271 } /* NGIRCd_Version */
272
273
274 LOCAL VOID Initialize_Signal_Handler( VOID )
275 {
276         /* Signal-Handler initialisieren: einige Signale
277          * werden ignoriert, andere speziell behandelt. */
278
279         struct sigaction saction;
280
281         /* Signal-Struktur initialisieren */
282         memset( &saction, 0, sizeof( saction ));
283
284         /* Signal-Handler einhaengen */
285         saction.sa_handler = Signal_Handler;
286         sigaction( SIGINT, &saction, NULL );
287         sigaction( SIGQUIT, &saction, NULL );
288         sigaction( SIGTERM, &saction, NULL);
289         sigaction( SIGCHLD, &saction, NULL);
290
291         /* einige Signale ignorieren */
292         saction.sa_handler = SIG_IGN;
293         sigaction( SIGPIPE, &saction, NULL );
294 } /* Initialize_Signal_Handler */
295
296
297 LOCAL VOID Signal_Handler( INT Signal )
298 {
299         /* Signal-Handler. Dieser wird aufgerufen, wenn eines der Signale eintrifft,
300          * fuer das wir uns registriert haben (vgl. Initialize_Signal_Handler). Die
301          * Nummer des eingetroffenen Signals wird der Funktion uebergeben. */
302
303         switch( Signal )
304         {
305                 case SIGTERM:
306                 case SIGINT:
307                 case SIGQUIT:
308                         /* wir soll(t)en uns wohl beenden ... */
309                         Log( LOG_WARNING, "Got signal %d, terminating now ...", Signal );
310                         NGIRCd_Quit = TRUE;
311                         break;
312                 case SIGCHLD:
313                         /* Child-Prozess wurde beendet. Zombies vermeiden: */
314                         while( waitpid( -1, NULL, WNOHANG ) > 0);
315                         break;
316                 default:
317                         /* unbekanntes bzw. unbehandeltes Signal */
318                         Log( LOG_NOTICE, "Got signal %d! Ignored.", Signal );
319         }
320 } /* Signal_Handler */
321
322
323 LOCAL VOID Initialize_Listen_Ports( VOID )
324 {
325         /* Ports, auf denen der Server Verbindungen entgegennehmen
326          * soll, initialisieren */
327         
328         INT created, i;
329
330         created = 0;
331         for( i = 0; i < Conf_ListenPorts_Count; i++ )
332         {
333                 if( Conn_NewListener( Conf_ListenPorts[i] )) created++;
334                 else Log( LOG_ERR, "Can't listen on port %d!", Conf_ListenPorts[i] );
335         }
336
337         if( created < 1 )
338         {
339                 Log( LOG_ALERT, "Server isn't listening on a single port!" );
340                 Log( LOG_ALERT, PACKAGE" exiting due to fatal errors!" );
341                 exit( 1 );
342         }
343 } /* Initialize_Listen_Ports */
344
345
346 LOCAL VOID Show_Version( VOID )
347 {
348         puts( NGIRCd_Version( ));
349         puts( "Copyright (c)2001,2002 by Alexander Barton (alex@barton.de).\n" );
350         puts( "This is free software; see the source for copying conditions. There is NO" );
351         puts( "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." );
352 } /* Show_Version */
353
354
355 LOCAL VOID Show_Help( VOID )
356 {
357 #ifdef DEBUG
358         puts( "  -d, --debug       log extra debug messages" );
359 #endif
360         puts( "  -n, --nodaemon    don't fork and don't detatch from controlling terminal" );
361         puts( "      --version     display this help and exit" );
362         puts( "      --help        output version information and exit" );
363 } /* Show_Help */
364
365
366 /* -eof- */