GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
main.in.cc
Go to the documentation of this file.
1 // %NO_EDIT_WARNING%
2 /*
3 
4 Copyright (C) 2012-2017 John W. Eaton
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 // NOTE: This program is supposed to be a small wrapper that exists
25 // primarily to give up the controlling TTY and then exec Octave with
26 // its GUI. It may also execute Octave without the GUI or the command
27 // line version of Octave that is not linked with GUI libraries. So
28 // that it remains small, it should NOT depend on or be linked with
29 // liboctave or libinterp.
30 
31 #if defined (HAVE_CONFIG_H)
32 # include "config.h"
33 #endif
34 
35 #include <cstdlib>
36 #include <cstring>
37 
38 #include <algorithm>
39 #include <iostream>
40 #include <string>
41 
42 #include "fcntl-wrappers.h"
43 #include "signal-wrappers.h"
44 #include "strdup-wrapper.h"
45 #include "unistd-wrappers.h"
46 #include "wait-wrappers.h"
47 
48 #if ! defined (OCTAVE_VERSION)
49 # define OCTAVE_VERSION %OCTAVE_VERSION%
50 #endif
51 
52 #if ! defined (OCTAVE_ARCHLIBDIR)
53 # define OCTAVE_ARCHLIBDIR %OCTAVE_ARCHLIBDIR%
54 #endif
55 
56 #if ! defined (OCTAVE_BINDIR)
57 # define OCTAVE_BINDIR %OCTAVE_BINDIR%
58 #endif
59 
60 #if ! defined (OCTAVE_PREFIX)
61 # define OCTAVE_PREFIX %OCTAVE_PREFIX%
62 #endif
63 
64 #include "display-available.h"
65 #include "shared-fcns.h"
66 
67 #if defined (HAVE_OCTAVE_QT_GUI) && ! defined (OCTAVE_USE_WINDOWS_API)
68 
69 // Forward signals to the GUI process.
70 
71 static pid_t gui_pid = 0;
72 
73 static int caught_signal = -1;
74 
75 static void
76 gui_driver_sig_handler (int sig)
77 {
78  if (gui_pid > 0)
79  caught_signal = sig;
80 }
81 
82 static void
83 gui_driver_set_signal_handler (const char *signame,
84  octave_sig_handler *handler)
85 {
86  octave_set_signal_handler_by_name (signame, handler, false);
87 }
88 
89 static void
91 {
92  gui_driver_set_signal_handler ("SIGINT", gui_driver_sig_handler);
93  gui_driver_set_signal_handler ("SIGBREAK", gui_driver_sig_handler);
94  gui_driver_set_signal_handler ("SIGABRT", gui_driver_sig_handler);
95  gui_driver_set_signal_handler ("SIGALRM", gui_driver_sig_handler);
96  gui_driver_set_signal_handler ("SIGBUS", gui_driver_sig_handler);
97 
98  // SIGCHLD
99  // SIGCLD
100  // SIGCONT
101 
102  gui_driver_set_signal_handler ("SIGEMT", gui_driver_sig_handler);
103  gui_driver_set_signal_handler ("SIGFPE", gui_driver_sig_handler);
104  gui_driver_set_signal_handler ("SIGHUP", gui_driver_sig_handler);
105  gui_driver_set_signal_handler ("SIGILL", gui_driver_sig_handler);
106 
107  // SIGINFO
108  // SIGINT
109 
110  gui_driver_set_signal_handler ("SIGIOT", gui_driver_sig_handler);
111  gui_driver_set_signal_handler ("SIGLOST", gui_driver_sig_handler);
112  gui_driver_set_signal_handler ("SIGPIPE", gui_driver_sig_handler);
113  gui_driver_set_signal_handler ("SIGPOLL", gui_driver_sig_handler);
114 
115  // SIGPROF
116  // SIGPWR
117 
118  gui_driver_set_signal_handler ("SIGQUIT", gui_driver_sig_handler);
119  gui_driver_set_signal_handler ("SIGSEGV", gui_driver_sig_handler);
120 
121  // SIGSTOP
122 
123  gui_driver_set_signal_handler ("SIGSYS", gui_driver_sig_handler);
124  gui_driver_set_signal_handler ("SIGTERM", gui_driver_sig_handler);
125  gui_driver_set_signal_handler ("SIGTRAP", gui_driver_sig_handler);
126 
127  // SIGTSTP
128  // SIGTTIN
129  // SIGTTOU
130  // SIGURG
131 
132  gui_driver_set_signal_handler ("SIGUSR1", gui_driver_sig_handler);
133  gui_driver_set_signal_handler ("SIGUSR2", gui_driver_sig_handler);
134  gui_driver_set_signal_handler ("SIGVTALRM", gui_driver_sig_handler);
135  gui_driver_set_signal_handler ("SIGIO", gui_driver_sig_handler);
136 
137  // SIGWINCH
138 
139  gui_driver_set_signal_handler ("SIGXCPU", gui_driver_sig_handler);
140  gui_driver_set_signal_handler ("SIGXFSZ", gui_driver_sig_handler);
141 }
142 
143 #endif
144 
145 static std::string
147 {
148  // Accept value from the environment literally, but substitute
149  // OCTAVE_HOME in the configuration value OCTAVE_BINDIR in case Octave
150  // has been relocated to some installation directory other than the
151  // one originally configured.
152 
153  std::string obd = octave_getenv ("OCTAVE_BINDIR");
154 
155  return obd.empty () ? subst_octave_home (std::string (OCTAVE_BINDIR)) : obd;
156 }
157 
158 static std::string
160 {
161  // Accept value from the environment literally, but substitute
162  // OCTAVE_HOME in the configuration value OCTAVE_ARCHLIBDIR in case
163  // Octave has been relocated to some installation directory other than
164  // the one originally configured.
165 
166  std::string dir = octave_getenv ("OCTAVE_ARCHLIBDIR");
167 
168  return dir.empty () ? subst_octave_home (std::string (OCTAVE_ARCHLIBDIR))
169  : dir;
170 }
171 
172 static int
174 {
175  int status = octave_execv_wrapper (file.c_str (), argv);
176 
177  std::cerr << argv[0] << ": failed to exec '" << file << "'" << std::endl;
178 
179  return status;
180 }
181 
182 static char *
183 strsave (const char *s)
184 {
185  if (! s)
186  return 0;
187 
188  int len = strlen (s);
189  char *tmp = new char [len+1];
190  tmp = strcpy (tmp, s);
191  return tmp;
192 }
193 
194 int
195 main (int argc, char **argv)
196 {
197  int retval = 0;
198 
199  bool start_gui = true;
200  bool gui_libs = true;
201 
202  std::string octave_bindir = get_octave_bindir ();
203  std::string octave_archlibdir = get_octave_archlibdir ();
204  std::string octave_cli
205  = octave_bindir + dir_sep_char + "octave-cli-" OCTAVE_VERSION;
206  std::string octave_gui = octave_archlibdir + dir_sep_char + "octave-gui";
207 
208 #if defined (HAVE_OCTAVE_QT_GUI)
209  // The Octave version number is already embedded in the
210  // octave_archlibdir directory name so we don't need to append it to
211  // the octave-gui filename.
212 
213  std::string file = octave_gui;
214 #else
215  std::string file = octave_cli;
216 #endif
217 
218  // Declaring new_argv static avoids leak warnings when using GCC's
219  // --address-sanitizer option.
220  static char **new_argv = new char * [argc + 1];
221 
222  int k = 1;
223 
224  bool warn_display = true;
225  bool no_display = false;
226 
227  for (int i = 1; i < argc; i++)
228  {
229  if (! strcmp (argv[i], "--no-gui-libs"))
230  {
231  // Run the version of Octave that is not linked with any GUI
232  // libraries. It may not be possible to do plotting or any
233  // ui* calls, but it will be a little faster to start and
234  // require less memory. Don't pass the --no-gui-libs option
235  // on as that option is not recognized by Octave.
236 
237  start_gui = false;
238  gui_libs = false;
239  file = octave_cli;
240  }
241  else if (! strcmp (argv[i], "--no-gui"))
242  {
243  // If we see this option, then we can just exec octave; we
244  // don't have to create a child process and wait for it to
245  // exit. But do exec "octave-gui", not "octave-cli", because
246  // even if the --no-gui option is given, we may be asked to do
247  // some plotting or ui* calls.
248 
249  start_gui = false;
250  new_argv[k++] = argv[i];
251  }
252  else if (! strcmp (argv[i], "--silent") || ! strcmp (argv[i], "--quiet")
253  || ! strcmp (argv[i], "-q"))
254  {
255  warn_display = false;
256  new_argv[k++] = argv[i];
257  }
258  else if (! strcmp (argv[i], "--no-window-system")
259  || ! strcmp (argv[i], "-W"))
260  {
261  no_display = true;
262  new_argv[k++] = argv[i];
263  }
264  else
265  new_argv[k++] = argv[i];
266  }
267 
268  new_argv[k] = 0;
269 
270  if (no_display)
271  {
272  start_gui = false;
273  gui_libs = false;
274 
275  file = octave_cli;
276  }
277  else if (gui_libs || start_gui)
278  {
279  int dpy_avail;
280 
281  const char *display_check_err_msg = display_available (&dpy_avail);
282 
283  if (! dpy_avail)
284  {
285  start_gui = false;
286  gui_libs = false;
287 
288  file = octave_cli;
289 
290  if (warn_display)
291  {
292  if (! display_check_err_msg)
293  display_check_err_msg = "graphical display unavailable";
294 
295  std::cerr << "octave: " << display_check_err_msg << std::endl;
296  std::cerr << "octave: disabling GUI features" << std::endl;
297  }
298  }
299  }
300 
301 #if defined (OCTAVE_USE_WINDOWS_API)
302  file += ".exe";
303 #endif
304 
305  new_argv[0] = strsave (file.c_str ());
306 
307 #if defined (HAVE_OCTAVE_QT_GUI) && ! defined (OCTAVE_USE_WINDOWS_API)
308 
309  if (gui_libs && start_gui)
310  {
311  // Fork and exec when starting the GUI so that we will call
312  // setsid to give up the controlling terminal (if any) and so that
313  // the GUI process will be in a separate process group.
314  //
315  // The GUI process must be in a separate process group so that we
316  // can send an interrupt signal to all child processes when
317  // interrupting the interpreter. See also bug #49609 and the
318  // function pthread_thread_manager::interrupt in the file
319  // libgui/src/thread-manager.cc.
320 
322 
323  gui_pid = octave_fork_wrapper ();
324 
325  if (gui_pid < 0)
326  {
327  std::cerr << "octave: fork failed!" << std::endl;
328 
329  retval = 1;
330  }
331  else if (gui_pid == 0)
332  {
333  // Child.
334 
335  if (octave_setsid_wrapper () < 0)
336  {
337  std::cerr << "octave: error calling setsid!" << std::endl;
338 
339  retval = 1;
340  }
341  else
342  retval = octave_exec (file, new_argv);
343  }
344  else
345  {
346  // Parent. Forward signals to child while waiting for it to exit.
347 
348  int status;
349 
350  while (true)
351  {
352  octave_waitpid_wrapper (gui_pid, &status, 0);
353 
354  if (caught_signal > 0)
355  {
356  int sig = caught_signal;
357 
358  caught_signal = -1;
359 
360  octave_kill_wrapper (gui_pid, sig);
361  }
362  else if (octave_wifexited_wrapper (status))
363  {
364  retval = octave_wexitstatus_wrapper (status);
365  break;
366  }
367  else if (octave_wifsignaled_wrapper (status))
368  {
369  std::cerr << "octave exited with signal "
370  << octave_wtermsig_wrapper (status) << std::endl;
371  break;
372  }
373  }
374  }
375  }
376  else
377  {
378  retval = octave_exec (file, new_argv);
379 
380  if (retval < 0)
381  std::cerr << argv[0] << ": " << std::strerror (errno) << std::endl;
382  }
383 
384 #else
385 
386  retval = octave_exec (file, new_argv);
387 
388  if (retval < 0)
389  std::cerr << argv[0] << ": " << std::strerror (errno) << std::endl;
390 
391 #endif
392 
393  return retval;
394 }
395 
396 /*!
397 @mainpage Source code documentation for GNU Octave
398 
399 GNU Octave is a high-level language, primarily intended for numerical
400 computations. It provides a convenient interactive command line
401 interface for solving linear and nonlinear problems numerically, and
402 for performing other numerical experiments. It may also be used as a
403 batch-oriented language for data processing.
404 
405 GNU Octave is free software. You may redistribute it and/or modify it
406 under the terms of the <a href="http://www.gnu.org/licenses/">GNU
407 General Public License</a> as published by the Free Software Foundation.
408 
409 This is the developer documentation for Octave's own source code. It is
410 intended to help for hacking Octave. It may also be useful for
411 understanding the Octave API when writing your own .oct files.
412 */
bool octave_wifsignaled_wrapper(int status)
Definition: wait-wrappers.c:91
For example cd octave end example noindent changes the current working directory to file
Definition: dirfns.cc:120
#define OCTAVE_ARCHLIBDIR
Definition: main.in.cc:53
bool octave_wifexited_wrapper(int status)
Definition: wait-wrappers.c:85
static std::string subst_octave_home(const std::string &s)
Definition: shared-fcns.h:100
int octave_kill_wrapper(pid_t pid, int signum)
int argc
Definition: load-save.cc:633
for large enough k
Definition: lu.cc:606
const char * display_available(int *dpy_avail)
void octave_sig_handler(int)
s
Definition: file-io.cc:2682
static int octave_exec(const std::string &file, char **argv)
Definition: main.in.cc:173
string_vector argv
Definition: load-save.cc:635
#define OCTAVE_VERSION
Definition: main.in.cc:49
#define OCTAVE_BINDIR
Definition: main.in.cc:57
int octave_wtermsig_wrapper(int status)
int main(int argc, char **argv)
Definition: main.in.cc:195
bool strcmp(const T &str_a, const T &str_b)
True if strings are the same.
Definition: oct-string.cc:112
double tmp
Definition: data.cc:6300
octave_value retval
Definition: data.cc:6294
static const char dir_sep_char
Definition: shared-fcns.h:75
pid_t octave_fork_wrapper(void)
pid_t octave_setsid_wrapper(void)
T::size_type strlen(const typename T::value_type *str)
Definition: oct-string.cc:75
int octave_wexitstatus_wrapper(int status)
static std::string get_octave_bindir(void)
Definition: main.in.cc:146
static char * strsave(const char *s)
Definition: main.in.cc:183
static std::string octave_getenv(const std::string &name)
Definition: shared-fcns.h:79
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
int octave_execv_wrapper(const char *file, char *const *argv)
pid_t octave_waitpid_wrapper(pid_t pid, int *statusp, int options)
Definition: wait-wrappers.c:50
static std::string get_octave_archlibdir(void)
Definition: main.in.cc:159
octave_sig_handler * octave_set_signal_handler_by_name(const char *signame, octave_sig_handler *handler, bool restart_syscalls)
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
void install_signal_handlers(void)
Definition: sighandlers.cc:604