1 /* $NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $ */
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #ifdef HAVE_SYS_CDEFS_H
36 #include <sys/cdefs.h>
40 static char sccsid
[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
42 __RCSID("$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $");
52 #define _PATH_DEFPATH "/usr/bin:/usr/sbin"
53 #include <iso/limits_iso.h>
56 #ifdef PC_OS2_LIBPATHS
61 #define LIBPATHSTRICT 3
68 DosQueryHeaderInfo(HMODULE hmod
, ULONG ulIndex
, PVOID pvBuffer
, ULONG cbBuffer
, ULONG ulSubFunction
);
69 #define QHINF_EXEINFO 1 /* NE exeinfo. */
70 #define QHINF_READRSRCTBL 2 /* Reads from the resource table. */
71 #define QHINF_READFILE 3 /* Reads from the executable file. */
72 #define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
73 #define QHINF_LIBPATH 5 /* Gets the entire libpath. */
74 #define QHINF_FIXENTRY 6 /* NE only */
75 #define QHINF_STE 7 /* NE only */
76 #define QHINF_MAPSEL 8 /* NE only */
88 #include "nodes.h" /* for other headers */
89 #include "eval.h" /* defines cmdenviron */
101 #include "myhistedit.h"
115 void (*func
)(const char *);
123 struct var vhistsize
;
139 #ifdef PC_OS2_LIBPATHS
140 static struct var libpath_vars
[4];
141 static const char *libpath_envs
[4] = {"LIBPATH=", "BEGINLIBPATH=", "ENDLIBPATH=", "LIBPATHSTRICT="};
144 const struct varinit varinit
[] = {
146 { &vatty
, VSTRFIXED
|VTEXTFIXED
|VUNSET
, "ATTY=",
150 { &vhistsize
, VSTRFIXED
|VTEXTFIXED
|VUNSET
, "HISTSIZE=",
153 { &vifs
, VSTRFIXED
|VTEXTFIXED
, "IFS= \t\n",
155 { &vmail
, VSTRFIXED
|VTEXTFIXED
|VUNSET
, "MAIL=",
157 { &vmpath
, VSTRFIXED
|VTEXTFIXED
|VUNSET
, "MAILPATH=",
159 { &vpath
, VSTRFIXED
|VTEXTFIXED
, "PATH=" _PATH_DEFPATH
,
162 { &vpath2
, VSTRFIXED
|VTEXTFIXED
, "Path=",
166 * vps1 depends on uid
168 { &vps2
, VSTRFIXED
|VTEXTFIXED
, "PS2=> ",
170 { &vps4
, VSTRFIXED
|VTEXTFIXED
, "PS4=+ ",
173 { &vterm
, VSTRFIXED
|VTEXTFIXED
|VUNSET
, "TERM=",
176 { &voptind
, VSTRFIXED
|VTEXTFIXED
|VNOFUNC
, "OPTIND=1",
182 struct var
*vartab
[VTABSIZE
];
184 STATIC
int strequal(const char *, const char *);
185 STATIC
struct var
*find_var(const char *, struct var
***, int *);
188 * Initialize the varable symbol tables and import the environment
193 MKINIT
char **environ
;
198 for (envp
= environ
; *envp
; envp
++) {
199 if (strchr(*envp
, '=')) {
200 setvareq(*envp
, VEXPORT
|VTEXTFIXED
);
208 * This routine initializes the builtin variables. It is called when the
209 * shell is initialized and again when a shell procedure is spawned.
215 const struct varinit
*ip
;
219 #ifdef PC_OS2_LIBPATHS
220 char *psz
= ckmalloc(2048);
223 for (i
= 0; i
< 4; i
++)
225 libpath_vars
[i
].flags
= VSTRFIXED
| VOS2LIBPATH
;
226 libpath_vars
[i
].func
= NULL
;
230 psz
[0] = psz
[1] = psz
[2] = psz
[3] = '\0';
231 rc
= DosQueryExtLIBPATH(psz
, i
);
235 rc
= DosQueryHeaderInfo(NULLHANDLE
, 0, psz
, 2048, QHINF_LIBPATH
);
236 libpath_vars
[i
].flags
|= VREADONLY
;
240 int cch1
= strlen(libpath_envs
[i
]);
241 int cch2
= strlen(psz
) + 1;
242 libpath_vars
[i
].text
= ckmalloc(cch1
+ cch2
);
243 memcpy(libpath_vars
[i
].text
, libpath_envs
[i
], cch1
);
244 memcpy(libpath_vars
[i
].text
+ cch1
, psz
, cch2
);
248 libpath_vars
[i
].flags
|= VUNSET
| VTEXTFIXED
;
249 libpath_vars
[i
].text
= (char*)libpath_envs
[i
];
251 if (find_var(libpath_vars
[i
].text
, &vpp
, &libpath_vars
[i
].name_len
) != NULL
)
253 libpath_vars
[i
].next
= *vpp
;
254 *vpp
= &libpath_vars
[i
];
259 for (ip
= varinit
; (vp
= ip
->var
) != NULL
; ip
++) {
260 if (find_var(ip
->text
, &vpp
, &vp
->name_len
) != NULL
)
264 vp
->text
= strdup(ip
->text
);
265 vp
->flags
= ip
->flags
;
271 if (find_var("PS1", &vpp
, &vps1
.name_len
) == NULL
) {
274 vps1
.text
= strdup(geteuid() ? "PS1=$ " : "PS1=# ");
275 vps1
.flags
= VSTRFIXED
|VTEXTFIXED
;
280 * Safe version of setvar, returns 1 on success 0 on failure.
284 setvarsafe(const char *name
, const char *val
, int flags
)
286 struct jmploc jmploc
;
287 struct jmploc
*volatile savehandler
= handler
;
293 if (setjmp(jmploc
.loc
))
297 setvar(name
, val
, flags
);
299 handler
= savehandler
;
304 * Set the value of a variable. The flags argument is ored with the
305 * flags of the variable. If val is NULL, the variable is unset.
309 setvar(const char *name
, const char *val
, int flags
)
325 if (! is_in_name(*p
)) {
326 if (*p
== '\0' || *p
== '=')
334 error("%.*s: bad variable name", namelen
, name
);
335 len
= namelen
+ 2; /* 2 is space for '=' and '\0' */
341 d
= nameeq
= ckmalloc(len
);
343 while (--namelen
>= 0)
349 setvareq(nameeq
, flags
);
355 * Same as setvar except that the variable and value are passed in
356 * the first argument as name=value. Since the first argument will
357 * be actually stored in the table, it should not be a string that
362 setvareq(char *s
, int flags
)
364 struct var
*vp
, **vpp
;
369 vp
= find_var(s
, &vpp
, &nlen
);
371 if (vp
->flags
& VREADONLY
)
372 error("%.*s: is read only", vp
->name_len
, s
);
377 if (vp
->func
&& (flags
& VNOFUNC
) == 0)
378 (*vp
->func
)(s
+ vp
->name_len
+ 1);
380 if ((vp
->flags
& (VTEXTFIXED
|VSTACK
)) == 0)
383 vp
->flags
&= ~(VTEXTFIXED
|VSTACK
|VUNSET
);
384 vp
->flags
|= flags
& ~VNOFUNC
;
386 #ifdef PC_OS2_LIBPATHS
387 if ((vp
->flags
& VOS2LIBPATH
) && (vp
->flags
& VEXPORT
))
388 vp
->flags
&= ~VEXPORT
;
392 * We could roll this to a function, to handle it as
393 * a regular variable function callback, but why bother?
395 if (vp
== &vmpath
|| (vp
== &vmail
&& ! mpathset()))
403 vp
= ckmalloc(sizeof (*vp
));
404 vp
->flags
= flags
& ~VNOFUNC
;
415 * Process a linked list of variable assignments.
419 listsetvar(struct strlist
*list
, int flags
)
424 for (lp
= list
; lp
; lp
= lp
->next
) {
425 setvareq(savestr(lp
->text
), flags
);
431 listmklocal(struct strlist
*list
, int flags
)
435 for (lp
= list
; lp
; lp
= lp
->next
)
436 mklocal(lp
->text
, flags
);
441 * Find the value of a variable. Returns NULL if not set.
445 lookupvar(const char *name
)
449 v
= find_var(name
, NULL
, NULL
);
450 if (v
== NULL
|| v
->flags
& VUNSET
)
452 return v
->text
+ v
->name_len
+ 1;
458 * Search the environment of a builtin command. If the second argument
459 * is nonzero, return the value of a variable even if it hasn't been
464 bltinlookup(const char *name
, int doall
)
469 for (sp
= cmdenviron
; sp
; sp
= sp
->next
) {
470 if (strequal(sp
->text
, name
))
471 return strchr(sp
->text
, '=') + 1;
474 v
= find_var(name
, NULL
, NULL
);
476 if (v
== NULL
|| v
->flags
& VUNSET
|| (!doall
&& !(v
->flags
& VEXPORT
)))
478 return v
->text
+ v
->name_len
+ 1;
484 * Generate a list of exported variables. This routine is used to construct
485 * the third argument to execve when executing a program.
498 for (vpp
= vartab
; vpp
< vartab
+ VTABSIZE
; vpp
++) {
499 for (vp
= *vpp
; vp
; vp
= vp
->next
)
500 if (vp
->flags
& VEXPORT
)
503 ep
= env
= stalloc((nenv
+ 1) * sizeof *env
);
504 for (vpp
= vartab
; vpp
< vartab
+ VTABSIZE
; vpp
++) {
505 for (vp
= *vpp
; vp
; vp
= vp
->next
)
506 if (vp
->flags
& VEXPORT
)
511 #ifdef PC_OS2_LIBPATHS
513 * Set the libpaths now as this is exec() time.
515 for (nenv
= 0; nenv
< 3; nenv
++)
516 DosSetExtLIBPATH(strchr(libpath_vars
[nenv
].text
, '=') + 1, nenv
);
524 * Called when a shell procedure is invoked to clear out nonexported
525 * variables. It is also necessary to reallocate variables of with
526 * VSTACK set since these are currently allocated on the stack.
530 void shprocvar(void);
541 struct var
*vp
, **prev
;
543 for (vpp
= vartab
; vpp
< vartab
+ VTABSIZE
; vpp
++) {
544 for (prev
= vpp
; (vp
= *prev
) != NULL
; ) {
545 if ((vp
->flags
& VEXPORT
) == 0) {
547 if ((vp
->flags
& VTEXTFIXED
) == 0)
549 if ((vp
->flags
& VSTRFIXED
) == 0)
552 if (vp
->flags
& VSTACK
) {
553 vp
->text
= savestr(vp
->text
);
554 vp
->flags
&=~ VSTACK
;
566 * Command to list all variables which are set. Currently this command
567 * is invoked from the set command when the set command is called without
572 print_quoted(const char *p
)
576 if (strcspn(p
, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p
)) {
591 out1fmt("'%.*s'", (int)(q
- p
), p
);
597 sort_var(const void *v_v1
, const void *v_v2
)
599 const struct var
* const *v1
= v_v1
;
600 const struct var
* const *v2
= v_v2
;
602 /* XXX Will anyone notice we include the '=' of the shorter name? */
603 return strcoll((*v1
)->text
, (*v2
)->text
);
607 * POSIX requires that 'set' (but not export or readonly) output the
608 * variables in lexicographic order - by the locale's collating order (sigh).
609 * Maybe we could keep them in an ordered balanced binary tree
610 * instead of hashed lists.
611 * For now just roll 'em through qsort for printing...
615 showvars(const char *name
, int flag
, int show_value
)
621 static struct var
**list
; /* static in case we are interrupted */
627 list
= ckmalloc(list_len
* sizeof *list
);
630 for (vpp
= vartab
; vpp
< vartab
+ VTABSIZE
; vpp
++) {
631 for (vp
= *vpp
; vp
; vp
= vp
->next
) {
632 if (flag
&& !(vp
->flags
& flag
))
634 if (vp
->flags
& VUNSET
&& !(show_value
& 2))
636 if (count
>= list_len
) {
637 list
= ckrealloc(list
,
638 (list_len
<< 1) * sizeof *list
);
645 qsort(list
, count
, sizeof *list
, sort_var
);
647 for (vpp
= list
; count
--; vpp
++) {
650 out1fmt("%s ", name
);
651 for (p
= vp
->text
; *p
!= '=' ; p
++)
653 if (!(vp
->flags
& VUNSET
) && show_value
) {
665 * The export and readonly commands.
669 exportcmd(int argc
, char **argv
)
674 int flag
= argv
[0][0] == 'r'? VREADONLY
: VEXPORT
;
677 pflag
= nextopt("p") == 'p' ? 3 : 0;
678 if (argc
<= 1 || pflag
) {
679 showvars( pflag
? argv
[0] : 0, flag
, pflag
);
683 while ((name
= *argptr
++) != NULL
) {
684 if ((p
= strchr(name
, '=')) != NULL
) {
687 vp
= find_var(name
, NULL
, NULL
);
693 setvar(name
, p
, flag
);
700 * The "local" command.
704 localcmd(int argc
, char **argv
)
709 error("Not in a function");
710 while ((name
= *argptr
++) != NULL
) {
718 * Make a variable a local variable. When a variable is made local, it's
719 * value and flags are saved in a localvar structure. The saved values
720 * will be restored when the shell function returns. We handle the name
721 * "-" as a special case.
725 mklocal(const char *name
, int flags
)
727 struct localvar
*lvp
;
732 lvp
= ckmalloc(sizeof (struct localvar
));
733 if (name
[0] == '-' && name
[1] == '\0') {
735 p
= ckmalloc(sizeof_optlist
);
736 lvp
->text
= memcpy(p
, optlist
, sizeof_optlist
);
739 vp
= find_var(name
, &vpp
, NULL
);
741 if (strchr(name
, '='))
742 setvareq(savestr(name
), VSTRFIXED
|flags
);
744 setvar(name
, NULL
, VSTRFIXED
|flags
);
745 vp
= *vpp
; /* the new variable */
749 lvp
->text
= vp
->text
;
750 lvp
->flags
= vp
->flags
;
751 vp
->flags
|= VSTRFIXED
|VTEXTFIXED
;
752 if (name
[vp
->name_len
] == '=')
753 setvareq(savestr(name
), flags
);
757 lvp
->next
= localvars
;
764 * Called after a function returns.
770 struct localvar
*lvp
;
773 while ((lvp
= localvars
) != NULL
) {
774 localvars
= lvp
->next
;
776 TRACE(("poplocalvar %s", vp
? vp
->text
: "-"));
777 if (vp
== NULL
) { /* $- saved */
778 memcpy(optlist
, lvp
->text
, sizeof_optlist
);
780 } else if ((lvp
->flags
& (VUNSET
|VSTRFIXED
)) == VUNSET
) {
781 (void)unsetvar(vp
->text
, 0);
783 if (vp
->func
&& (vp
->flags
& VNOFUNC
) == 0)
784 (*vp
->func
)(lvp
->text
+ vp
->name_len
+ 1);
785 if ((vp
->flags
& VTEXTFIXED
) == 0)
787 vp
->flags
= lvp
->flags
;
788 vp
->text
= lvp
->text
;
796 setvarcmd(int argc
, char **argv
)
799 return unsetcmd(argc
, argv
);
801 setvar(argv
[1], argv
[2], 0);
803 error("List assignment not implemented");
809 * The unset builtin command. We unset the function before we unset the
810 * variable to allow a function to be unset when there is a readonly variable
811 * with the same name.
815 unsetcmd(int argc
, char **argv
)
823 while ((i
= nextopt("evf")) != '\0') {
829 if (flg_func
== 0 && flg_var
== 0)
832 for (ap
= argptr
; *ap
; ap
++) {
834 ret
|= unsetfunc(*ap
);
836 ret
|= unsetvar(*ap
, flg_var
== 'e');
843 * Unset the specified variable.
847 unsetvar(const char *s
, int unexport
)
852 vp
= find_var(s
, &vpp
, NULL
);
856 if (vp
->flags
& VREADONLY
)
861 vp
->flags
&= ~VEXPORT
;
863 if (vp
->text
[vp
->name_len
+ 1] != '\0')
864 setvar(s
, nullstr
, 0);
865 vp
->flags
&= ~VEXPORT
;
867 if ((vp
->flags
& VSTRFIXED
) == 0) {
868 if ((vp
->flags
& VTEXTFIXED
) == 0)
880 * Returns true if the two strings specify the same varable. The first
881 * variable name is terminated by '='; the second may be terminated by
882 * either '=' or '\0'.
886 strequal(const char *p
, const char *q
)
892 if (*p
== '=' && *(q
- 1) == '\0')
898 * Search for a variable.
899 * 'name' may be terminated by '=' or a NUL.
900 * vppp is set to the pointer to vp, or the list head if vp isn't found
901 * lenp is set to the number of charactets in 'name'
905 find_var(const char *name
, struct var
***vppp
, int *lenp
)
907 unsigned int hashval
;
909 struct var
*vp
, **vpp
;
910 const char *p
= name
;
913 while (*p
&& *p
!= '=')
914 hashval
= 2 * hashval
+ (unsigned char)*p
++;
919 vpp
= &vartab
[hashval
% VTABSIZE
];
923 for (vp
= *vpp
; vp
; vpp
= &vp
->next
, vp
= *vpp
) {
924 if (vp
->name_len
!= len
)
926 if (memcmp(vp
->text
, name
, len
) != 0)