LCOV - code coverage report
Current view: top level - vlib/unix - main.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 160 250 64.0 %
Date: 2023-07-05 22:20:52 Functions: 19 20 95.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : /*
      16             :  * main.c: Unix main routine
      17             :  *
      18             :  * Copyright (c) 2008 Eliot Dresselhaus
      19             :  *
      20             :  * Permission is hereby granted, free of charge, to any person obtaining
      21             :  * a copy of this software and associated documentation files (the
      22             :  * "Software"), to deal in the Software without restriction, including
      23             :  * without limitation the rights to use, copy, modify, merge, publish,
      24             :  * distribute, sublicense, and/or sell copies of the Software, and to
      25             :  * permit persons to whom the Software is furnished to do so, subject to
      26             :  * the following conditions:
      27             :  *
      28             :  * The above copyright notice and this permission notice shall be
      29             :  * included in all copies or substantial portions of the Software.
      30             :  *
      31             :  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      32             :  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      33             :  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      34             :  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      35             :  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      36             :  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      37             :  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      38             :  */
      39             : #include <vlib/vlib.h>
      40             : #include <vlib/unix/unix.h>
      41             : #include <vlib/unix/plugin.h>
      42             : 
      43             : #include <limits.h>
      44             : #include <signal.h>
      45             : #include <sys/ucontext.h>
      46             : #include <syslog.h>
      47             : #include <sys/types.h>
      48             : #include <sys/stat.h>
      49             : #include <fcntl.h>
      50             : #include <sys/time.h>
      51             : #include <sys/resource.h>
      52             : #include <unistd.h>
      53             : 
      54             : /** Default CLI pager limit is not configured in startup.conf */
      55             : #define UNIX_CLI_DEFAULT_PAGER_LIMIT 100000
      56             : 
      57             : /** Default CLI history depth if not configured in startup.conf */
      58             : #define UNIX_CLI_DEFAULT_HISTORY 50
      59             : 
      60             : char *vlib_default_runtime_dir __attribute__ ((weak));
      61             : char *vlib_default_runtime_dir = "vlib";
      62             : 
      63             : unix_main_t unix_main;
      64             : clib_file_main_t file_main;
      65             : 
      66             : static clib_error_t *
      67         559 : unix_main_init (vlib_main_t * vm)
      68             : {
      69         559 :   unix_main_t *um = &unix_main;
      70         559 :   um->vlib_main = vm;
      71         559 :   return 0;
      72             : }
      73             : 
      74             : /* *INDENT-OFF* */
      75        1679 : VLIB_INIT_FUNCTION (unix_main_init) =
      76             : {
      77             :   .runs_before = VLIB_INITS ("unix_input_init"),
      78             : };
      79             : /* *INDENT-ON* */
      80             : 
      81             : static int
      82           0 : unsetup_signal_handlers (int sig)
      83             : {
      84             :   struct sigaction sa;
      85             : 
      86           0 :   sa.sa_handler = SIG_DFL;
      87           0 :   sa.sa_flags = 0;
      88           0 :   sigemptyset (&sa.sa_mask);
      89           0 :   return sigaction (sig, &sa, 0);
      90             : }
      91             : 
      92             : 
      93             : /* allocate this buffer from mheap when setting up the signal handler.
      94             :     dangerous to vec_resize it when crashing, mheap itself might have been
      95             :     corrupted already */
      96             : static u8 *syslog_msg = 0;
      97             : int vlib_last_signum = 0;
      98             : uword vlib_last_faulting_address = 0;
      99             : 
     100             : static void
     101         559 : unix_signal_handler (int signum, siginfo_t * si, ucontext_t * uc)
     102             : {
     103         559 :   uword fatal = 0;
     104             : 
     105             :   /* These come in handy when looking at core files from optimized images */
     106         559 :   vlib_last_signum = signum;
     107         559 :   vlib_last_faulting_address = (uword) si->si_addr;
     108             : 
     109         559 :   syslog_msg = format (syslog_msg, "received signal %U, PC %U",
     110             :                        format_signal, signum, format_ucontext_pc, uc);
     111             : 
     112         559 :   if (signum == SIGSEGV)
     113           0 :     syslog_msg = format (syslog_msg, ", faulting address %p", si->si_addr);
     114             : 
     115         559 :   switch (signum)
     116             :     {
     117             :       /* these (caught) signals cause the application to exit */
     118         559 :     case SIGTERM:
     119             :       /*
     120             :        * Ignore SIGTERM if it's sent before we're ready.
     121             :        */
     122         559 :       if (unix_main.vlib_main && unix_main.vlib_main->main_loop_exit_set)
     123             :         {
     124         559 :           syslog (LOG_ERR | LOG_DAEMON, "received SIGTERM, exiting...");
     125         559 :           unix_main.vlib_main->main_loop_exit_now = 1;
     126             :         }
     127             :       else
     128           0 :         syslog (LOG_ERR | LOG_DAEMON, "IGNORE early SIGTERM...");
     129         559 :       break;
     130             :       /* fall through */
     131           0 :     case SIGQUIT:
     132             :     case SIGINT:
     133             :     case SIGILL:
     134             :     case SIGBUS:
     135             :     case SIGSEGV:
     136             :     case SIGHUP:
     137             :     case SIGFPE:
     138             :     case SIGABRT:
     139           0 :       fatal = 1;
     140           0 :       break;
     141             : 
     142             :       /* by default, print a message and continue */
     143           0 :     default:
     144           0 :       fatal = 0;
     145           0 :       break;
     146             :     }
     147             : 
     148             :   /* Null terminate. */
     149         559 :   vec_add1 (syslog_msg, 0);
     150             : 
     151         559 :   if (fatal)
     152             :     {
     153           0 :       syslog (LOG_ERR | LOG_DAEMON, "%s", syslog_msg);
     154             : 
     155             :       /* Address of callers: outer first, inner last. */
     156             :       uword callers[15];
     157           0 :       uword n_callers = clib_backtrace (callers, ARRAY_LEN (callers), 0);
     158             :       int i;
     159           0 :       for (i = 0; i < n_callers; i++)
     160             :         {
     161           0 :           vec_reset_length (syslog_msg);
     162             : 
     163           0 :           syslog_msg =
     164           0 :             format (syslog_msg, "#%-2d 0x%016lx %U%c", i, callers[i],
     165             :                     format_clib_elf_symbol_with_address, callers[i], 0);
     166             : 
     167           0 :           syslog (LOG_ERR | LOG_DAEMON, "%s", syslog_msg);
     168             :         }
     169             : 
     170             :       /* have to remove SIGABRT to avoid recursive - os_exit calling abort() */
     171           0 :       unsetup_signal_handlers (SIGABRT);
     172             : 
     173             :       /* os_exit(1) causes core generation, skip that for SIGINT, SIGHUP */
     174           0 :       if (signum == SIGINT || signum == SIGHUP)
     175           0 :         os_exit (0);
     176             :       else
     177           0 :         os_exit (1);
     178             :     }
     179             :   else
     180         559 :     clib_warning ("%s", syslog_msg);
     181             : 
     182         559 : }
     183             : 
     184             : static clib_error_t *
     185         559 : setup_signal_handlers (unix_main_t * um)
     186             : {
     187             :   uword i;
     188             :   struct sigaction sa;
     189             : 
     190             :   /* give a big enough buffer for msg, most likely it can avoid vec_resize  */
     191         559 :   vec_alloc (syslog_msg, 2048);
     192             : 
     193       17888 :   for (i = 1; i < 32; i++)
     194             :     {
     195       17329 :       clib_memset (&sa, 0, sizeof (sa));
     196       17329 :       sa.sa_sigaction = (void *) unix_signal_handler;
     197       17329 :       sa.sa_flags = SA_SIGINFO;
     198             : 
     199       17329 :       switch (i)
     200             :         {
     201             :           /* these signals take the default action */
     202        3354 :         case SIGKILL:
     203             :         case SIGCONT:
     204             :         case SIGSTOP:
     205             :         case SIGUSR1:
     206             :         case SIGUSR2:
     207             :         case SIGPROF:
     208        3354 :           continue;
     209             : 
     210             :           /* ignore SIGPIPE, SIGCHLD */
     211        1118 :         case SIGPIPE:
     212             :         case SIGCHLD:
     213        1118 :           sa.sa_sigaction = (void *) SIG_IGN;
     214        1118 :           break;
     215             : 
     216             :           /* catch and handle all other signals */
     217       12857 :         default:
     218       12857 :           break;
     219             :         }
     220             : 
     221       13975 :       if (sigaction (i, &sa, 0) < 0)
     222           0 :         return clib_error_return_unix (0, "sigaction %U", format_signal, i);
     223             :     }
     224             : 
     225         559 :   return 0;
     226             : }
     227             : 
     228             : static void
     229         853 : unix_error_handler (void *arg, u8 * msg, int msg_len)
     230             : {
     231         853 :   unix_main_t *um = arg;
     232             : 
     233             :   /* Echo to stderr when interactive or syslog is disabled. */
     234         853 :   if (um->flags & (UNIX_FLAG_INTERACTIVE | UNIX_FLAG_NOSYSLOG))
     235             :     {
     236           0 :       CLIB_UNUSED (int r) = write (2, msg, msg_len);
     237             :     }
     238             :   else
     239             :     {
     240         853 :       syslog (LOG_ERR | LOG_DAEMON, "%.*s", msg_len, msg);
     241             :     }
     242         853 : }
     243             : 
     244             : void
     245          14 : vlib_unix_error_report (vlib_main_t * vm, clib_error_t * error)
     246             : {
     247          14 :   unix_main_t *um = &unix_main;
     248             : 
     249          14 :   if (um->flags & UNIX_FLAG_INTERACTIVE || error == 0)
     250           0 :     return;
     251             : 
     252             :   {
     253          14 :     u8 *msg = error->what;
     254          14 :     u32 len = vec_len (msg);
     255          14 :     int msg_len = (len > INT_MAX) ? INT_MAX : len;
     256          14 :     syslog (LOG_ERR | LOG_DAEMON, "%.*s", msg_len, msg);
     257             :   }
     258             : }
     259             : 
     260             : static uword
     261         559 : startup_config_process (vlib_main_t * vm,
     262             :                         vlib_node_runtime_t * rt, vlib_frame_t * f)
     263             : {
     264         559 :   unix_main_t *um = &unix_main;
     265             :   unformat_input_t in;
     266             : 
     267         559 :   vlib_process_suspend (vm, 2.0);
     268             : 
     269         451 :   while (um->unix_config_complete == 0)
     270           0 :     vlib_process_suspend (vm, 0.1);
     271             : 
     272         451 :   if (!um->startup_config_filename)
     273             :     {
     274         451 :       return 0;
     275             :     }
     276             : 
     277           0 :   unformat_init_vector (&in,
     278             :                         format (0, "exec %s", um->startup_config_filename));
     279             : 
     280           0 :   vlib_cli_input (vm, &in, 0, 0);
     281             : 
     282           0 :   unformat_free (&in);
     283             : 
     284           0 :   return 0;
     285             : }
     286             : 
     287             : /* *INDENT-OFF* */
     288      178120 : VLIB_REGISTER_NODE (startup_config_node,static) = {
     289             :     .function = startup_config_process,
     290             :     .type = VLIB_NODE_TYPE_PROCESS,
     291             :     .name = "startup-config-process",
     292             :     .process_log2_n_stack_bytes = 18,
     293             : };
     294             : /* *INDENT-ON* */
     295             : 
     296             : static clib_error_t *
     297         559 : unix_config (vlib_main_t * vm, unformat_input_t * input)
     298             : {
     299         559 :   vlib_global_main_t *vgm = vlib_get_global_main ();
     300         559 :   unix_main_t *um = &unix_main;
     301         559 :   clib_error_t *error = 0;
     302             :   gid_t gid;
     303         559 :   int pidfd = -1;
     304             : 
     305             :   /* Defaults */
     306         559 :   um->cli_pager_buffer_limit = UNIX_CLI_DEFAULT_PAGER_LIMIT;
     307         559 :   um->cli_history_limit = UNIX_CLI_DEFAULT_HISTORY;
     308             : 
     309        2795 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     310             :     {
     311             :       char *cli_prompt;
     312        2236 :       if (unformat (input, "interactive"))
     313           0 :         um->flags |= UNIX_FLAG_INTERACTIVE;
     314        2236 :       else if (unformat (input, "nodaemon"))
     315         559 :         um->flags |= UNIX_FLAG_NODAEMON;
     316        1677 :       else if (unformat (input, "nosyslog"))
     317           0 :         um->flags |= UNIX_FLAG_NOSYSLOG;
     318        1677 :       else if (unformat (input, "nocolor"))
     319           0 :         um->flags |= UNIX_FLAG_NOCOLOR;
     320        1677 :       else if (unformat (input, "nobanner"))
     321           0 :         um->flags |= UNIX_FLAG_NOBANNER;
     322        1677 :       else if (unformat (input, "cli-prompt %s", &cli_prompt))
     323           0 :         vlib_unix_cli_set_prompt (cli_prompt);
     324             :       else
     325        1677 :         if (unformat (input, "cli-listen %s", &um->cli_listen_socket.config))
     326             :         ;
     327        1677 :       else if (unformat (input, "runtime-dir %s", &um->runtime_dir))
     328             :         ;
     329        1118 :       else if (unformat (input, "cli-line-mode"))
     330           0 :         um->cli_line_mode = 1;
     331        1118 :       else if (unformat (input, "cli-no-banner"))
     332           0 :         um->cli_no_banner = 1;
     333        1118 :       else if (unformat (input, "cli-no-pager"))
     334           0 :         um->cli_no_pager = 1;
     335        1118 :       else if (unformat (input, "poll-sleep-usec %d", &um->poll_sleep_usec))
     336             :         ;
     337        1118 :       else if (unformat (input, "cli-pager-buffer-limit %d",
     338             :                          &um->cli_pager_buffer_limit))
     339             :         ;
     340             :       else
     341        1118 :         if (unformat (input, "cli-history-limit %d", &um->cli_history_limit))
     342             :         ;
     343        1118 :       else if (unformat (input, "coredump-size"))
     344             :         {
     345         559 :           uword coredump_size = 0;
     346         559 :           if (unformat (input, "unlimited"))
     347             :             {
     348         559 :               coredump_size = RLIM_INFINITY;
     349             :             }
     350             :           else
     351           0 :             if (!unformat (input, "%U", unformat_memory_size, &coredump_size))
     352             :             {
     353           0 :               return clib_error_return (0,
     354             :                                         "invalid coredump-size parameter `%U'",
     355             :                                         format_unformat_error, input);
     356             :             }
     357         559 :           const struct rlimit new_limit = { coredump_size, coredump_size };
     358         559 :           if (0 != setrlimit (RLIMIT_CORE, &new_limit))
     359             :             {
     360           0 :               clib_unix_warning ("prlimit() failed");
     361             :             }
     362             :         }
     363         559 :       else if (unformat (input, "full-coredump"))
     364             :         {
     365             :           int fd;
     366             : 
     367         559 :           fd = open ("/proc/self/coredump_filter", O_WRONLY);
     368         559 :           if (fd >= 0)
     369             :             {
     370         559 :               if (write (fd, "0x6f\n", 5) != 5)
     371           0 :                 clib_unix_warning ("coredump filter write failed!");
     372         559 :               close (fd);
     373             :             }
     374             :           else
     375           0 :             clib_unix_warning ("couldn't open /proc/self/coredump_filter");
     376             :         }
     377           0 :       else if (unformat (input, "startup-config %s",
     378             :                          &um->startup_config_filename))
     379             :         ;
     380           0 :       else if (unformat (input, "exec %s", &um->startup_config_filename))
     381             :         ;
     382           0 :       else if (unformat (input, "log %s", &um->log_filename))
     383             :         {
     384           0 :           um->log_fd = open ((char *) um->log_filename,
     385             :                              O_CREAT | O_WRONLY | O_APPEND, 0644);
     386           0 :           if (um->log_fd < 0)
     387             :             {
     388           0 :               clib_warning ("couldn't open log '%s'\n", um->log_filename);
     389           0 :               um->log_fd = 0;
     390             :             }
     391             :           else
     392             :             {
     393           0 :               u8 *lv = 0;
     394           0 :               lv = format (0, "%U: ***** Start: PID %d *****\n",
     395             :                            format_timeval, NULL /* current bat-format */,
     396             :                            0 /* current bat-time */, getpid ());
     397             :               {
     398           0 :                 int rv __attribute__ ((unused)) =
     399           0 :                   write (um->log_fd, lv, vec_len (lv));
     400             :               }
     401           0 :               vec_free (lv);
     402             :             }
     403             :         }
     404           0 :       else if (unformat (input, "gid %U", unformat_unix_gid, &gid))
     405             :         {
     406           0 :           if (setegid (gid) == -1)
     407           0 :             return clib_error_return_unix (0, "setegid");
     408             :         }
     409           0 :       else if (unformat (input, "pidfile %s", &um->pidfile))
     410             :         ;
     411             :       else
     412           0 :         return clib_error_return (0, "unknown input `%U'",
     413             :                                   format_unformat_error, input);
     414             :     }
     415             : 
     416         559 :   if (um->runtime_dir == 0)
     417             :     {
     418           0 :       uid_t uid = geteuid ();
     419           0 :       if (uid == 00)
     420           0 :         um->runtime_dir = format (0, "/run/%s%c",
     421             :                                   vlib_default_runtime_dir, 0);
     422             :       else
     423           0 :         um->runtime_dir = format (0, "/run/user/%u/%s%c", uid,
     424             :                                   vlib_default_runtime_dir, 0);
     425             :     }
     426             : 
     427             :   /* Ensure the runtime directory is created */
     428         559 :   error = vlib_unix_recursive_mkdir ((char *) um->runtime_dir);
     429         559 :   if (error)
     430           0 :     return error;
     431             : 
     432         559 :   if (chdir ((char *) um->runtime_dir) < 0)
     433           0 :     return clib_error_return_unix (0, "chdir('%s')", um->runtime_dir);
     434             : 
     435         559 :   error = setup_signal_handlers (um);
     436         559 :   if (error)
     437           0 :     return error;
     438             : 
     439         559 :   if (um->pidfile)
     440             :     {
     441           0 :       if ((error = vlib_unix_validate_runtime_file (um,
     442           0 :                                                     (char *) um->pidfile,
     443             :                                                     &um->pidfile)))
     444           0 :         return error;
     445             : 
     446           0 :       if (((pidfd = open ((char *) um->pidfile,
     447             :                           O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0))
     448             :         {
     449           0 :           return clib_error_return_unix (0, "open");
     450             :         }
     451             :     }
     452             : 
     453         559 :   if (!(um->flags & (UNIX_FLAG_INTERACTIVE | UNIX_FLAG_NOSYSLOG)))
     454             :     {
     455         559 :       openlog (vgm->name, LOG_CONS | LOG_PERROR | LOG_PID, LOG_DAEMON);
     456         559 :       clib_error_register_handler (unix_error_handler, um);
     457             : 
     458         559 :       if (!(um->flags & UNIX_FLAG_NODAEMON) && daemon ( /* chdir to / */ 0,
     459             :                                                        /* stdin/stdout/stderr -> /dev/null */
     460             :                                                        0) < 0)
     461           0 :         clib_error_return (0, "daemon () fails");
     462             :     }
     463             : 
     464         559 :   if (pidfd >= 0)
     465             :     {
     466           0 :       u8 *lv = format (0, "%d", getpid ());
     467           0 :       if (write (pidfd, (char *) lv, vec_len (lv)) != vec_len (lv))
     468             :         {
     469           0 :           vec_free (lv);
     470           0 :           close (pidfd);
     471           0 :           return clib_error_return_unix (0, "write");
     472             :         }
     473           0 :       vec_free (lv);
     474           0 :       close (pidfd);
     475             :     }
     476             : 
     477         559 :   um->unix_config_complete = 1;
     478             : 
     479         559 :   return 0;
     480             : }
     481             : 
     482             : /* unix { ... } configuration. */
     483             : /*?
     484             :  *
     485             :  * @cfgcmd{interactive}
     486             :  * Attach CLI to stdin/out and provide a debugging command line interface.
     487             :  * Implies @c nodaemon.
     488             :  *
     489             :  * @cfgcmd{nodaemon}
     490             :  * Do not fork or background the VPP process. Typically used when invoking
     491             :  * VPP applications from a process monitor.
     492             :  *
     493             :  * @cfgcmd{nosyslog}
     494             :  * Do not send e.g. clib_warning(...) output to syslog. Used
     495             :  * when invoking VPP applications from a process monitor which
     496             :  * pipe stdout/stderr to a dedicated logger service.
     497             :  *
     498             :  * @cfgcmd{nocolor}
     499             :  * Do not use colors in outputs.
     500             :  * *
     501             :  * @cfgcmd{nobanner}
     502             :  * Do not display startup banner.
     503             :  *
     504             :  * @cfgcmd{exec, &lt;filename&gt;}
     505             :  * @par <code>startup-config &lt;filename&gt;</code>
     506             :  * Read startup operational configuration from @c filename.
     507             :  * The contents of the file will be performed as though entered at the CLI.
     508             :  * The two keywords are aliases for the same function; if both are specified,
     509             :  * only the last will have an effect.
     510             :  *
     511             :  * @cfgcmd{log, &lt;filename&gt;}
     512             :  * Logs the startup configuration and all subsequent CLI commands in
     513             :  * @c filename.
     514             :  * Very useful in situations where folks don't remember or can't be bothered
     515             :  * to include CLI commands in bug reports.
     516             :  *
     517             :  * @cfgcmd{pidfile, &lt;filename&gt;}
     518             :  * Writes the pid of the main thread in @c filename.
     519             :  *
     520             :  * @cfgcmd{full-coredump}
     521             :  * Ask the Linux kernel to dump all memory-mapped address regions, instead
     522             :  * of just text+data+bss.
     523             :  *
     524             :  * @cfgcmd{runtime-dir}
     525             :  * Define directory where VPP is going to store all runtime files.
     526             :  * Default is /run/vpp when running as root, /run/user/<UID>/vpp if running as
     527             :  * an unprivileged user.
     528             :  *
     529             :  * @cfgcmd{cli-listen, &lt;address:port&gt;}
     530             :  * Bind the CLI to listen at the address and port given. @c localhost
     531             :  * on TCP port @c 5002, given as <tt>cli-listen localhost:5002</tt>,
     532             :  * is typical.
     533             :  *
     534             :  * @cfgcmd{cli-line-mode}
     535             :  * Disable character-by-character I/O on stdin. Useful when combined with,
     536             :  * for example, <tt>emacs M-x gud-gdb</tt>.
     537             :  *
     538             :  * @cfgcmd{cli-prompt, &lt;string&gt;}
     539             :  * Configure the CLI prompt to be @c string.
     540             :  *
     541             :  * @cfgcmd{cli-history-limit, &lt;nn&gt;}
     542             :  * Limit command history to @c nn  lines. A value of @c 0
     543             :  * disables command history. Default value: @c 50
     544             :  *
     545             :  * @cfgcmd{cli-no-banner}
     546             :  * Disable the login banner on stdin and Telnet connections.
     547             :  *
     548             :  * @cfgcmd{cli-no-pager}
     549             :  * Disable the output pager.
     550             :  *
     551             :  * @cfgcmd{cli-pager-buffer-limit, &lt;nn&gt;}
     552             :  * Limit pager buffer to @c nn lines of output.
     553             :  * A value of @c 0 disables the pager. Default value: @c 100000
     554             :  *
     555             :  * @cfgcmd{gid, &lt;nn&gt;}
     556             :  * Set the effective gid under which the vpp process is to run.
     557             :  *
     558             :  * @cfgcmd{poll-sleep-usec, &lt;nn&gt;}
     559             :  * Set a fixed poll sleep interval between main loop polls.
     560             : ?*/
     561        7306 : VLIB_EARLY_CONFIG_FUNCTION (unix_config, "unix");
     562             : 
     563             : static clib_error_t *
     564         559 : unix_exit (vlib_main_t * vm)
     565             : {
     566             :   /* Close syslog connection. */
     567         559 :   closelog ();
     568         559 :   return 0;
     569             : }
     570             : 
     571        1678 : VLIB_MAIN_LOOP_EXIT_FUNCTION (unix_exit);
     572             : 
     573             : u8 **vlib_thread_stacks;
     574             : 
     575             : static uword
     576         559 : thread0 (uword arg)
     577             : {
     578         559 :   vlib_main_t *vm = (vlib_main_t *) arg;
     579         559 :   vlib_global_main_t *vgm = vlib_get_global_main ();
     580             :   unformat_input_t input;
     581             :   int i;
     582             : 
     583         559 :   vlib_process_finish_switch_stack (vm);
     584             : 
     585         559 :   unformat_init_command_line (&input, (char **) vgm->argv);
     586         559 :   i = vlib_main (vm, &input);
     587         559 :   unformat_free (&input);
     588             : 
     589         559 :   return i;
     590             : }
     591             : 
     592             : u8 *
     593         613 : vlib_thread_stack_init (uword thread_index)
     594             : {
     595             :   void *stack;
     596         613 :   ASSERT (thread_index < vec_len (vlib_thread_stacks));
     597         613 :   stack = clib_mem_vm_map_stack (VLIB_THREAD_STACK_SIZE,
     598             :                                  CLIB_MEM_PAGE_SZ_DEFAULT,
     599             :                                  "thread stack: thread %u", thread_index);
     600             : 
     601         613 :   if (stack == CLIB_MEM_VM_MAP_FAILED)
     602           0 :     clib_panic ("failed to allocate thread %u stack", thread_index);
     603             : 
     604         613 :   vlib_thread_stacks[thread_index] = stack;
     605         613 :   return stack;
     606             : }
     607             : 
     608             : #ifndef PATH_MAX
     609             : #define PATH_MAX 4096
     610             : #endif
     611             : 
     612             : int
     613         559 : vlib_unix_main (int argc, char *argv[])
     614             : {
     615         559 :   vlib_global_main_t *vgm = vlib_get_global_main ();
     616         559 :   vlib_main_t *vm = vlib_get_first_main (); /* one and only time for this! */
     617             :   unformat_input_t input;
     618             :   clib_error_t *e;
     619             :   char buffer[PATH_MAX];
     620             :   int i;
     621             : 
     622         559 :   vec_validate_aligned (vgm->vlib_mains, 0, CLIB_CACHE_LINE_BYTES);
     623             : 
     624         559 :   if ((i = readlink ("/proc/self/exe", buffer, sizeof (buffer) - 1)) > 0)
     625             :     {
     626             :       int j;
     627         559 :       buffer[i] = 0;
     628         559 :       vgm->exec_path = vec_new (char, i + 1);
     629         559 :       clib_memcpy_fast (vgm->exec_path, buffer, i + 1);
     630        1677 :       for (j = i - 1; j > 0; j--)
     631        1677 :         if (buffer[j - 1] == '/')
     632         559 :           break;
     633         559 :       vgm->name = vec_new (char, i - j + 1);
     634         559 :       clib_memcpy_fast (vgm->name, buffer + j, i - j + 1);
     635             :     }
     636             :   else
     637           0 :     vgm->exec_path = vgm->name = argv[0];
     638             : 
     639         559 :   vgm->argv = (u8 **) argv;
     640             : 
     641         559 :   clib_time_init (&vm->clib_time);
     642             : 
     643             :   /* Turn on the event logger at the first possible moment */
     644         559 :   vgm->configured_elog_ring_size = 128 << 10;
     645         559 :   elog_init (vlib_get_elog_main (), vgm->configured_elog_ring_size);
     646         559 :   elog_enable_disable (vlib_get_elog_main (), 1);
     647             : 
     648         559 :   unformat_init_command_line (&input, (char **) vgm->argv);
     649         559 :   if ((e = vlib_plugin_config (vm, &input)))
     650             :     {
     651           0 :       clib_error_report (e);
     652           0 :       return 1;
     653             :     }
     654         559 :   unformat_free (&input);
     655             : 
     656         559 :   i = vlib_plugin_early_init (vm);
     657         559 :   if (i)
     658           0 :     return i;
     659             : 
     660         559 :   unformat_init_command_line (&input, (char **) vgm->argv);
     661         559 :   if (vgm->init_functions_called == 0)
     662           0 :     vgm->init_functions_called = hash_create (0, /* value bytes */ 0);
     663         559 :   e = vlib_call_all_config_functions (vm, &input, 1 /* early */ );
     664         559 :   if (e != 0)
     665             :     {
     666           0 :       clib_error_report (e);
     667           0 :       return 1;
     668             :     }
     669         559 :   unformat_free (&input);
     670             : 
     671             :   /* always load symbols, for signal handler and mheap memory get/put backtrace */
     672         559 :   clib_elf_main_init (vgm->exec_path);
     673             : 
     674         559 :   vec_validate (vlib_thread_stacks, 0);
     675         559 :   vlib_thread_stack_init (0);
     676             : 
     677         559 :   __os_thread_index = 0;
     678         559 :   vm->thread_index = 0;
     679             : 
     680         559 :   vlib_process_start_switch_stack (vm, 0);
     681        1118 :   i = clib_calljmp (thread0, (uword) vm,
     682         559 :                     (void *) (vlib_thread_stacks[0] +
     683             :                               VLIB_THREAD_STACK_SIZE));
     684         559 :   return i;
     685             : }
     686             : 
     687             : /*
     688             :  * fd.io coding-style-patch-verification: ON
     689             :  *
     690             :  * Local Variables:
     691             :  * eval: (c-set-style "gnu")
     692             :  * End:
     693             :  */

Generated by: LCOV version 1.14