📄 options.c
字号:
while (w != NULL) { opt = find_option(w->word); if (opt == NULL) { option_error("In secrets file: unrecognized option '%s'", w->word); goto err; } n = n_arguments(opt); w0 = w; for (i = 0; i < n; ++i) { w = w->next; if (w == NULL) { option_error( "In secrets file: too few parameters for option '%s'", w0->word); goto err; } argv[i] = w->word; } if (!process_option(opt, w0->word, argv)) goto err; w = w->next; } ret = 1;err: return ret;}/* * match_option - see if this option matches an option_t structure. */static intmatch_option(name, opt, dowild) char *name; option_t *opt; int dowild;{ int (*match) __P((char *, char **, int)); if (dowild != (opt->type == o_wild)) return 0; if (!dowild) return strcmp(name, opt->name) == 0; match = (int (*) __P((char *, char **, int))) opt->addr; return (*match)(name, NULL, 0);}/* * find_option - scan the option lists for the various protocols * looking for an entry with the given name. * This could be optimized by using a hash table. */static option_t *find_option(name) const char *name;{ option_t *opt; struct option_list *list; int i, dowild; for (dowild = 0; dowild <= 1; ++dowild) { for (opt = general_options; opt->name != NULL; ++opt) if (match_option(name, opt, dowild)) return opt; for (opt = auth_options; opt->name != NULL; ++opt) if (match_option(name, opt, dowild)) return opt; for (list = extra_options; list != NULL; list = list->next) for (opt = list->options; opt->name != NULL; ++opt) if (match_option(name, opt, dowild)) return opt; for (opt = the_channel->options; opt->name != NULL; ++opt) if (match_option(name, opt, dowild)) return opt; for (i = 0; protocols[i] != NULL; ++i) if ((opt = protocols[i]->options) != NULL) for (; opt->name != NULL; ++opt) if (match_option(name, opt, dowild)) return opt; } return NULL;}/* * process_option - process one new-style option. */static intprocess_option(opt, cmd, argv) option_t *opt; char *cmd; char **argv;{ u_int32_t v; int iv, a; char *sv; int (*parser) __P((char **)); int (*wildp) __P((char *, char **, int)); char *optopt = (opt->type == o_wild)? "": " option"; int prio = option_priority; option_t *mainopt = opt; current_option = opt->name; if ((opt->flags & OPT_PRIVFIX) && privileged_option) prio += OPRIO_ROOT; while (mainopt->flags & OPT_PRIOSUB) --mainopt; if (mainopt->flags & OPT_PRIO) { if (prio < mainopt->priority) { /* new value doesn't override old */ if (prio == OPRIO_CMDLINE && mainopt->priority > OPRIO_ROOT) { option_error("%s%s set in %s cannot be overridden\n", opt->name, optopt, mainopt->source); return 0; } return 1; } if (prio > OPRIO_ROOT && mainopt->priority == OPRIO_CMDLINE) warn("%s%s from %s overrides command line", opt->name, optopt, option_source); } if ((opt->flags & OPT_INITONLY) && phase != PHASE_INITIALIZE) { option_error("%s%s cannot be changed after initialization", opt->name, optopt); return 0; } if ((opt->flags & OPT_PRIV) && !privileged_option) { option_error("using the %s%s requires root privilege", opt->name, optopt); return 0; } if ((opt->flags & OPT_ENABLE) && *(bool *)(opt->addr2) == 0) { option_error("%s%s is disabled", opt->name, optopt); return 0; } if ((opt->flags & OPT_DEVEQUIV) && devnam_fixed) { option_error("the %s%s may not be changed in %s", opt->name, optopt, option_source); return 0; } switch (opt->type) { case o_bool: v = opt->flags & OPT_VALUE; *(bool *)(opt->addr) = v; if (opt->addr2 && (opt->flags & OPT_A2COPY)) *(bool *)(opt->addr2) = v; else if (opt->addr2 && (opt->flags & OPT_A2CLR)) *(bool *)(opt->addr2) = 0; else if (opt->addr2 && (opt->flags & OPT_A2CLRB)) *(u_char *)(opt->addr2) &= ~v; else if (opt->addr2 && (opt->flags & OPT_A2OR)) *(u_char *)(opt->addr2) |= v; break; case o_int: iv = 0; if ((opt->flags & OPT_NOARG) == 0) { if (!int_option(*argv, &iv)) return 0; if ((((opt->flags & OPT_LLIMIT) && iv < opt->lower_limit) || ((opt->flags & OPT_ULIMIT) && iv > opt->upper_limit)) && !((opt->flags & OPT_ZEROOK && iv == 0))) { char *zok = (opt->flags & OPT_ZEROOK)? " zero or": ""; switch (opt->flags & OPT_LIMITS) { case OPT_LLIMIT: option_error("%s value must be%s >= %d", opt->name, zok, opt->lower_limit); break; case OPT_ULIMIT: option_error("%s value must be%s <= %d", opt->name, zok, opt->upper_limit); break; case OPT_LIMITS: option_error("%s value must be%s between %d and %d", opt->name, zok, opt->lower_limit, opt->upper_limit); break; } return 0; } } a = opt->flags & OPT_VALUE; if (a >= 128) a -= 256; /* sign extend */ iv += a; if (opt->flags & OPT_INC) iv += *(int *)(opt->addr); if ((opt->flags & OPT_NOINCR) && !privileged_option) { int oldv = *(int *)(opt->addr); if ((opt->flags & OPT_ZEROINF) ? (oldv != 0 && (iv == 0 || iv > oldv)) : (iv > oldv)) { option_error("%s value cannot be increased", opt->name); return 0; } } *(int *)(opt->addr) = iv; if (opt->addr2 && (opt->flags & OPT_A2COPY)) *(int *)(opt->addr2) = iv; break; case o_uint32: if (opt->flags & OPT_NOARG) { v = opt->flags & OPT_VALUE; if (v & 0x80) v |= 0xffffff00U; } else if (!number_option(*argv, &v, 16)) return 0; if (opt->flags & OPT_OR) v |= *(u_int32_t *)(opt->addr); *(u_int32_t *)(opt->addr) = v; if (opt->addr2 && (opt->flags & OPT_A2COPY)) *(u_int32_t *)(opt->addr2) = v; break; case o_string: if (opt->flags & OPT_STATIC) { strlcpy((char *)(opt->addr), *argv, opt->upper_limit); } else { sv = strdup(*argv); if (sv == NULL) novm("option argument"); *(char **)(opt->addr) = sv; } break; case o_special_noarg: case o_special: parser = (int (*) __P((char **))) opt->addr; if (!(*parser)(argv)) return 0; if (opt->flags & OPT_A2LIST) { struct option_value *ovp, **pp; ovp = malloc(sizeof(*ovp) + strlen(*argv)); if (ovp != 0) { strcpy(ovp->value, *argv); ovp->source = option_source; ovp->next = NULL; pp = (struct option_value **) &opt->addr2; while (*pp != 0) pp = &(*pp)->next; *pp = ovp; } } break; case o_wild: wildp = (int (*) __P((char *, char **, int))) opt->addr; if (!(*wildp)(cmd, argv, 1)) return 0; break; } if (opt->addr2 && (opt->flags & (OPT_A2COPY|OPT_ENABLE |OPT_A2PRINTER|OPT_A2STRVAL|OPT_A2LIST|OPT_A2OR)) == 0) *(bool *)(opt->addr2) = !(opt->flags & OPT_A2CLR); mainopt->source = option_source; mainopt->priority = prio; mainopt->winner = opt - mainopt; return 1;}/* * override_value - if the option priorities would permit us to * override the value of option, return 1 and update the priority * and source of the option value. Otherwise returns 0. */intoverride_value(option, priority, source) const char *option; int priority; const char *source;{ option_t *opt; opt = find_option(option); if (opt == NULL) return 0; while (opt->flags & OPT_PRIOSUB) --opt; if ((opt->flags & OPT_PRIO) && priority < opt->priority) return 0; opt->priority = priority; opt->source = source; opt->winner = -1; return 1;}/* * n_arguments - tell how many arguments an option takes */static intn_arguments(opt) option_t *opt;{ return (opt->type == o_bool || opt->type == o_special_noarg || (opt->flags & OPT_NOARG))? 0: 1;}/* * add_options - add a list of options to the set we grok. */voidadd_options(opt) option_t *opt;{ struct option_list *list; list = malloc(sizeof(*list)); if (list == 0) novm("option list entry"); list->options = opt; list->next = extra_options; extra_options = list;}/* * check_options - check that options are valid and consistent. */voidcheck_options(){ if (logfile_fd >= 0 && logfile_fd != log_to_fd) close(logfile_fd);}/* * print_option - print out an option and its value */static voidprint_option(opt, mainopt, printer, arg) option_t *opt, *mainopt; void (*printer) __P((void *, char *, ...)); void *arg;{ int i, v; char *p; if (opt->flags & OPT_NOPRINT) return; switch (opt->type) { case o_bool: v = opt->flags & OPT_VALUE; if (*(bool *)opt->addr != v) /* this can happen legitimately, e.g. lock option turned off for default device */ break; printer(arg, "%s", opt->name); break; case o_int: v = opt->flags & OPT_VALUE; if (v >= 128) v -= 256; i = *(int *)opt->addr; if (opt->flags & OPT_NOARG) { printer(arg, "%s", opt->name); if (i != v) { if (opt->flags & OPT_INC) { for (; i > v; i -= v) printer(arg, " %s", opt->name); } else printer(arg, " # oops: %d not %d\n", i, v); } } else { printer(arg, "%s %d", opt->name, i); } break; case o_uint32: printer(arg, "%s", opt->name); if ((opt->flags & OPT_NOARG) == 0) printer(arg, " %x", *(u_int32_t *)opt->addr); break; case o_string: if (opt->flags & OPT_HIDE) { p = "??????"; } else { p = (char *) opt->addr; if ((opt->flags & OPT_STATIC) == 0) p = *(char **)p; } printer(arg, "%s %q", opt->name, p); break; case o_special: case o_special_noarg: case o_wild: if (opt->type != o_wild) { printer(arg, "%s", opt->name); if (n_arguments(opt) == 0) break; printer(arg, " "); } if (opt->flags & OPT_A2PRINTER) { void (*oprt) __P((option_t *, void ((*)__P((void *, char *, ...))), void *)); oprt = (void (*) __P((option_t *, void ((*)__P((void *, char *, ...))), void *)))opt->addr2; (*oprt)(opt, printer, arg); } else if (opt->flags & OPT_A2STRVAL) { p = (char *) opt->addr2; if ((opt->flags & OPT_STATIC) == 0) p = *(char **)p; printer("%q", p); } else if (opt->flags & OPT_A2LIST) { struct option_value *ovp; ovp = (struct option_value *) opt->addr2; for (;;) { printer(arg, "%q", ovp->value); if ((ovp = ovp->next) == NULL) break; printer(arg, "\t\t# (from %s)\n%s ", ovp->source, opt->name); } } else { printer(arg, "xxx # [don't know how to print value]"); } break; default: printer(arg, "# %s value (type %d\?\?)", opt->name, opt->type); break; } printer(arg, "\t\t# (from %s)\n", mainopt->source);}/* * print_option_list - print out options in effect from an * array of options. */static voidprint_option_list(opt, printer, arg) option_t *opt; void (*printer) __P((void *, char *, ...)); void *arg;{ while (opt->name != NULL) { if (opt->priority != OPRIO_DEFAULT && opt->winner != (short int) -1) print_option(opt + opt->winner, opt, printer, arg); do { ++opt; } while (opt->flags & OPT_PRIOSUB); }}/* * print_options - print out what options are in effect. */voidprint_options(printer, arg) void (*printer) __P((void *, char *, ...)); void *arg;{ struct option_list *list; int i; printer(arg, "pppd options in effect:\n"); print_option_list(general_options, printer, arg); print_option_list(auth_options, printer, arg); for (list = extra_options; list != NULL; list = list->next) print_option_list(list->options, printer, arg); print_option_list(the_channel->options, printer, arg); for (i = 0; protocols[i] != NULL; ++i) print_option_list(protocols[i]->options, printer, arg);}/* * usage - print out a message telling how to use the program. */static voidusage(){ if (phase == PHASE_INITIALIZE) fprintf(stderr, usage_string, VERSION, progname);}/* * showhelp - print out usage message and exit. */static intshowhelp(argv) char **argv;{ if (phase == PHASE_INITIALIZE) { usage(); exit(0); } return 0;}/* * showversion - print out the version number and exit. */static intshowversion(argv) char **argv;{ if (phase == PHASE_INITIALIZE) { fprintf(stderr, "pppd version %s\n", VERSION); exit(0); } return 0;}/* * option_error - print a message about an error in an option. * The message is logged, and also sent to * stderr if phase == PHASE_INITIALIZE. */voidoption_error __V((char *fmt, ...)){ va_list args; char buf[1024];#if defined(__STDC__) va_start(args, fmt);#else char *fmt; va_start(args); fmt = va_arg(args, char *);#endif vslprintf(buf, sizeof(buf), fmt, args); va_end(args); if (phase == PHASE_INITIALIZE) fprintf(stderr, "%s: %s\n", progname, buf); syslog(LOG_ERR, "%s", buf);}#if 0/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -