remove src/main.h file
[midnight-commander.git] / src / main.c
blobc3a821008c893c019a37a3a8bdfa276afe6846df
1 /*
2 Main program for the Midnight Commander
4 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5 2003, 2004, 2005, 2006, 2007, 2009, 2011
6 The Free Software Foundation, Inc.
8 Written by:
9 Miguel de Icaza, 1994, 1995, 1996, 1997
10 Janne Kukonlehto, 1994, 1995
11 Norbert Warmuth, 1997
13 This file is part of the Midnight Commander.
15 The Midnight Commander is free software: you can redistribute it
16 and/or modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation, either version 3 of the License,
18 or (at your option) any later version.
20 The Midnight Commander is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 /** \file main.c
30 * \brief Source: this is a main module
33 #include <config.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <locale.h>
38 #include <pwd.h> /* for username in xterm title */
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <sys/wait.h>
43 #include <signal.h>
45 #include "lib/global.h"
47 #include "lib/event.h"
48 #include "lib/tty/tty.h"
49 #include "lib/tty/key.h" /* For init_key() */
50 #include "lib/skin.h"
51 #include "lib/filehighlight.h"
52 #include "lib/fileloc.h"
53 #include "lib/strutil.h"
54 #include "lib/util.h"
55 #include "lib/vfs/vfs.h" /* vfs_init(), vfs_shut() */
57 #include "filemanager/midnight.h" /* current_panel */
58 #include "filemanager/treestore.h" /* tree_store_save */
59 #include "filemanager/layout.h" /* command_prompt */
60 #include "filemanager/ext.h" /* flush_extension_file() */
61 #include "filemanager/command.h" /* cmdline */
62 #include "filemanager/panel.h" /* panalized_panel */
64 #include "vfs/plugins_init.h"
66 #include "events_init.h"
67 #include "args.h"
68 #include "subshell.h"
69 #include "setup.h" /* load_setup() */
71 #ifdef HAVE_CHARSET
72 #include "lib/charsets.h"
73 #include "selcodepage.h"
74 #endif /* HAVE_CHARSET */
76 #include "consaver/cons.saver.h" /* cons_saver_pid */
78 /*** global variables ****************************************************************************/
80 /*** file scope macro definitions ****************************************************************/
82 /*** file scope type declarations ****************************************************************/
84 /*** file scope variables ************************************************************************/
86 /*** file scope functions ************************************************************************/
87 /* --------------------------------------------------------------------------------------------- */
89 static void
90 check_codeset (void)
92 const char *current_system_codepage = NULL;
94 current_system_codepage = str_detect_termencoding ();
96 #ifdef HAVE_CHARSET
98 const char *_display_codepage;
100 _display_codepage = get_codepage_id (mc_global.display_codepage);
102 if (strcmp (_display_codepage, current_system_codepage) != 0)
104 mc_global.display_codepage = get_codepage_index (current_system_codepage);
105 if (mc_global.display_codepage == -1)
106 mc_global.display_codepage = 0;
108 mc_config_set_string (mc_main_config, CONFIG_MISC_SECTION, "display_codepage",
109 cp_display);
112 #endif
114 mc_global.utf8_display = str_isutf8 (current_system_codepage);
117 /* --------------------------------------------------------------------------------------------- */
119 /** POSIX version. The only version we support. */
120 static void
121 OS_Setup (void)
123 const char *shell_env;
124 const char *datadir_env;
126 shell_env = getenv ("SHELL");
127 if ((shell_env == NULL) || (shell_env[0] == '\0'))
129 struct passwd *pwd;
130 pwd = getpwuid (geteuid ());
131 if (pwd != NULL)
132 shell = g_strdup (pwd->pw_shell);
134 else
135 shell = g_strdup (shell_env);
137 if ((shell == NULL) || (shell[0] == '\0'))
139 g_free (shell);
140 shell = g_strdup ("/bin/sh");
143 /* This is the directory, where MC was installed, on Unix this is DATADIR */
144 /* and can be overriden by the MC_DATADIR environment variable */
145 datadir_env = g_getenv ("MC_DATADIR");
146 if (datadir_env != NULL)
147 mc_global.sysconfig_dir = g_strdup (datadir_env);
148 else
149 mc_global.sysconfig_dir = g_strdup (SYSCONFDIR);
151 mc_global.share_data_dir = g_strdup (DATADIR);
153 /* Set up temporary directory */
154 mc_tmpdir ();
157 /* --------------------------------------------------------------------------------------------- */
159 static void
160 sigchld_handler_no_subshell (int sig)
162 #ifdef __linux__
163 int pid, status;
165 if (!mc_global.tty.console_flag != '\0')
166 return;
168 /* COMMENT: if it were true that after the call to handle_console(..INIT)
169 the value of mc_global.tty.console_flag never changed, we could simply not install
170 this handler at all if (!mc_global.tty.console_flag && !mc_global.tty.use_subshell). */
172 /* That comment is no longer true. We need to wait() on a sigchld
173 handler (that's at least what the tarfs code expects currently). */
175 pid = waitpid (cons_saver_pid, &status, WUNTRACED | WNOHANG);
177 if (pid == cons_saver_pid)
180 if (WIFSTOPPED (status))
182 /* Someone has stopped cons.saver - restart it */
183 kill (pid, SIGCONT);
185 else
187 /* cons.saver has died - disable console saving */
188 handle_console (CONSOLE_DONE);
189 mc_global.tty.console_flag = '\0';
192 /* If we got here, some other child exited; ignore it */
193 #endif /* __linux__ */
195 (void) sig;
198 /* --------------------------------------------------------------------------------------------- */
200 static void
201 init_sigchld (void)
203 struct sigaction sigchld_action;
205 sigchld_action.sa_handler =
206 #ifdef HAVE_SUBSHELL_SUPPORT
207 mc_global.tty.use_subshell ? sigchld_handler :
208 #endif /* HAVE_SUBSHELL_SUPPORT */
209 sigchld_handler_no_subshell;
211 sigemptyset (&sigchld_action.sa_mask);
213 #ifdef SA_RESTART
214 sigchld_action.sa_flags = SA_RESTART;
215 #else
216 sigchld_action.sa_flags = 0;
217 #endif /* !SA_RESTART */
219 if (sigaction (SIGCHLD, &sigchld_action, NULL) == -1)
221 #ifdef HAVE_SUBSHELL_SUPPORT
223 * This may happen on QNX Neutrino 6, where SA_RESTART
224 * is defined but not implemented. Fallback to no subshell.
226 mc_global.tty.use_subshell = FALSE;
227 #endif /* HAVE_SUBSHELL_SUPPORT */
231 /* --------------------------------------------------------------------------------------------- */
232 /*** public functions ****************************************************************************/
233 /* --------------------------------------------------------------------------------------------- */
236 main (int argc, char *argv[])
238 GError *error = NULL;
239 int exit_code = EXIT_FAILURE;
241 /* We had LC_CTYPE before, LC_ALL includs LC_TYPE as well */
242 #ifdef HAVE_SETLOCALE
243 (void) setlocale (LC_ALL, "");
244 #endif
245 (void) bindtextdomain (PACKAGE, LOCALEDIR);
246 (void) textdomain (PACKAGE);
248 /* do this before args parsing */
249 str_init_strings (NULL);
251 if (!mc_args_parse (&argc, &argv, "mc", &error))
253 startup_exit_falure:
254 fprintf (stderr, _("Failed to run:\n%s\n"), error->message);
255 g_error_free (error);
256 g_free (shell);
257 startup_exit_ok:
258 str_uninit_strings ();
259 return exit_code;
262 /* do this before mc_args_show_info () to view paths in the --datadir-info output */
263 OS_Setup ();
265 if (!g_path_is_absolute (mc_config_get_home_dir ()))
267 error = g_error_new (MC_ERROR, 0, "%s: %s", _("Home directory path is not absolute"),
268 mc_config_get_home_dir ());
269 mc_event_deinit (NULL);
270 goto startup_exit_falure;
273 if (!mc_args_show_info ())
275 exit_code = EXIT_SUCCESS;
276 goto startup_exit_ok;
279 if (!events_init (&error))
280 goto startup_exit_falure;
282 mc_config_init_config_paths (&error);
283 if (error == NULL && mc_config_deprecated_dir_present ())
284 mc_config_migrate_from_old_place (&error);
285 if (error != NULL)
287 mc_event_deinit (NULL);
288 goto startup_exit_falure;
291 vfs_init ();
292 vfs_plugins_init ();
293 vfs_setup_work_dir ();
295 /* do this after vfs initialization due to mc_setctl() call in mc_setup_by_args() */
296 if (!mc_setup_by_args (argc, argv, &error))
298 vfs_shut ();
299 mc_event_deinit (NULL);
300 goto startup_exit_falure;
303 /* check terminal type
304 * $TEMR must be set and not empty
305 * mc_global.tty.xterm_flag is used in init_key() and tty_init()
306 * Do this after mc_args_handle() where mc_args__force_xterm is set up.
308 mc_global.tty.xterm_flag = tty_check_term (mc_args__force_xterm);
310 /* NOTE: This has to be called before tty_init or whatever routine
311 calls any define_sequence */
312 init_key ();
314 /* Must be done before installing the SIGCHLD handler [[FIXME]] */
315 handle_console (CONSOLE_INIT);
317 #ifdef HAVE_SUBSHELL_SUPPORT
318 /* Don't use subshell when invoked as viewer or editor */
319 if (mc_global.mc_run_mode != MC_RUN_FULL)
320 mc_global.tty.use_subshell = FALSE;
322 if (mc_global.tty.use_subshell)
323 subshell_get_console_attributes ();
324 #endif /* HAVE_SUBSHELL_SUPPORT */
326 /* Install the SIGCHLD handler; must be done before init_subshell() */
327 init_sigchld ();
329 /* We need this, since ncurses endwin () doesn't restore the signals */
330 save_stop_handler ();
332 /* Must be done before init_subshell, to set up the terminal size: */
333 /* FIXME: Should be removed and LINES and COLS computed on subshell */
334 tty_init (!mc_args__nomouse, mc_global.tty.xterm_flag);
336 load_setup ();
338 /* start check mc_global.display_codepage and mc_global.source_codepage */
339 check_codeset ();
341 /* Removing this from the X code let's us type C-c */
342 load_key_defs ();
344 load_keymap_defs (!mc_args__nokeymap);
346 macros_list = g_array_new (TRUE, FALSE, sizeof (macros_t));
348 tty_init_colors (mc_global.tty.disable_colors, mc_args__force_colors);
350 mc_skin_init (&error);
351 if (error != NULL)
353 message (D_ERROR, _("Warning"), "%s", error->message);
354 g_error_free (error);
355 error = NULL;
358 mc_filehighlight = mc_fhl_new (TRUE);
359 dlg_set_default_colors ();
361 #ifdef HAVE_SUBSHELL_SUPPORT
362 /* Done here to ensure that the subshell doesn't */
363 /* inherit the file descriptors opened below, etc */
364 if (mc_global.tty.use_subshell)
365 init_subshell ();
367 #endif /* HAVE_SUBSHELL_SUPPORT */
369 /* Also done after init_subshell, to save any shell init file messages */
370 if (mc_global.tty.console_flag != '\0')
371 handle_console (CONSOLE_SAVE);
373 if (mc_global.tty.alternate_plus_minus)
374 application_keypad_mode ();
376 #ifdef HAVE_SUBSHELL_SUPPORT
377 if (mc_global.tty.use_subshell)
379 mc_prompt = strip_ctrl_codes (subshell_prompt);
380 if (mc_prompt == NULL)
381 mc_prompt = (geteuid () == 0) ? "# " : "$ ";
383 else
384 #endif /* HAVE_SUBSHELL_SUPPORT */
385 mc_prompt = (geteuid () == 0) ? "# " : "$ ";
387 /* Program main loop */
388 if (mc_global.midnight_shutdown)
389 exit_code = EXIT_SUCCESS;
390 else
391 exit_code = do_nc ()? EXIT_SUCCESS : EXIT_FAILURE;
393 /* Save the tree store */
394 (void) tree_store_save ();
396 free_keymap_defs ();
398 /* Virtual File System shutdown */
399 vfs_shut ();
401 flush_extension_file (); /* does only free memory */
403 mc_fhl_free (&mc_filehighlight);
404 mc_skin_deinit ();
405 tty_colors_done ();
407 tty_shutdown ();
409 done_setup ();
411 if (mc_global.tty.console_flag != '\0' && (quit & SUBSHELL_EXIT) == 0)
412 handle_console (CONSOLE_RESTORE);
413 if (mc_global.tty.alternate_plus_minus)
414 numeric_keypad_mode ();
416 (void) signal (SIGCHLD, SIG_DFL); /* Disable the SIGCHLD handler */
418 if (mc_global.tty.console_flag != '\0')
419 handle_console (CONSOLE_DONE);
421 if (mc_global.mc_run_mode == MC_RUN_FULL && mc_args__last_wd_file != NULL
422 && last_wd_string != NULL && !print_last_revert)
424 int last_wd_fd;
426 last_wd_fd = open (mc_args__last_wd_file, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
427 S_IRUSR | S_IWUSR);
428 if (last_wd_fd != -1)
430 ssize_t ret1;
431 int ret2;
432 ret1 = write (last_wd_fd, last_wd_string, strlen (last_wd_string));
433 ret2 = close (last_wd_fd);
436 g_free (last_wd_string);
438 g_free (shell);
440 done_key ();
442 if (macros_list != NULL)
444 guint i;
445 macros_t *macros;
446 for (i = 0; i < macros_list->len; i++)
448 macros = &g_array_index (macros_list, struct macros_t, i);
449 if (macros != NULL && macros->macro != NULL)
450 (void) g_array_free (macros->macro, FALSE);
452 (void) g_array_free (macros_list, TRUE);
455 str_uninit_strings ();
457 if (mc_global.mc_run_mode != MC_RUN_EDITOR)
458 g_free (mc_run_param0);
459 else
461 g_list_foreach ((GList *) mc_run_param0, (GFunc) mcedit_arg_free, NULL);
462 g_list_free ((GList *) mc_run_param0);
464 g_free (mc_run_param1);
466 mc_config_deinit_config_paths ();
468 (void) mc_event_deinit (&error);
469 if (error != NULL)
471 fprintf (stderr, _("\nFailed while close:\n%s\n"), error->message);
472 g_error_free (error);
473 exit_code = EXIT_FAILURE;
476 (void) putchar ('\n'); /* Hack to make shell's prompt start at left of screen */
478 return exit_code;
481 /* --------------------------------------------------------------------------------------------- */