1/* flags.c -- Everything about flags except the `set' command. That 2 is in builtins.c */ 3 4/* Copyright (C) 1987,1989 Free Software Foundation, Inc. 5 6This file is part of GNU Bash, the Bourne Again SHell. 7 8Bash is free software; you can redistribute it and/or modify it under 9the terms of the GNU General Public License as published by the Free 10Software Foundation; either version 2, or (at your option) any later 11version. 12 13Bash is distributed in the hope that it will be useful, but WITHOUT ANY 14WARRANTY; without even the implied warranty of MERCHANTABILITY or 15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16for more details. 17 18You should have received a copy of the GNU General Public License along 19with Bash; see the file COPYING. If not, write to the Free Software 20Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 21 22/* Flags hacking. */ 23#include "config.h" 24#if defined (HAVE_UNISTD_H) 25# include <unistd.h> 26#endif 27 28#include "shell.h" 29#include "flags.h" 30 31#if defined (BANG_HISTORY) 32# include "bashhist.h" 33#endif 34 35#if defined (JOB_CONTROL) 36extern int set_job_control __P((int)); 37#endif 38 39#if defined (RESTRICTED_SHELL) 40extern char *shell_name; 41#endif 42 43extern int shell_initialized; 44 45/* -c, -s invocation options -- not really flags, but they show up in $- */ 46extern int want_pending_command, read_from_stdin; 47 48/* **************************************************************** */ 49/* */ 50/* The Standard Sh Flags. */ 51/* */ 52/* **************************************************************** */ 53 54/* Non-zero means automatically mark variables which are modified or created 55 as auto export variables. */ 56int mark_modified_vars = 0; 57 58/* Non-zero causes asynchronous job notification. Otherwise, job state 59 notification only takes place just before a primary prompt is printed. */ 60int asynchronous_notification = 0; 61 62/* Non-zero means exit immediately if a command exits with a non-zero 63 exit status. */ 64int exit_immediately_on_error = 0; 65 66/* Non-zero means disable filename globbing. */ 67int disallow_filename_globbing = 0; 68 69/* Non-zero means that all keyword arguments are placed into the environment 70 for a command, not just those that appear on the line before the command 71 name. */ 72int place_keywords_in_env = 0; 73 74/* Non-zero means read commands, but don't execute them. This is useful 75 for debugging shell scripts that should do something hairy and possibly 76 destructive. */ 77int read_but_dont_execute = 0; 78 79/* Non-zero means end of file is after one command. */ 80int just_one_command = 0; 81 82/* Non-zero means don't overwrite existing files while doing redirections. */ 83int noclobber = 0; 84 85/* Non-zero means trying to get the value of $i where $i is undefined 86 causes an error, instead of a null substitution. */ 87int unbound_vars_is_error = 0; 88 89/* Non-zero means type out input lines after you read them. */ 90int echo_input_at_read = 0; 91 92/* Non-zero means type out the command definition after reading, but 93 before executing. */ 94int echo_command_at_execute = 0; 95 96/* Non-zero means turn on the job control features. */ 97int jobs_m_flag = 0; 98 99/* Non-zero means this shell is interactive, even if running under a 100 pipe. */ 101int forced_interactive = 0; 102 103/* By default, follow the symbolic links as if they were real directories 104 while hacking the `cd' command. This means that `cd ..' moves up in 105 the string of symbolic links that make up the current directory, instead 106 of the absolute directory. The shell variable `nolinks' also controls 107 this flag. */ 108int no_symbolic_links = 0; 109 110/* **************************************************************** */ 111/* */ 112/* Non-Standard Flags Follow Here. */ 113/* */ 114/* **************************************************************** */ 115 116#if 0 117/* Non-zero means do lexical scoping in the body of a FOR command. */ 118int lexical_scoping = 0; 119#endif 120 121/* Non-zero means no such thing as invisible variables. */ 122int no_invisible_vars = 0; 123 124/* Non-zero means look up and remember command names in a hash table, */ 125int hashing_enabled = 1; 126 127#if defined (BANG_HISTORY) 128/* Non-zero means that we are doing history expansion. The default. 129 This means !22 gets the 22nd line of history. */ 130int history_expansion = 1; 131#endif /* BANG_HISTORY */ 132 133/* Non-zero means that we allow comments to appear in interactive commands. */ 134int interactive_comments = 1; 135 136#if defined (RESTRICTED_SHELL) 137/* Non-zero means that this shell is `restricted'. A restricted shell 138 disallows: changing directories, command or path names containing `/', 139 unsetting or resetting the values of $PATH and $SHELL, and any type of 140 output redirection. */ 141int restricted = 0; /* currently restricted */ 142int restricted_shell = 0; /* shell was started in restricted mode. */ 143#endif /* RESTRICTED_SHELL */ 144 145/* Non-zero means that this shell is running in `privileged' mode. This 146 is required if the shell is to run setuid. If the `-p' option is 147 not supplied at startup, and the real and effective uids or gids 148 differ, disable_priv_mode is called to relinquish setuid status. */ 149int privileged_mode = 0; 150 151#if defined (BRACE_EXPANSION) 152/* Zero means to disable brace expansion: foo{a,b} -> fooa foob */ 153int brace_expansion = 1; 154#endif 155 156/* Non-zero means that shell functions inherit the DEBUG trap. */ 157int function_trace_mode = 0; 158 159/* Non-zero means that shell functions inherit the ERR trap. */ 160int error_trace_mode = 0; 161 162/* Non-zero means that the rightmost non-zero exit status in a pipeline 163 is the exit status of the entire pipeline. If each processes exits 164 with a 0 status, the status of the pipeline is 0. */ 165int pipefail_opt = 0; 166 167/* **************************************************************** */ 168/* */ 169/* The Flags ALIST. */ 170/* */ 171/* **************************************************************** */ 172 173struct flags_alist shell_flags[] = { 174 /* Standard sh flags. */ 175 { 'a', &mark_modified_vars }, 176#if defined (JOB_CONTROL) 177 { 'b', &asynchronous_notification }, 178#endif /* JOB_CONTROL */ 179 { 'e', &exit_immediately_on_error }, 180 { 'f', &disallow_filename_globbing }, 181 { 'h', &hashing_enabled }, 182 { 'i', &forced_interactive }, 183 { 'k', &place_keywords_in_env }, 184#if defined (JOB_CONTROL) 185 { 'm', &jobs_m_flag }, 186#endif /* JOB_CONTROL */ 187 { 'n', &read_but_dont_execute }, 188 { 'p', &privileged_mode }, 189#if defined (RESTRICTED_SHELL) 190 { 'r', &restricted }, 191#endif /* RESTRICTED_SHELL */ 192 { 't', &just_one_command }, 193 { 'u', &unbound_vars_is_error }, 194 { 'v', &echo_input_at_read }, 195 { 'x', &echo_command_at_execute }, 196 197 /* New flags that control non-standard things. */ 198#if 0 199 { 'l', &lexical_scoping }, 200#endif 201#if defined (BRACE_EXPANSION) 202 { 'B', &brace_expansion }, 203#endif 204 { 'C', &noclobber }, 205 { 'E', &error_trace_mode }, 206#if defined (BANG_HISTORY) 207 { 'H', &history_expansion }, 208#endif /* BANG_HISTORY */ 209 { 'I', &no_invisible_vars }, 210 { 'P', &no_symbolic_links }, 211 { 'T', &function_trace_mode }, 212 {0, (int *)NULL} 213}; 214 215#define NUM_SHELL_FLAGS (sizeof (shell_flags) / sizeof (struct flags_alist)) 216 217char optflags[NUM_SHELL_FLAGS+4] = { '+' }; 218 219int * 220find_flag (name) 221 int name; 222{ 223 int i; 224 for (i = 0; shell_flags[i].name; i++) 225 { 226 if (shell_flags[i].name == name) 227 return (shell_flags[i].value); 228 } 229 return (FLAG_UNKNOWN); 230} 231 232/* Change the state of a flag, and return it's original value, or return 233 FLAG_ERROR if there is no flag FLAG. ON_OR_OFF must be either 234 FLAG_ON or FLAG_OFF. */ 235int 236change_flag (flag, on_or_off) 237 int flag; 238 int on_or_off; 239{ 240 int *value, old_value; 241 242#if defined (RESTRICTED_SHELL) 243 /* Don't allow "set +r" in a shell which is `restricted'. */ 244 if (restricted && flag == 'r' && on_or_off == FLAG_OFF) 245 return (FLAG_ERROR); 246#endif /* RESTRICTED_SHELL */ 247 248 value = find_flag (flag); 249 250 if ((value == (int *)FLAG_UNKNOWN) || (on_or_off != FLAG_ON && on_or_off != FLAG_OFF)) 251 return (FLAG_ERROR); 252 253 old_value = *value; 254 255 *value = (on_or_off == FLAG_ON) ? 1 : 0; 256 257 /* Special cases for a few flags. */ 258 switch (flag) 259 { 260#if defined (BANG_HISTORY) 261 case 'H': 262 if (on_or_off == FLAG_ON) 263 bash_initialize_history (); 264 break; 265#endif 266 267#if defined (JOB_CONTROL) 268 case 'm': 269 set_job_control (on_or_off == FLAG_ON); 270 break; 271#endif /* JOB_CONTROL */ 272 273 case 'n': 274 if (interactive_shell) 275 read_but_dont_execute = 0; 276 break; 277 278 case 'p': 279 if (on_or_off == FLAG_OFF) 280 disable_priv_mode (); 281 break; 282 283#if defined (RESTRICTED_SHELL) 284 case 'r': 285 if (on_or_off == FLAG_ON && shell_initialized) 286 maybe_make_restricted (shell_name); 287 break; 288#endif 289 290 } 291 292 return (old_value); 293} 294 295/* Return a string which is the names of all the currently 296 set shell flags. */ 297char * 298which_set_flags () 299{ 300 char *temp; 301 int i, string_index; 302 303 temp = (char *)xmalloc (1 + NUM_SHELL_FLAGS + read_from_stdin + want_pending_command); 304 for (i = string_index = 0; shell_flags[i].name; i++) 305 if (*(shell_flags[i].value)) 306 temp[string_index++] = shell_flags[i].name; 307 308 if (want_pending_command) 309 temp[string_index++] = 'c'; 310 if (read_from_stdin) 311 temp[string_index++] = 's'; 312 313 temp[string_index] = '\0'; 314 return (temp); 315} 316 317void 318reset_shell_flags () 319{ 320 mark_modified_vars = exit_immediately_on_error = disallow_filename_globbing = 0; 321 place_keywords_in_env = read_but_dont_execute = just_one_command = 0; 322 noclobber = unbound_vars_is_error = echo_input_at_read = 0; 323 echo_command_at_execute = jobs_m_flag = forced_interactive = 0; 324 no_symbolic_links = no_invisible_vars = privileged_mode = pipefail_opt = 0; 325 326 hashing_enabled = interactive_comments = 1; 327 328#if defined (JOB_CONTROL) 329 asynchronous_notification = 0; 330#endif 331 332#if defined (BANG_HISTORY) 333 history_expansion = 1; 334#endif 335 336#if defined (BRACE_EXPANSION) 337 brace_expansion = 1; 338#endif 339 340#if defined (RESTRICTED_SHELL) 341 restricted = 0; 342#endif 343} 344 345void 346initialize_flags () 347{ 348 register int i; 349 350 for (i = 0; shell_flags[i].name; i++) 351 optflags[i+1] = shell_flags[i].name; 352 optflags[++i] = 'o'; 353 optflags[++i] = ';'; 354 optflags[i+1] = '\0'; 355} 356