diff options
Diffstat (limited to 'vlib/vlib/unix/main.c')
-rw-r--r-- | vlib/vlib/unix/main.c | 557 |
1 files changed, 0 insertions, 557 deletions
diff --git a/vlib/vlib/unix/main.c b/vlib/vlib/unix/main.c deleted file mode 100644 index 562778e0e5d..00000000000 --- a/vlib/vlib/unix/main.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * main.c: Unix main routine - * - * Copyright (c) 2008 Eliot Dresselhaus - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#include <vlib/vlib.h> -#include <vlib/unix/unix.h> -#include <vlib/unix/plugin.h> - -#include <signal.h> -#include <sys/ucontext.h> -#include <syslog.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -/** Default CLI pager limit is not configured in startup.conf */ -#define UNIX_CLI_DEFAULT_PAGER_LIMIT 100000 - -/** Default CLI history depth if not configured in startup.conf */ -#define UNIX_CLI_DEFAULT_HISTORY 50 - - -unix_main_t unix_main; - -static clib_error_t * -unix_main_init (vlib_main_t * vm) -{ - unix_main_t *um = &unix_main; - um->vlib_main = vm; - return vlib_call_init_function (vm, unix_input_init); -} - -VLIB_INIT_FUNCTION (unix_main_init); - -static void -unix_signal_handler (int signum, siginfo_t * si, ucontext_t * uc) -{ - uword fatal; - u8 *msg = 0; - - msg = format (msg, "received signal %U, PC %U", - format_signal, signum, format_ucontext_pc, uc); - - if (signum == SIGSEGV) - msg = format (msg, ", faulting address %p", si->si_addr); - - switch (signum) - { - /* these (caught) signals cause the application to exit */ - case SIGTERM: - if (unix_main.vlib_main->main_loop_exit_set) - { - syslog (LOG_ERR | LOG_DAEMON, "received SIGTERM, exiting..."); - - clib_longjmp (&unix_main.vlib_main->main_loop_exit, - VLIB_MAIN_LOOP_EXIT_CLI); - } - /* fall through */ - case SIGQUIT: - case SIGINT: - case SIGILL: - case SIGBUS: - case SIGSEGV: - case SIGHUP: - case SIGFPE: - fatal = 1; - break; - - /* by default, print a message and continue */ - default: - fatal = 0; - break; - } - - /* Null terminate. */ - vec_add1 (msg, 0); - - if (fatal) - { - syslog (LOG_ERR | LOG_DAEMON, "%s", msg); - os_exit (1); - } - else - clib_warning ("%s", msg); - - vec_free (msg); -} - -static clib_error_t * -setup_signal_handlers (unix_main_t * um) -{ - uword i; - struct sigaction sa; - - for (i = 1; i < 32; i++) - { - memset (&sa, 0, sizeof (sa)); - sa.sa_sigaction = (void *) unix_signal_handler; - sa.sa_flags = SA_SIGINFO; - - switch (i) - { - /* these signals take the default action */ - case SIGABRT: - case SIGKILL: - case SIGSTOP: - case SIGUSR1: - case SIGUSR2: - continue; - - /* ignore SIGPIPE, SIGCHLD */ - case SIGPIPE: - case SIGCHLD: - sa.sa_sigaction = (void *) SIG_IGN; - break; - - /* catch and handle all other signals */ - default: - break; - } - - if (sigaction (i, &sa, 0) < 0) - return clib_error_return_unix (0, "sigaction %U", format_signal, i); - } - - return 0; -} - -static void -unix_error_handler (void *arg, u8 * msg, int msg_len) -{ - unix_main_t *um = arg; - - /* Echo to stderr when interactive. */ - if (um->flags & UNIX_FLAG_INTERACTIVE) - { - CLIB_UNUSED (int r) = write (2, msg, msg_len); - } - else - { - char save = msg[msg_len - 1]; - - /* Null Terminate. */ - msg[msg_len - 1] = 0; - - syslog (LOG_ERR | LOG_DAEMON, "%s", msg); - - msg[msg_len - 1] = save; - } -} - -void -vlib_unix_error_report (vlib_main_t * vm, clib_error_t * error) -{ - unix_main_t *um = &unix_main; - - if (um->flags & UNIX_FLAG_INTERACTIVE || error == 0) - return; - - { - char save; - u8 *msg; - u32 msg_len; - - msg = error->what; - msg_len = vec_len (msg); - - /* Null Terminate. */ - save = msg[msg_len - 1]; - msg[msg_len - 1] = 0; - - syslog (LOG_ERR | LOG_DAEMON, "%s", msg); - - msg[msg_len - 1] = save; - } -} - -static uword -startup_config_process (vlib_main_t * vm, - vlib_node_runtime_t * rt, vlib_frame_t * f) -{ - unix_main_t *um = &unix_main; - u8 *buf = 0; - uword l, n = 1; - - vlib_process_suspend (vm, 2.0); - - while (um->unix_config_complete == 0) - vlib_process_suspend (vm, 0.1); - - if (um->startup_config_filename) - { - unformat_input_t sub_input; - int fd; - struct stat s; - char *fn = (char *) um->startup_config_filename; - - fd = open (fn, O_RDONLY); - if (fd < 0) - { - clib_warning ("failed to open `%s'", fn); - return 0; - } - - if (fstat (fd, &s) < 0) - { - clib_warning ("failed to stat `%s'", fn); - bail: - close (fd); - return 0; - } - - if (!(S_ISREG (s.st_mode) || S_ISLNK (s.st_mode))) - { - clib_warning ("not a regular file: `%s'", fn); - goto bail; - } - - while (n > 0) - { - l = vec_len (buf); - vec_resize (buf, 4096); - n = read (fd, buf + l, 4096); - if (n > 0) - { - _vec_len (buf) = l + n; - if (n < 4096) - break; - } - else - break; - } - if (um->log_fd && vec_len (buf)) - { - u8 *lv = 0; - lv = format (lv, "%U: ***** Startup Config *****\n%v", - format_timeval, 0 /* current bat-time */ , - 0 /* current bat-format */ , - buf); - { - int rv __attribute__ ((unused)) = - write (um->log_fd, lv, vec_len (lv)); - } - vec_reset_length (lv); - lv = format (lv, "%U: ***** End Startup Config *****\n", - format_timeval, 0 /* current bat-time */ , - 0 /* current bat-format */ ); - { - int rv __attribute__ ((unused)) = - write (um->log_fd, lv, vec_len (lv)); - } - vec_free (lv); - } - - if (vec_len (buf)) - { - unformat_init_vector (&sub_input, buf); - vlib_cli_input (vm, &sub_input, 0, 0); - /* frees buf for us */ - unformat_free (&sub_input); - } - close (fd); - } - return 0; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (startup_config_node,static) = { - .function = startup_config_process, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "startup-config-process", -}; -/* *INDENT-ON* */ - -static clib_error_t * -unix_config (vlib_main_t * vm, unformat_input_t * input) -{ - unix_main_t *um = &unix_main; - clib_error_t *error = 0; - - /* Defaults */ - um->cli_pager_buffer_limit = UNIX_CLI_DEFAULT_PAGER_LIMIT; - um->cli_history_limit = UNIX_CLI_DEFAULT_HISTORY; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - char *cli_prompt; - if (unformat (input, "interactive")) - um->flags |= UNIX_FLAG_INTERACTIVE; - else if (unformat (input, "nodaemon")) - um->flags |= UNIX_FLAG_NODAEMON; - else if (unformat (input, "cli-prompt %s", &cli_prompt)) - vlib_unix_cli_set_prompt (cli_prompt); - else - if (unformat (input, "cli-listen %s", &um->cli_listen_socket.config)) - ; - else if (unformat (input, "cli-line-mode")) - um->cli_line_mode = 1; - else if (unformat (input, "cli-no-banner")) - um->cli_no_banner = 1; - else if (unformat (input, "cli-no-pager")) - um->cli_no_pager = 1; - else if (unformat (input, "cli-pager-buffer-limit %d", - &um->cli_pager_buffer_limit)) - ; - else - if (unformat (input, "cli-history-limit %d", &um->cli_history_limit)) - ; - else if (unformat (input, "full-coredump")) - { - int fd; - - fd = open ("/proc/self/coredump_filter", O_WRONLY); - if (fd >= 0) - { - if (write (fd, "0x6f\n", 5) != 5) - clib_unix_warning ("coredump filter write failed!"); - close (fd); - } - else - clib_unix_warning ("couldn't open /proc/self/coredump_filter"); - } - else if (unformat (input, "startup-config %s", - &um->startup_config_filename)) - ; - else if (unformat (input, "exec %s", &um->startup_config_filename)) - ; - else if (unformat (input, "log %s", &um->log_filename)) - { - um->log_fd = open ((char *) um->log_filename, - O_CREAT | O_WRONLY | O_APPEND, 0644); - if (um->log_fd < 0) - { - clib_warning ("couldn't open log '%s'\n", um->log_filename); - um->log_fd = 0; - } - else - { - u8 *lv = 0; - lv = format (0, "%U: ***** Start: PID %d *****\n", - format_timeval, 0 /* current bat-time */ , - 0 /* current bat-format */ , - getpid ()); - { - int rv __attribute__ ((unused)) = - write (um->log_fd, lv, vec_len (lv)); - } - vec_free (lv); - } - } - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - } - - if (!(um->flags & UNIX_FLAG_INTERACTIVE)) - { - error = setup_signal_handlers (um); - if (error) - return error; - - openlog (vm->name, LOG_CONS | LOG_PERROR | LOG_PID, LOG_DAEMON); - clib_error_register_handler (unix_error_handler, um); - - if (!(um->flags & UNIX_FLAG_NODAEMON) && daemon ( /* chdir to / */ 0, - /* stdin/stdout/stderr -> /dev/null */ - 0) < 0) - clib_error_return (0, "daemon () fails"); - } - um->unix_config_complete = 1; - - return 0; -} - -/* unix { ... } configuration. */ -/*? - * - * @cfgcmd{interactive} - * Attach CLI to stdin/out and provide a debugging command line interface. - * Implies @c nodaemon. - * - * @cfgcmd{nodaemon} - * Do not fork or background the VPP process. Typically used when invoking - * VPP applications from a process monitor. - * - * @cfgcmd{exec, <filename>} - * @par <code>startup-config <filename></code> - * Read startup operational configuration from @c filename. - * The contents of the file will be performed as though entered at the CLI. - * The two keywords are aliases for the same function; if both are specified, - * only the last will have an effect. - * - * @cfgcmd{log, <filename>} - * Logs the startup configuration and all subsequent CLI commands in - * @c filename. - * Very useful in situations where folks don't remember or can't be bothered - * to include CLI commands in bug reports. - * - * @cfgcmd{full-coredump} - * Ask the Linux kernel to dump all memory-mapped address regions, instead - * of just text+data+bss. - * - * @cfgcmd{cli-listen, <address:port>} - * Bind the CLI to listen at the address and port given. @clocalhost - * on TCP port @c 5002, given as <tt>cli-listen localhost:5002</tt>, - * is typical. - * - * @cfgcmd{cli-line-mode} - * Disable character-by-character I/O on stdin. Useful when combined with, - * for example, <tt>emacs M-x gud-gdb</tt>. - * - * @cfgcmd{cli-prompt, <string>} - * Configure the CLI prompt to be @c string. - * - * @cfgcmd{cli-history-limit, <nn>} - * Limit commmand history to @c nn lines. A value of @c 0 - * disables command history. Default value: @c 50 - * - * @cfgcmd{cli-no-banner} - * Disable the login banner on stdin and Telnet connections. - * - * @cfgcmd{cli-no-pager} - * Disable the output pager. - * - * @cfgcmd{cli-pager-buffer-limit, <nn>} - * Limit pager buffer to @c nn lines of output. - * A value of @c 0 disables the pager. Default value: @c 100000 -?*/ -VLIB_CONFIG_FUNCTION (unix_config, "unix"); - -static clib_error_t * -unix_exit (vlib_main_t * vm) -{ - /* Close syslog connection. */ - closelog (); - return 0; -} - -VLIB_MAIN_LOOP_EXIT_FUNCTION (unix_exit); - -u8 **vlib_thread_stacks; - -static uword -thread0 (uword arg) -{ - vlib_main_t *vm = (vlib_main_t *) arg; - unformat_input_t input; - int i; - - unformat_init_command_line (&input, (char **) vm->argv); - i = vlib_main (vm, &input); - unformat_free (&input); - - return i; -} - -int -vlib_unix_main (int argc, char *argv[]) -{ - vlib_main_t *vm = &vlib_global_main; /* one and only time for this! */ - vlib_thread_main_t *tm = &vlib_thread_main; - unformat_input_t input; - u8 *thread_stacks; - clib_error_t *e; - int i; - - vm->argv = (u8 **) argv; - vm->name = argv[0]; - vm->heap_base = clib_mem_get_heap (); - ASSERT (vm->heap_base); - - i = vlib_plugin_early_init (vm); - if (i) - return i; - - unformat_init_command_line (&input, (char **) vm->argv); - if (vm->init_functions_called == 0) - vm->init_functions_called = hash_create (0, /* value bytes */ 0); - e = vlib_call_all_config_functions (vm, &input, 1 /* early */ ); - if (e != 0) - { - clib_error_report (e); - return 1; - } - unformat_free (&input); - - /* - * allocate n x VLIB_THREAD_STACK_SIZE stacks, aligned to a - * VLIB_THREAD_STACK_SIZE boundary - * See also: os_get_cpu_number() in vlib/vlib/threads.c - */ - thread_stacks = clib_mem_alloc_aligned - ((uword) tm->n_thread_stacks * VLIB_THREAD_STACK_SIZE, - VLIB_THREAD_STACK_SIZE); - - vec_validate (vlib_thread_stacks, tm->n_thread_stacks - 1); - for (i = 0; i < vec_len (vlib_thread_stacks); i++) - { - vlib_thread_stacks[i] = thread_stacks; - - /* - * Disallow writes to the bottom page of the stack, to - * catch stack overflows. - */ - if (mprotect (thread_stacks, clib_mem_get_page_size (), PROT_READ) < 0) - clib_unix_warning ("thread stack"); - - thread_stacks += VLIB_THREAD_STACK_SIZE; - } - - i = clib_calljmp (thread0, (uword) vm, - (void *) (vlib_thread_stacks[0] + - VLIB_THREAD_STACK_SIZE)); - return i; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |