Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/sh Implement a bunch of new shell environment variables....



details:   https://anonhg.NetBSD.org/src/rev/f1d3fd6d6022
branches:  trunk
changeset: 825130:f1d3fd6d6022
user:      kre <kre%NetBSD.org@localhost>
date:      Fri Jun 30 23:05:45 2017 +0000

description:
Implement a bunch of new shell environment variables. many mostly useful
in prompts when expanded at prompt time, but all available for general use.
Many of the new ones are not available in SMALL shells (they work as normal
if assigned, but the shell does not set or use them - and there is no magic
in a SMALL shell (usually for install media.))

diffstat:

 bin/sh/Makefile |    4 +-
 bin/sh/var.c    |  377 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 bin/sh/var.h    |    5 +-
 3 files changed, 373 insertions(+), 13 deletions(-)

diffs (truncated from 562 to 300 lines):

diff -r 6ce571353735 -r f1d3fd6d6022 bin/sh/Makefile
--- a/bin/sh/Makefile   Fri Jun 30 23:02:56 2017 +0000
+++ b/bin/sh/Makefile   Fri Jun 30 23:05:45 2017 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: Makefile,v 1.112 2017/06/08 02:25:43 kre Exp $
+#      $NetBSD: Makefile,v 1.113 2017/06/30 23:05:45 kre Exp $
 #      @(#)Makefile    8.4 (Berkeley) 5/5/95
 
 .include <bsd.own.mk>
@@ -24,6 +24,7 @@
        SED=${TOOL_SED:Q}
 
 CPPFLAGS+=-DSHELL -I. -I${.CURDIR}
+CPPFLAGS+= -DUSE_LRAND48
 #XXX: For testing only.
 #CPPFLAGS+=-DDEBUG=3
 #COPTS+=-g
@@ -90,6 +91,7 @@
 
 COPTS.printf.c = -Wno-format-nonliteral
 COPTS.jobs.c = -Wno-format-nonliteral
+COPTS.var.c = -Wno-format-nonliteral
 
 .include <bsd.prog.mk>
 .include <bsd.subdir.mk>
diff -r 6ce571353735 -r f1d3fd6d6022 bin/sh/var.c
--- a/bin/sh/var.c      Fri Jun 30 23:02:56 2017 +0000
+++ b/bin/sh/var.c      Fri Jun 30 23:05:45 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: var.c,v 1.62 2017/06/28 13:46:06 kre Exp $     */
+/*     $NetBSD: var.c,v 1.63 2017/06/30 23:05:45 kre Exp $     */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)var.c      8.3 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: var.c,v 1.62 2017/06/28 13:46:06 kre Exp $");
+__RCSID("$NetBSD: var.c,v 1.63 2017/06/30 23:05:45 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -47,6 +47,9 @@
 #include <string.h>
 #include <paths.h>
 #include <limits.h>
+#include <time.h>
+#include <pwd.h>
+#include <fcntl.h>
 
 /*
  * Shell variables.
@@ -68,6 +71,7 @@
 #include "mystring.h"
 #include "parser.h"
 #include "show.h"
+#include "machdep.h"
 #ifndef SMALL
 #include "myhistedit.h"
 #endif
@@ -90,6 +94,14 @@
 
 char *get_lineno(struct var *);
 
+#ifndef SMALL
+char *get_tod(struct var *);
+char *get_hostname(struct var *);
+char *get_seconds(struct var *);
+char *get_euser(struct var *);
+char *get_random(struct var *);
+#endif
+
 struct localvar *localvars;
 
 #ifndef SMALL
@@ -108,6 +120,15 @@
 struct var vvers;
 struct var voptind;
 struct var line_num;
+#ifndef SMALL
+struct var tod;
+struct var host_name;
+struct var seconds;
+struct var euname;
+struct var random_num;
+
+intmax_t sh_start_time;
+#endif
 
 struct var line_num;
 int line_number;
@@ -150,6 +171,18 @@
           { .set_func= getoptsreset } },
        { &line_num,    VSTRFIXED|VTEXTFIXED|VFUNCREF,  "LINENO=1",
           { .ref_func= get_lineno } },
+#ifndef SMALL
+       { &tod,         VSTRFIXED|VTEXTFIXED|VFUNCREF,  "ToD=",
+          { .ref_func= get_tod } },
+       { &host_name,   VSTRFIXED|VTEXTFIXED|VFUNCREF,  "HOSTNAME=",
+          { .ref_func= get_hostname } },
+       { &seconds,     VSTRFIXED|VTEXTFIXED|VFUNCREF,  "SECONDS=",
+          { .ref_func= get_seconds } },
+       { &euname,      VSTRFIXED|VTEXTFIXED|VFUNCREF,  "EUSER=",
+          { .ref_func= get_euser } },
+       { &random_num,  VSTRFIXED|VTEXTFIXED|VFUNCREF,  "RANDOM=",
+          { .ref_func= get_random } },
+#endif
        { NULL, 0,                              NULL,
           { NULL } }
 };
@@ -166,6 +199,7 @@
 #ifdef mkinit
 INCLUDE <stdio.h>
 INCLUDE <unistd.h>
+INCLUDE <time.h>
 INCLUDE "var.h"
 INCLUDE "version.h"
 MKINIT char **environ;
@@ -173,7 +207,18 @@
        char **envp;
        char buf[64];
 
+#ifndef SMALL
+       sh_start_time = (intmax_t)time((time_t *)0);
+#endif
+       /*
+        * Set up our default variables and their values.
+        */
        initvar();
+
+       /*
+        * Import variables from the environment, which will
+        * override anything initialised just previously.
+        */
        for (envp = environ ; *envp ; envp++) {
                if (strchr(*envp, '=')) {
                        setvareq(*envp, VEXPORT|VTEXTFIXED);
@@ -185,12 +230,20 @@
         *
         * PPID is readonly
         * Always default IFS
+        * PSc indicates the root/non-root status of this shell.
         * NETBSD_SHELL is a constant (readonly), and is never exported
+        * START_TIME belongs only to this shell.
         * LINENO is simply magic...
         */
        snprintf(buf, sizeof(buf), "%d", (int)getppid());
        setvar("PPID", buf, VREADONLY);
        setvar("IFS", ifs_default, VTEXTFIXED);
+       setvar("PSc", (geteuid() == 0 ? "#" : "$"), VTEXTFIXED);
+
+#ifndef SMALL
+       snprintf(buf, sizeof(buf), "%jd", sh_start_time);
+       setvar("START_TIME", buf, VTEXTFIXED);
+#endif
 
        setvar("NETBSD_SHELL", NETBSD_SHELL
 #ifdef BUILD_DATE
@@ -248,7 +301,7 @@
                vp->next = *vpp;
                *vpp = vp;
                vp->text = strdup(ip->text);
-               vp->flags = ip->flags;
+               vp->flags = (ip->flags & ~VTEXTFIXED) | VSTRFIXED;
                vp->v_u = ip->v_u;
        }
        /*
@@ -257,7 +310,7 @@
        if (find_var("PS1", &vpp, &vps1.name_len) == NULL) {
                vps1.next = *vpp;
                *vpp = &vps1;
-               vps1.flags = VSTRFIXED|VTEXTFIXED;
+               vps1.flags = VSTRFIXED;
                vps1.text = NULL;
                choose_ps1();
        }
@@ -266,8 +319,15 @@
 void
 choose_ps1(void)
 {
-       free(vps1.text);
+       if ((vps1.flags & (VTEXTFIXED|VSTACK)) == 0)
+               free(vps1.text);
        vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
+       vps1.flags &= ~(VTEXTFIXED|VSTACK);
+
+       /*
+        * Update PSc whenever we feel the need to update PS1
+        */
+       setvarsafe("PSc", (geteuid() == 0 ? "#" : "$"), 0);
 }
 
 /*
@@ -294,6 +354,11 @@
 /*
  * Set the value of a variable.  The flags argument is ored with the
  * flags of the variable.  If val is NULL, the variable is unset.
+ *
+ * This always copies name and val when setting a variable, so
+ * the source strings can be from anywhere, and are no longer needed
+ * after this function returns.  The VTEXTFIXED and VSTACK flags should
+ * not be used (but just in case they were, clear them.)
  */
 
 void
@@ -337,7 +402,7 @@
        *d = '\0';
        if (val)
                scopy(val, d);
-       setvareq(nameeq, flags);
+       setvareq(nameeq, flags & ~(VTEXTFIXED | VSTACK));
 }
 
 
@@ -346,7 +411,9 @@
  * Same as setvar except that the variable and value are passed in
  * the first argument as name=value.  Since the first argument will
  * be actually stored in the table, it should not be a string that
- * will go away.
+ * will go away.   The flags (VTEXTFIXED or VSTACK) can be used to
+ * indicate the source of the string (if neither is set, the string will
+ * eventually be free()d when a replacement value is assigned.)
  */
 
 void
@@ -405,7 +472,7 @@
                return;
        }
        vp = ckmalloc(sizeof (*vp));
