1/* Virtual terminal interface shell. 2 * Copyright (C) 2000 Kunihiro Ishiguro 3 * 4 * This file is part of GNU Zebra. 5 * 6 * GNU Zebra is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2, or (at your option) any 9 * later version. 10 * 11 * GNU Zebra is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with GNU Zebra; see the file COPYING. If not, write to the Free 18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 * 02111-1307, USA. 20 */ 21 22#include <zebra.h> 23 24#include <sys/un.h> 25#include <setjmp.h> 26#include <sys/wait.h> 27#include <pwd.h> 28 29#include <readline/readline.h> 30#include <readline/history.h> 31 32#include "version.h" 33#include "getopt.h" 34#include "command.h" 35 36#include "vtysh/vtysh.h" 37#include "vtysh/vtysh_user.h" 38 39/* VTY shell program name. */ 40char *progname; 41 42/* Configuration file name. Usually this is configurable, but vtysh 43 has static configuration file only. */ 44char *config_file = NULL; 45 46/* Configuration file and directory. */ 47char *config_current = NULL; 48char config_default[] = SYSCONFDIR VTYSH_DEFAULT_CONFIG; 49 50/* Integrated configuration file. */ 51char *integrate_file = NULL; 52char *integrate_current = NULL; 53#if 0 54char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG; 55#endif 56 57/* Flag for indicate executing child command. */ 58int execute_flag = 0; 59 60/* For sigsetjmp() & siglongjmp(). */ 61static sigjmp_buf jmpbuf; 62 63/* Flag for avoid recursive siglongjmp() call. */ 64static int jmpflag = 0; 65 66/* A static variable for holding the line. */ 67static char *line_read; 68 69/* Master of threads. */ 70struct thread_master *master; 71 72/* SIGTSTP handler. This function care user's ^Z input. */ 73void 74sigtstp (int sig) 75{ 76 /* Execute "end" command. */ 77 vtysh_execute ("end"); 78 79 /* Initialize readline. */ 80 rl_initialize (); 81 printf ("\n"); 82 83 /* Check jmpflag for duplicate siglongjmp(). */ 84 if (! jmpflag) 85 return; 86 87 jmpflag = 0; 88 89 /* Back to main command loop. */ 90 siglongjmp (jmpbuf, 1); 91} 92 93/* SIGINT handler. This function care user's ^Z input. */ 94void 95sigint (int sig) 96{ 97 /* Check this process is not child process. */ 98 if (! execute_flag) 99 { 100 rl_initialize (); 101 printf ("\n"); 102 rl_forced_update_display (); 103 } 104} 105 106/* Signale wrapper. */ 107RETSIGTYPE * 108signal_set (int signo, void (*func)(int)) 109{ 110 int ret; 111 struct sigaction sig; 112 struct sigaction osig; 113 114 sig.sa_handler = func; 115 sigemptyset (&sig.sa_mask); 116 sig.sa_flags = 0; 117#ifdef SA_RESTART 118 sig.sa_flags |= SA_RESTART; 119#endif /* SA_RESTART */ 120 121 ret = sigaction (signo, &sig, &osig); 122 123 if (ret < 0) 124 return (SIG_ERR); 125 else 126 return (osig.sa_handler); 127} 128 129/* Initialization of signal handles. */ 130void 131signal_init () 132{ 133 signal_set (SIGINT, sigint); 134 signal_set (SIGTSTP, sigtstp); 135 signal_set (SIGPIPE, SIG_IGN); 136} 137 138/* Help information display. */ 139static void 140usage (int status) 141{ 142 if (status != 0) 143 fprintf (stderr, "Try `%s --help' for more information.\n", progname); 144 else 145 { 146 printf ("Usage : %s [OPTION...]\n\n\ 147Daemon which manages kernel routing table management and \ 148redistribution between different routing protocols.\n\n\ 149-b, --boot Execute boot startup configuration\n\ 150-e, --eval Execute argument as command\n\ 151-h, --help Display this help and exit\n\ 152\n\ 153Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS); 154 } 155 exit (status); 156} 157 158/* VTY shell options, we use GNU getopt library. */ 159struct option longopts[] = 160{ 161 { "boot", no_argument, NULL, 'b'}, 162 { "eval", required_argument, NULL, 'e'}, 163 { "help", no_argument, NULL, 'h'}, 164 { 0 } 165}; 166 167/* Read a string, and return a pointer to it. Returns NULL on EOF. */ 168char * 169vtysh_rl_gets () 170{ 171 /* If the buffer has already been allocated, return the memory 172 to the free pool. */ 173 if (line_read) 174 { 175 free (line_read); 176 line_read = NULL; 177 } 178 179 /* Get a line from the user. Change prompt according to node. XXX. */ 180 line_read = readline (vtysh_prompt ()); 181 182 /* If the line has any text in it, save it on the history. */ 183 if (line_read && *line_read) 184 add_history (line_read); 185 186 return (line_read); 187} 188 189/* VTY shell main routine. */ 190int 191main (int argc, char **argv, char **env) 192{ 193 char *p; 194 int opt; 195 int eval_flag = 0; 196 int boot_flag = 0; 197 char *eval_line = NULL; 198 char *integrated_file = NULL; 199 200 /* Preserve name of myself. */ 201 progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); 202 203 /* Option handling. */ 204 while (1) 205 { 206 opt = getopt_long (argc, argv, "be:h", longopts, 0); 207 208 if (opt == EOF) 209 break; 210 211 switch (opt) 212 { 213 case 0: 214 break; 215 case 'b': 216 boot_flag = 1; 217 break; 218 case 'e': 219 eval_flag = 1; 220 eval_line = optarg; 221 break; 222 case 'h': 223 usage (0); 224 break; 225 case 'i': 226 integrated_file = strdup (optarg); 227 default: 228 usage (1); 229 break; 230 } 231 } 232 233 /* Initialize user input buffer. */ 234 line_read = NULL; 235 236 /* Signal and others. */ 237 signal_init (); 238 239 /* Make vty structure and register commands. */ 240 vtysh_init_vty (); 241 vtysh_init_cmd (); 242 vtysh_user_init (); 243 vtysh_config_init (); 244 245 vty_init_vtysh (); 246 247 sort_node (); 248 249 vtysh_connect_all (); 250 251 /* Read vtysh configuration file. */ 252 vtysh_read_config (config_file, config_current, config_default); 253 254 /* If eval mode */ 255 if (eval_flag) 256 { 257 vtysh_execute_no_pager (eval_line); 258 exit (0); 259 } 260 261 /* Boot startup configuration file. */ 262 if (boot_flag) 263 { 264 vtysh_read_config (integrate_file, integrate_current, integrate_default); 265 exit (0); 266 } 267 268 vtysh_pager_init (); 269 270 vtysh_readline_init (); 271 272 vty_hello (vty); 273 274 vtysh_auth (); 275 276 /* Preparation for longjmp() in sigtstp(). */ 277 sigsetjmp (jmpbuf, 1); 278 jmpflag = 1; 279 280 /* Main command loop. */ 281 while (vtysh_rl_gets ()) 282 vtysh_execute (line_read); 283 284 printf ("\n"); 285 286 /* Rest in peace. */ 287 exit (0); 288} 289