]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/inspircd_io.cpp
405b3d046cbf3fa7df0f7d99dd92c0f00c6635a5
[user/henk/code/inspircd.git] / src / inspircd_io.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  Inspire is copyright (C) 2002-2004 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 #ifdef __linux__ 
18 #include <sys/resource.h>
19 #endif
20
21 #include <sys/types.h>
22 #include <string>
23 #include <unistd.h>
24 #include <sstream>
25 #include <iostream>
26 #include <fstream>
27 #include "inspircd.h"
28 #include "inspircd_io.h"
29 #include "inspircd_util.h"
30
31 using namespace std;
32
33 extern FILE *log_file;
34
35 void WriteOpers(char* text, ...);
36
37 void Exit (int status)
38 {
39   if (log_file)
40         fclose(log_file);
41   send_error("Server shutdown.");
42   exit (status);
43 }
44
45 void Killed(int status)
46 {
47   if (log_file)
48         fclose(log_file);
49   send_error("Server terminated.");
50   exit(status);
51 }
52
53 void Rehash(int status)
54 {
55   ReadConfig();
56   WriteOpers("Rehashing config file %s due to SIGHUP",CONFIG_FILE);
57 }
58
59
60
61 void Start (void)
62 {
63   printf("\033[1;37mInspire Internet Relay Chat Server, compiled " __DATE__ " at " __TIME__ "\n");
64   printf("(C) ChatSpike Development team.\033[0;37m\n\n");
65   printf("\033[1;37mDevelopers:\033[0;37m     Brain, FrostyCoolSlug, RD\n");
66   printf("\033[1;37mDocumentation:\033[0;37m  FrostyCoolSlug, w00t\n");
67   printf("\033[1;37mTesters:\033[0;37m        typobox43, piggles, Lord_Zathras, CC\n");
68   printf("\033[1;37mName concept:\033[0;37m   Lord_Zathras\n\n");
69 }
70
71
72 void DeadPipe(int status)
73 {
74   signal (SIGPIPE, DeadPipe);
75 }
76
77 int DaemonSeed (void)
78 {
79   int childpid;
80   signal (SIGALRM, SIG_IGN);
81   signal (SIGHUP, Rehash);
82   signal (SIGPIPE, DeadPipe);
83   signal (SIGTERM, Exit);
84   signal (SIGABRT, Exit);
85   signal (SIGSEGV, Error);
86   signal (SIGURG, Exit);
87   signal (SIGKILL, Exit);
88   if ((childpid = fork ()) < 0)
89     return (ERROR);
90   else if (childpid > 0)
91     exit (0);
92   setsid ();
93   umask (077);
94   /* close stdout, stdin, stderr */
95   close(0);
96   close(1);
97   close(2);
98
99   #ifdef __linux__ 
100   setpriority(PRIO_PROCESS,(int)getpid(),15); /* ircd sets to low process priority so it doesnt hog the box */
101   #endif
102   
103   return (TRUE);
104 }
105
106
107 /* Make Sure Modules Are Avaliable!
108  * (BugFix By Craig.. See? I do work! :p)
109  * Modified by brain, requires const char*
110  * to work with other API functions
111  */
112
113 bool FileExists (const char* file)
114 {
115   FILE *input;
116   
117   if ((input = fopen (file, "r")) == NULL) { return(false); }
118   else { fclose (input); return(true); }
119 }
120
121
122 bool LoadConf(const char* filename, std::stringstream *target)
123 {
124         target->clear();
125         FILE* conf = fopen(filename,"r");
126         if (!FileExists(filename))
127         {
128                 return false;
129         }
130         char buffer[MAXBUF];
131         if (conf)
132         {
133                 target->clear();
134                 while (!feof(conf))
135                 {
136                         if (fgets(buffer, MAXBUF, conf))
137                         {
138                                 if ((!feof(conf)) && (buffer) && (strlen(buffer)))
139                                 {
140                                         if (buffer[0] != '#')
141                                         {
142                                                 *target << std::string(buffer);
143                                         }
144                                 }
145                         }
146                 }
147                 fclose(conf);
148         }
149         target->seekg(0);
150         return true;
151 }
152
153 /* Counts the number of tags of a certain type within the config file, e.g. to enumerate opers */
154
155 int EnumConf(std::stringstream *config, const char* tag)
156 {
157         int ptr = 0;
158         char buffer[MAXBUF], c_tag[MAXBUF], c, lastc;
159         int in_token, in_quotes, tptr, j, idx = 0;
160         char* key;
161
162         const char* buf = config->str().c_str();
163         long bptr = 0;
164         long len = strlen(buf);
165         
166         ptr = 0;
167         in_token = 0;
168         in_quotes = 0;
169         lastc = '\0';
170         while (bptr<len)
171         {
172                 lastc = c;
173                 c = buf[bptr++];
174                 if ((c == '#') && (lastc == '\n'))
175                 {
176                         while ((c != '\n') && (bptr<len))
177                         {
178                                 lastc = c;
179                                 c = buf[bptr++];
180                         }
181                 }
182                 if ((c == '<') && (!in_quotes))
183                 {
184                         tptr = 0;
185                         in_token = 1;
186                         do {
187                                 c = buf[bptr++];
188                                 if (c != ' ')
189                                 {
190                                         c_tag[tptr++] = c;
191                                         c_tag[tptr] = '\0';
192                                 }
193                         } while (c != ' ');
194                 }
195                 if (c == '"')
196                 {
197                         in_quotes = (!in_quotes);
198                 }
199                 if ((c == '>') && (!in_quotes))
200                 {
201                         in_token = 0;
202                         if (!strcmp(c_tag,tag))
203                         {
204                                 /* correct tag, but wrong index */
205                                 idx++;
206                         }
207                         c_tag[0] = '\0';
208                         buffer[0] = '\0';
209                         ptr = 0;
210                         tptr = 0;
211                 }
212                 if (c != '>')
213                 {
214                         if ((in_token) && (c != '\n') && (c != '\r'))
215                         {
216                                 buffer[ptr++] = c;
217                                 buffer[ptr] = '\0';
218                         }
219                 }
220         }
221         return idx;
222 }
223
224 /* Counts the number of values within a certain tag */
225
226 int EnumValues(std::stringstream *config, const char* tag, int index)
227 {
228         int ptr = 0;
229         char buffer[MAXBUF], c_tag[MAXBUF], c, lastc;
230         int in_token, in_quotes, tptr, j, idx = 0;
231         char* key;
232         
233         bool correct_tag = false;
234         int num_items = 0;
235
236         const char* buf = config->str().c_str();
237         long bptr = 0;
238         long len = strlen(buf);
239         
240         ptr = 0;
241         in_token = 0;
242         in_quotes = 0;
243         lastc = '\0';
244         while (bptr<len)
245         {
246                 lastc = c;
247                 c = buf[bptr++];
248                 if ((c == '#') && (lastc == '\n'))
249                 {
250                         while ((c != '\n') && (bptr<len))
251                         {
252                                 lastc = c;
253                                 c = buf[bptr++];
254                         }
255                 }
256                 if ((c == '<') && (!in_quotes))
257                 {
258                         tptr = 0;
259                         in_token = 1;
260                         do {
261                                 c = buf[bptr++];
262                                 if (c != ' ')
263                                 {
264                                         c_tag[tptr++] = c;
265                                         c_tag[tptr] = '\0';
266                                         
267                                         if ((!strcmp(c_tag,tag)) && (idx == index))
268                                         {
269                                                 correct_tag = true;
270                                         }
271                                 }
272                         } while (c != ' ');
273                 }
274                 if (c == '"')
275                 {
276                         in_quotes = (!in_quotes);
277                 }
278                 
279                 if ( (correct_tag) && (!in_quotes) && ( (c == ' ') || (c == '\n') || (c == '\r') ) )
280                 {
281                         num_items++;
282                 }
283                 if ((c == '>') && (!in_quotes))
284                 {
285                         in_token = 0;
286                         if (correct_tag)
287                                 correct_tag = false;
288                         if (!strcmp(c_tag,tag))
289                         {
290                                 /* correct tag, but wrong index */
291                                 idx++;
292                         }
293                         c_tag[0] = '\0';
294                         buffer[0] = '\0';
295                         ptr = 0;
296                         tptr = 0;
297                 }
298                 if (c != '>')
299                 {
300                         if ((in_token) && (c != '\n') && (c != '\r'))
301                         {
302                                 buffer[ptr++] = c;
303                                 buffer[ptr] = '\0';
304                         }
305                 }
306         }
307         return num_items+1;
308 }
309
310
311
312 int ConfValueEnum(char* tag, std::stringstream* config)
313 {
314         return EnumConf(config,tag);
315 }
316
317
318
319 /* Retrieves a value from the config file. If there is more than one value of the specified
320  * key and section (e.g. for opers etc) then the index value specifies which to retreive, e.g.
321  *
322  * ConfValue("oper","name",2,result);
323  */
324
325 int ReadConf(std::stringstream *config, const char* tag, const char* var, int index, char *result)
326 {
327         int ptr = 0;
328         char buffer[65535], c_tag[MAXBUF], c, lastc;
329         int in_token, in_quotes, tptr, j, idx = 0;
330         char* key;
331
332         const char* buf = config->str().c_str();
333         long bptr = 0;
334         long len = strlen(buf);
335         
336         ptr = 0;
337         in_token = 0;
338         in_quotes = 0;
339         lastc = '\0';
340         c_tag[0] = '\0';
341         buffer[0] = '\0';
342         while (bptr<len)
343         {
344                 lastc = c;
345                 c = buf[bptr++];
346                 // FIX: Treat tabs as spaces
347                 if (c == 9)
348                         c = 32;
349                 if ((c == '<') && (!in_quotes))
350                 {
351                         tptr = 0;
352                         in_token = 1;
353                         do {
354                                 c = buf[bptr++];
355                                 if (c != ' ')
356                                 {
357                                         c_tag[tptr++] = c;
358                                         c_tag[tptr] = '\0';
359                                 }
360                         // FIX: Tab can follow a tagname as well as space.
361                         } while ((c != ' ') && (c != 9));
362                 }
363                 if (c == '"')
364                 {
365                         in_quotes = (!in_quotes);
366                 }
367                 if ((c == '>') && (!in_quotes))
368                 {
369                         in_token = 0;
370                         if (idx == index)
371                         {
372                                 if (!strcmp(c_tag,tag))
373                                 {
374                                         if ((buffer) && (c_tag) && (var))
375                                         {
376                                                 key = strstr(buffer,var);
377                                                 if (!key)
378                                                 {
379                                                         /* value not found in tag */
380                                                         strcpy(result,"");
381                                                         return 0;
382                                                 }
383                                                 else
384                                                 {
385                                                         key+=strlen(var);
386                                                         while (key[0] !='"')
387                                                         {
388                                                                 if (!strlen(key))
389                                                                 {
390                                                                         /* missing quote */
391                                                                         strcpy(result,"");
392                                                                         return 0;
393                                                                 }
394                                                                 key++;
395                                                         }
396                                                         key++;
397                                                         for (j = 0; j < strlen(key); j++)
398                                                         {
399                                                                 if (key[j] == '"')
400                                                                 {
401                                                                         key[j] = '\0';
402                                                                 }
403                                                         }
404                                                         strcpy(result,key);
405                                                         return 1;
406                                                 }
407                                         }
408                                 }
409                         }
410                         if (!strcmp(c_tag,tag))
411                         {
412                                 /* correct tag, but wrong index */
413                                 idx++;
414                         }
415                         c_tag[0] = '\0';
416                         buffer[0] = '\0';
417                         ptr = 0;
418                         tptr = 0;
419                 }
420                 if (c != '>')
421                 {
422                         if ((in_token) && (c != '\n') && (c != '\r'))
423                         {
424                                 buffer[ptr++] = c;
425                                 buffer[ptr] = '\0';
426                         }
427                 }
428         }
429         strcpy(result,""); // value or its tag not found at all
430         return 0;
431 }
432
433
434
435 int ConfValue(char* tag, char* var, int index, char *result,std::stringstream *config)
436 {
437         ReadConf(config, tag, var, index, result);
438         return 0;
439 }
440
441
442
443 /* This will bind a socket to a port. It works for UDP/TCP */
444 int BindSocket (int sockfd, struct sockaddr_in client, struct sockaddr_in server, int port, char* addr)
445 {
446   bzero((char *)&server,sizeof(server));
447   struct in_addr addy;
448   inet_aton(addr,&addy);
449
450   server.sin_family = AF_INET;
451   if (!strcmp(addr,""))
452   {
453           server.sin_addr.s_addr = htonl(INADDR_ANY);
454   }
455   else
456   {
457           server.sin_addr = addy;
458   }
459
460   server.sin_port = htons(port);
461
462   if (bind(sockfd,(struct sockaddr*)&server,sizeof(server))<0)
463   {
464     return(ERROR);
465   }
466   else
467   {
468     listen(sockfd,5);
469     return(TRUE);
470   }
471 }
472
473
474 /* Open a TCP Socket */
475 int OpenTCPSocket (void)
476 {
477   int sockfd;
478   int on = 0;
479   struct linger linger = { 0 };
480   
481   if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
482     return (ERROR);
483   else
484   {
485     setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on));
486     /* This is BSD compatible, setting l_onoff to 0 is *NOT* http://web.irc.org/mla/ircd-dev/msg02259.html */
487     linger.l_onoff = 1;
488     linger.l_linger = 0;
489     setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (const char*)&linger,sizeof(linger));
490     return (sockfd);
491   }
492 }
493