-       vp->flags = flags & ~(VNOFUNC|VFUNCREF);
+       vp->flags = flags & ~(VNOFUNC|VFUNCREF|VSTRFIXED);
        vp->text = s;
        vp->name_len = nlen;
        vp->next = *vpp;
@@ -1058,16 +1125,304 @@
        return NULL;
 }
 
+/*
+ * The following are the functions that create the values for
+ * shell variables that are dynamically produced when needed.
+ *
+ * The output strings cannot be malloc'd as there is nothing to
+ * free them - callers assume these are ordinary variables where
+ * the value returned is vp->text
+ *
+ * Each function needs its own storage space, as the results are
+ * used to create processes' environment, and (if exported) all
+ * the values will (might) be needed simultaneously.
+ *
+ * It is not a problem if a var is updated while nominally in use
+ * somewhere, all these are intended to be dynamic, the value they
+ * return is not guaranteed, an updated vaue is just as good.
+ *
+ * So, malloc a single buffer for the result of each function,
+ * grow, and even shrink, it as needed, but once we have one that
+ * is a suitable size for the actual usage, simply hold it forever.
+ *
+ * For a SMALL shell we implement only LINENO, none of the others,
+ * and give it just a fixed length static buffer for its result.
+ */
+
+#ifndef SMALL
+
+struct space_reserved {                /* record of space allocated for results */
+       char *b;
+       int len;
+};
+
+/* rough (over-)estimate of the number of bytes needed to hold a number */
+static int
+digits_in(intmax_t number)
+{
+       int res = 0;
+
+       if (number & ~((1LL << 62) - 1))
+               res = 64;       /* enough for 2^200 and a bit more */
+       else if (number & ~((1LL << 32) - 1))
+               res = 20;       /* enough for 2^64 */
+       else if (number & ~((1 << 23) - 1))
+               res = 10;       /* enough for 2^32 */
+       else
+               res = 8;        /* enough for 2^23 or smaller */
+
+       return res;
+}
+
+static int
+make_space(struct space_reserved *m, int bytes)
+{
+       void *p;
+
+       if (m->len >= bytes && m->len <= (bytes<<2))
+               return 1;
+
+       bytes = SHELL_ALIGN(bytes);
+       /* not ckrealloc() - we want failure, not error() here */
+       p = realloc(m->b, bytes);
+       if (p == NULL)  /* what we had should still be there */



Home | Main Index | Thread Index | Old Index