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