Init file highlighting only in full mode.
[midnight-commander.git] / src / main.c
blobc25d72e1a598536559aca66174450b07a546ad7b
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 #ifdef ENABLE_SUBSHELL
69 #include "subshell.h"
70 #endif
71 #include "setup.h" /* load_setup() */
73 #ifdef HAVE_CHARSET
74 #include "lib/charsets.h"
75 #include "selcodepage.h"
76 #endif /* HAVE_CHARSET */
78 #include "consaver/cons.saver.h" /* cons_saver_pid */
80 /*** global variables ****************************************************************************/
82 /*** file scope macro definitions ****************************************************************/
84 /*** file scope type declarations ****************************************************************/
86 /*** file scope variables ************************************************************************/
88 /*** file scope functions ************************************************************************/
89 /* --------------------------------------------------------------------------------------------- */
91 static void
92 check_codeset (void)
94 const char *current_system_codepage = NULL;
96 current_system_codepage = str_detect_termencoding ();
98 #ifdef HAVE_CHARSET
100 const char *_display_codepage;
102 _display_codepage = get_codepage_id (mc_global.display_codepage);
104 if (strcmp (_display_codepage, current_system_codepage) != 0)
106 mc_global.display_codepage = get_codepage_index (current_system_codepage);
107 if (mc_global.display_codepage == -1)
108 mc_global.display_codepage = 0;
110 mc_config_set_string (mc_main_config, CONFIG_MISC_SECTION, "display_codepage",
111 cp_display);
114 #endif
116 mc_global.utf8_display = str_isutf8 (current_system_codepage);
119 /* --------------------------------------------------------------------------------------------- */
121 /** POSIX version. The only version we support. */
122 static void
123 OS_Setup (void)
125 const char *shell_env;
126 const char *datadir_env;
128 shell_env = getenv ("SHELL");
129 if ((shell_env == NULL) || (shell_env[0] == '\0'))
131 struct passwd *pwd;
132 pwd = getpwuid (geteuid ());
133 if (pwd != NULL)
134 shell = g_strdup (pwd->pw_shell);
136 else
137 shell = g_strdup (shell_env);
139 if ((shell == NULL) || (shell[0] == '\0'))
141 g_free (shell);
142 shell = g_strdup ("/bin/sh");
145 /* This is the directory, where MC was installed, on Unix this is DATADIR */
146 /* and can be overriden by the MC_DATADIR environment variable */
147 datadir_env = g_getenv ("MC_DATADIR");
148 if (datadir_env != NULL)
149 mc_global.sysconfig_dir = g_strdup (datadir_env);
150 else
151 mc_global.sysconfig_dir = g_strdup (SYSCONFDIR);
153 mc_global.share_data_dir = g_strdup (DATADIR);
155 /* Set up temporary directory */
156 mc_tmpdir ();
159 /* --------------------------------------------------------------------------------------------- */
161 static void
162 sigchld_handler_no_subshell (int sig)
164 #ifdef __linux__
165 int pid, status;
167 if (!mc_global.tty.console_flag != '\0')
168 return;
170 /* COMMENT: if it were true that after the call to handle_console(..INIT)
171 the value of mc_global.tty.console_flag never changed, we could simply not install
172 this handler at all if (!mc_global.tty.console_flag && !mc_global.tty.use_subshell). */
174 /* That comment is no longer true. We need to wait() on a sigchld
175 handler (that's at least what the tarfs code expects currently). */
177 pid = waitpid (cons_saver_pid, &status, WUNTRACED | WNOHANG);
179 if (pid == cons_saver_pid)
182 if (WIFSTOPPED (status))
184 /* Someone has stopped cons.saver - restart it */
185 kill (pid, SIGCONT);
187 else
189 /* cons.saver has died - disable console saving */
190 handle_console (CONSOLE_DONE);
191 mc_global.tty.console_flag = '\0';
194 /* If we got here, some other child exited; ignore it */
195 #endif /* __linux__ */
197 (void) sig;
200 /* --------------------------------------------------------------------------------------------- */
202 static void
203 init_sigchld (void)
205 struct sigaction sigchld_action;
207 sigchld_action.sa_handler =
208 #ifdef ENABLE_SUBSHELL
209 mc_global.tty.use_subshell ? sigchld_handler :
210 #endif /* ENABLE_SUBSHELL */
211 sigchld_handler_no_subshell;
213 sigemptyset (&sigchld_action.sa_mask);
215 #ifdef SA_RESTART
216 sigchld_action.sa_flags = SA_RESTART;
217 #else
218 sigchld_action.sa_flags = 0;
219 #endif /* !SA_RESTART */
221 if (sigaction (SIGCHLD, &sigchld_action, NULL) == -1)
223 #ifdef ENABLE_SUBSHELL
225 * This may happen on QNX Neutrino 6, where SA_RESTART
226 * is defined but not implemented. Fallback to no subshell.
228 mc_global.tty.use_subshell = FALSE;
229 #endif /* ENABLE_SUBSHELL */
233 /* --------------------------------------------------------------------------------------------- */
234 /*** public functions ****************************************************************************/
235 /* --------------------------------------------------------------------------------------------- */
238 main (int argc, char *argv[])
240 GError *error = NULL;
241 int exit_code = EXIT_FAILURE;
243 /* We had LC_CTYPE before, LC_ALL includs LC_TYPE as well */
244 #ifdef HAVE_SETLOCALE
245 (void) setlocale (LC_ALL, "");
246 #endif
247 (void) bindtextdomain (PACKAGE, LOCALEDIR);
248 (void) textdomain (PACKAGE);
250 /* do this before args parsing */
251 str_init_strings (NULL);
253 if (!mc_args_parse (&argc, &argv, "mc", &error))
255 startup_exit_falure:
256 fprintf (stderr, _("Failed to run:\n%s\n"), error->message);
257 g_error_free (error);
258 g_free (shell);
259 startup_exit_ok:
260 str_uninit_strings ();
261 return exit_code;
264 /* do this before mc_args_show_info () to view paths in the --datadir-info output */
265 OS_Setup ();
267 if (!g_path_is_absolute (mc_config_get_home_dir ()))
269 error = g_error_new (MC_ERROR, 0, "%s: %s", _("Home directory path is not absolute"),
270 mc_config_get_home_dir ());
271 mc_event_deinit (NULL);
272 goto startup_exit_falure;
275 if (!mc_args_show_info ())
277 exit_code = EXIT_SUCCESS;
278 goto startup_exit_ok;
281 if (!events_init (&error))
282 goto startup_exit_falure;
284 mc_config_init_config_paths (&error);
285 if (error == NULL && mc_config_deprecated_dir_present ())
286 mc_config_migrate_from_old_place (&error);
287 if (error != NULL)
289 mc_event_deinit (NULL);
290 goto startup_exit_falure;
293 vfs_init ();
294 vfs_plugins_init ();
295 vfs_setup_work_dir ();
297 /* do this after vfs initialization due to mc_setctl() call in mc_setup_by_args() */
298 if (!mc_setup_by_args (argc, argv, &error))
300 vfs_shut ();
301 mc_event_deinit (NULL);
302 goto startup_exit_falure;
305 /* check terminal type
306 * $TEMR must be set and not empty
307 * mc_global.tty.xterm_flag is used in init_key() and tty_init()
308 * Do this after mc_args_handle() where mc_args__force_xterm is set up.
310 mc_global.tty.xterm_flag = tty_check_term (mc_args__force_xterm);
312 /* NOTE: This has to be called before tty_init or whatever routine
313 calls any define_sequence */
314 init_key ();
316 /* Must be done before installing the SIGCHLD handler [[FIXME]] */
317 handle_console (CONSOLE_INIT);
319 #ifdef ENABLE_SUBSHELL
320 /* Don't use subshell when invoked as viewer or editor */
321 if (mc_global.mc_run_mode != MC_RUN_FULL)
322 mc_global.tty.use_subshell = FALSE;
324 if (mc_global.tty.use_subshell)
325 subshell_get_console_attributes ();
326 #endif /* ENABLE_SUBSHELL */
328 /* Install the SIGCHLD handler; must be done before init_subshell() */
329 init_sigchld ();
331 /* We need this, since ncurses endwin () doesn't restore the signals */
332 save_stop_handler ();
334 /* Must be done before init_subshell, to set up the terminal size: */
335 /* FIXME: Should be removed and LINES and COLS computed on subshell */
336 tty_init (!mc_args__nomouse, mc_global.tty.xterm_flag);
338 load_setup ();
340 /* start check mc_global.display_codepage and mc_global.source_codepage */
341 check_codeset ();
343 /* Removing this from the X code let's us type C-c */
344 load_key_defs ();
346 load_keymap_defs (!mc_args__nokeymap);
348 macros_list = g_array_new (TRUE, FALSE, sizeof (macros_t));
350 tty_init_colors (mc_global.tty.disable_colors, mc_args__force_colors);
352 mc_skin_init (&error);
353 if (error != NULL)
355 message (D_ERROR, _("Warning"), "%s", error->message);
356 g_error_free (error);
357 error = NULL;
360 dlg_set_default_colors ();
362 #ifdef ENABLE_SUBSHELL
363 /* Done here to ensure that the subshell doesn't */
364 /* inherit the file descriptors opened below, etc */
365 if (mc_global.tty.use_subshell)
366 init_subshell ();
368 #endif /* ENABLE_SUBSHELL */
370 /* Also done after init_subshell, to save any shell init file messages */
371 if (mc_global.tty.console_flag != '\0')
372 handle_console (CONSOLE_SAVE);
374 if (mc_global.tty.alternate_plus_minus)
375 application_keypad_mode ();
377 #ifdef ENABLE_SUBSHELL
378 if (mc_global.tty.use_subshell)
380 mc_prompt = strip_ctrl_codes (subshell_prompt);
381 if (mc_prompt == NULL)
382 mc_prompt = (geteuid () == 0) ? "# " : "$ ";
384 else
385 #endif /* ENABLE_SUBSHELL */
386 mc_prompt = (geteuid () == 0) ? "# " : "$ ";
388 /* Program main loop */
389 if (mc_global.midnight_shutdown)
390 exit_code = EXIT_SUCCESS;
391 else
392 exit_code = do_nc ()? EXIT_SUCCESS : EXIT_FAILURE;
394 /* Save the tree store */
395 (void) tree_store_save ();
397 free_keymap_defs ();
399 /* Virtual File System shutdown */
400 vfs_shut ();
402 flush_extension_file (); /* does only free memory */
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 /* --------------------------------------------------------------------------------------------- */