⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 opts.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * 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. * * 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. * * $Id: opts.c,v 5.2.2.3 1992/05/31 16:34:13 jsp Exp $ */#ifndef lintstatic char sccsid[] = "@(#)opts.c	8.1 (Berkeley) 6/6/93";#endif /* not lint */#include "am.h"extern char *getenv P((const char *));/* * static copy of the options with * which to play */static struct am_opts fs_static;static char *opt_host = hostname;static char *opt_hostd = hostd;static char nullstr[] = "";static char *opt_key = nullstr;static char *opt_map = nullstr;static char *opt_path = nullstr;static char *vars[8];/* * Length of longest option name */#define	NLEN	16	/* conservative */#define S(x) (x) , (sizeof(x)-1)static struct opt {	char *name;		/* Name of the option */	int nlen;		/* Length of option name */	char **optp;		/* Pointer to option value string */	char **sel_p;		/* Pointer to selector value string */} opt_fields[] = {	/* Options in something corresponding to frequency of use */	{ S("opts"), &fs_static.opt_opts, 0 },	{ S("host"), 0, &opt_host },	{ S("hostd"), 0, &opt_hostd },	{ S("type"), &fs_static.opt_type, 0 },	{ S("rhost"), &fs_static.opt_rhost, 0 },	{ S("rfs"), &fs_static.opt_rfs, 0 },	{ S("fs"), &fs_static.opt_fs, 0 },	{ S("key"), 0, &opt_key },	{ S("map"), 0, &opt_map },	{ S("sublink"), &fs_static.opt_sublink, 0 },	{ S("arch"), 0, &arch },	{ S("dev"), &fs_static.opt_dev, 0 },	{ S("pref"), &fs_static.opt_pref, 0 },	{ S("path"), 0, &opt_path },	{ S("autodir"), 0, &auto_dir },	{ S("delay"), &fs_static.opt_delay, 0 },	{ 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("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("user"), &fs_static.opt_user, 0 },	{ S("group"), &fs_static.opt_group, 0 },	{ S("var0"), &vars[0], 0 },	{ S("var1"), &vars[1], 0 },	{ S("var2"), &vars[2], 0 },	{ S("var3"), &vars[3], 0 },	{ S("var4"), &vars[4], 0 },	{ S("var5"), &vars[5], 0 },	{ S("var6"), &vars[6], 0 },	{ S("var7"), &vars[7], 0 },	{ 0, 0, 0, 0 },};typedef struct opt_apply opt_apply;struct opt_apply {	char **opt;	char *val;};/* * Specially expand the remote host name first */static opt_apply rhost_expansion[] = {	{ &fs_static.opt_rhost, "${host}" },	{ 0, 0 },};/* * List of options which need to be expanded * Note that this the order here _may_ be important. */static opt_apply expansions[] = {/*	{ &fs_static.opt_dir, 0 },	*/	{ &fs_static.opt_sublink, 0 },	{ &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 },};/* * List of options which need to be free'ed before re-use */static opt_apply to_free[] = {	{ &fs_static.fs_glob, 0 },	{ &fs_static.fs_local, 0 },	{ &fs_static.fs_mtab, 0 },/*	{ &fs_static.opt_dir, 0 },	*/	{ &fs_static.opt_sublink, 0 },	{ &fs_static.opt_rfs, 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 },	{ &vars[1], 0 },	{ &vars[2], 0 },	{ &vars[3], 0 },	{ &vars[4], 0 },	{ &vars[5], 0 },	{ &vars[6], 0 },	{ &vars[7], 0 },	{ 0, 0 },};/* * Skip to next option in the string */static char *opt P((char**));static char *opt(p)char **p;{	char *cp = *p;	char *dp = cp;	char *s = cp;top:	while (*cp && *cp != ';') {		if (*cp == '\"') {			/*			 * Skip past string			 */			cp++;			while (*cp && *cp != '\"')				*dp++ = *cp++;			if (*cp)				cp++;		} else {			*dp++ = *cp++;		}	}	/*	 * Skip past any remaining ';'s	 */	while (*cp == ';')		cp++;	/*	 * If we have a zero length string	 * and there are more fields, then	 * parse the next one.  This allows	 * sequences of empty fields.	 */	if (*cp && dp == s)		goto top;	*dp = '\0';	*p = cp;	return s;}static int eval_opts P((char*, char*));static int eval_opts(opts, mapkey)char *opts;char *mapkey;{	/*	 * Fill in the global structure fs_static by	 * cracking the string opts.  opts may be	 * scribbled on at will.	 */	char *o = opts;	char *f;	/*	 * For each user-specified option	 */	while (*(f = opt(&o))) {		struct opt *op;		enum vs_opt { OldSyn, SelEQ, SelNE, VarAss } vs_opt;		char *eq = strchr(f, '=');		char *opt;		if (!eq || eq[1] == '\0' || eq == f) {			/*			 * No value, just continue			 */			plog(XLOG_USER, "key %s: No value component in \"%s\"", mapkey, f);			continue;		}		/*		 * Check what type of operation is happening		 * !=, =!  is SelNE		 * == is SelEQ		 * := is VarAss		 * = is OldSyn (either SelEQ or VarAss)		 */		if (eq[-1] == '!') {		/* != */			vs_opt = SelNE;			eq[-1] = '\0';			opt = eq + 1;		} else if (eq[-1] == ':') {	/* := */			vs_opt = VarAss;			eq[-1] = '\0';			opt = eq + 1;		} else if (eq[1] == '=') {	/* == */			vs_opt = SelEQ;			eq[0] = '\0';			opt = eq + 2;		} else if (eq[1] == '!') {	/* =! */			vs_opt = SelNE;			eq[0] = '\0';			opt = eq + 2;		} else {			/* = */			vs_opt = OldSyn;			eq[0] = '\0';			opt = eq + 1;		}		/*		 * For each recognised option		 */		for (op = opt_fields; op->name; op++) {			/*			 * Check whether they match			 */			if (FSTREQ(op->name, f)) {				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;					}					/* fall through ... */#endif /* 5000108 */				case SelEQ:				case SelNE:					if (op->sel_p && (STREQ(*op->sel_p, opt) == (vs_opt == SelNE))) {						plog(XLOG_MAP, "key %s: map selector %s (=%s) did not %smatch %s",							mapkey,							op->name,							*op->sel_p,							vs_opt == SelNE ? "not " : "",							opt);						return 0;					}					break;				case VarAss:					if (op->sel_p) {						plog(XLOG_USER, "key %s: Can't assign to a selector (%s)", mapkey, op->name);						return 0;					}					*op->optp = opt;					break;				}				break;			}		}		if (!op->name)			plog(XLOG_USER, "key %s: Unrecognised key/option \"%s\"", mapkey, f);	}	return 1;}/* * Free an option */static void free_op P((opt_apply*, int));/*ARGSUSED*/static void free_op(p, b)opt_apply *p;int b;{	if (*p->opt) {		free(*p->opt);		*p->opt = 0;	}}/* * 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. * If sel is true then old expand selectors, otherwise * don't expand selectors. */static void expand_op P((opt_apply*, int));static void expand_op(p, sel_p)opt_apply *p;int sel_p;{/* * The BUFSPACE macros checks that there is enough space * left in the expansion buffer.  If there isn't then we * give up completely.  This is done to avoid crashing the * automounter itself (which would be a bad thing to do). */#define BUFSPACE(ep, len) (((ep) + (len)) < expbuf+MAXPATHLEN)static char expand_error[] = "No space to expand \"%s\"";	char expbuf[MAXPATHLEN+1];	char nbuf[NLEN+1];	char *ep = expbuf;	char *cp = *p->opt;	char *dp;#ifdef DEBUG	char *cp_orig = *p->opt;#endif /* DEBUG */	struct opt *op;	while (dp = strchr(cp, '$')) {		char ch;		/*		 * First copy up to the $		 */		{ int len = dp - cp;		  if (BUFSPACE(ep, len)) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -