4 * Copyright (C) 2005-2009 Mikael Berthe <mikael@lilotux.net>
5 * Parts of this file come from Cabber <cabber@ajmacias.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or (at
10 * your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29 #include <sys/types.h>
55 static unsigned int terminate_ui
;
56 GMainLoop
*main_loop
= NULL
;
58 static struct termios
*backup_termios
;
60 char *mcabber_version(void)
64 ver
= g_strdup_printf("%s (%s)", PACKAGE_VERSION
, HGCSET
);
66 ver
= g_strdup(PACKAGE_VERSION
);
71 static void mcabber_terminate(const char *msg
)
75 scr_TerminateCurses();
77 // Restore term settings, if needed.
79 tcsetattr(fileno(stdin
), TCSAFLUSH
, backup_termios
);
82 fprintf(stderr
, "%s\n", msg
);
87 void sig_handler(int signum
)
89 if (signum
== SIGCHLD
) {
93 pid
= waitpid (WAIT_ANY
, &status
, WNOHANG
);
94 // Check the exit status value if 'eventcmd_checkstatus' is set
95 if (settings_opt_get_int("eventcmd_checkstatus")) {
97 // exit status 2 -> beep
98 if (WIFEXITED(status
) && WEXITSTATUS(status
) == 2) {
104 signal(SIGCHLD
, sig_handler
);
105 } else if (signum
== SIGTERM
) {
106 mcabber_terminate("Killed by SIGTERM");
107 } else if (signum
== SIGINT
) {
108 mcabber_terminate("Killed by SIGINT");
110 } else if (signum
== SIGWINCH
) {
114 scr_LogPrint(LPRINT_LOGNORM
, "Caught signal: %d", signum
);
118 // ask_password(what)
119 // Return the password, or NULL.
120 // The string must be freed after use.
121 static char *ask_password(const char *what
)
124 size_t passsize
= 128;
125 struct termios orig
, new;
127 password
= g_new0(char, passsize
);
129 /* Turn echoing off and fail if we can't. */
130 if (tcgetattr(fileno(stdin
), &orig
) != 0) return NULL
;
131 backup_termios
= &orig
;
134 new.c_lflag
&= ~ECHO
;
135 if (tcsetattr(fileno(stdin
), TCSAFLUSH
, &new) != 0) return NULL
;
137 /* Read the password. */
138 printf("Please enter %s: ", what
);
139 if (fgets(password
, passsize
, stdin
) == NULL
) return NULL
;
141 /* Restore terminal. */
142 tcsetattr(fileno(stdin
), TCSAFLUSH
, &orig
);
144 backup_termios
= NULL
;
146 for (p
= (char*)password
; *p
; p
++)
148 for ( ; p
> (char*)password
; p
--)
149 if (*p
== '\n' || *p
== '\r') *p
= 0;
154 static void credits(void)
156 const char *v_fmt
= "MCabber %s -- Email: mcabber [at] lilotux [dot] net\n";
157 char *v
= mcabber_version();
159 scr_LogPrint(LPRINT_LOGNORM
|LPRINT_NOTUTF8
, v_fmt
, v
);
163 static void compile_options(void)
165 puts("Installation data directory: " DATA_DIR
"\n");
167 puts("Compiled with unicode support.");
169 #ifdef MODULES_ENABLE
170 puts ("Compiled with modules support.");
173 puts("Compiled with GPG support.");
176 puts("Compiled with OTR support.");
179 puts("Compiled with Enchant support.");
182 puts("Compiled with Aspell support.");
185 puts("Compiled with debugging support.");
189 static void main_init_pgp(void)
193 char *typed_passwd
= NULL
;
195 bool pgp_invalid
= FALSE
;
199 p
= getenv("GPG_AGENT_INFO");
200 pgp_agent
= (p
&& strchr(p
, ':'));
202 pk
= settings_opt_get("pgp_private_key");
203 pp
= settings_opt_get("pgp_passphrase");
205 if (settings_opt_get("pgp_passphrase_retries"))
206 retries
= settings_opt_get_int("pgp_passphrase_retries");
211 scr_LogPrint(LPRINT_LOGNORM
, "WARNING: unknown PGP private key");
213 } else if (!(pp
|| pgp_agent
)) {
214 // Request PGP passphrase
215 pp
= typed_passwd
= ask_password("PGP passphrase");
218 // Erase password from the settings array
220 memset((char*)pp
, 0, strlen(pp
));
222 g_free(typed_passwd
);
224 settings_set(SETTINGS_TYPE_OPTION
, "pgp_passphrase", NULL
);
226 if (!pgp_agent
&& pk
&& pp
&& gpg_test_passphrase()) {
227 // Let's check the pasphrase
229 for (i
= 1; retries
< 0 || i
<= retries
; i
++) {
230 typed_passwd
= ask_password("PGP passphrase"); // Ask again...
232 gpg_set_passphrase(typed_passwd
);
233 memset(typed_passwd
, 0, strlen(typed_passwd
));
234 g_free(typed_passwd
);
236 if (!gpg_test_passphrase())
243 scr_LogPrint(LPRINT_LOGNORM
, "WARNING: PGP key/pass invalid");
244 #else /* not HAVE_GPGME */
245 scr_LogPrint(LPRINT_LOGNORM
, "WARNING: not compiled with PGP support");
246 #endif /* HAVE_GPGME */
249 void mcabber_set_terminate_ui(void)
254 gboolean
mcabber_loop()
259 g_main_loop_quit(main_loop
);
265 while (kcode
.value
!= ERR
) {
270 scr_CheckAutoAway(FALSE
);
279 int main(int argc
, char **argv
)
281 char *configFile
= NULL
;
282 const char *optstring
;
288 signal(SIGTERM
, sig_handler
);
289 signal(SIGINT
, sig_handler
);
290 signal(SIGCHLD
, sig_handler
);
292 signal(SIGWINCH
, sig_handler
);
294 signal(SIGPIPE
, SIG_IGN
);
296 /* Parse command line options */
298 int c
= getopt(argc
, argv
, "hVf:");
305 printf("Usage: %s [-h|-V|-f mcabberrc_file]\n\n", argv
[0]);
306 return (c
== 'h' ? 0 : -1);
311 configFile
= g_strdup(optarg
);
317 fprintf(stderr
, "Usage: %s [-h|-V|-f mcabberrc_file]\n\n", argv
[0]);
321 /* Initialize command system, roster and default key bindings */
327 /* Initialize charset */
328 scr_InitLocaleCharSet();
330 /* Parsing config file... */
331 ret
= cfg_read_file(configFile
, TRUE
);
332 /* free() configFile if it has been allocated during options parsing */
334 /* Leave if there was an error in the config. file */
338 optstring
= settings_opt_get("tracelog_file");
340 ut_InitDebug(settings_opt_get_int("tracelog_level"), optstring
);
342 /* If no password is stored, we ask for it before entering
343 ncurses mode -- unless the username is unknown. */
344 if (settings_opt_get("jid") && !settings_opt_get("password")) {
347 p
= settings_opt_get("server");
349 printf("Server: %s\n", p
);
350 p
= settings_opt_get("jid");
352 printf("User JID: %s\n", p
);
354 pwd
= ask_password("Jabber password");
355 settings_set(SETTINGS_TYPE_OPTION
, "password", pwd
);
359 /* Initialize PGP system
360 We do it before ncurses initialization because we may need to request
362 if (settings_opt_get_int("pgp"))
365 /* Initialize N-Curses */
366 scr_LogPrint(LPRINT_DEBUG
, "Initializing N-Curses...");
368 scr_DrawMainWindow(TRUE
);
370 optval
= (settings_opt_get_int("logging") > 0);
371 optval2
= (settings_opt_get_int("load_logs") > 0);
372 if (optval
|| optval2
)
373 hlog_enable(optval
, settings_opt_get("logging_dir"), optval2
);
375 #if defined(WITH_ENCHANT) || defined(WITH_ASPELL)
376 /* Initialize spelling */
377 if (settings_opt_get_int("spell_enable")) {
382 optstring
= settings_opt_get("events_command");
384 hk_ext_cmd_init(optstring
);
386 optstring
= settings_opt_get("roster_display_filter");
388 scr_RosterDisplay(optstring
);
389 // Empty filter isn't allowed...
390 if (!buddylist_get_filter())
391 scr_RosterDisplay("*");
393 chatstates_disabled
= settings_opt_get_int("disable_chatstates");
395 /* Initialize FIFO named pipe */
396 fifo_init(settings_opt_get("fifo_name"));
398 /* Load previous roster state */
401 main_loop
= g_main_loop_new(NULL
, TRUE
);
404 scr_LogPrint(LPRINT_NORMAL
, "No configuration file has been found.");
405 scr_ShowBuddyWindow();
411 scr_LogPrint(LPRINT_DEBUG
, "Entering into main loop...");
413 g_timeout_add(10, mcabber_loop
, NULL
);
414 g_main_loop_run(main_loop
);
416 scr_TerminateCurses();
417 #ifdef MODULES_ENABLE
428 #if defined(WITH_ENCHANT) || defined(WITH_ASPELL)
429 /* Deinitialize spelling */
430 if (settings_opt_get_int("spell_enable"))
433 /* Save pending message state */
437 printf("\n\nThanks for using mcabber!\n");
442 /* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */