diff options
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 105 |
1 files changed, 101 insertions, 4 deletions
diff --git a/shell/hush.c b/shell/hush.c index 9f1614d1f..eb3ffcea1 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -250,6 +250,7 @@ static struct jobset *job_list; | |||
| 250 | static unsigned int last_bg_pid=0; | 250 | static unsigned int last_bg_pid=0; |
| 251 | static char *PS1; | 251 | static char *PS1; |
| 252 | static char *PS2 = "> "; | 252 | static char *PS2 = "> "; |
| 253 | static char **__shell_local_env = 0; | ||
| 253 | 254 | ||
| 254 | #define B_CHUNK (100) | 255 | #define B_CHUNK (100) |
| 255 | #define B_NOSPAC 1 | 256 | #define B_NOSPAC 1 |
| @@ -1609,11 +1610,104 @@ static int xglob(o_string *dest, int flags, glob_t *pglob) | |||
| 1609 | return gr; | 1610 | return gr; |
| 1610 | } | 1611 | } |
| 1611 | 1612 | ||
| 1612 | 1613 | /* This is used to set local variables (i.e. stuff not going into the environment) */ | |
| 1613 | static int set_local_var(const char *s) | 1614 | static int set_local_var(const char *s) |
| 1614 | { | 1615 | { |
| 1615 | /* when you write this, also need to update lookup_param() */ | 1616 | char **ep; |
| 1616 | printf("assignment %s not handled: write me!\n",s); | 1617 | char *tmp,*name, *value; |
| 1618 | size_t size; | ||
| 1619 | size_t namelen; | ||
| 1620 | size_t vallen; | ||
| 1621 | int result=0; | ||
| 1622 | |||
| 1623 | name=tmp=strdup(s); | ||
| 1624 | |||
| 1625 | /* Assume when we enter this function that we are already in | ||
| 1626 | * NAME=VALUE format. So the first order of business is to | ||
| 1627 | * split 's' on the '=' into 'name' and 'value' */ | ||
| 1628 | value = strchr(name, '='); | ||
| 1629 | if (!value) { | ||
| 1630 | result = -1; | ||
| 1631 | goto done_already; | ||
| 1632 | } | ||
| 1633 | *value='\0'; | ||
| 1634 | ++value; | ||
| 1635 | printf("name='%s' and value='%s'\n",name, value); | ||
| 1636 | |||
| 1637 | namelen = strlen (name); | ||
| 1638 | vallen = strlen (value); | ||
| 1639 | |||
| 1640 | /* Now see how many local environment entries we have, and check | ||
| 1641 | * if we match an existing environment entry (so we can overwrite it) */ | ||
| 1642 | size = 0; | ||
| 1643 | for (ep = __shell_local_env; ep && *ep != NULL; ++ep) { | ||
| 1644 | if (!memcmp (*ep, name, namelen) && (*ep)[namelen] == '=') | ||
| 1645 | break; | ||
| 1646 | else | ||
| 1647 | ++size; | ||
| 1648 | } | ||
| 1649 | |||
| 1650 | if (ep == NULL || *ep == NULL) { | ||
| 1651 | static char **last_environ = NULL; | ||
| 1652 | char **new_environ = (char **) malloc((size + 2) * sizeof(char *)); | ||
| 1653 | if (new_environ == NULL) { | ||
| 1654 | result = -1; | ||
| 1655 | goto done_already; | ||
| 1656 | } | ||
| 1657 | memcpy((__ptr_t) new_environ, (__ptr_t) __shell_local_env, size * sizeof(char *)); | ||
| 1658 | |||
| 1659 | new_environ[size] = malloc (namelen + 1 + vallen + 1); | ||
| 1660 | if (new_environ[size] == NULL) { | ||
| 1661 | free (new_environ); | ||
| 1662 | errno=ENOMEM; | ||
| 1663 | result = -1; | ||
| 1664 | goto done_already; | ||
| 1665 | } | ||
| 1666 | memcpy (new_environ[size], name, namelen); | ||
| 1667 | new_environ[size][namelen] = '='; | ||
| 1668 | memcpy (&new_environ[size][namelen + 1], value, vallen + 1); | ||
| 1669 | |||
| 1670 | new_environ[size + 1] = NULL; | ||
| 1671 | |||
| 1672 | if (last_environ != NULL) | ||
| 1673 | free ((__ptr_t) last_environ); | ||
| 1674 | last_environ = new_environ; | ||
| 1675 | __shell_local_env = new_environ; | ||
| 1676 | } | ||
| 1677 | else { | ||
| 1678 | size_t len = strlen (*ep); | ||
| 1679 | if (len < namelen + 1 + vallen) { | ||
| 1680 | char *new = malloc (namelen + 1 + vallen + 1); | ||
| 1681 | if (new == NULL) { | ||
| 1682 | result = -1; | ||
| 1683 | goto done_already; | ||
| 1684 | } | ||
| 1685 | *ep = new; | ||
| 1686 | memcpy (*ep, name, namelen); | ||
| 1687 | (*ep)[namelen] = '='; | ||
| 1688 | } | ||
| 1689 | memcpy (&(*ep)[namelen + 1], value, vallen + 1); | ||
| 1690 | } | ||
| 1691 | |||
| 1692 | done_already: | ||
| 1693 | free(name); | ||
| 1694 | return result; | ||
| 1695 | } | ||
| 1696 | |||
| 1697 | char *get_local_var(const char *var) | ||
| 1698 | { | ||
| 1699 | char **p; | ||
| 1700 | int len; | ||
| 1701 | |||
| 1702 | len = strlen(var); | ||
| 1703 | |||
| 1704 | if (!__shell_local_env) | ||
| 1705 | return 0; | ||
| 1706 | |||
| 1707 | for (p = __shell_local_env; *p; p++) { | ||
| 1708 | if (memcmp(var, *p, len) == 0 && (*p)[len] == '=') | ||
| 1709 | return *p + len + 1; | ||
| 1710 | } | ||
| 1617 | return 0; | 1711 | return 0; |
| 1618 | } | 1712 | } |
| 1619 | 1713 | ||
| @@ -2018,7 +2112,10 @@ static int parse_group(o_string *dest, struct p_context *ctx, | |||
| 2018 | static void lookup_param(o_string *dest, struct p_context *ctx, o_string *src) | 2112 | static void lookup_param(o_string *dest, struct p_context *ctx, o_string *src) |
| 2019 | { | 2113 | { |
| 2020 | const char *p=NULL; | 2114 | const char *p=NULL; |
| 2021 | if (src->data) p = getenv(src->data); | 2115 | if (src->data) { |
| 2116 | p = get_local_var(src->data); | ||
| 2117 | if (!p) p = getenv(src->data); | ||
| 2118 | } | ||
| 2022 | if (p) parse_string(dest, ctx, p); /* recursion */ | 2119 | if (p) parse_string(dest, ctx, p); /* recursion */ |
| 2023 | b_free(src); | 2120 | b_free(src); |
| 2024 | } | 2121 | } |
