[BusyBox-cvs] busybox/shell ash.c,1.90,1.91

Erik Andersen andersen at busybox.net
Thu Mar 11 13:34:27 UTC 2004


Update of /var/cvs/busybox/shell
In directory nail:/tmp/cvs-serv7604/shell

Modified Files:
	ash.c 
Log Message:
Paul Mundt, lethal at linux-sh dot org writes:

Here's a follow-up replacement to the patch I sent earlier, this adjusts some
of the semantics of the dynamic variable setting. Namely, dynamic vars can hook
a set handler (which RANDOM uses to adjust the seed). They'll only lose their
dynamic status if they're unset.

I've used the same approach that bash does to come up with the random number,
mostly just for consistency.

For example:

$ echo $RANDOM
13759
$ echo $RANDOM
20057
$ echo $RANDOM
1502
$ export RANDOM=42
$ echo $RANDOM
24179
$ echo $RANDOM
2046
$ unset RANDOM
$ echo $RANDOM

$ export RANDOM=42
$ echo $RANDOM
42
$



Index: ash.c
===================================================================
RCS file: /var/cvs/busybox/shell/ash.c,v
retrieving revision 1.90
retrieving revision 1.91
diff -u -d -r1.90 -r1.91
--- a/ash.c	18 Feb 2004 09:40:41 -0000	1.90
+++ b/ash.c	11 Mar 2004 13:34:24 -0000	1.91
@@ -37,6 +37,8 @@
  * used in busybox and size optimizations,
  * support locale, rewrited arith (see notes to this)
  *
+ * Modified by Paul Mundt <lethal at linux-sh.org> (c) 2004 to support
+ * dynamic variables.
  */
 
 
@@ -88,7 +90,7 @@
 #include <signal.h>
 #include <stdint.h>
 #include <sysexits.h>
-
+#include <time.h>
 #include <fnmatch.h>
 
 
@@ -1465,6 +1467,7 @@
 #define VNOFUNC         0x40    /* don't call the callback function */
 #define VNOSET          0x80    /* do not set variable - just readonly test */
 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
+#define VDYNAMIC		0x200	/* dynamic variable */
 
 
 struct var {
@@ -1474,6 +1477,9 @@
 	void (*func)(const char *);
 					/* function to be called when  */
 					/* the variable gets set/unset */
+	char *(*lookup_func)(const char *);
+					/* function to be called when  */
+					/* the variable is read (if dynamic) */
 };
 
 struct localvar {
@@ -1500,6 +1506,9 @@
 static void change_lc_ctype(const char *value);
 #endif
 
+static char *get_random(const char *);
+static void change_random(const char *);
+
 #define VTABSIZE 39
 
 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
@@ -1513,30 +1522,32 @@
 
 static struct var varinit[] = {
 #ifdef IFS_BROKEN
-	{ 0,    VSTRFIXED|VTEXTFIXED,           defifsvar,      0 },
+	{ 0,    VSTRFIXED|VTEXTFIXED,           defifsvar,      0, 0 },
 #else
-	{ 0,    VSTRFIXED|VTEXTFIXED|VUNSET,    "IFS\0",        0 },
+	{ 0,    VSTRFIXED|VTEXTFIXED|VUNSET,    "IFS\0",        0, 0 },
 #endif
 
 #ifdef CONFIG_ASH_MAIL
-	{ 0,    VSTRFIXED|VTEXTFIXED|VUNSET,    "MAIL\0",       changemail },
-	{ 0,    VSTRFIXED|VTEXTFIXED|VUNSET,    "MAILPATH\0",   changemail },
+	{ 0,    VSTRFIXED|VTEXTFIXED|VUNSET,    "MAIL\0",       changemail, 0 },
+	{ 0,    VSTRFIXED|VTEXTFIXED|VUNSET,    "MAILPATH\0",   changemail, 0 },
 #endif
 
-	{ 0,    VSTRFIXED|VTEXTFIXED,           defpathvar,     changepath },
-	{ 0,    VSTRFIXED|VTEXTFIXED,           "PS1=$ ",       0 },
-	{ 0,    VSTRFIXED|VTEXTFIXED,           "PS2=> ",       0 },
-	{ 0,    VSTRFIXED|VTEXTFIXED,           "PS4=+ ",       0 },
+	{ 0,    VSTRFIXED|VTEXTFIXED,           defpathvar,     changepath, 0 },
+	{ 0,    VSTRFIXED|VTEXTFIXED,           "PS1=$ ",       0,			0 },
+	{ 0,    VSTRFIXED|VTEXTFIXED,           "PS2=> ",       0, 			0 },
+	{ 0,    VSTRFIXED|VTEXTFIXED,           "PS4=+ ",       0,			0 },
 #ifdef CONFIG_ASH_GETOPTS
-	{ 0,    VSTRFIXED|VTEXTFIXED,           "OPTIND=1",     getoptsreset },
+	{ 0,    VSTRFIXED|VTEXTFIXED,           "OPTIND=1",     getoptsreset, 0 },
 #endif
 #ifdef CONFIG_LOCALE_SUPPORT
-	{0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL=", change_lc_all},
-	{0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE=", change_lc_ctype},
+	{0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL=", change_lc_all, 0},
+	{0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE=", change_lc_ctype, 0},
 #endif
 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
-	{0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE=", NULL},
+	{0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE=", NULL, 0},
 #endif
+	{0, VSTRFIXED | VTEXTFIXED | VUNSET | VDYNAMIC, "RANDOM\0",
+		change_random, get_random},
 };
 
 #define vifs varinit[0]
@@ -9019,6 +9030,22 @@
 
 #endif
 
+/* Roughly copied from bash.. */
+static unsigned long rseed = 1;
+static char *get_random(const char *var)
+{
+	char buf[255];
+	rseed = (rseed + getpid() + ((time_t)time((time_t *)0)));
+	rseed = rseed * 1103515245 + 12345;
+	sprintf(buf, "%d", (unsigned int)((rseed >> 16 & 32767)));
+	return bb_xstrdup(buf);
+}
+
+static void change_random(const char *value)
+{
+	rseed = strtoul(value, (char **)NULL, 10);
+}
+
 #ifdef CONFIG_ASH_GETOPTS
 static int
 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
@@ -12031,9 +12058,20 @@
 {
 	struct var *v;
 
-	if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
+	if ((v = *findvar(hashvar(name), name)) && !(v->flags & (VUNSET|VDYNAMIC))) {
 		return strchrnul(v->text, '=') + 1;
 	}
+
+	/*
+	 * Dynamic variables are implemented roughly the same way they are
+	 * in bash. Namely, they're "special" so long as they aren't unset.
+	 * As soon as they're unset, they're no longer dynamic, and dynamic
+	 * lookup will no longer happen at that point. -- PFM.
+	 */
+	if (v && ((v->flags & VDYNAMIC)))
+		if (v->lookup_func)
+			return v->lookup_func(name);
+
 	return NULL;
 }
 
@@ -12308,6 +12346,8 @@
 		retval = 1;
 		if (flags & VREADONLY)
 			goto out;
+		if (flags & VDYNAMIC)
+			vp->flags &= ~VDYNAMIC;
 		if (flags & VUNSET)
 			goto ok;
 		if ((flags & VSTRFIXED) == 0) {




More information about the busybox-cvs mailing list