📄 options.c
字号:
* readable - check if a file is readable by the real user. */intreadable(fd) int fd;{ uid_t uid; int i; struct stat sbuf; uid = getuid(); if (uid == 0) return 1; if (fstat(fd, &sbuf) != 0) return 0; if (sbuf.st_uid == uid) return sbuf.st_mode & S_IRUSR; if (sbuf.st_gid == getgid()) return sbuf.st_mode & S_IRGRP; for (i = 0; i < ngroups; ++i) if (sbuf.st_gid == groups[i]) return sbuf.st_mode & S_IRGRP; return sbuf.st_mode & S_IROTH;}#endif/* * Read a word from a file. * Words are delimited by white-space or by quotes (" or '). * Quotes, white-space and \ may be escaped with \. * \<newline> is ignored. */intgetword(f, word, newlinep, filename) FILE *f; char *word; int *newlinep; char *filename;{ int c, len, escape; int quoted, comment; int value, digit, got, n;#define isoctal(c) ((c) >= '0' && (c) < '8') *newlinep = 0; len = 0; escape = 0; comment = 0; /* * First skip white-space and comments. */ for (;;) { c = getc(f); if (c == EOF) break; /* * A newline means the end of a comment; backslash-newline * is ignored. Note that we cannot have escape && comment. */ if (c == '\n') { if (!escape) { *newlinep = 1; comment = 0; } else escape = 0; continue; } /* * Ignore characters other than newline in a comment. */ if (comment) continue; /* * If this character is escaped, we have a word start. */ if (escape) break; /* * If this is the escape character, look at the next character. */ if (c == '\\') { escape = 1; continue; } /* * If this is the start of a comment, ignore the rest of the line. */ if (c == '#') { comment = 1; continue; } /* * A non-whitespace character is the start of a word. */ if (!isspace(c)) break; } /* * Save the delimiter for quoted strings. */ if (!escape && (c == '"' || c == '\'')) { quoted = c; c = getc(f); } else quoted = 0; /* * Process characters until the end of the word. */ while (c != EOF) { if (escape) { /* * This character is escaped: backslash-newline is ignored, * various other characters indicate particular values * as for C backslash-escapes. */ escape = 0; if (c == '\n') { c = getc(f); continue; } got = 0; switch (c) { case 'a': value = '\a'; break; case 'b': value = '\b'; break; case 'f': value = '\f'; break; case 'n': value = '\n'; break; case 'r': value = '\r'; break; case 's': value = ' '; break; case 't': value = '\t'; break; default: if (isoctal(c)) { /* * \ddd octal sequence */ value = 0; for (n = 0; n < 3 && isoctal(c); ++n) { value = (value << 3) + (c & 07); c = getc(f); } got = 1; break; } if (c == 'x') { /* * \x<hex_string> sequence */ value = 0; c = getc(f); for (n = 0; n < 2 && isxdigit(c); ++n) { digit = toupper(c) - '0'; if (digit > 10) digit += '0' + 10 - 'A'; value = (value << 4) + digit; c = getc (f); } got = 1; break; } /* * Otherwise the character stands for itself. */ value = c; break; } /* * Store the resulting character for the escape sequence. */ if (len < MAXWORDLEN-1) word[len] = value; ++len; if (!got) c = getc(f); continue; } /* * Not escaped: see if we've reached the end of the word. */ if (quoted) { if (c == quoted) break; } else { if (isspace(c) || c == '#') { ungetc (c, f); break; } } /* * Backslash starts an escape sequence. */ if (c == '\\') { escape = 1; c = getc(f); continue; } /* * An ordinary character: store it in the word and get another. */ if (len < MAXWORDLEN-1) word[len] = c; ++len; c = getc(f); } /* * End of the word: check for errors. */ if (c == EOF) { if (ferror(f)) { if (errno == 0) errno = EIO; option_error("Error reading %s: %m", filename); die(1); } /* * If len is zero, then we didn't find a word before the * end of the file. */ if (len == 0) return 0; } /* * Warn if the word was too long, and append a terminating null. */ if (len >= MAXWORDLEN) { option_error("warning: word in file %s too long (%.20s...)", filename, word); len = MAXWORDLEN - 1; } word[len] = 0; return 1;#undef isoctal}/* * number_option - parse an unsigned numeric parameter for an option. */static intnumber_option(str, valp, base) char *str; u_int32_t *valp; int base;{ char *ptr; *valp = strtoul(str, &ptr, base); if (ptr == str) { option_error("invalid numeric parameter '%s' for %s option", str, current_option); return 0; } return 1;}/* * int_option - like number_option, but valp is int *, * the base is assumed to be 0, and *valp is not changed * if there is an error. */intint_option(str, valp) char *str; int *valp;{ u_int32_t v; if (!number_option(str, &v, 0)) return 0; *valp = (int) v; return 1;}/* * The following procedures parse options. *//* * readfile - take commands from a file. */static intreadfile(argv) char **argv;{ return options_from_file(*argv, 1, 1, privileged_option);}/* * callfile - take commands from /etc/ppp/peers/<name>. * Name may not contain /../, start with / or ../, or end in /.. */static intcallfile(argv) char **argv;{ char *fname, *arg, *p; int l, ok; arg = *argv; ok = 1; if (arg[0] == '/' || arg[0] == 0) ok = 0; else { for (p = arg; *p != 0; ) { if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) { ok = 0; break; } while (*p != '/' && *p != 0) ++p; if (*p == '/') ++p; } } if (!ok) { option_error("call option value may not contain .. or start with /"); return 0; } l = strlen(arg) + strlen(_PATH_PEERFILES) + 1; if ((fname = (char *) malloc(l)) == NULL) novm("call file name"); slprintf(fname, l, "%s%s", _PATH_PEERFILES, arg); ok = options_from_file(fname, 1, 1, 1); free(fname); return ok;}#ifdef PPP_FILTER/* * setpassfilter - Set the pass filter for packets */static intsetpassfilter(argv) char **argv;{ pcap_t *pc; int ret = 1; pc = pcap_open_dead(DLT_PPP_PPPD, 65535); if (pcap_compile(pc, &pass_filter, *argv, 1, netmask) == -1) { option_error("error in pass-filter expression: %s\n", pcap_geterr(pc)); ret = 0; } pcap_close(pc); return ret;}/* * setactivefilter - Set the active filter for packets */static intsetactivefilter(argv) char **argv;{ pcap_t *pc; int ret = 1; pc = pcap_open_dead(DLT_PPP_PPPD, 65535); if (pcap_compile(pc, &active_filter, *argv, 1, netmask) == -1) { option_error("error in active-filter expression: %s\n", pcap_geterr(pc)); ret = 0; } pcap_close(pc); return ret;}#endif/* * setdomain - Set domain name to append to hostname */static intsetdomain(argv) char **argv;{ gethostname(hostname, MAXNAMELEN); if (**argv != 0) { if (**argv != '.') strncat(hostname, ".", MAXNAMELEN - strlen(hostname)); domain = hostname + strlen(hostname); strncat(hostname, *argv, MAXNAMELEN - strlen(hostname)); } hostname[MAXNAMELEN-1] = 0; return (1);}static intsetlogfile(argv) char **argv;{ int fd, err; uid_t euid; euid = geteuid(); if (!privileged_option && seteuid(getuid()) == -1) { option_error("unable to drop permissions to open %s: %m", *argv); return 0; } fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644); if (fd < 0 && errno == EEXIST) fd = open(*argv, O_WRONLY | O_APPEND); err = errno; if (!privileged_option && seteuid(euid) == -1) fatal("unable to regain privileges: %m"); if (fd < 0) { errno = err; option_error("Can't open log file %s: %m", *argv); return 0; } strlcpy(logfile_name, *argv, sizeof(logfile_name)); if (logfile_fd >= 0) close(logfile_fd); logfile_fd = fd; log_to_fd = fd; log_default = 0; return 1;}#ifdef MAXOCTETSstatic intsetmodir(argv) char **argv;{ if(*argv == NULL) return 0; if(!strcmp(*argv,"in")) { maxoctets_dir = PPP_OCTETS_DIRECTION_IN; } else if (!strcmp(*argv,"out")) { maxoctets_dir = PPP_OCTETS_DIRECTION_OUT; } else if (!strcmp(*argv,"max")) { maxoctets_dir = PPP_OCTETS_DIRECTION_MAXOVERAL; } else { maxoctets_dir = PPP_OCTETS_DIRECTION_SUM; } return 1;}#endif#ifdef PLUGINstatic intloadplugin(argv) char **argv;{ char *arg = *argv; void *handle; const char *err; void (*init) __P((void)); char *path = arg; const char *vers; if (strchr(arg, '/') == 0) { const char *base = _PATH_PLUGIN; int l = strlen(base) + strlen(arg) + 2; path = malloc(l); if (path == 0) novm("plugin file path"); strlcpy(path, base, l); strlcat(path, "/", l); strlcat(path, arg, l); } handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW); if (handle == 0) { err = dlerror(); if (err != 0) option_error("%s", err); option_error("Couldn't load plugin %s", arg); goto err; } init = (void (*)(void))dlsym(handle, "plugin_init"); if (init == 0) { option_error("%s has no initialization entry point", arg); goto errclose; } vers = (const char *) dlsym(handle, "pppd_version"); if (vers == 0) { warn("Warning: plugin %s has no version information", arg); } else if (strcmp(vers, VERSION) != 0) { option_error("Plugin %s is for pppd version %s, this is %s", arg, vers, VERSION); goto errclose; } info("Plugin %s loaded.", arg); (*init)(); return 1; errclose: dlclose(handle); err: if (path != arg) free(path); return 0;}#endif /* PLUGIN */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -