BSD 4_4 release
[unix-history] / usr / src / usr.sbin / amd / amd / opts.c
index b389941..54c9675 100644 (file)
@@ -1,34 +1,50 @@
-/*
- * $Id: opts.c,v 5.2 90/06/23 22:19:51 jsp Rel $
- *
+/*-
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
  * Copyright (c) 1989 Jan-Simon Pendry
  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
- * Copyright (c) 1989 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Jan-Simon Pendry at Imperial College, London.
  *
  *
  * This code is derived from software contributed to Berkeley by
  * Jan-Simon Pendry at Imperial College, London.
  *
- * Redistribution and use in source and binary forms are permitted provided
- * that: (1) source distributions retain this entire copyright notice and
- * comment, and (2) distributions including binaries display the following
- * acknowledgement:  ``This product includes software developed by the
- * University of California, Berkeley and its contributors'' in the
- * documentation or other materials provided with the distribution and in
- * all advertising materials mentioning features or use of this software.
- * Neither the name of the University nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  *
  *
- *     @(#)opts.c      5.1 (Berkeley) 6/29/90
+ * $Id: opts.c,v 5.2.2.3 1992/05/31 16:34:13 jsp Exp $
  */
 
  */
 
+#ifndef lint
+static char sccsid[] = "@(#)opts.c     8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
 #include "am.h"
 
 #include "am.h"
 
-extern char *getenv P((char *));
+extern char *getenv P((const char *));
 
 /*
  * static copy of the options with
 
 /*
  * static copy of the options with
@@ -48,7 +64,7 @@ static char *vars[8];
 /*
  * Length of longest option name
  */
 /*
  * Length of longest option name
  */
-#define        NLEN    16
+#define        NLEN    16      /* conservative */
 #define S(x) (x) , (sizeof(x)-1)
 static struct opt {
        char *name;             /* Name of the option */
 #define S(x) (x) , (sizeof(x)-1)
 static struct opt {
        char *name;             /* Name of the option */
@@ -76,8 +92,10 @@ static struct opt {
        { S("domain"), 0, &hostdomain },
        { S("karch"), 0, &karch },
        { S("cluster"), 0, &cluster },
        { S("domain"), 0, &hostdomain },
        { S("karch"), 0, &karch },
        { S("cluster"), 0, &cluster },
+       { S("wire"), 0, &wire },
        { S("byte"), 0, &endian },
        { S("os"), 0, &op_sys },
        { S("byte"), 0, &endian },
        { S("os"), 0, &op_sys },
+       { S("remopts"), &fs_static.opt_remopts, 0 },
        { S("mount"), &fs_static.opt_mount, 0 },
        { S("unmount"), &fs_static.opt_unmount, 0 },
        { S("cache"), &fs_static.opt_cache, 0 },
        { S("mount"), &fs_static.opt_mount, 0 },
        { S("unmount"), &fs_static.opt_unmount, 0 },
        { S("cache"), &fs_static.opt_cache, 0 },
@@ -117,6 +135,7 @@ static opt_apply expansions[] = {
        { &fs_static.opt_rfs, "${path}" },
        { &fs_static.opt_fs, "${autodir}/${rhost}${rfs}" },
        { &fs_static.opt_opts, "rw" },
        { &fs_static.opt_rfs, "${path}" },
        { &fs_static.opt_fs, "${autodir}/${rhost}${rfs}" },
        { &fs_static.opt_opts, "rw" },
+       { &fs_static.opt_remopts, "${opts}" },
        { &fs_static.opt_mount, 0 },
        { &fs_static.opt_unmount, 0 },
        { 0, 0 },
        { &fs_static.opt_mount, 0 },
        { &fs_static.opt_unmount, 0 },
        { 0, 0 },
@@ -135,6 +154,7 @@ static opt_apply to_free[] = {
        { &fs_static.opt_fs, 0 },
        { &fs_static.opt_rhost, 0 },
        { &fs_static.opt_opts, 0 },
        { &fs_static.opt_fs, 0 },
        { &fs_static.opt_rhost, 0 },
        { &fs_static.opt_opts, 0 },
+       { &fs_static.opt_remopts, 0 },
        { &fs_static.opt_mount, 0 },
        { &fs_static.opt_unmount, 0 },
        { &vars[0], 0 },
        { &fs_static.opt_mount, 0 },
        { &fs_static.opt_unmount, 0 },
        { &vars[0], 0 },
@@ -196,9 +216,10 @@ top:
        return s;
 }
 
        return s;
 }
 
-static int eval_opts P((char*));
-static int eval_opts(opts)
+static int eval_opts P((char*, char*));
+static int eval_opts(opts, mapkey)
 char *opts;
 char *opts;
+char *mapkey;
 {
        /*
         * Fill in the global structure fs_static by
 {
        /*
         * Fill in the global structure fs_static by
@@ -220,7 +241,7 @@ char *opts;
                        /*
                         * No value, just continue
                         */
                        /*
                         * No value, just continue
                         */
-                       plog(XLOG_USER, "No value component in \"%s\"", f);
+                       plog(XLOG_USER, "key %s: No value component in \"%s\"", mapkey, f);
                        continue;
                }
 
                        continue;
                }
 
@@ -264,6 +285,7 @@ char *opts;
                                switch (vs_opt) {
 #if AMD_COMPAT <= 5000108
                                case OldSyn:
                                switch (vs_opt) {
 #if AMD_COMPAT <= 5000108
                                case OldSyn:
+                                       plog(XLOG_WARNING, "key %s: Old syntax selector found: %s=%s", mapkey, f, opt);
                                        if (!op->sel_p) {
                                                *op->optp = opt;
                                                break;
                                        if (!op->sel_p) {
                                                *op->optp = opt;
                                                break;
@@ -273,7 +295,8 @@ char *opts;
                                case SelEQ:
                                case SelNE:
                                        if (op->sel_p && (STREQ(*op->sel_p, opt) == (vs_opt == SelNE))) {
                                case SelEQ:
                                case SelNE:
                                        if (op->sel_p && (STREQ(*op->sel_p, opt) == (vs_opt == SelNE))) {
-                                               plog(XLOG_MAP, "map selector %s (=%s) did not %smatch %s",
+                                               plog(XLOG_MAP, "key %s: map selector %s (=%s) did not %smatch %s",
+                                                       mapkey,
                                                        op->name,
                                                        *op->sel_p,
                                                        vs_opt == SelNE ? "not " : "",
                                                        op->name,
                                                        *op->sel_p,
                                                        vs_opt == SelNE ? "not " : "",
@@ -284,7 +307,7 @@ char *opts;
 
                                case VarAss:
                                        if (op->sel_p) {
 
                                case VarAss:
                                        if (op->sel_p) {
-                                               plog(XLOG_USER, "Can't assign to a selector (%s)", op->name);
+                                               plog(XLOG_USER, "key %s: Can't assign to a selector (%s)", mapkey, op->name);
                                                return 0;
                                        }
                                        *op->optp = opt;
                                                return 0;
                                        }
                                        *op->optp = opt;
@@ -295,7 +318,7 @@ char *opts;
                }
 
                if (!op->name)
                }
 
                if (!op->name)
-                       plog(XLOG_USER, "Unrecognised key \"%s\"", f);
+                       plog(XLOG_USER, "key %s: Unrecognised key/option \"%s\"", mapkey, f);
        }
 
        return 1;
        }
 
        return 1;
@@ -316,6 +339,46 @@ int b;
        }
 }
 
        }
 }
 
+/*
+ * Normalize slashes in the string.
+ */
+void normalize_slash P((char *p));
+void normalize_slash(p)
+char *p;
+{
+       char *f = strchr(p, '/');
+       char *f0 = f;
+       if (f) {
+               char *t = f;
+               do {
+                       /* assert(*f == '/'); */
+                       if (f == f0 && f[0] == '/' && f[1] == '/') {
+                               /* copy double slash iff first */
+                               *t++ = *f++;
+                               *t++ = *f++;
+                       } else {
+                               /* copy a single / across */
+                               *t++ = *f++;
+                       }
+
+                       /* assert(f[-1] == '/'); */
+                       /* skip past more /'s */
+                       while (*f == '/')
+                               f++;
+
+                       /* assert(*f != '/'); */
+                       /* keep copying up to next / */
+                       while (*f && *f != '/') {
+                               *t++ = *f++;
+                       }
+
+                       /* assert(*f == 0 || *f == '/'); */
+
+               } while (*f);
+               *t = 0;                 /* derived from fix by Steven Glassman */
+       }
+}
+
 /*
  * Macro-expand an option.  Note that this does not
  * handle recursive expansions.  They will go badly wrong.
 /*
  * Macro-expand an option.  Note that this does not
  * handle recursive expansions.  They will go badly wrong.
@@ -371,7 +434,7 @@ static char expand_error[] = "No space to expand \"%s\"";
                        }
                } else if (ch == '{') {
                        /* Expansion... */
                        }
                } else if (ch == '{') {
                        /* Expansion... */
-                       enum { E_All, E_Dir, E_File } todo;
+                       enum { E_All, E_Dir, E_File, E_Domain, E_Host } todo;
                        /*
                         * Find closing brace
                         */
                        /*
                         * Find closing brace
                         */
@@ -404,6 +467,19 @@ static char expand_error[] = "No space to expand \"%s\"";
                                 */
                                todo = E_Dir;
                                --len;
                                 */
                                todo = E_Dir;
                                --len;
+                       } else if (*cp == '.') {
+                               /*
+                                * Take domain name
+                                */
+                               todo = E_Domain;
+                               cp++;
+                               --len;
+                       } else if (br_p[-1] == '.') {
+                               /*
+                                * Take host name
+                                */
+                               todo = E_Host;
+                               --len;
                        } else {
                                /*
                                 * Take the whole lot
                        } else {
                                /*
                                 * Take the whole lot
@@ -446,9 +522,11 @@ static char expand_error[] = "No space to expand \"%s\"";
                                                 * Copy the string across unexpanded
                                                 */
                                                sprintf(xbuf, "${%s%s%s}",
                                                 * Copy the string across unexpanded
                                                 */
                                                sprintf(xbuf, "${%s%s%s}",
-                                                       todo == E_File ? "/" : "",
+                                                       todo == E_File ? "/" :
+                                                               todo == E_Domain ? "." : "",
                                                        nbuf,
                                                        nbuf,
-                                                       todo == E_Dir ? "/" : "");
+                                                       todo == E_Dir ? "/" :
+                                                               todo == E_Host ? "." : "");
                                                val = xbuf;
                                                /*
                                                 * Make sure expansion doesn't
                                                val = xbuf;
                                                /*
                                                 * Make sure expansion doesn't
@@ -465,6 +543,8 @@ static char expand_error[] = "No space to expand \"%s\"";
                                                 * Do expansion:
                                                 * ${/var} means take just the last part
                                                 * ${var/} means take all but the last part
                                                 * Do expansion:
                                                 * ${/var} means take just the last part
                                                 * ${var/} means take all but the last part
+                                                * ${.var} means take all but first part
+                                                * ${var.} means take just the first part
                                                 * ${var} means take the whole lot
                                                 */
                                                int vlen = strlen(val);
                                                 * ${var} means take the whole lot
                                                 */
                                                int vlen = strlen(val);
@@ -484,6 +564,24 @@ static char expand_error[] = "No space to expand \"%s\"";
                                                        } else
                                                                vptr = val;
                                                        break;
                                                        } else
                                                                vptr = val;
                                                        break;
