📄 readcf.c
字号:
** Side Effects:** gives a syserr.*/toomany(id, maxcnt) char id; int maxcnt;{ syserr("too many %c lines, %d max", id, maxcnt);}/*** FILECLASS -- read members of a class from a file**** Parameters:** class -- class to define.** filename -- name of file to read.** fmt -- scanf string to use for match.** safe -- if set, this is a safe read.** optional -- if set, it is not an error for the file to** not exist.**** Returns:** none**** Side Effects:**** puts all lines in filename that match a scanf into** the named class.*/fileclass(class, filename, fmt, safe, optional) int class; char *filename; char *fmt; bool safe; bool optional;{ FILE *f; struct stat stbuf; char buf[MAXLINE]; if (tTd(37, 2)) printf("fileclass(%s, fmt=%s)\n", filename, fmt); if (filename[0] == '|') { syserr("fileclass: pipes (F%c%s) not supported due to security problems", class, filename); return; } if (stat(filename, &stbuf) < 0) { if (tTd(37, 2)) printf(" cannot stat (%s)\n", errstring(errno)); if (!optional) syserr("fileclass: cannot stat %s", filename); return; } if (!S_ISREG(stbuf.st_mode)) { syserr("fileclass: %s not a regular file", filename); return; } if (!safe && access(filename, R_OK) < 0) { syserr("fileclass: access denied on %s", filename); return; } f = fopen(filename, "r"); if (f == NULL) { syserr("fileclass: cannot open %s", filename); return; } while (fgets(buf, sizeof buf, f) != NULL) { register STAB *s; register char *p;# ifdef SCANF char wordbuf[MAXNAME+1]; if (sscanf(buf, fmt, wordbuf) != 1) continue; p = wordbuf;# else /* SCANF */ p = buf;# endif /* SCANF */ /* ** Break up the match into words. */ while (*p != '\0') { register char *q; /* strip leading spaces */ while (isascii(*p) && isspace(*p)) p++; if (*p == '\0') break; /* find the end of the word */ q = p; while (*p != '\0' && !(isascii(*p) && isspace(*p))) p++; if (*p != '\0') *p++ = '\0'; /* enter the word in the symbol table */ setclass(class, q); } } (void) fclose(f);}/*** MAKEMAILER -- define a new mailer.**** Parameters:** line -- description of mailer. This is in labeled** fields. The fields are:** P -- the path to the mailer** F -- the flags associated with the mailer** A -- the argv for this mailer** S -- the sender rewriting set** R -- the recipient rewriting set** E -- the eol string** The first word is the canonical name of the mailer.**** Returns:** none.**** Side Effects:** enters the mailer into the mailer table.*/makemailer(line) char *line;{ register char *p; register struct mailer *m; register STAB *s; int i; char fcode; auto char *endp; extern int NextMailer; extern char **makeargv(); extern char *munchstring(); extern long atol(); /* allocate a mailer and set up defaults */ m = (struct mailer *) xalloc(sizeof *m); bzero((char *) m, sizeof *m); m->m_eol = "\n"; /* collect the mailer name */ for (p = line; *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p)); p++) continue; if (*p != '\0') *p++ = '\0'; m->m_name = newstr(line); /* now scan through and assign info from the fields */ while (*p != '\0') { auto char *delimptr; while (*p != '\0' && (*p == ',' || (isascii(*p) && isspace(*p)))) p++; /* p now points to field code */ fcode = *p; while (*p != '\0' && *p != '=' && *p != ',') p++; if (*p++ != '=') { syserr("mailer %s: `=' expected", m->m_name); return; } while (isascii(*p) && isspace(*p)) p++; /* p now points to the field body */ p = munchstring(p, &delimptr); /* install the field into the mailer struct */ switch (fcode) { case 'P': /* pathname */ m->m_mailer = newstr(p); break; case 'F': /* flags */ for (; *p != '\0'; p++) if (!(isascii(*p) && isspace(*p))) setbitn(*p, m->m_flags); break; case 'S': /* sender rewriting ruleset */ case 'R': /* recipient rewriting ruleset */ i = strtol(p, &endp, 10); if (i < 0 || i >= MAXRWSETS) { syserr("invalid rewrite set, %d max", MAXRWSETS); return; } if (fcode == 'S') m->m_sh_rwset = m->m_se_rwset = i; else m->m_rh_rwset = m->m_re_rwset = i; p = endp; if (*p++ == '/') { i = strtol(p, NULL, 10); if (i < 0 || i >= MAXRWSETS) { syserr("invalid rewrite set, %d max", MAXRWSETS); return; } if (fcode == 'S') m->m_sh_rwset = i; else m->m_rh_rwset = i; } break; case 'E': /* end of line string */ m->m_eol = newstr(p); break; case 'A': /* argument vector */ m->m_argv = makeargv(p); break; case 'M': /* maximum message size */ m->m_maxsize = atol(p); break; case 'L': /* maximum line length */ m->m_linelimit = atoi(p); break; case 'D': /* working directory */ m->m_execdir = newstr(p); break; } p = delimptr; } /* do some heuristic cleanup for back compatibility */ if (bitnset(M_LIMITS, m->m_flags)) { if (m->m_linelimit == 0) m->m_linelimit = SMTPLINELIM; if (ConfigLevel < 2) setbitn(M_7BITS, m->m_flags); } /* do some rationality checking */ if (m->m_argv == NULL) { syserr("M%s: A= argument required", m->m_name); return; } if (m->m_mailer == NULL) { syserr("M%s: P= argument required", m->m_name); return; } if (NextMailer >= MAXMAILERS) { syserr("too many mailers defined (%d max)", MAXMAILERS); return; } s = stab(m->m_name, ST_MAILER, ST_ENTER); if (s->s_mailer != NULL) { i = s->s_mailer->m_mno; free(s->s_mailer); } else { i = NextMailer++; } Mailer[i] = s->s_mailer = m; m->m_mno = i;}/*** MUNCHSTRING -- translate a string into internal form.**** Parameters:** p -- the string to munch.** delimptr -- if non-NULL, set to the pointer of the** field delimiter character.**** Returns:** the munched string.*/char *munchstring(p, delimptr) register char *p; char **delimptr;{ register char *q; bool backslash = FALSE; bool quotemode = FALSE; static char buf[MAXLINE]; for (q = buf; *p != '\0'; p++) { if (backslash) { /* everything is roughly literal */ backslash = FALSE; switch (*p) { case 'r': /* carriage return */ *q++ = '\r'; continue; case 'n': /* newline */ *q++ = '\n'; continue; case 'f': /* form feed */ *q++ = '\f'; continue; case 'b': /* backspace */ *q++ = '\b'; continue; } *q++ = *p; } else { if (*p == '\\') backslash = TRUE; else if (*p == '"') quotemode = !quotemode; else if (quotemode || *p != ',') *q++ = *p; else break; } } if (delimptr != NULL) *delimptr = p; *q++ = '\0'; return (buf);}/*** MAKEARGV -- break up a string into words**** Parameters:** p -- the string to break up.**** Returns:** a char **argv (dynamically allocated)**** Side Effects:** munges p.*/char **makeargv(p) register char *p;{ char *q; int i; char **avp; char *argv[MAXPV + 1]; /* take apart the words */ i = 0; while (*p != '\0' && i < MAXPV) { q = p; while (*p != '\0' && !(isascii(*p) && isspace(*p))) p++; while (isascii(*p) && isspace(*p)) *p++ = '\0'; argv[i++] = newstr(q); } argv[i++] = NULL; /* now make a copy of the argv */ avp = (char **) xalloc(sizeof *avp * i); bcopy((char *) argv, (char *) avp, sizeof *avp * i); return (avp);}/*** PRINTRULES -- print rewrite rules (for debugging)**** Parameters:** none.**** Returns:** none.**** Side Effects:** prints rewrite rules.*/printrules(){ register struct rewrite *rwp; register int ruleset; for (ruleset = 0; ruleset < 10; ruleset++) { if (RewriteRules[ruleset] == NULL) continue; printf("\n----Rule Set %d:", ruleset); for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next) { printf("\nLHS:"); printav(rwp->r_lhs); printf("RHS:"); printav(rwp->r_rhs); } }}/*** SETOPTION -- set global processing option**** Parameters:** opt -- option name.** val -- option value (as a text string).** safe -- set if this came from a configuration file.** Some options (if set from the command line) will** reset the user id to avoid security problems.** sticky -- if set, don't let other setoptions override** this value.** e -- the main envelope.**** Returns:** none.**** Side Effects:** Sets options as implied by the arguments.*/static BITMAP StickyOpt; /* set if option is stuck */#if NAMED_BINDstruct resolverflags{ char *rf_name; /* name of the flag */ long rf_bits; /* bits to set/clear */} ResolverFlags[] ={ "debug", RES_DEBUG, "aaonly", RES_AAONLY, "usevc", RES_USEVC, "primary", RES_PRIMARY, "igntc", RES_IGNTC, "recurse", RES_RECURSE, "defnames", RES_DEFNAMES, "stayopen", RES_STAYOPEN, "dnsrch", RES_DNSRCH, "true", 0, /* to avoid error on old syntax */ NULL, 0};#endifsetoption(opt, val, safe, sticky, e) char opt; char *val; bool safe; bool sticky; register ENVELOPE *e;{ register char *p; extern bool atobool(); extern time_t convtime(); extern int QueueLA; extern int RefuseLA; extern bool Warn_Q_option; extern bool trusteduser(); if (tTd(37, 1)) printf("setoption %c=%s", opt, val); /* ** See if this option is preset for us. */ if (!sticky && bitnset(opt, StickyOpt)) { if (tTd(37, 1)) printf(" (ignored)\n"); return; } /* ** Check to see if this option can be specified by this user. */ if (!safe && RealUid == 0) safe = TRUE; if (!safe && strchr("bCdeijLmoprsvw7", opt) == NULL) { if (opt != 'M' || (val[0] != 'r' && val[0] != 's')) { if (tTd(37, 1)) printf(" (unsafe)"); if (RealUid != geteuid()) { if (tTd(37, 1)) printf("(Resetting uid)"); (void) setgid(RealGid); (void) setuid(RealUid); } } } if (tTd(37, 1)) printf("\n"); switch (opt) { case '7': /* force seven-bit input */ SevenBit = atobool(val); break; case 'A': /* set default alias file */ if (val[0] == '\0') setalias("aliases"); else setalias(val); break; case 'a': /* look N minutes for "@:@" in alias file */ if (val[0] == '\0') SafeAlias = 5 * 60; /* five minutes */ else SafeAlias = convtime(val, 'm'); break; case 'B': /* substitution for blank character */ SpaceSub = val[0]; if (SpaceSub == '\0') SpaceSub = ' '; break; case 'b': /* min blocks free on queue fs/max msg size */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -