Merge Irssi 0.8.16-rc1
[silc.git] / apps / irssi / src / core / core.c
1 /*
2  core.c : irssi
3
4     Copyright (C) 1999-2000 Timo Sirainen
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License along
17     with this program; if not, write to the Free Software Foundation, Inc.,
18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "module.h"
22 #include <signal.h>
23
24 #include "args.h"
25 #include "pidwait.h"
26 #include "misc.h"
27
28 #include "net-disconnect.h"
29 #include "signals.h"
30 #include "settings.h"
31 #include "session.h"
32
33 #include "chat-protocols.h"
34 #include "servers.h"
35 #include "chatnets.h"
36 #include "commands.h"
37 #include "expandos.h"
38 #include "write-buffer.h"
39 #include "log.h"
40 #include "rawlog.h"
41 #include "ignore.h"
42 #include "recode.h"
43
44 #include "channels.h"
45 #include "queries.h"
46 #include "nicklist.h"
47 #include "nickmatch-cache.h"
48
49 #ifdef HAVE_SYS_RESOURCE_H
50 #  include <sys/resource.h>
51    static struct rlimit orig_core_rlimit;
52 #endif
53
54 void chat_commands_init(void);
55 void chat_commands_deinit(void);
56
57 void log_away_init(void);
58 void log_away_deinit(void);
59
60 int irssi_gui;
61 int irssi_init_finished;
62 int reload_config;
63 time_t client_start_time;
64
65 static char *irssi_dir, *irssi_config_file;
66 static GSList *dialog_type_queue, *dialog_text_queue;
67
68 const char *get_irssi_dir(void)
69 {
70         return irssi_dir;
71 }
72
73 /* return full path for ~/.irssi/config */
74 const char *get_irssi_config(void)
75 {
76         return irssi_config_file;
77 }
78
79 static void sig_reload_config(int signo)
80 {
81         reload_config = TRUE;
82 }
83
84 static void read_settings(void)
85 {
86 #ifndef WIN32
87         static int signals[] = {
88                 SIGINT, SIGQUIT, SIGTERM,
89                 SIGALRM, SIGUSR1, SIGUSR2
90         };
91         static char *signames[] = {
92                 "int", "quit", "term",
93                 "alrm", "usr1", "usr2"
94         };
95
96         const char *ignores;
97         struct sigaction act;
98         int n;
99
100         ignores = settings_get_str("ignore_signals");
101
102         sigemptyset (&act.sa_mask);
103         act.sa_flags = 0;
104
105         /* reload config on SIGHUP */
106         act.sa_handler = sig_reload_config;
107         sigaction(SIGHUP, &act, NULL);
108
109         for (n = 0; n < sizeof(signals)/sizeof(signals[0]); n++) {
110                 act.sa_handler = find_substr(ignores, signames[n]) ?
111                         SIG_IGN : SIG_DFL;
112                 sigaction(signals[n], &act, NULL);
113         }
114
115 #ifdef HAVE_SYS_RESOURCE_H
116         if (!settings_get_bool("override_coredump_limit"))
117                 setrlimit(RLIMIT_CORE, &orig_core_rlimit);
118         else {
119                 struct rlimit rlimit;
120
121                 rlimit.rlim_cur = RLIM_INFINITY;
122                 rlimit.rlim_max = RLIM_INFINITY;
123                 if (setrlimit(RLIMIT_CORE, &rlimit) == -1)
124                         settings_set_bool("override_coredump_limit", FALSE);
125         }
126 #endif
127 #endif
128 }
129
130 static void sig_gui_dialog(const char *type, const char *text)
131 {
132         dialog_type_queue = g_slist_append(dialog_type_queue, g_strdup(type));
133         dialog_text_queue = g_slist_append(dialog_text_queue, g_strdup(text));
134 }
135
136 static void sig_init_finished(void)
137 {
138         GSList *type, *text;
139
140         signal_remove("gui dialog", (SIGNAL_FUNC) sig_gui_dialog);
141         signal_remove("irssi init finished", (SIGNAL_FUNC) sig_init_finished);
142
143         /* send the dialog texts that were in queue before irssi
144            was initialized */
145         type = dialog_type_queue;
146         text = dialog_text_queue;
147         for (; text != NULL; text = text->next, type = type->next) {
148                 signal_emit("gui dialog", 2, type->data, text->data);
149                 g_free(type->data);
150                 g_free(text->data);
151         }
152         g_slist_free(dialog_type_queue);
153         g_slist_free(dialog_text_queue);
154 }
155
156 static char *fix_path(const char *str)
157 {
158         char *new_str = convert_home(str);
159         if (!g_path_is_absolute(new_str)) {
160                 char *tmp_str = new_str;
161                 new_str = g_strdup_printf("%s/%s", g_get_current_dir(), tmp_str);
162                 g_free(tmp_str);
163         }
164         return new_str;
165 }
166
167 void core_register_options(void)
168 {
169         static GOptionEntry options[] = {
170                 { "config", 0, 0, G_OPTION_ARG_STRING, &irssi_config_file, "Configuration file location (~/.irssi/config)", "PATH" },
171                 { "home", 0, 0, G_OPTION_ARG_STRING, &irssi_dir, "Irssi home dir location (~/.irssi)", "PATH" },
172                 { NULL }
173         };
174
175         args_register(options);
176         session_register_options();
177 }
178
179 void core_preinit(const char *path)
180 {
181         const char *home;
182         char *str;
183         int len;
184
185         if (irssi_dir == NULL) {
186                 home = g_get_home_dir();
187                 if (home == NULL)
188                         home = ".";
189
190                 irssi_dir = g_strdup_printf(IRSSI_DIR_FULL, home);
191         } else {
192                 str = irssi_dir;
193                 irssi_dir = fix_path(str);
194                 g_free(str);
195                 len = strlen(irssi_dir);
196                 if (irssi_dir[len-1] == G_DIR_SEPARATOR)
197                         irssi_dir[len-1] = '\0';
198         }
199         if (irssi_config_file == NULL)
200                 irssi_config_file = g_strdup_printf("%s/"IRSSI_HOME_CONFIG, irssi_dir);
201         else {
202                 str = irssi_config_file;
203                 irssi_config_file = fix_path(str);
204                 g_free(str);
205         }
206
207         session_set_binary(path);
208 }
209
210 static void sig_irssi_init_finished(void)
211 {
212         irssi_init_finished = TRUE;
213 }
214
215 void core_init(void)
216 {
217         dialog_type_queue = NULL;
218         dialog_text_queue = NULL;
219         client_start_time = time(NULL);
220
221         modules_init();
222 #ifndef WIN32
223         pidwait_init();
224 #endif
225
226         net_disconnect_init();
227         signals_init();
228
229         signal_add_first("gui dialog", (SIGNAL_FUNC) sig_gui_dialog);
230         signal_add_first("irssi init finished", (SIGNAL_FUNC) sig_init_finished);
231
232         settings_init();
233         commands_init();
234         nickmatch_cache_init();
235         session_init();
236
237         chat_protocols_init();
238         chatnets_init();
239         expandos_init();
240         ignore_init();
241         servers_init();
242         write_buffer_init();
243         log_init();
244         log_away_init();
245         rawlog_init();
246         recode_init();
247
248         channels_init();
249         queries_init();
250         nicklist_init();
251
252         chat_commands_init();
253
254         settings_add_str("misc", "ignore_signals", "");
255         settings_add_bool("misc", "override_coredump_limit", FALSE);
256
257 #ifdef HAVE_SYS_RESOURCE_H
258         getrlimit(RLIMIT_CORE, &orig_core_rlimit);
259 #endif
260         read_settings();
261         signal_add("setup changed", (SIGNAL_FUNC) read_settings);
262         signal_add("irssi init finished", (SIGNAL_FUNC) sig_irssi_init_finished);
263
264         settings_check();
265
266         module_register("core", "core");
267 }
268
269 void core_deinit(void)
270 {
271         module_uniq_destroy("WINDOW ITEM TYPE");
272
273         signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
274         signal_remove("irssi init finished", (SIGNAL_FUNC) sig_irssi_init_finished);
275
276         chat_commands_deinit();
277
278         nicklist_deinit();
279         queries_deinit();
280         channels_deinit();
281
282         recode_deinit();
283         rawlog_deinit();
284         log_away_deinit();
285         log_deinit();
286         write_buffer_deinit();
287         servers_deinit();
288         ignore_deinit();
289         expandos_deinit();
290         chatnets_deinit();
291         chat_protocols_deinit();
292
293         session_deinit();
294         nickmatch_cache_deinit();
295         commands_deinit();
296         settings_deinit();
297         signals_deinit();
298         net_disconnect_deinit();
299
300 #ifndef WIN32
301         pidwait_deinit();
302 #endif
303         modules_deinit();
304
305         g_free(irssi_dir);
306         g_free(irssi_config_file);
307 }