Mercurial > octave-nkf
diff src/main.in.cc @ 17778:b5d58667d32d
new main program wrapper to handle giving up controlling tty
* octave-gui.cc (octave_cli_thread): New class, from QtHandles.
(dissociate_terminal): Delete.
(octave_start_gui): Third arg is now START_GUI instead of FORK.
Don't call dissociate_terminal. If start_gui is false, use
octave_cli_thread to start Octave within a QApplication context.
* sighandlers.cc (gui_driver_sig_handler): Move to src/main.in.cc.
(install_gui_driver_signal_handlers): Move to src/main.in.cc and rename
to octave_set_signal_handler.
* octave.cc (no_fork_option): Delete.
(process_command_line): Don't handle NO_FORK_OPTION.
(octave_fork_gui): Move to src/main.in.cc and rename to
have_controlling_terminal.
* options-usage.h (usage_string, octave_print_verbose_usage_and_exit):
Delete --no-fork from text.
(long_opts): Delete no-fork from list.
(NO_FORK_OPTION): Delete.
* run-octave.in: Set OCTAVE_BINDIR in environment before exec-ing
Octave binary.
* src/Makefile.am: Build octave-gui, octave-cli, and octave instead of
octave-cli and octave.
* main-gui.cc: Rename from main.cc. Call octave_start_gui and pass
START_GUI as parameter.
* main.in.cc: New file.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sun, 27 Oct 2013 18:47:22 -0400 |
parents | |
children | 8b353af4a1ca |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.in.cc Sun Oct 27 18:47:22 2013 -0400 @@ -0,0 +1,442 @@ +// %NO_EDIT_WARNING% +/* + +Copyright (C) 2012-2013 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +<http://www.gnu.org/licenses/>. + +*/ + +// NOTE: This program is supposed to be a small wrapper that exists +// primarily to give up the controlling TTY and then exec Octave with +// its GUI. It may also execute Octave without the GUI or the command +// line version of Octave that is not linked with GUI libraries. So +// that it remains small, it should NOT depend on or be linked with +// liboctave or libinterp. + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <cstdlib> +#include <cstring> + +#include <algorithm> +#include <iostream> +#include <string> + +#include <sys/wait.h> +#include <sys/types.h> +#include <sys/signal.h> +#include <fcntl.h> +#include <unistd.h> + +#ifndef OCTAVE_BINDIR +#define OCTAVE_BINDIR %OCTAVE_BINDIR% +#endif + +#ifndef OCTAVE_PREFIX +#define OCTAVE_PREFIX %OCTAVE_PREFIX% +#endif + +typedef void sig_handler (int); + +// Forward signals to the GUI process. + +static pid_t gui_pid = 0; + +static void +gui_driver_sig_handler (int sig) +{ + if (gui_pid > 0) + kill (gui_pid, sig); +} + +static sig_handler * +octave_set_signal_handler (int sig, sig_handler *handler) +{ + struct sigaction act, oact; + + act.sa_handler = handler; + act.sa_flags = 0; + + gnulib::sigemptyset (&act.sa_mask); + gnulib::sigemptyset (&oact.sa_mask); + + gnulib::sigaction (sig, &act, &oact); + + return oact.sa_handler; +} + +static void +install_signal_handlers (void) +{ + +#ifdef SIGINT + octave_set_signal_handler (SIGINT, gui_driver_sig_handler); +#endif + +#ifdef SIGBREAK + octave_set_signal_handler (SIGBREAK, gui_driver_sig_handler); +#endif + +#ifdef SIGABRT + octave_set_signal_handler (SIGABRT, gui_driver_sig_handler); +#endif + +#ifdef SIGALRM + octave_set_signal_handler (SIGALRM, gui_driver_sig_handler); +#endif + +#ifdef SIGBUS + octave_set_signal_handler (SIGBUS, gui_driver_sig_handler); +#endif + + // SIGCHLD + // SIGCLD + // SIGCONT + +#ifdef SIGEMT + octave_set_signal_handler (SIGEMT, gui_driver_sig_handler); +#endif + +#ifdef SIGFPE + octave_set_signal_handler (SIGFPE, gui_driver_sig_handler); +#endif + +#ifdef SIGHUP + octave_set_signal_handler (SIGHUP, gui_driver_sig_handler); +#endif + +#ifdef SIGILL + octave_set_signal_handler (SIGILL, gui_driver_sig_handler); +#endif + + // SIGINFO + // SIGINT + +#ifdef SIGIOT + octave_set_signal_handler (SIGIOT, gui_driver_sig_handler); +#endif + +#ifdef SIGLOST + octave_set_signal_handler (SIGLOST, gui_driver_sig_handler); +#endif + +#ifdef SIGPIPE + octave_set_signal_handler (SIGPIPE, gui_driver_sig_handler); +#endif + +#ifdef SIGPOLL + octave_set_signal_handler (SIGPOLL, gui_driver_sig_handler); +#endif + + // SIGPROF + // SIGPWR + +#ifdef SIGQUIT + octave_set_signal_handler (SIGQUIT, gui_driver_sig_handler); +#endif + +#ifdef SIGSEGV + octave_set_signal_handler (SIGSEGV, gui_driver_sig_handler); +#endif + + // SIGSTOP + +#ifdef SIGSYS + octave_set_signal_handler (SIGSYS, gui_driver_sig_handler); +#endif + +#ifdef SIGTERM + octave_set_signal_handler (SIGTERM, gui_driver_sig_handler); +#endif + +#ifdef SIGTRAP + octave_set_signal_handler (SIGTRAP, gui_driver_sig_handler); +#endif + + // SIGTSTP + // SIGTTIN + // SIGTTOU + // SIGURG + +#ifdef SIGUSR1 + octave_set_signal_handler (SIGUSR1, gui_driver_sig_handler); +#endif + +#ifdef SIGUSR2 + octave_set_signal_handler (SIGUSR2, gui_driver_sig_handler); +#endif + +#ifdef SIGVTALRM + octave_set_signal_handler (SIGVTALRM, gui_driver_sig_handler); +#endif + +#ifdef SIGIO + octave_set_signal_handler (SIGIO, gui_driver_sig_handler); +#endif + + // SIGWINCH + +#ifdef SIGXCPU + octave_set_signal_handler (SIGXCPU, gui_driver_sig_handler); +#endif + +#ifdef SIGXFSZ + octave_set_signal_handler (SIGXFSZ, gui_driver_sig_handler); +#endif + +} + +static int +have_controlling_terminal (void) +{ + int retval = 0; + +#if ! (defined (__WIN32__) || defined (__APPLE__)) || defined (__CYGWIN__) + +#if defined (HAVE_CTERMID) + const char *ctty = ctermid (0); +#else + const char *ctty = "/dev/tty"; +#endif + + int fd = gnulib::open (ctty, O_RDWR, 0); + + if (fd >= 0) + { + gnulib::close (fd); + + retval = 1; + } + +#endif + + return retval; +} + +// Find the directory where the octave binary is supposed to be +// installed. + +#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \ + && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) +static const char dir_sep_char = '\\'; +#else +static const char dir_sep_char = '/'; +#endif + +static std::string +octave_getenv (const std::string& name) +{ + char *value = ::getenv (name.c_str ()); + + return value ? value : ""; +} + +static std::string +get_octave_home (void) +{ + std::string oh = octave_getenv ("OCTAVE_HOME"); + + return oh.empty () ? std::string (OCTAVE_PREFIX) : oh; +} + +static std::string +subst_octave_home (const std::string& s) +{ + std::string retval; + + std::string octave_home = get_octave_home (); + + std::string prefix = OCTAVE_PREFIX; + + retval = s; + + if (octave_home != prefix) + { + octave_idx_type len = prefix.length (); + + if (s.substr (0, len) == prefix) + retval.replace (0, len, octave_home); + } + + if (dir_sep_char != '/') + std::replace (retval.begin (), retval.end (), '/', dir_sep_char); + + return retval; +} + +static std::string +get_octave_bindir (void) +{ + // Accept value from the environment literally, but substitute + // OCTAVE_HOME in the configuration value OCTAVE_BINDIR in case Octave + // has been relocated to some installation directory other than the + // one originally configured. + + std::string obd = octave_getenv ("OCTAVE_BINDIR"); + + return obd.empty () ? subst_octave_home (std::string (OCTAVE_BINDIR)) : obd; +} + +static int +octave_exec (const std::string& file, char **argv) +{ + execv (file.c_str (), argv); + + std::cerr << "octave: failed to exec '" << file << "'" << std::endl; + + return 1; +} + +static char * +strsave (const char *s) +{ + if (! s) + return 0; + + int len = strlen (s); + char *tmp = new char [len+1]; + tmp = strcpy (tmp, s); + return tmp; +} + +int +main (int argc, char **argv) +{ + int retval = 0; + + bool start_gui = true; + bool cli_only = false; + +#if defined (__WIN32__) || defined (__CYGWIN__) + bool no_fork_required = true; +#else + bool no_fork_required = false; +#endif + + std::string octave_bindir = get_octave_bindir (); + + std::string file = octave_bindir + dir_sep_char + "octave-gui"; + + char **new_argv = new char * [argc + 1]; + + int k = 0; + new_argv[k++] = strsave ("octave"); + + for (int i = 1; i < argc; i++) + { + if (! strcmp (argv[i], "--no-gui-libs")) + { + // Run the version of Octave that is not linked with any GUI + // libraries. It may not be possible to do plotting or any + // ui* calls, but it will be a little faster to start and + // require less memory. Don't pass the --no-gui-libs option + // on as that option is not recognized by Octave. + + cli_only = true; + file = octave_bindir + dir_sep_char + "octave-cli"; + } + else if (! strcmp (argv[i], "--no-gui")) + { + // If we see this option, then we can just exec octave; we + // don't have to create a child process and wait for it to + // exit. But do exec "octave", not "octave-cli", because even + // if the --no-gui option is given, we may be asked to do some + // plotting or ui* calls. + + start_gui = false; + new_argv[k++] = argv[i]; + } + else + new_argv[k++] = argv[i]; + } + + new_argv[k] = 0; + + if (cli_only || no_fork_required + || (! start_gui && ! have_controlling_terminal ())) + { + retval = octave_exec (file, new_argv); + } + else + { + install_signal_handlers (); + + gui_pid = fork (); + + if (gui_pid < 0) + { + std::cerr << "octave: fork failed!" << std::endl; + + retval = 1; + } + else if (gui_pid == 0) + { + // Child. + + if (setsid () < 0) + { + std::cerr << "octave: error calling setsid!" << std::endl; + + retval = 1; + } + + retval = octave_exec (file, new_argv); + } + else + { + // Parent. Forward signals to the child while waiting for it + // to exit. + + int status; + + while (1) + { + waitpid (gui_pid, &status, 0); + + if (WIFEXITED (status)) + { + retval = WIFEXITED (status) ? WEXITSTATUS (status) : 127; + + break; + } + } + } + } + + return retval; +} + +/*! +@mainpage Source code documentation for GNU Octave + +GNU Octave is a high-level language, primarily intended for numerical +computations. It provides a convenient interactive command line +interface for solving linear and nonlinear problems numerically, and +for performing other numerical experiments. It may also be used as a +batch-oriented language for data processing. + +GNU Octave is free software. You may redistribute it and/or modify it +under the terms of the <a href="http://www.gnu.org/licenses/">GNU +General Public License</a> as published by the Free Software Foundation. + +This is the developer documentation for Octave's own source code. It is +intended to help for hacking Octave. It may also be useful for +understanding the Octave API when writing your own .oct files. +*/