fixed statistics
[NeonServV5.git] / src / main.c
1 /* main.c - NeonServ v5.2
2  * Copyright (C) 2011  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "main.h"
19 #include "ClientSocket.h"
20 #include "UserNode.h"
21 #include "ChanNode.h"
22 #include "IRCEvents.h"
23 #include "IRCParser.h"
24 #include "modcmd.h"
25 #include "WHOHandler.h"
26 #include "bots.h"
27 #include "mysqlConn.h"
28 #include "HandleInfoHandler.h"
29 #include "lang.h"
30 #include "tools.h"
31 #include "timeq.h"
32 #include "EventLogger.h"
33 #include "ModeNode.h"
34 #include "IRCQueue.h"
35 #include "DBHelper.h"
36 #include "commands.h"
37 #include "ConfigParser.h"
38
39 time_t start_time;
40 static int running;
41 static int statistics_requested_lusers = 0;
42 int statistics_enabled;
43 TIMEQ_CALLBACK(main_statistics);
44
45 void cleanup() {
46     free_sockets();
47     free_parser();
48     free_UserNode();
49     free_ChanNode();
50     free_bind();
51     free_modcmd();
52     free_whoqueue();
53     free_bots();
54     free_mysql();
55     free_handleinfohandler();
56     free_lang();
57 }
58
59 static int load_mysql_config() {
60     char *mysql_host, *mysql_user, *mysql_pass, *mysql_base;
61     int mysql_serverport;
62     if(loadConfig("neonserv.conf")) {
63         mysql_host = get_string_field("MySQL.host");
64         if(!mysql_host) {
65             perror("invalid neonserv.conf: missing MySQL.host");
66             return 0;
67         }
68         mysql_serverport = get_int_field("MySQL.port");
69         if(!mysql_serverport)
70             mysql_serverport = 3306;
71         mysql_user = get_string_field("MySQL.user");
72         if(!mysql_user) {
73             perror("invalid neonserv.conf: missing MySQL.user");
74             return 0;
75         }
76         mysql_pass = get_string_field("MySQL.pass");
77         if(!mysql_pass) {
78             perror("invalid neonserv.conf: missing MySQL.pass");
79             return 0;
80         }
81         mysql_base = get_string_field("MySQL.base");
82         if(!mysql_base) {
83             perror("invalid neonserv.conf: missing MySQL base");
84             return 0;
85         }
86     } else {
87         perror("Unable to load neonserv.conf");
88         return 0;
89     }
90     init_mysql(mysql_host, mysql_serverport, mysql_user, mysql_pass, mysql_base);
91     return 1;
92 }
93
94 int main(void) {
95 main:
96     
97     start_time = time(0);
98     
99     #ifdef WIN32
100     int res;
101     WSADATA wsadata;
102     // Start Windows Sockets.
103     res = WSAStartup(MAKEWORD(2, 0), &wsadata);
104     if (res)
105     {
106         perror("Unable to start Windows Sockets");
107         return 0;
108     }
109     #endif
110     
111     if(!load_mysql_config()) return 0;
112     
113     statistics_enabled = get_int_field("statistics.enable");
114     
115     queue_init();
116     init_lang();
117     init_parser();
118     init_UserNode();
119     init_ChanNode();
120     init_ModeNode();
121     init_bind();
122         init_modcmd();
123     init_handleinfohandler();
124     init_tools();
125     register_commands();
126     init_bots();
127     init_DBHelper();
128     
129     load_languages();
130     int update_minutes = get_int_field("statistics.frequency");
131     if(!update_minutes) update_minutes = 2;
132     timeq_add(update_minutes * 60 + 10, main_statistics, NULL);
133     
134     time_t socket_wait;
135     running = 1;
136     while(running) {
137         socket_wait = time(0) + SOCKET_SELECT_TIME;
138         do {
139             socket_loop(SOCKET_SELECT_TIME);
140         } while(time(0) < socket_wait);
141         timeq_tick();
142         loop_bots();
143         clearTempUsers();
144         destroyEvents();
145         queue_loop();
146     }
147     cleanup();
148     goto main;
149 }
150
151 int stricmp (const char *s1, const char *s2)
152 {
153    if (s1 == NULL) return s2 == NULL ? 0 : -(*s2);
154    if (s2 == NULL) return *s1;
155    char c1, c2;
156    while ((c1 = tolower (*s1)) == (c2 = tolower (*s2)))
157    {
158      if (*s1 == '\0') break;
159      ++s1; ++s2;
160    }
161    return c1 - c2;
162 }
163
164 int stricmplen (const char *s1, const char *s2, int len)
165 {
166    if (s1 == NULL) return s2 == NULL ? 0 : -(*s2);
167    if (s2 == NULL) return *s1;
168    char c1, c2;
169    int i = 0;
170    while ((c1 = tolower (*s1)) == (c2 = tolower (*s2)))
171    {
172      i++;
173      if (*s1 == '\0') break;
174      ++s1; ++s2;
175      if(i == len) break;
176    }
177    return c1 - c2;
178 }
179
180 void restart_bot(int hard_restart) {
181     running = 0;
182 }
183
184 void stop_bot() {
185     cleanup();
186     exit(0);
187 }
188
189 void reload_config() {
190     loadConfig("neonserv.conf");
191 }
192
193 TIMEQ_CALLBACK(main_statistics) {
194     int update_minutes = get_int_field("statistics.frequency");
195     if(!update_minutes) update_minutes = 2;
196     timeq_add(update_minutes * 60, main_statistics, NULL);
197     if(get_int_field("statistics.enable")) {
198         statistics_enabled = 1;
199         statistics_requested_lusers = 1;
200         if(get_int_field("statistics.include_lusers")) {
201             struct ClientSocket *bot, *lusersbot = NULL;
202             for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
203                 if(bot->flags & SOCKET_FLAG_PREFERRED)
204                     lusersbot = bot;
205             }
206             bot = lusersbot;
207             if(bot == NULL) bot = getBots(SOCKET_FLAG_READY, NULL);
208             putsock(bot, "LUSERS");
209         } else {
210             statistics_update();
211         }
212     } else
213         statistics_enabled = 0;
214 }
215
216 void statistics_update() {
217     if(get_int_field("statistics.enable") && statistics_requested_lusers && get_string_field("statistics.execute")) {
218         statistics_requested_lusers = 0;
219         char command[MAXLEN];
220         /* parameters:
221          - visible users
222          - visible chanusers
223          - visible channels
224          - privmsg per minute
225          - commands per minute
226          - network users
227          - network channels
228         */
229         sprintf(command, "%s %d %d %d %d %d %d %d", get_string_field("statistics.execute"), getUserCount(), getChanUserCount(), getChannelCount(), statistics_privmsg, statistics_commands, statistics_network_users, statistics_network_channels);
230         statistics_privmsg = 0;
231         statistics_commands = 0;
232         system(command);
233     }
234 }