📄 opts.c
字号:
strncpy(ep, cp, len); ep += len; } else { plog(XLOG_ERROR, expand_error, *p->opt); goto out; } } cp = dp + 1; ch = *cp++; if (ch == '$') { if (BUFSPACE(ep, 1)) { *ep++ = '$'; } else { plog(XLOG_ERROR, expand_error, *p->opt); goto out; } } else if (ch == '{') { /* Expansion... */ enum { E_All, E_Dir, E_File, E_Domain, E_Host } todo; /* * Find closing brace */ char *br_p = strchr(cp, '}'); int len; /* * Check we found it */ if (!br_p) { /* * Just give up */ plog(XLOG_USER, "No closing '}' in \"%s\"", *p->opt); goto out; } len = br_p - cp; /* * Figure out which part of the variable to grab. */ if (*cp == '/') { /* * Just take the last component */ todo = E_File; cp++; --len; } else if (br_p[-1] == '/') { /* * Take all but the last component */ 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 */ todo = E_All; } /* * Truncate if too long. Since it won't * match anyway it doesn't matter that * it has been cut short. */ if (len > NLEN) len = NLEN; /* * Put the string into another buffer so * we can do comparisons. */ strncpy(nbuf, cp, len); nbuf[len] = '\0'; /* * Advance cp */ cp = br_p + 1; /* * Search the option array */ for (op = opt_fields; op->name; op++) { /* * Check for match */ if (len == op->nlen && STREQ(op->name, nbuf)) { char xbuf[NLEN+3]; char *val; /* * Found expansion. Copy * the correct value field. */ if (!(!op->sel_p == !sel_p)) { /* * Copy the string across unexpanded */ sprintf(xbuf, "${%s%s%s}", todo == E_File ? "/" : todo == E_Domain ? "." : "", nbuf, todo == E_Dir ? "/" : todo == E_Host ? "." : ""); val = xbuf; /* * Make sure expansion doesn't * munge the value! */ todo = E_All; } else if (op->sel_p) { val = *op->sel_p; } else { val = *op->optp; } if (val) { /* * 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); char *vptr = val; switch (todo) { case E_Dir: vptr = strrchr(val, '/'); if (vptr) vlen = vptr - val; vptr = val; break; case E_File: vptr = strrchr(val, '/'); if (vptr) { vptr++; vlen = strlen(vptr); } 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);*/#endif /* DEBUG */ if (BUFSPACE(ep, vlen)) { strcpy(ep, vptr); ep += vlen; } else { plog(XLOG_ERROR, expand_error, *p->opt); goto out; } } /* * Done with this variable */ break; } } /* * Check that the search was succesful */ if (!op->name) { /* * If it wasn't then scan the * environment for that name * and use any value found */ char *env = getenv(nbuf); if (env) { int vlen = strlen(env); if (BUFSPACE(ep, vlen)) { strcpy(ep, env); ep += vlen; } else { plog(XLOG_ERROR, expand_error, *p->opt); goto out; }#ifdef DEBUG Debug(D_STR) plog(XLOG_DEBUG, "Environment gave \"%s\" -> \"%s\"", nbuf, env);#endif /* DEBUG */ } else { plog(XLOG_USER, "Unknown sequence \"${%s}\"", nbuf); } } } else { /* * Error, error */ plog(XLOG_USER, "Unknown $ sequence in \"%s\"", *p->opt); } }out: /* * Handle common case - no expansion */ if (cp == *p->opt) { *p->opt = strdup(cp); } else { /* * Finish off the expansion */ if (BUFSPACE(ep, strlen(cp))) { strcpy(ep, cp); /*ep += strlen(ep);*/ } else { plog(XLOG_ERROR, expand_error, *p->opt); } /* * Save the exansion */ *p->opt = strdup(expbuf); } normalize_slash(*p->opt);#ifdef DEBUG Debug(D_STR) { plog(XLOG_DEBUG, "Expansion of \"%s\"...", cp_orig); plog(XLOG_DEBUG, "... is \"%s\"", *p->opt); }#endif /* DEBUG */}/* * Wrapper for expand_op */static void expand_opts P((opt_apply*, int));static void expand_opts(p, sel_p)opt_apply *p;int sel_p;{ if (*p->opt) { expand_op(p, sel_p); } else if (p->val) { /* * Do double expansion, remembering * to free the string from the first * expansion... */ char *s = *p->opt = expand_key(p->val); expand_op(p, sel_p); free(s); }}/* * Apply a function to a list of options */static void apply_opts(op, ppp, b)void (*op)();opt_apply ppp[];int b;{ opt_apply *pp; for (pp = ppp; pp->opt; pp++) (*op)(pp, b);}/* * Free the option table */void free_opts(fo)am_opts *fo;{ /* * Copy in the structure we are playing with */ fs_static = *fo; /* * Free previously allocated memory */ apply_opts(free_op, to_free, FALSE);}/* * Expand lookup key */char *expand_key(key)char *key;{ opt_apply oa; oa.opt = &key; oa.val = 0; expand_opts(&oa, TRUE); return key;}/* * Remove trailing /'s from a string * unless the string is a single / (Steven Glassman) */void deslashify P((char *s));void deslashify(s)char *s;{ if (s && *s) { char *sl = s + strlen(s); while (*--sl == '/' && sl > s) *sl = '\0'; }}int eval_fs_opts(fo, opts, g_opts, path, key, map)am_opts *fo;char *opts, *g_opts, *path, *key, *map;{ int ok = TRUE; free_opts(fo); /* * Clear out the option table */ bzero((voidp) &fs_static, sizeof(fs_static)); bzero((voidp) vars, sizeof(vars)); bzero((voidp) fo, sizeof(*fo)); /* * Set key, map & path before expansion */ opt_key = key; opt_map = map; opt_path = path; /* * Expand global options */ fs_static.fs_glob = expand_key(g_opts); /* * Expand local options */ fs_static.fs_local = expand_key(opts); /* * Expand default (global) options */ if (!eval_opts(fs_static.fs_glob, key)) ok = FALSE; /* * Expand local options */ if (ok && !eval_opts(fs_static.fs_local, key)) ok = FALSE; /* * Normalise remote host name. * 1. Expand variables * 2. Normalize relative to host tables * 3. Strip local domains from the remote host * name before using it in other expansions. * This makes mount point names and other things * much shorter, while allowing cross domain * sharing of mount maps. */ apply_opts(expand_opts, rhost_expansion, FALSE); if (ok && fs_static.opt_rhost && *fs_static.opt_rhost) host_normalize(&fs_static.opt_rhost); /* * Macro expand the options. * Do this regardless of whether we are accepting * this mount - otherwise nasty things happen * with memory allocation. */ apply_opts(expand_opts, expansions, FALSE); /* * Strip trailing slashes from local pathname... */ deslashify(fs_static.opt_fs); /* * ok... copy the data back out. */ *fo = fs_static; /* * Clear defined options */ opt_key = opt_map = opt_path = nullstr; return ok;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -