1/* shopt.c, created from shopt.def. */ 2#line 23 "shopt.def" 3 4#line 36 "shopt.def" 5 6#include <config.h> 7 8#if defined (HAVE_UNISTD_H) 9# ifdef _MINIX 10# include <sys/types.h> 11# endif 12# include <unistd.h> 13#endif 14 15#include <stdio.h> 16 17#include "../bashintl.h" 18 19#include "../shell.h" 20#include "../flags.h" 21#include "common.h" 22#include "bashgetopt.h" 23 24#define UNSETOPT 0 25#define SETOPT 1 26 27#define OPTFMT "%-15s\t%s\n" 28 29extern int allow_null_glob_expansion, fail_glob_expansion, glob_dot_filenames; 30extern int cdable_vars, mail_warning, source_uses_path; 31extern int no_exit_on_failed_exec, print_shift_error; 32extern int check_hashed_filenames, promptvars; 33extern int cdspelling, expand_aliases; 34extern int extended_quote; 35extern int check_window_size; 36extern int glob_ignore_case, match_ignore_case; 37extern int hup_on_exit; 38extern int xpg_echo; 39extern int gnu_error_format; 40 41#if defined (EXTENDED_GLOB) 42extern int extended_glob; 43#endif 44 45#if defined (HISTORY) 46extern int literal_history, command_oriented_history; 47extern int force_append_history; 48#endif 49 50#if defined (READLINE) 51extern int hist_verify, history_reediting, perform_hostname_completion; 52extern int no_empty_command_completion; 53extern int force_fignore; 54extern int enable_hostname_completion __P((int)); 55#endif 56 57#if defined (PROGRAMMABLE_COMPLETION) 58extern int prog_completion_enabled; 59#endif 60 61#if defined (RESTRICTED_SHELL) 62extern char *shell_name; 63#endif 64 65#if defined (DEBUGGER) 66extern int debugging_mode; 67#endif 68 69static void shopt_error __P((char *)); 70 71static int set_shellopts_after_change __P((int)); 72 73static int set_compatibility_level __P((int)); 74 75#if defined (RESTRICTED_SHELL) 76static int set_restricted_shell __P((int)); 77#endif 78 79static int shopt_login_shell; 80static int shopt_compat31; 81 82typedef int shopt_set_func_t __P((int)); 83 84static struct { 85 char *name; 86 int *value; 87 shopt_set_func_t *set_func; 88} shopt_vars[] = { 89 { "cdable_vars", &cdable_vars, (shopt_set_func_t *)NULL }, 90 { "cdspell", &cdspelling, (shopt_set_func_t *)NULL }, 91 { "checkhash", &check_hashed_filenames, (shopt_set_func_t *)NULL }, 92 { "checkwinsize", &check_window_size, (shopt_set_func_t *)NULL }, 93#if defined (HISTORY) 94 { "cmdhist", &command_oriented_history, (shopt_set_func_t *)NULL }, 95#endif 96 { "compat31", &shopt_compat31, set_compatibility_level }, 97 { "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL }, 98 { "execfail", &no_exit_on_failed_exec, (shopt_set_func_t *)NULL }, 99 { "expand_aliases", &expand_aliases, (shopt_set_func_t *)NULL }, 100#if defined (DEBUGGER) 101 { "extdebug", &debugging_mode, (shopt_set_func_t *)NULL }, 102#endif 103#if defined (EXTENDED_GLOB) 104 { "extglob", &extended_glob, (shopt_set_func_t *)NULL }, 105#endif 106 { "extquote", &extended_quote, (shopt_set_func_t *)NULL }, 107 { "failglob", &fail_glob_expansion, (shopt_set_func_t *)NULL }, 108#if defined (READLINE) 109 { "force_fignore", &force_fignore, (shopt_set_func_t *)NULL }, 110#endif 111 { "gnu_errfmt", &gnu_error_format, (shopt_set_func_t *)NULL }, 112#if defined (HISTORY) 113 { "histappend", &force_append_history, (shopt_set_func_t *)NULL }, 114#endif 115#if defined (READLINE) 116 { "histreedit", &history_reediting, (shopt_set_func_t *)NULL }, 117 { "histverify", &hist_verify, (shopt_set_func_t *)NULL }, 118 { "hostcomplete", &perform_hostname_completion, enable_hostname_completion }, 119#endif 120 { "huponexit", &hup_on_exit, (shopt_set_func_t *)NULL }, 121 { "interactive_comments", &interactive_comments, set_shellopts_after_change }, 122#if defined (HISTORY) 123 { "lithist", &literal_history, (shopt_set_func_t *)NULL }, 124#endif 125 { "login_shell", &shopt_login_shell, set_login_shell }, 126 { "mailwarn", &mail_warning, (shopt_set_func_t *)NULL }, 127#if defined (READLINE) 128 { "no_empty_cmd_completion", &no_empty_command_completion, (shopt_set_func_t *)NULL }, 129#endif 130 { "nocaseglob", &glob_ignore_case, (shopt_set_func_t *)NULL }, 131 { "nocasematch", &match_ignore_case, (shopt_set_func_t *)NULL }, 132 { "nullglob", &allow_null_glob_expansion, (shopt_set_func_t *)NULL }, 133#if defined (PROGRAMMABLE_COMPLETION) 134 { "progcomp", &prog_completion_enabled, (shopt_set_func_t *)NULL }, 135#endif 136 { "promptvars", &promptvars, (shopt_set_func_t *)NULL }, 137#if defined (RESTRICTED_SHELL) 138 { "restricted_shell", &restricted_shell, set_restricted_shell }, 139#endif 140 { "shift_verbose", &print_shift_error, (shopt_set_func_t *)NULL }, 141 { "sourcepath", &source_uses_path, (shopt_set_func_t *)NULL }, 142 { "xpg_echo", &xpg_echo, (shopt_set_func_t *)NULL }, 143 { (char *)0, (int *)0, (shopt_set_func_t *)NULL } 144}; 145 146static char *on = "on"; 147static char *off = "off"; 148 149static int find_shopt __P((char *)); 150static int toggle_shopts __P((int, WORD_LIST *, int)); 151static void print_shopt __P((char *, int, int)); 152static int list_shopts __P((WORD_LIST *, int)); 153static int list_some_shopts __P((int, int)); 154static int list_shopt_o_options __P((WORD_LIST *, int)); 155static int list_some_o_options __P((int, int)); 156static int set_shopt_o_options __P((int, WORD_LIST *, int)); 157 158#define SFLAG 0x01 159#define UFLAG 0x02 160#define QFLAG 0x04 161#define OFLAG 0x08 162#define PFLAG 0x10 163 164int 165shopt_builtin (list) 166 WORD_LIST *list; 167{ 168 int opt, flags, rval; 169 170 flags = 0; 171 reset_internal_getopt (); 172 while ((opt = internal_getopt (list, "psuoq")) != -1) 173 { 174 switch (opt) 175 { 176 case 's': 177 flags |= SFLAG; 178 break; 179 case 'u': 180 flags |= UFLAG; 181 break; 182 case 'q': 183 flags |= QFLAG; 184 break; 185 case 'o': 186 flags |= OFLAG; 187 break; 188 case 'p': 189 flags |= PFLAG; 190 break; 191 default: 192 builtin_usage (); 193 return (EX_USAGE); 194 } 195 } 196 list = loptend; 197 198 if ((flags & (SFLAG|UFLAG)) == (SFLAG|UFLAG)) 199 { 200 builtin_error (_("cannot set and unset shell options simultaneously")); 201 return (EXECUTION_FAILURE); 202 } 203 204 rval = EXECUTION_SUCCESS; 205 if ((flags & OFLAG) && ((flags & (SFLAG|UFLAG)) == 0)) /* shopt -o */ 206 rval = list_shopt_o_options (list, flags); 207 else if (list && (flags & OFLAG)) /* shopt -so args */ 208 rval = set_shopt_o_options ((flags & SFLAG) ? FLAG_ON : FLAG_OFF, list, flags & QFLAG); 209 else if (flags & OFLAG) /* shopt -so */ 210 rval = list_some_o_options ((flags & SFLAG) ? 1 : 0, flags); 211 else if (list && (flags & (SFLAG|UFLAG))) /* shopt -su args */ 212 rval = toggle_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, list, flags & QFLAG); 213 else if ((flags & (SFLAG|UFLAG)) == 0) /* shopt [args] */ 214 rval = list_shopts (list, flags); 215 else /* shopt -su */ 216 rval = list_some_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, flags); 217 return (rval); 218} 219 220/* Reset the options managed by `shopt' to the values they would have at 221 shell startup. */ 222void 223reset_shopt_options () 224{ 225 allow_null_glob_expansion = glob_dot_filenames = 0; 226 cdable_vars = mail_warning = 0; 227 no_exit_on_failed_exec = print_shift_error = 0; 228 check_hashed_filenames = cdspelling = expand_aliases = check_window_size = 0; 229 230 source_uses_path = promptvars = 1; 231 232#if defined (EXTENDED_GLOB) 233 extended_glob = 0; 234#endif 235 236#if defined (HISTORY) 237 literal_history = force_append_history = 0; 238 command_oriented_history = 1; 239#endif 240 241#if defined (READLINE) 242 hist_verify = history_reediting = 0; 243 perform_hostname_completion = 1; 244#endif 245 246 shopt_login_shell = login_shell; 247} 248 249static int 250find_shopt (name) 251 char *name; 252{ 253 int i; 254 255 for (i = 0; shopt_vars[i].name; i++) 256 if (STREQ (name, shopt_vars[i].name)) 257 return i; 258 return -1; 259} 260 261static void 262shopt_error (s) 263 char *s; 264{ 265 builtin_error (_("%s: invalid shell option name"), s); 266} 267 268static int 269toggle_shopts (mode, list, quiet) 270 int mode; 271 WORD_LIST *list; 272 int quiet; 273{ 274 WORD_LIST *l; 275 int ind, rval; 276 277 for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next) 278 { 279 ind = find_shopt (l->word->word); 280 if (ind < 0) 281 { 282 shopt_error (l->word->word); 283 rval = EXECUTION_FAILURE; 284 } 285 else 286 { 287 *shopt_vars[ind].value = mode; /* 1 for set, 0 for unset */ 288 if (shopt_vars[ind].set_func) 289 (*shopt_vars[ind].set_func) (mode); 290 } 291 } 292 return (rval); 293} 294 295static void 296print_shopt (name, val, flags) 297 char *name; 298 int val, flags; 299{ 300 if (flags & PFLAG) 301 printf ("shopt %s %s\n", val ? "-s" : "-u", name); 302 else 303 printf (OPTFMT, name, val ? on : off); 304} 305 306/* List the values of all or any of the `shopt' options. Returns 0 if 307 all were listed or all variables queried were on; 1 otherwise. */ 308static int 309list_shopts (list, flags) 310 WORD_LIST *list; 311 int flags; 312{ 313 WORD_LIST *l; 314 int i, val, rval; 315 316 if (list == 0) 317 { 318 for (i = 0; shopt_vars[i].name; i++) 319 { 320 val = *shopt_vars[i].value; 321 if ((flags & QFLAG) == 0) 322 print_shopt (shopt_vars[i].name, val, flags); 323 } 324 return (EXECUTION_SUCCESS); 325 } 326 327 for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next) 328 { 329 i = find_shopt (l->word->word); 330 if (i < 0) 331 { 332 shopt_error (l->word->word); 333 rval = EXECUTION_FAILURE; 334 continue; 335 } 336 val = *shopt_vars[i].value; 337 if (val == 0) 338 rval = EXECUTION_FAILURE; 339 if ((flags & QFLAG) == 0) 340 print_shopt (l->word->word, val, flags); 341 } 342 343 return (rval); 344} 345 346static int 347list_some_shopts (mode, flags) 348 int mode, flags; 349{ 350 int val, i; 351 352 for (i = 0; shopt_vars[i].name; i++) 353 { 354 val = *shopt_vars[i].value; 355 if (((flags & QFLAG) == 0) && mode == val) 356 print_shopt (shopt_vars[i].name, val, flags); 357 } 358 return (EXECUTION_SUCCESS); 359} 360 361static int 362list_shopt_o_options (list, flags) 363 WORD_LIST *list; 364 int flags; 365{ 366 WORD_LIST *l; 367 int val, rval; 368 369 if (list == 0) 370 { 371 if ((flags & QFLAG) == 0) 372 list_minus_o_opts (-1, (flags & PFLAG)); 373 return (EXECUTION_SUCCESS); 374 } 375 376 for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next) 377 { 378 val = minus_o_option_value (l->word->word); 379 if (val == -1) 380 { 381 sh_invalidoptname (l->word->word); 382 rval = EXECUTION_FAILURE; 383 continue; 384 } 385 if (val == 0) 386 rval = EXECUTION_FAILURE; 387 if ((flags & QFLAG) == 0) 388 { 389 if (flags & PFLAG) 390 printf ("set %co %s\n", val ? '-' : '+', l->word->word); 391 else 392 printf (OPTFMT, l->word->word, val ? on : off); 393 } 394 } 395 return (rval); 396} 397 398static int 399list_some_o_options (mode, flags) 400 int mode, flags; 401{ 402 if ((flags & QFLAG) == 0) 403 list_minus_o_opts (mode, (flags & PFLAG)); 404 return (EXECUTION_SUCCESS); 405} 406 407static int 408set_shopt_o_options (mode, list, quiet) 409 int mode; 410 WORD_LIST *list; 411 int quiet; 412{ 413 WORD_LIST *l; 414 int rval; 415 416 for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next) 417 { 418 if (set_minus_o_option (mode, l->word->word) == EXECUTION_FAILURE) 419 rval = EXECUTION_FAILURE; 420 } 421 set_shellopts (); 422 return rval; 423} 424 425/* If we set or unset interactive_comments with shopt, make sure the 426 change is reflected in $SHELLOPTS. */ 427static int 428set_shellopts_after_change (mode) 429 int mode; 430{ 431 set_shellopts (); 432 return (0); 433} 434 435static int 436set_compatibility_level (mode) 437 int mode; 438{ 439 /* Need to change logic here as we add more compatibility levels */ 440 if (shopt_compat31) 441 shell_compatibility_level = 31; 442 else 443 shell_compatibility_level = 32; 444 return 0; 445} 446 447#if defined (RESTRICTED_SHELL) 448/* Don't allow the value of restricted_shell to be modified. */ 449 450static int 451set_restricted_shell (mode) 452 int mode; 453{ 454 static int save_restricted = -1; 455 456 if (save_restricted == -1) 457 save_restricted = shell_is_restricted (shell_name); 458 459 restricted_shell = save_restricted; 460 return (0); 461} 462#endif /* RESTRICTED_SHELL */ 463 464/* Not static so shell.c can call it to initialize shopt_login_shell */ 465int 466set_login_shell (mode) 467 int mode; 468{ 469 shopt_login_shell = login_shell != 0; 470 return (0); 471} 472 473char ** 474get_shopt_options () 475{ 476 char **ret; 477 int n, i; 478 479 n = sizeof (shopt_vars) / sizeof (shopt_vars[0]); 480 ret = strvec_create (n + 1); 481 for (i = 0; shopt_vars[i].name; i++) 482 ret[i] = savestring (shopt_vars[i].name); 483 ret[i] = (char *)NULL; 484 return ret; 485} 486 487/* 488 * External interface for other parts of the shell. NAME is a string option; 489 * MODE is 0 if we want to unset an option; 1 if we want to set an option. 490 * REUSABLE is 1 if we want to print output in a form that may be reused. 491 */ 492int 493shopt_setopt (name, mode) 494 char *name; 495 int mode; 496{ 497 WORD_LIST *wl; 498 int r; 499 500 wl = add_string_to_list (name, (WORD_LIST *)NULL); 501 r = toggle_shopts (mode, wl, 0); 502 dispose_words (wl); 503 return r; 504} 505 506int 507shopt_listopt (name, reusable) 508 char *name; 509 int reusable; 510{ 511 int i; 512 513 if (name == 0) 514 return (list_shopts ((WORD_LIST *)NULL, reusable ? PFLAG : 0)); 515 516 i = find_shopt (name); 517 if (i < 0) 518 { 519 shopt_error (name); 520 return (EXECUTION_FAILURE); 521 } 522 523 print_shopt (name, *shopt_vars[i].value, reusable ? PFLAG : 0); 524 return (EXECUTION_SUCCESS); 525} 526