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