1/* 2 * options.c - shell options 3 * 4 * This file is part of zsh, the Z shell. 5 * 6 * Copyright (c) 1992-1997 Paul Falstad 7 * All rights reserved. 8 * 9 * Permission is hereby granted, without written agreement and without 10 * license or royalty fees, to use, copy, modify, and distribute this 11 * software and to distribute modified versions of this software for any 12 * purpose, provided that the above copyright notice and the following 13 * two paragraphs appear in all copies of this software. 14 * 15 * In no event shall Paul Falstad or the Zsh Development Group be liable 16 * to any party for direct, indirect, special, incidental, or consequential 17 * damages arising out of the use of this software and its documentation, 18 * even if Paul Falstad and the Zsh Development Group have been advised of 19 * the possibility of such damage. 20 * 21 * Paul Falstad and the Zsh Development Group specifically disclaim any 22 * warranties, including, but not limited to, the implied warranties of 23 * merchantability and fitness for a particular purpose. The software 24 * provided hereunder is on an "as is" basis, and Paul Falstad and the 25 * Zsh Development Group have no obligation to provide maintenance, 26 * support, updates, enhancements, or modifications. 27 * 28 */ 29 30#include "zsh.mdh" 31#include "options.pro" 32 33/* current emulation (used to decide which set of option letters is used) */ 34 35/**/ 36mod_export int emulation; 37 38/* current sticky emulation: sticky = NULL means none */ 39 40/**/ 41mod_export Emulation_options sticky; 42 43/* the options; e.g. if opts[SHGLOB] != 0, SH_GLOB is turned on */ 44 45/**/ 46mod_export char opts[OPT_SIZE]; 47 48/* Option name hash table */ 49 50/**/ 51mod_export HashTable optiontab; 52 53/* The canonical option name table */ 54 55#define OPT_CSH EMULATE_CSH 56#define OPT_KSH EMULATE_KSH 57#define OPT_SH EMULATE_SH 58#define OPT_ZSH EMULATE_ZSH 59 60#define OPT_ALL (OPT_CSH|OPT_KSH|OPT_SH|OPT_ZSH) 61#define OPT_BOURNE (OPT_KSH|OPT_SH) 62#define OPT_BSHELL (OPT_KSH|OPT_SH|OPT_ZSH) 63#define OPT_NONBOURNE (OPT_ALL & ~OPT_BOURNE) 64#define OPT_NONZSH (OPT_ALL & ~OPT_ZSH) 65 66/* option is relevant to emulation */ 67#define OPT_EMULATE (EMULATE_UNUSED) 68/* option should never be set by emulate() */ 69#define OPT_SPECIAL (EMULATE_UNUSED<<1) 70/* option is an alias to an other option */ 71#define OPT_ALIAS (EMULATE_UNUSED<<2) 72 73#define defset(X, my_emulation) (!!((X)->node.flags & my_emulation)) 74 75/* 76 * Note that option names should usually be fewer than 20 characters long 77 * to avoid formatting problems. 78 */ 79static struct optname optns[] = { 80{{NULL, "aliases", OPT_EMULATE|OPT_ALL}, ALIASESOPT}, 81{{NULL, "allexport", OPT_EMULATE}, ALLEXPORT}, 82{{NULL, "alwayslastprompt", OPT_ALL}, ALWAYSLASTPROMPT}, 83{{NULL, "alwaystoend", 0}, ALWAYSTOEND}, 84{{NULL, "appendhistory", OPT_ALL}, APPENDHISTORY}, 85{{NULL, "autocd", OPT_EMULATE}, AUTOCD}, 86{{NULL, "autocontinue", 0}, AUTOCONTINUE}, 87{{NULL, "autolist", OPT_ALL}, AUTOLIST}, 88{{NULL, "automenu", OPT_ALL}, AUTOMENU}, 89{{NULL, "autonamedirs", 0}, AUTONAMEDIRS}, 90{{NULL, "autoparamkeys", OPT_ALL}, AUTOPARAMKEYS}, 91{{NULL, "autoparamslash", OPT_ALL}, AUTOPARAMSLASH}, 92{{NULL, "autopushd", 0}, AUTOPUSHD}, 93{{NULL, "autoremoveslash", OPT_ALL}, AUTOREMOVESLASH}, 94{{NULL, "autoresume", 0}, AUTORESUME}, 95{{NULL, "badpattern", OPT_EMULATE|OPT_NONBOURNE},BADPATTERN}, 96{{NULL, "banghist", OPT_NONBOURNE}, BANGHIST}, 97{{NULL, "bareglobqual", OPT_EMULATE|OPT_ZSH}, BAREGLOBQUAL}, 98{{NULL, "bashautolist", 0}, BASHAUTOLIST}, 99{{NULL, "bashrematch", 0}, BASHREMATCH}, 100{{NULL, "beep", OPT_ALL}, BEEP}, 101{{NULL, "bgnice", OPT_EMULATE|OPT_NONBOURNE},BGNICE}, 102{{NULL, "braceccl", OPT_EMULATE}, BRACECCL}, 103{{NULL, "bsdecho", OPT_EMULATE|OPT_SH}, BSDECHO}, 104{{NULL, "caseglob", OPT_ALL}, CASEGLOB}, 105{{NULL, "casematch", OPT_ALL}, CASEMATCH}, 106{{NULL, "cbases", 0}, CBASES}, 107{{NULL, "cprecedences", OPT_EMULATE|OPT_NONZSH}, CPRECEDENCES}, 108{{NULL, "cdablevars", OPT_EMULATE}, CDABLEVARS}, 109{{NULL, "chasedots", OPT_EMULATE}, CHASEDOTS}, 110{{NULL, "chaselinks", OPT_EMULATE}, CHASELINKS}, 111{{NULL, "checkjobs", OPT_EMULATE|OPT_ZSH}, CHECKJOBS}, 112{{NULL, "clobber", OPT_EMULATE|OPT_ALL}, CLOBBER}, 113{{NULL, "combiningchars", 0}, COMBININGCHARS}, 114{{NULL, "completealiases", 0}, COMPLETEALIASES}, 115{{NULL, "completeinword", 0}, COMPLETEINWORD}, 116{{NULL, "continueonerror", 0}, CONTINUEONERROR}, 117{{NULL, "correct", 0}, CORRECT}, 118{{NULL, "correctall", 0}, CORRECTALL}, 119{{NULL, "cshjunkiehistory", OPT_EMULATE|OPT_CSH}, CSHJUNKIEHISTORY}, 120{{NULL, "cshjunkieloops", OPT_EMULATE|OPT_CSH}, CSHJUNKIELOOPS}, 121{{NULL, "cshjunkiequotes", OPT_EMULATE|OPT_CSH}, CSHJUNKIEQUOTES}, 122{{NULL, "cshnullcmd", OPT_EMULATE|OPT_CSH}, CSHNULLCMD}, 123{{NULL, "cshnullglob", OPT_EMULATE|OPT_CSH}, CSHNULLGLOB}, 124{{NULL, "debugbeforecmd", OPT_ALL}, DEBUGBEFORECMD}, 125{{NULL, "emacs", 0}, EMACSMODE}, 126{{NULL, "equals", OPT_EMULATE|OPT_ZSH}, EQUALS}, 127{{NULL, "errexit", OPT_EMULATE}, ERREXIT}, 128{{NULL, "errreturn", OPT_EMULATE}, ERRRETURN}, 129{{NULL, "exec", OPT_ALL}, EXECOPT}, 130{{NULL, "extendedglob", OPT_EMULATE}, EXTENDEDGLOB}, 131{{NULL, "extendedhistory", OPT_CSH}, EXTENDEDHISTORY}, 132{{NULL, "evallineno", OPT_EMULATE|OPT_ZSH}, EVALLINENO}, 133{{NULL, "flowcontrol", OPT_ALL}, FLOWCONTROL}, 134{{NULL, "forcefloat", 0}, FORCEFLOAT}, 135{{NULL, "functionargzero", OPT_EMULATE|OPT_NONBOURNE},FUNCTIONARGZERO}, 136{{NULL, "glob", OPT_EMULATE|OPT_ALL}, GLOBOPT}, 137{{NULL, "globalexport", OPT_EMULATE|OPT_ZSH}, GLOBALEXPORT}, 138{{NULL, "globalrcs", OPT_ALL}, GLOBALRCS}, 139{{NULL, "globassign", OPT_EMULATE|OPT_CSH}, GLOBASSIGN}, 140{{NULL, "globcomplete", 0}, GLOBCOMPLETE}, 141{{NULL, "globdots", OPT_EMULATE}, GLOBDOTS}, 142{{NULL, "globsubst", OPT_EMULATE|OPT_NONZSH}, GLOBSUBST}, 143{{NULL, "hashcmds", OPT_ALL}, HASHCMDS}, 144{{NULL, "hashdirs", OPT_ALL}, HASHDIRS}, 145{{NULL, "hashexecutablesonly", 0}, HASHEXECUTABLESONLY}, 146{{NULL, "hashlistall", OPT_ALL}, HASHLISTALL}, 147{{NULL, "histallowclobber", 0}, HISTALLOWCLOBBER}, 148{{NULL, "histbeep", OPT_ALL}, HISTBEEP}, 149{{NULL, "histexpiredupsfirst",0}, HISTEXPIREDUPSFIRST}, 150{{NULL, "histfcntllock", 0}, HISTFCNTLLOCK}, 151{{NULL, "histfindnodups", 0}, HISTFINDNODUPS}, 152{{NULL, "histignorealldups", 0}, HISTIGNOREALLDUPS}, 153{{NULL, "histignoredups", 0}, HISTIGNOREDUPS}, 154{{NULL, "histignorespace", 0}, HISTIGNORESPACE}, 155{{NULL, "histlexwords", 0}, HISTLEXWORDS}, 156{{NULL, "histnofunctions", 0}, HISTNOFUNCTIONS}, 157{{NULL, "histnostore", 0}, HISTNOSTORE}, 158{{NULL, "histsubstpattern", OPT_EMULATE}, HISTSUBSTPATTERN}, 159{{NULL, "histreduceblanks", 0}, HISTREDUCEBLANKS}, 160{{NULL, "histsavebycopy", OPT_ALL}, HISTSAVEBYCOPY}, 161{{NULL, "histsavenodups", 0}, HISTSAVENODUPS}, 162{{NULL, "histverify", 0}, HISTVERIFY}, 163{{NULL, "hup", OPT_EMULATE|OPT_ZSH}, HUP}, 164{{NULL, "ignorebraces", OPT_EMULATE|OPT_SH}, IGNOREBRACES}, 165{{NULL, "ignoreclosebraces", OPT_EMULATE}, IGNORECLOSEBRACES}, 166{{NULL, "ignoreeof", 0}, IGNOREEOF}, 167{{NULL, "incappendhistory", 0}, INCAPPENDHISTORY}, 168{{NULL, "interactive", OPT_SPECIAL}, INTERACTIVE}, 169{{NULL, "interactivecomments",OPT_BOURNE}, INTERACTIVECOMMENTS}, 170{{NULL, "ksharrays", OPT_EMULATE|OPT_BOURNE}, KSHARRAYS}, 171{{NULL, "kshautoload", OPT_EMULATE|OPT_BOURNE}, KSHAUTOLOAD}, 172{{NULL, "kshglob", OPT_EMULATE|OPT_KSH}, KSHGLOB}, 173{{NULL, "kshoptionprint", OPT_EMULATE|OPT_KSH}, KSHOPTIONPRINT}, 174{{NULL, "kshtypeset", OPT_EMULATE|OPT_KSH}, KSHTYPESET}, 175{{NULL, "kshzerosubscript", 0}, KSHZEROSUBSCRIPT}, 176{{NULL, "listambiguous", OPT_ALL}, LISTAMBIGUOUS}, 177{{NULL, "listbeep", OPT_ALL}, LISTBEEP}, 178{{NULL, "listpacked", 0}, LISTPACKED}, 179{{NULL, "listrowsfirst", 0}, LISTROWSFIRST}, 180{{NULL, "listtypes", OPT_ALL}, LISTTYPES}, 181{{NULL, "localoptions", OPT_EMULATE|OPT_KSH}, LOCALOPTIONS}, 182{{NULL, "localpatterns", OPT_EMULATE}, LOCALPATTERNS}, 183{{NULL, "localtraps", OPT_EMULATE|OPT_KSH}, LOCALTRAPS}, 184{{NULL, "login", OPT_SPECIAL}, LOGINSHELL}, 185{{NULL, "longlistjobs", 0}, LONGLISTJOBS}, 186{{NULL, "magicequalsubst", OPT_EMULATE}, MAGICEQUALSUBST}, 187{{NULL, "mailwarning", 0}, MAILWARNING}, 188{{NULL, "markdirs", 0}, MARKDIRS}, 189{{NULL, "menucomplete", 0}, MENUCOMPLETE}, 190{{NULL, "monitor", OPT_SPECIAL}, MONITOR}, 191{{NULL, "multibyte", 192#ifdef MULTIBYTE_SUPPORT 193 OPT_EMULATE|OPT_ZSH|OPT_CSH|OPT_KSH 194#else 195 0 196#endif 197 }, MULTIBYTE}, 198{{NULL, "multifuncdef", OPT_EMULATE|OPT_ZSH}, MULTIFUNCDEF}, 199{{NULL, "multios", OPT_EMULATE|OPT_ZSH}, MULTIOS}, 200{{NULL, "nomatch", OPT_EMULATE|OPT_NONBOURNE},NOMATCH}, 201{{NULL, "notify", OPT_ZSH}, NOTIFY}, 202{{NULL, "nullglob", OPT_EMULATE}, NULLGLOB}, 203{{NULL, "numericglobsort", OPT_EMULATE}, NUMERICGLOBSORT}, 204{{NULL, "octalzeroes", OPT_EMULATE|OPT_SH}, OCTALZEROES}, 205{{NULL, "overstrike", 0}, OVERSTRIKE}, 206{{NULL, "pathdirs", OPT_EMULATE}, PATHDIRS}, 207{{NULL, "pathscript", OPT_EMULATE|OPT_BOURNE}, PATHSCRIPT}, 208{{NULL, "pipefail", OPT_EMULATE}, PIPEFAIL}, 209{{NULL, "posixaliases", OPT_EMULATE|OPT_BOURNE}, POSIXALIASES}, 210{{NULL, "posixbuiltins", OPT_EMULATE|OPT_BOURNE}, POSIXBUILTINS}, 211{{NULL, "posixcd", OPT_EMULATE|OPT_BOURNE}, POSIXCD}, 212{{NULL, "posixidentifiers", OPT_EMULATE|OPT_BOURNE}, POSIXIDENTIFIERS}, 213{{NULL, "posixjobs", OPT_EMULATE|OPT_BOURNE}, POSIXJOBS}, 214{{NULL, "posixstrings", OPT_EMULATE|OPT_BOURNE}, POSIXSTRINGS}, 215{{NULL, "posixtraps", OPT_EMULATE|OPT_BOURNE}, POSIXTRAPS}, 216{{NULL, "printeightbit", 0}, PRINTEIGHTBIT}, 217{{NULL, "printexitvalue", 0}, PRINTEXITVALUE}, 218{{NULL, "privileged", OPT_SPECIAL}, PRIVILEGED}, 219{{NULL, "promptbang", OPT_KSH}, PROMPTBANG}, 220{{NULL, "promptcr", OPT_ALL}, PROMPTCR}, 221{{NULL, "promptpercent", OPT_NONBOURNE}, PROMPTPERCENT}, 222{{NULL, "promptsp", OPT_ALL}, PROMPTSP}, 223{{NULL, "promptsubst", OPT_BOURNE}, PROMPTSUBST}, 224{{NULL, "pushdignoredups", OPT_EMULATE}, PUSHDIGNOREDUPS}, 225{{NULL, "pushdminus", OPT_EMULATE}, PUSHDMINUS}, 226{{NULL, "pushdsilent", 0}, PUSHDSILENT}, 227{{NULL, "pushdtohome", OPT_EMULATE}, PUSHDTOHOME}, 228{{NULL, "rcexpandparam", OPT_EMULATE}, RCEXPANDPARAM}, 229{{NULL, "rcquotes", OPT_EMULATE}, RCQUOTES}, 230{{NULL, "rcs", OPT_ALL}, RCS}, 231{{NULL, "recexact", 0}, RECEXACT}, 232{{NULL, "rematchpcre", 0}, REMATCHPCRE}, 233{{NULL, "restricted", OPT_SPECIAL}, RESTRICTED}, 234{{NULL, "rmstarsilent", OPT_BOURNE}, RMSTARSILENT}, 235{{NULL, "rmstarwait", 0}, RMSTARWAIT}, 236{{NULL, "sharehistory", OPT_KSH}, SHAREHISTORY}, 237{{NULL, "shfileexpansion", OPT_EMULATE|OPT_BOURNE}, SHFILEEXPANSION}, 238{{NULL, "shglob", OPT_EMULATE|OPT_BOURNE}, SHGLOB}, 239{{NULL, "shinstdin", OPT_SPECIAL}, SHINSTDIN}, 240{{NULL, "shnullcmd", OPT_EMULATE|OPT_BOURNE}, SHNULLCMD}, 241{{NULL, "shoptionletters", OPT_EMULATE|OPT_BOURNE}, SHOPTIONLETTERS}, 242{{NULL, "shortloops", OPT_EMULATE|OPT_NONBOURNE},SHORTLOOPS}, 243{{NULL, "shwordsplit", OPT_EMULATE|OPT_BOURNE}, SHWORDSPLIT}, 244{{NULL, "singlecommand", OPT_SPECIAL}, SINGLECOMMAND}, 245{{NULL, "singlelinezle", OPT_KSH}, SINGLELINEZLE}, 246{{NULL, "sourcetrace", 0}, SOURCETRACE}, 247{{NULL, "sunkeyboardhack", 0}, SUNKEYBOARDHACK}, 248{{NULL, "transientrprompt", 0}, TRANSIENTRPROMPT}, 249{{NULL, "trapsasync", 0}, TRAPSASYNC}, 250{{NULL, "typesetsilent", OPT_EMULATE|OPT_BOURNE}, TYPESETSILENT}, 251{{NULL, "unset", OPT_EMULATE|OPT_BSHELL}, UNSET}, 252{{NULL, "verbose", 0}, VERBOSE}, 253{{NULL, "vi", 0}, VIMODE}, 254{{NULL, "warncreateglobal", 0}, WARNCREATEGLOBAL}, 255{{NULL, "xtrace", 0}, XTRACE}, 256{{NULL, "zle", OPT_SPECIAL}, USEZLE}, 257{{NULL, "braceexpand", OPT_ALIAS}, /* ksh/bash */ -IGNOREBRACES}, 258{{NULL, "dotglob", OPT_ALIAS}, /* bash */ GLOBDOTS}, 259{{NULL, "hashall", OPT_ALIAS}, /* bash */ HASHCMDS}, 260{{NULL, "histappend", OPT_ALIAS}, /* bash */ APPENDHISTORY}, 261{{NULL, "histexpand", OPT_ALIAS}, /* bash */ BANGHIST}, 262{{NULL, "log", OPT_ALIAS}, /* ksh */ -HISTNOFUNCTIONS}, 263{{NULL, "mailwarn", OPT_ALIAS}, /* bash */ MAILWARNING}, 264{{NULL, "onecmd", OPT_ALIAS}, /* bash */ SINGLECOMMAND}, 265{{NULL, "physical", OPT_ALIAS}, /* ksh/bash */ CHASELINKS}, 266{{NULL, "promptvars", OPT_ALIAS}, /* bash */ PROMPTSUBST}, 267{{NULL, "stdin", OPT_ALIAS}, /* ksh */ SHINSTDIN}, 268{{NULL, "trackall", OPT_ALIAS}, /* ksh */ HASHCMDS}, 269{{NULL, "dvorak", 0}, DVORAK}, 270{{NULL, NULL, 0}, 0} 271}; 272 273/* Option letters */ 274 275#define optletters (isset(SHOPTIONLETTERS) ? kshletters : zshletters) 276 277#define FIRST_OPT '0' 278#define LAST_OPT 'y' 279 280static short zshletters[LAST_OPT - FIRST_OPT + 1] = { 281 /* 0 */ CORRECT, 282 /* 1 */ PRINTEXITVALUE, 283 /* 2 */ -BADPATTERN, 284 /* 3 */ -NOMATCH, 285 /* 4 */ GLOBDOTS, 286 /* 5 */ NOTIFY, 287 /* 6 */ BGNICE, 288 /* 7 */ IGNOREEOF, 289 /* 8 */ MARKDIRS, 290 /* 9 */ AUTOLIST, 291 /* : */ 0, 292 /* ; */ 0, 293 /* < */ 0, 294 /* = */ 0, 295 /* > */ 0, 296 /* ? */ 0, 297 /* @ */ 0, 298 /* A */ 0, /* use with set for arrays */ 299 /* B */ -BEEP, 300 /* C */ -CLOBBER, 301 /* D */ PUSHDTOHOME, 302 /* E */ PUSHDSILENT, 303 /* F */ -GLOBOPT, 304 /* G */ NULLGLOB, 305 /* H */ RMSTARSILENT, 306 /* I */ IGNOREBRACES, 307 /* J */ AUTOCD, 308 /* K */ -BANGHIST, 309 /* L */ SUNKEYBOARDHACK, 310 /* M */ SINGLELINEZLE, 311 /* N */ AUTOPUSHD, 312 /* O */ CORRECTALL, 313 /* P */ RCEXPANDPARAM, 314 /* Q */ PATHDIRS, 315 /* R */ LONGLISTJOBS, 316 /* S */ RECEXACT, 317 /* T */ CDABLEVARS, 318 /* U */ MAILWARNING, 319 /* V */ -PROMPTCR, 320 /* W */ AUTORESUME, 321 /* X */ LISTTYPES, 322 /* Y */ MENUCOMPLETE, 323 /* Z */ USEZLE, 324 /* [ */ 0, 325 /* \ */ 0, 326 /* ] */ 0, 327 /* ^ */ 0, 328 /* _ */ 0, 329 /* ` */ 0, 330 /* a */ ALLEXPORT, 331 /* b */ 0, /* in non-Bourne shells, end of options */ 332 /* c */ 0, /* command follows */ 333 /* d */ -GLOBALRCS, 334 /* e */ ERREXIT, 335 /* f */ -RCS, 336 /* g */ HISTIGNORESPACE, 337 /* h */ HISTIGNOREDUPS, 338 /* i */ INTERACTIVE, 339 /* j */ 0, 340 /* k */ INTERACTIVECOMMENTS, 341 /* l */ LOGINSHELL, 342 /* m */ MONITOR, 343 /* n */ -EXECOPT, 344 /* o */ 0, /* long option name follows */ 345 /* p */ PRIVILEGED, 346 /* q */ 0, 347 /* r */ RESTRICTED, 348 /* s */ SHINSTDIN, 349 /* t */ SINGLECOMMAND, 350 /* u */ -UNSET, 351 /* v */ VERBOSE, 352 /* w */ CHASELINKS, 353 /* x */ XTRACE, 354 /* y */ SHWORDSPLIT, 355}; 356 357static short kshletters[LAST_OPT - FIRST_OPT + 1] = { 358 /* 0 */ 0, 359 /* 1 */ 0, 360 /* 2 */ 0, 361 /* 3 */ 0, 362 /* 4 */ 0, 363 /* 5 */ 0, 364 /* 6 */ 0, 365 /* 7 */ 0, 366 /* 8 */ 0, 367 /* 9 */ 0, 368 /* : */ 0, 369 /* ; */ 0, 370 /* < */ 0, 371 /* = */ 0, 372 /* > */ 0, 373 /* ? */ 0, 374 /* @ */ 0, 375 /* A */ 0, 376 /* B */ 0, 377 /* C */ -CLOBBER, 378 /* D */ 0, 379 /* E */ 0, 380 /* F */ 0, 381 /* G */ 0, 382 /* H */ 0, 383 /* I */ 0, 384 /* J */ 0, 385 /* K */ 0, 386 /* L */ 0, 387 /* M */ 0, 388 /* N */ 0, 389 /* O */ 0, 390 /* P */ 0, 391 /* Q */ 0, 392 /* R */ 0, 393 /* S */ 0, 394 /* T */ TRAPSASYNC, 395 /* U */ 0, 396 /* V */ 0, 397 /* W */ 0, 398 /* X */ MARKDIRS, 399 /* Y */ 0, 400 /* Z */ 0, 401 /* [ */ 0, 402 /* \ */ 0, 403 /* ] */ 0, 404 /* ^ */ 0, 405 /* _ */ 0, 406 /* ` */ 0, 407 /* a */ ALLEXPORT, 408 /* b */ NOTIFY, 409 /* c */ 0, 410 /* d */ 0, 411 /* e */ ERREXIT, 412 /* f */ -GLOBOPT, 413 /* g */ 0, 414 /* h */ 0, 415 /* i */ INTERACTIVE, 416 /* j */ 0, 417 /* k */ 0, 418 /* l */ LOGINSHELL, 419 /* m */ MONITOR, 420 /* n */ -EXECOPT, 421 /* o */ 0, 422 /* p */ PRIVILEGED, 423 /* q */ 0, 424 /* r */ RESTRICTED, 425 /* s */ SHINSTDIN, 426 /* t */ SINGLECOMMAND, 427 /* u */ -UNSET, 428 /* v */ VERBOSE, 429 /* w */ 0, 430 /* x */ XTRACE, 431 /* y */ 0, 432}; 433 434/* Initialisation of the option name hash table */ 435 436/**/ 437static void 438printoptionnode(HashNode hn, int set) 439{ 440 Optname on = (Optname) hn; 441 int optno = on->optno; 442 443 if (optno < 0) 444 optno = -optno; 445 if (isset(KSHOPTIONPRINT)) { 446 if (defset(on, emulation)) 447 printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on"); 448 else 449 printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off"); 450 } else if (set == (isset(optno) ^ defset(on, emulation))) { 451 if (set ^ isset(optno)) 452 fputs("no", stdout); 453 puts(on->node.nam); 454 } 455} 456 457/**/ 458void 459createoptiontable(void) 460{ 461 Optname on; 462 463 optiontab = newhashtable(101, "optiontab", NULL); 464 465 optiontab->hash = hasher; 466 optiontab->emptytable = NULL; 467 optiontab->filltable = NULL; 468 optiontab->cmpnodes = strcmp; 469 optiontab->addnode = addhashnode; 470 optiontab->getnode = gethashnode; 471 optiontab->getnode2 = gethashnode2; 472 optiontab->removenode = NULL; 473 optiontab->disablenode = disablehashnode; 474 optiontab->enablenode = enablehashnode; 475 optiontab->freenode = NULL; 476 optiontab->printnode = printoptionnode; 477 478 for (on = optns; on->node.nam; on++) 479 optiontab->addnode(optiontab, on->node.nam, on); 480} 481 482/* Emulation appropriate to the setemulate function */ 483 484static int setemulate_emulation; 485 486/* Option array manipulated within the setemulate function */ 487 488/**/ 489static char *setemulate_opts; 490 491/* Setting of default options */ 492 493/**/ 494static void 495setemulate(HashNode hn, int fully) 496{ 497 Optname on = (Optname) hn; 498 499 /* Set options: each non-special option is set according to the * 500 * current emulation mode if either it is considered relevant * 501 * to emulation or we are doing a full emulation (as indicated * 502 * by the `fully' parameter). */ 503 if (!(on->node.flags & OPT_ALIAS) && 504 ((fully && !(on->node.flags & OPT_SPECIAL)) || 505 (on->node.flags & OPT_EMULATE))) 506 setemulate_opts[on->optno] = defset(on, setemulate_emulation); 507} 508 509/**/ 510void 511installemulation(int new_emulation, char *new_opts) 512{ 513 setemulate_emulation = new_emulation; 514 setemulate_opts = new_opts; 515 scanhashtable(optiontab, 0, 0, 0, setemulate, 516 !!(new_emulation & EMULATE_FULLY)); 517} 518 519/**/ 520void 521emulate(const char *zsh_name, int fully, int *new_emulation, char *new_opts) 522{ 523 char ch = *zsh_name; 524 525 if (ch == 'r') 526 ch = zsh_name[1]; 527 528 /* Work out the new emulation mode */ 529 if (ch == 'c') 530 *new_emulation = EMULATE_CSH; 531 else if (ch == 'k') 532 *new_emulation = EMULATE_KSH; 533 else if (ch == 's' || ch == 'b') 534 *new_emulation = EMULATE_SH; 535 else 536 *new_emulation = EMULATE_ZSH; 537 538 if (fully) 539 *new_emulation |= EMULATE_FULLY; 540 installemulation(*new_emulation, new_opts); 541 542 if (funcstack && funcstack->tp == FS_FUNC) { 543 /* 544 * We are inside a function. Decide if it's traced. 545 * Pedantic note: the function in the function table isn't 546 * guaranteed to be what we're executing, but it's 547 * close enough. 548 */ 549 Shfunc shf = (Shfunc)shfunctab->getnode(shfunctab, funcstack->name); 550 if (shf && (shf->node.flags & (PM_TAGGED|PM_TAGGED_LOCAL))) { 551 /* Tracing is on, so set xtrace */ 552 new_opts[XTRACE] = 1; 553 } 554 } 555} 556 557/* setopt, unsetopt */ 558 559/**/ 560static void 561setoption(HashNode hn, int value) 562{ 563 dosetopt(((Optname) hn)->optno, value, 0, opts); 564} 565 566/**/ 567int 568bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) 569{ 570 int action, optno, match = 0; 571 572 /* With no arguments or options, display options. */ 573 if (!*args) { 574 scanhashtable(optiontab, 1, 0, OPT_ALIAS, optiontab->printnode, !isun); 575 return 0; 576 } 577 578 /* loop through command line options (begins with "-" or "+") */ 579 while (*args && (**args == '-' || **args == '+')) { 580 action = (**args == '-') ^ isun; 581 if(!args[0][1]) 582 *args = "--"; 583 while (*++*args) { 584 if(**args == Meta) 585 *++*args ^= 32; 586 /* The pseudo-option `--' signifies the end of options. */ 587 if (**args == '-') { 588 args++; 589 goto doneoptions; 590 } else if (**args == 'o') { 591 if (!*++*args) 592 args++; 593 if (!*args) { 594 zwarnnam(nam, "string expected after -o"); 595 inittyptab(); 596 return 1; 597 } 598 if(!(optno = optlookup(*args))) 599 zwarnnam(nam, "no such option: %s", *args); 600 else if(dosetopt(optno, action, 0, opts)) 601 zwarnnam(nam, "can't change option: %s", *args); 602 break; 603 } else if(**args == 'm') { 604 match = 1; 605 } else { 606 if (!(optno = optlookupc(**args))) 607 zwarnnam(nam, "bad option: -%c", **args); 608 else if(dosetopt(optno, action, 0, opts)) 609 zwarnnam(nam, "can't change option: -%c", **args); 610 } 611 } 612 args++; 613 } 614 doneoptions: 615 616 if (!match) { 617 /* Not globbing the arguments -- arguments are simply option names. */ 618 while (*args) { 619 if(!(optno = optlookup(*args++))) 620 zwarnnam(nam, "no such option: %s", args[-1]); 621 else if(dosetopt(optno, !isun, 0, opts)) 622 zwarnnam(nam, "can't change option: %s", args[-1]); 623 } 624 } else { 625 /* Globbing option (-m) set. */ 626 while (*args) { 627 Patprog pprog; 628 char *s, *t; 629 630 t = s = dupstring(*args); 631 while (*t) 632 if (*t == '_') 633 chuck(t); 634 else { 635 /* See comment in optlookup() */ 636 if (*t >= 'A' && *t <= 'Z') 637 *t = (*t - 'A') + 'a'; 638 t++; 639 } 640 641 /* Expand the current arg. */ 642 tokenize(s); 643 if (!(pprog = patcompile(s, PAT_STATIC, NULL))) { 644 zwarnnam(nam, "bad pattern: %s", *args); 645 continue; 646 } 647 /* Loop over expansions. */ 648 scanmatchtable(optiontab, pprog, 0, 0, OPT_ALIAS, 649 setoption, !isun); 650 args++; 651 } 652 } 653 inittyptab(); 654 return 0; 655} 656 657/* Identify an option name */ 658 659/**/ 660mod_export int 661optlookup(char const *name) 662{ 663 char *s, *t; 664 Optname n; 665 666 s = t = dupstring(name); 667 668 /* exorcise underscores, and change to lowercase */ 669 while (*t) 670 if (*t == '_') 671 chuck(t); 672 else { 673 /* 674 * Some locales (in particular tr_TR.UTF-8) may 675 * have non-standard mappings of ASCII characters, 676 * so be careful. Option names must be ASCII so 677 * we don't need to be too clever. 678 */ 679 if (*t >= 'A' && *t <= 'Z') 680 *t = (*t - 'A') + 'a'; 681 t++; 682 } 683 684 /* look up name in the table */ 685 if (s[0] == 'n' && s[1] == 'o' && 686 (n = (Optname) optiontab->getnode(optiontab, s + 2))) { 687 return -n->optno; 688 } else if ((n = (Optname) optiontab->getnode(optiontab, s))) 689 return n->optno; 690 else 691 return OPT_INVALID; 692} 693 694/* Identify an option letter */ 695 696/**/ 697int 698optlookupc(char c) 699{ 700 if(c < FIRST_OPT || c > LAST_OPT) 701 return 0; 702 703 return optletters[c - FIRST_OPT]; 704} 705 706/**/ 707static void 708restrictparam(char *nam) 709{ 710 Param pm = (Param) paramtab->getnode(paramtab, nam); 711 712 if (pm) { 713 pm->node.flags |= PM_SPECIAL | PM_RESTRICTED; 714 return; 715 } 716 createparam(nam, PM_SCALAR | PM_UNSET | PM_SPECIAL | PM_RESTRICTED); 717} 718 719/* list of restricted parameters which are not otherwise special */ 720static char *rparams[] = { 721 "SHELL", "HISTFILE", "LD_LIBRARY_PATH", "LD_AOUT_LIBRARY_PATH", 722 "LD_PRELOAD", "LD_AOUT_PRELOAD", NULL 723}; 724 725/* Set or unset an option, as a result of user request. The option * 726 * number may be negative, indicating that the sense is reversed * 727 * from the usual meaning of the option. */ 728 729/**/ 730mod_export int 731dosetopt(int optno, int value, int force, char *new_opts) 732{ 733 if(!optno) 734 return -1; 735 if(optno < 0) { 736 optno = -optno; 737 value = !value; 738 } 739 if (optno == RESTRICTED) { 740 if (isset(RESTRICTED)) 741 return value ? 0 : -1; 742 if (value) { 743 char **s; 744 745 for (s = rparams; *s; s++) 746 restrictparam(*s); 747 } 748 } else if(!force && optno == EXECOPT && !value && interact) { 749 /* cannot set noexec when interactive */ 750 return -1; 751 } else if(!force && (optno == INTERACTIVE || optno == SHINSTDIN || 752 optno == SINGLECOMMAND)) { 753 if (new_opts[optno] == value) 754 return 0; 755 /* it is not permitted to change the value of these options */ 756 return -1; 757 } else if(!force && optno == USEZLE && value) { 758 /* we require a terminal in order to use ZLE */ 759 if(!interact || SHTTY == -1 || !shout) 760 return -1; 761 } else if(optno == PRIVILEGED && !value) { 762 /* unsetting PRIVILEGED causes the shell to make itself unprivileged */ 763#ifdef HAVE_SETUID 764 setuid(getuid()); 765 setgid(getgid()); 766#endif /* HAVE_SETUID */ 767#ifdef JOB_CONTROL 768 } else if (!force && optno == MONITOR && value) { 769 if (new_opts[optno] == value) 770 return 0; 771 if (SHTTY != -1) { 772 origpgrp = GETPGRP(); 773 acquire_pgrp(); 774 } else 775 return -1; 776#else 777 } else if(optno == MONITOR && value) { 778 return -1; 779#endif /* not JOB_CONTROL */ 780#ifdef GETPWNAM_FAKED 781 } else if(optno == CDABLEVARS && value) { 782 return -1; 783#endif /* GETPWNAM_FAKED */ 784 } else if ((optno == EMACSMODE || optno == VIMODE) && value) { 785 if (sticky && sticky->emulation) 786 return -1; 787 zleentry(ZLE_CMD_SET_KEYMAP, optno); 788 new_opts[(optno == EMACSMODE) ? VIMODE : EMACSMODE] = 0; 789 } else if (optno == SUNKEYBOARDHACK) { 790 /* for backward compatibility */ 791 keyboardhackchar = (value ? '`' : '\0'); 792 } 793 new_opts[optno] = value; 794 if (optno == BANGHIST || optno == SHINSTDIN) 795 inittyptab(); 796 return 0; 797} 798 799/* Function to get value for special parameter `-' */ 800 801/**/ 802char * 803dashgetfn(UNUSED(Param pm)) 804{ 805 static char buf[LAST_OPT - FIRST_OPT + 2]; 806 char *val = buf; 807 int i; 808 809 for(i = 0; i <= LAST_OPT - FIRST_OPT; i++) { 810 int optno = optletters[i]; 811 if(optno && ((optno > 0) ? isset(optno) : unset(-optno))) 812 *val++ = FIRST_OPT + i; 813 } 814 *val = '\0'; 815 return buf; 816} 817 818/* print options for set -o/+o */ 819 820/**/ 821void 822printoptionstates(int hadplus) 823{ 824 scanhashtable(optiontab, 1, 0, OPT_ALIAS, printoptionnodestate, hadplus); 825} 826 827/**/ 828static void 829printoptionnodestate(HashNode hn, int hadplus) 830{ 831 Optname on = (Optname) hn; 832 int optno = on->optno; 833 834 if (hadplus) { 835 if (defset(on, emulation) != isset(optno)) 836 printf("set -o %s%s\n", defset(on, emulation) ? 837 "no" : "", on->node.nam); 838 } else { 839 if (defset(on, emulation)) 840 printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on"); 841 else 842 printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off"); 843 } 844} 845 846/* Print option list for --help */ 847 848/**/ 849void 850printoptionlist(void) 851{ 852 short *lp; 853 char c; 854 855 printf("\nNamed options:\n"); 856 scanhashtable(optiontab, 1, 0, OPT_ALIAS, printoptionlist_printoption, 0); 857 printf("\nOption aliases:\n"); 858 scanhashtable(optiontab, 1, OPT_ALIAS, 0, printoptionlist_printoption, 0); 859 printf("\nOption letters:\n"); 860 for(lp = optletters, c = FIRST_OPT; c <= LAST_OPT; lp++, c++) { 861 if(!*lp) 862 continue; 863 printf(" -%c ", c); 864 printoptionlist_printequiv(*lp); 865 } 866} 867 868/**/ 869static void 870printoptionlist_printoption(HashNode hn, UNUSED(int ignored)) 871{ 872 Optname on = (Optname) hn; 873 874 if(on->node.flags & OPT_ALIAS) { 875 printf(" --%-19s ", on->node.nam); 876 printoptionlist_printequiv(on->optno); 877 } else 878 printf(" --%s\n", on->node.nam); 879} 880 881/**/ 882static void 883printoptionlist_printequiv(int optno) 884{ 885 int isneg = optno < 0; 886 887 optno *= (isneg ? -1 : 1); 888 printf(" equivalent to --%s%s\n", isneg ? "no-" : "", optns[optno-1].node.nam); 889} 890