readcf.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 983 行 · 第 1/2 页
C
983 行
#ifndef lintstatic char *sccsid = "@(#)readcf.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1987 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************/# include "sendmail.h"/*** READCF -- read control file.**** This routine reads the control file and builds the internal** form.**** The file is formatted as a sequence of lines, each taken** atomically. The first character of each line describes how** the line is to be interpreted. The lines are:** Dxval Define macro x to have value val.** Cxword Put word into class x.** Fxfile [fmt] Read file for lines to put into** class x. Use scanf string 'fmt'** or "%s" if not present. Fmt should** only produce one string-valued result.** Hname: value Define header with field-name 'name'** and value as specified; this will be** macro expanded immediately before** use.** Sn Use rewriting set n.** Rlhs rhs Rewrite addresses that match lhs to** be rhs.** Mn arg=val... Define mailer. n is the internal name.** Args specify mailer parameters.** Oxvalue Set option x to value.** Pname=value Set precedence name to value.**** Parameters:** cfname -- control file name.**** Returns:** none.**** Side Effects:** Builds several internal tables.*/readcf(cfname) char *cfname;{ FILE *cf; int ruleset = 0; char *q; char **pv; struct rewrite *rwp = NULL; char buf[MAXLINE]; register char *p; extern char **prescan(); extern char **copyplist(); char exbuf[MAXLINE]; char pvpbuf[PSBUFSIZE]; extern char *fgetfolded(); extern char *munchstring(); cf = fopen(cfname, "r"); if (cf == NULL) { syserr("cannot open %s", cfname); exit(EX_OSFILE); } FileName = cfname; LineNumber = 0; while (fgetfolded(buf, sizeof buf, cf) != NULL) { /* map $ into \001 (ASCII SOH) for macro expansion */ for (p = buf; *p != '\0'; p++) { if (*p != '$') continue; if (p[1] == '$') { /* actual dollar sign.... */ (void) strcpy(p, p + 1); continue; } /* convert to macro expansion character */ *p = '\001'; } /* interpret this line */ switch (buf[0]) { case '\0': case '#': /* comment */ break; case 'R': /* rewriting rule */ for (p = &buf[1]; *p != '\0' && *p != '\t'; p++) continue; if (*p == '\0') { syserr("invalid rewrite line \"%s\"", buf); break; } /* allocate space for the rule header */ if (rwp == NULL) { RewriteRules[ruleset] = rwp = (struct rewrite *) xalloc(sizeof *rwp); } else { rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp); rwp = rwp->r_next; } rwp->r_next = NULL; /* expand and save the LHS */ *p = '\0'; expand(&buf[1], exbuf, &exbuf[sizeof exbuf], CurEnv); rwp->r_lhs = prescan(exbuf, '\t', pvpbuf); if (rwp->r_lhs != NULL) rwp->r_lhs = copyplist(rwp->r_lhs, TRUE); /* expand and save the RHS */ while (*++p == '\t') continue; q = p; while (*p != '\0' && *p != '\t') p++; *p = '\0'; expand(q, exbuf, &exbuf[sizeof exbuf], CurEnv); rwp->r_rhs = prescan(exbuf, '\t', pvpbuf); if (rwp->r_rhs != NULL) rwp->r_rhs = copyplist(rwp->r_rhs, TRUE); break; case 'S': /* select rewriting set */ ruleset = atoi(&buf[1]); if (ruleset >= MAXRWSETS || ruleset < 0) { syserr("bad ruleset %d (%d max)", ruleset, MAXRWSETS); ruleset = 0; } rwp = NULL; break; case 'D': /* macro definition */ define(buf[1], newstr(munchstring(&buf[2])), CurEnv); break; case 'H': /* required header line */ (void) chompheader(&buf[1], TRUE); break; case 'C': /* word class */ case 'F': /* word class from file */ /* read list of words from argument or file */ if (buf[0] == 'F') { /* read from file */ for (p = &buf[2]; *p != '\0' && !isspace(*p); p++) continue; if (*p == '\0') p = "%s"; else { *p = '\0'; while (isspace(*++p)) continue; } fileclass(buf[1], &buf[2], p); break; } /* scan the list of words and set class for all */ for (p = &buf[2]; *p != '\0'; ) { register char *wd; char delim; while (*p != '\0' && isspace(*p)) p++; wd = p; while (*p != '\0' && !isspace(*p)) p++; delim = *p; *p = '\0'; if (wd[0] != '\0') setclass(buf[1], wd); *p = delim; } break; case 'M': /* define mailer */ makemailer(&buf[1]); break; case 'O': /* set option */ setoption(buf[1], &buf[2], TRUE, FALSE); break; case 'P': /* set precedence */ if (NumPriorities >= MAXPRIORITIES) { toomany('P', MAXPRIORITIES); break; } for (p = &buf[1]; *p != '\0' && *p != '=' && *p != '\t'; p++) continue; if (*p == '\0') goto badline; *p = '\0'; Priorities[NumPriorities].pri_name = newstr(&buf[1]); Priorities[NumPriorities].pri_val = atoi(++p); NumPriorities++; break; case 'T': /* trusted user(s) */ p = &buf[1]; while (*p != '\0') { while (isspace(*p)) p++; q = p; while (*p != '\0' && !isspace(*p)) p++; if (*p != '\0') *p++ = '\0'; if (*q == '\0') continue; for (pv = TrustedUsers; *pv != NULL; pv++) continue; if (pv >= &TrustedUsers[MAXTRUST]) { toomany('T', MAXTRUST); break; } *pv = newstr(q); } break; default: badline: syserr("unknown control line \"%s\"", buf); } } FileName = NULL;}/*** TOOMANY -- signal too many of some option**** Parameters:** id -- the id of the error line** maxcnt -- the maximum possible values**** Returns:** none.**** 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.**** Returns:** none**** Side Effects:**** puts all lines in filename that match a scanf into** the named class.*/fileclass(class, filename, fmt) int class; char *filename; char *fmt;{ FILE *f; char buf[MAXLINE]; f = fopen(filename, "r"); if (f == NULL) { syserr("cannot open %s", filename); return; } while (fgets(buf, sizeof buf, f) != NULL) { register STAB *s; register char *p;/* In support of Yellow Pages, we need to use the sscanf logic. Define * the flag. Why is this set up this way I wonder ? */# define SCANF 1# ifdef SCANF char wordbuf[MAXNAME+1]; /* /etc/passwd file entries for Yellow Pages users * of the form +name:::::/home/dir: * must have the + stripped, else the user name * won't get into the class. */ if (buf[0] == '+') { if (sscanf(&buf[1], fmt, wordbuf) != 1) continue; } else { 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 (isspace(*p)) p++; if (*p == '\0') break; /* find the end of the word */ q = p; while (*p != '\0' && !isspace(*p)) p++; if (*p != '\0') *p++ = '\0'; /* enter the word in the symbol table */ s = stab(q, ST_CLASS, ST_ENTER); setbitn(class, s->s_class); } } (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; extern int NextMailer; extern char **makeargv(); extern char *munchstring(); extern char *DelimChar; extern long atol(); /* allocate a mailer and set up defaults */ m = (struct mailer *) xalloc(sizeof *m); bzero((char *) m, sizeof *m); m->m_mno = NextMailer; m->m_eol = "\n"; /* collect the mailer name */ for (p = line; *p != '\0' && *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') { while (*p != '\0' && (*p == ',' || isspace(*p))) p++; /* p now points to field code */ fcode = *p; while (*p != '\0' && *p != '=' && *p != ',') p++; if (*p++ != '=') { syserr("`=' expected"); return; } while (isspace(*p)) p++; /* p now points to the field body */ p = munchstring(p); /* 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++) setbitn(*p, m->m_flags); break; case 'S': /* sender rewriting ruleset */ case 'R': /* recipient rewriting ruleset */ i = atoi(p); if (i < 0 || i >= MAXRWSETS) { syserr("invalid rewrite set, %d max", MAXRWSETS); return; } if (fcode == 'S') m->m_s_rwset = i; else m->m_r_rwset = i; break; case 'E': /* end of line string */ m->m_eol = newstr(p); break; case 'A': /* argument vector */ m->m_argv = makeargv(p);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?