+                                               case E_Domain:
+                                                       vptr = strchr(val, '.');
+                                                       if (vptr) {
+                                                               vptr++;
+                                                               vlen = strlen(vptr);
+                                                       } else {
+                                                               vptr = "";
+                                                               vlen = 0;
+                                                       }
+                                                       break;
+                                               case E_Host:
+                                                       vptr = strchr(val, '.');
+                                                       if (vptr)
+                                                               vlen = vptr - val;
+                                                       vptr = val;
+                                                       break;
+                                               case E_All:
+                                                       break;
                                                }
 #ifdef DEBUG
                                        /*dlog("Expanding \"%s\" to \"%s\"", nbuf, val);*/
                                                }
 #ifdef DEBUG
                                        /*dlog("Expanding \"%s\" to \"%s\"", nbuf, val);*/
@@ -561,33 +659,7 @@ out:
                *p->opt = strdup(expbuf);
        }
 
                *p->opt = strdup(expbuf);
        }
 
-       /*
-        * Normalize slashes in the string.
-        */
-       { char *f = strchr(*p->opt, '/');
-         if (f) {
-               char *t = f;
-               do {
-                       /* assert(*f == '/'); */
-                       /* copy a single / across */
-                       *t++ = *f++;
-
-                       /* assert(f[-1] == '/'); */
-                       /* skip past more /'s */
-                       while (*f == '/')
-                               f++;
-
-                       /* assert(*f != '/'); */
-                       /* keep copying up to next / */
-                       do {
-                               *t++ = *f++;
-                       } while (*f && *f != '/');
-
-                       /* assert(*f == 0 || *f == '/'); */
-
-               } while (*f);
-         }
-       }
+       normalize_slash(*p->opt);
 
 #ifdef DEBUG
        Debug(D_STR) {
 
 #ifdef DEBUG
        Debug(D_STR) {
@@ -664,14 +736,16 @@ char *key;
 }
 
 /*
 }
 
 /*
- * Remove trailing / from a string
+ * Remove trailing /'s from a string
+ * unless the string is a single / (Steven Glassman)
  */
  */
-static void deslashify(s)
+void deslashify P((char *s));
+void deslashify(s)
 char *s;
 {
 char *s;
 {
-       if (s) {
-               char *sl = strrchr(s, '/');
-               if (sl && sl[1] == '\0')
+       if (s && *s) {
+               char *sl = s + strlen(s);
+               while (*--sl == '/' && sl > s)
                        *sl = '\0';
        }
 }
                        *sl = '\0';
        }
 }
@@ -711,13 +785,13 @@ char *opts, *g_opts, *path, *key, *map;
        /*
         * Expand default (global) options
         */
        /*
         * Expand default (global) options
         */
-       if (!eval_opts(fs_static.fs_glob))
+       if (!eval_opts(fs_static.fs_glob, key))
                ok = FALSE;
 
        /*
         * Expand local options
         */
                ok = FALSE;
 
        /*
         * Expand local options
         */
-       if (ok && !eval_opts(fs_static.fs_local))
+       if (ok && !eval_opts(fs_static.fs_local, key))
                ok = FALSE;
 
        /*
                ok = FALSE;
 
        /*