📄 conf.c
字号:
case ENETUNREACH: /* Network is unreachable */#endif#ifdef ENETRESET case ENETRESET: /* Network dropped connection on reset */#endif#ifdef ECONNABORTED case ECONNABORTED: /* Software caused connection abort */#endif#ifdef ECONNRESET case ECONNRESET: /* Connection reset by peer */#endif#ifdef ENOBUFS case ENOBUFS: /* No buffer space available */#endif#ifdef ESHUTDOWN case ESHUTDOWN: /* Can't send after socket shutdown */#endif#ifdef ECONNREFUSED case ECONNREFUSED: /* Connection refused */#endif#ifdef EHOSTDOWN case EHOSTDOWN: /* Host is down */#endif#ifdef EHOSTUNREACH case EHOSTUNREACH: /* No route to host */#endif#ifdef EDQUOT case EDQUOT: /* Disc quota exceeded */#endif#ifdef EPROCLIM case EPROCLIM: /* Too many processes */#endif#ifdef EUSERS case EUSERS: /* Too many users */#endif#ifdef EDEADLK case EDEADLK: /* Resource deadlock avoided */#endif#ifdef EISCONN case EISCONN: /* Socket already connected */#endif#ifdef EINPROGRESS case EINPROGRESS: /* Operation now in progress */#endif#ifdef EALREADY case EALREADY: /* Operation already in progress */#endif#ifdef EADDRINUSE case EADDRINUSE: /* Address already in use */#endif#ifdef EADDRNOTAVAIL case EADDRNOTAVAIL: /* Can't assign requested address */#endif#ifdef ETXTBSY case ETXTBSY: /* (Apollo) file locked */#endif#if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) case ENOSR: /* Out of streams resources */#endif return TRUE; } /* nope, must be permanent */ return FALSE;}/*** LOCKFILE -- lock a file using flock or (shudder) fcntl locking**** Parameters:** fd -- the file descriptor of the file.** filename -- the file name (for error messages).** ext -- the filename extension.** type -- type of the lock. Bits can be:** LOCK_EX -- exclusive lock.** LOCK_NB -- non-blocking.**** Returns:** TRUE if the lock was acquired.** FALSE otherwise.*/boollockfile(fd, filename, ext, type) int fd; char *filename; char *ext; int type;{# if !HASFLOCK int action; struct flock lfd; if (ext == NULL) ext = ""; bzero(&lfd, sizeof lfd); if (bitset(LOCK_UN, type)) lfd.l_type = F_UNLCK; else if (bitset(LOCK_EX, type)) lfd.l_type = F_WRLCK; else lfd.l_type = F_RDLCK; if (bitset(LOCK_NB, type)) action = F_SETLK; else action = F_SETLKW; if (tTd(55, 60)) printf("lockfile(%s%s, action=%d, type=%d): ", filename, ext, action, lfd.l_type); if (fcntl(fd, action, &lfd) >= 0) { if (tTd(55, 60)) printf("SUCCESS\n"); return TRUE; } if (tTd(55, 60)) printf("(%s) ", errstring(errno)); /* ** On SunOS, if you are testing using -oQ/tmp/mqueue or ** -oA/tmp/aliases or anything like that, and /tmp is mounted ** as type "tmp" (that is, served from swap space), the ** previous fcntl will fail with "Invalid argument" errors. ** Since this is fairly common during testing, we will assume ** that this indicates that the lock is successfully grabbed. */ if (errno == EINVAL) { if (tTd(55, 60)) printf("SUCCESS\n"); return TRUE; } if (!bitset(LOCK_NB, type) || (errno != EACCES && errno != EAGAIN)) { int omode = -1;# ifdef F_GETFL int oerrno = errno; (void) fcntl(fd, F_GETFL, &omode); errno = oerrno;# endif syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", filename, ext, fd, type, omode, geteuid()); }# else if (ext == NULL) ext = ""; if (tTd(55, 60)) printf("lockfile(%s%s, type=%o): ", filename, ext, type); if (flock(fd, type) >= 0) { if (tTd(55, 60)) printf("SUCCESS\n"); return TRUE; } if (tTd(55, 60)) printf("(%s) ", errstring(errno)); if (!bitset(LOCK_NB, type) || errno != EWOULDBLOCK) { int omode = -1;# ifdef F_GETFL int oerrno = errno; (void) fcntl(fd, F_GETFL, &omode); errno = oerrno;# endif syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", filename, ext, fd, type, omode, geteuid()); }# endif if (tTd(55, 60)) printf("FAIL\n"); return FALSE;}/*** CHOWNSAFE -- tell if chown is "safe" (executable only by root)**** Parameters:** fd -- the file descriptor to check.**** Returns:** TRUE -- if only root can chown the file to an arbitrary** user.** FALSE -- if an arbitrary user can give away a file.*/boolchownsafe(fd) int fd;{#ifdef __hpux char *s; int tfd; uid_t o_uid, o_euid; gid_t o_gid, o_egid; bool rval; struct stat stbuf; o_uid = getuid(); o_euid = geteuid(); o_gid = getgid(); o_egid = getegid(); fstat(fd, &stbuf); setresuid(stbuf.st_uid, stbuf.st_uid, -1); setresgid(stbuf.st_gid, stbuf.st_gid, -1); s = tmpnam(NULL); tfd = open(s, O_RDONLY|O_CREAT, 0600); rval = fchown(tfd, DefUid, DefGid) != 0; close(tfd); unlink(s); setreuid(o_uid, o_euid); setresgid(o_gid, o_egid, -1); return rval;#else# ifdef _POSIX_CHOWN_RESTRICTED# if _POSIX_CHOWN_RESTRICTED == -1 return FALSE;# else return TRUE;# endif# else# ifdef _PC_CHOWN_RESTRICTED return fpathconf(fd, _PC_CHOWN_RESTRICTED) > 0;# else# ifdef BSD return TRUE;# else return FALSE;# endif# endif# endif#endif}/*** GETCFNAME -- return the name of the .cf file.**** Some systems (e.g., NeXT) determine this dynamically.*/char *getcfname(){ if (ConfFile != NULL) return ConfFile;#ifdef NETINFO { extern char *ni_propval(); char *cflocation; cflocation = ni_propval("/locations/sendmail", "sendmail.cf"); if (cflocation != NULL) return cflocation; }#endif return _PATH_SENDMAILCF;}/*** SETVENDOR -- process vendor code from V configuration line**** Parameters:** vendor -- string representation of vendor.**** Returns:** TRUE -- if ok.** FALSE -- if vendor code could not be processed.**** Side Effects:** It is reasonable to set mode flags here to tweak** processing in other parts of the code if necessary.** For example, if you are a vendor that uses $%y to** indicate YP lookups, you could enable that here.*/boolsetvendor(vendor) char *vendor;{ if (strcasecmp(vendor, "Berkeley") == 0) return TRUE; /* add vendor extensions here */ return FALSE;}/*** STRTOL -- convert string to long integer**** For systems that don't have it in the C library.**** This is taken verbatim from the 4.4-Lite C library.*/#ifdef NEEDSTRTOL#if defined(LIBC_SCCS) && !defined(lint)static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";#endif /* LIBC_SCCS and not lint */#include <limits.h>/* * Convert a string to a long integer. * * Ignores `locale' stuff. Assumes that the upper and lower case * alphabets and digits are each contiguous. */longstrtol(nptr, endptr, base) const char *nptr; char **endptr; register int base;{ register const char *s = nptr; register unsigned long acc; register int c; register unsigned long cutoff; register int neg = 0, any, cutlim; /* * Skip white space and pick up leading +/- sign if any. * If base is 0, allow 0x for hex and 0 for octal, else * assume decimal; if base is already 16, allow 0x. */ do { c = *s++; } while (isspace(c)); if (c == '-') { neg = 1; c = *s++; } else if (c == '+') c = *s++; if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; /* * Compute the cutoff value between legal numbers and illegal * numbers. That is the largest legal value, divided by the * base. An input number that is greater than this value, if * followed by a legal input character, is too big. One that * is equal to this value may be valid or not; the limit * between valid and invalid numbers is then based on the last * digit. For instance, if the range for longs is * [-2147483648..2147483647] and the input base is 10, * cutoff will be set to 214748364 and cutlim to either * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated * a value > 214748364, or equal but the next digit is > 7 (or 8), * the number is too big, and we will return a range error. * * Set any if any `digits' consumed; make it negative to indicate * overflow. */ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; cutlim = cutoff % (unsigned long)base; cutoff /= (unsigned long)base; for (acc = 0, any = 0;; c = *s++) { if (isdigit(c)) c -= '0'; else if (isalpha(c)) c -= isupper(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) any = -1; else { any = 1; acc *= base; acc += c; } } if (any < 0) { acc = neg ? LONG_MIN : LONG_MAX; errno = ERANGE; } else if (neg) acc = -acc; if (endptr != 0) *endptr = (char *)(any ? s - 1 : nptr); return (acc);}#endif/*** SOLARIS_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX**** Solaris versions prior through 2.3 don't properly deliver a** canonical h_name field. This tries to work around it.*/#ifdef SOLARISstruct hostent *solaris_gethostbyname(name) const char *name;{# ifdef SOLARIS_2_3 static struct hostent hp; static char buf[1000]; extern struct hostent *_switch_gethostbyname_r(); return _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);# else extern struct hostent *__switch_gethostbyname(); return __switch_gethostbyname(name);# endif}struct hostent *solaris_gethostbyaddr(addr, len, type) const char *addr; int len; int type;{# ifdef SOLARIS_2_3 static struct hostent hp; static char buf[1000]; extern struct hostent *_switch_gethostbyaddr_r(); return _switch_gethostbyaddr_r(addr, len, type, &hp, buf, sizeof(buf), &h_errno);# else extern struct hostent *__switch_gethostbyaddr(); return __switch_gethostbyaddr(addr, len, type);# endif}#endif/*** NI_PROPVAL -- netinfo property value lookup routine**** Parameters:** directory -- the Netinfo directory name.** propname -- the Netinfo property name.**** Returns:** NULL -- if:** 1. the directory is not found** 2. the property name is not found** 3. the property contains multiple values** 4. some error occured** else -- the location of the config file.**** Notes:** Caller should free the return value of ni_proval*/#ifdef NETINFO# include <netinfo/ni.h># define LOCAL_NETINFO_DOMAIN "."# define PARENT_NETINFO_DOMAIN ".."# define MAX_NI_LEVELS 256char *ni_propval(directory, propname) char *directory; char *propname;{ char *propval = NULL; int i; void *ni = NULL; void *lastni = NULL; ni_status nis; ni_id nid; ni_namelist ninl; /* ** If the passed directory and property name are found ** in one of netinfo domains we need to search (starting ** from the local domain moving all the way back to the ** root domain) set propval to the property's value ** and return it. */ for (i = 0; i < MAX_NI_LEVELS; ++i) { if (i == 0) { nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); } else { if (lastni != NULL) ni_free(lastni); lastni = ni; nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); } /* ** Don't bother if we didn't get a handle on a ** proper domain. This is not necessarily an error. ** We would get a positive ni_status if, for instance ** we never found the directory or property and tried ** to open the parent of the root domain! */ if (nis != 0) break; /* ** Find the path to the server information. */ if (ni_pathsearch(ni, &nid, directory) != 0) continue; /* ** Find "host" information. */ if (ni_lookupprop(ni, &nid, propname, &ninl) != 0) continue; /* ** If there's only one name in ** the list, assume we've got ** what we want. */ if (ninl.ni_namelist_len == 1) { propval = ni_name_dup(ninl.ni_namelist_val[0]); break; } } /* ** Clean up. */ if (ni != NULL) ni_free(ni); if (lastni != NULL && ni != lastni) ni_free(lastni); return propval;}#endif /* NETINFO *//*** HARD_SYSLOG -- call syslog repeatedly until it works**** Needed on HP-UX, which apparently doesn't guarantee that** syslog succeeds during interrupt handlers.*/#ifdef __hpux# define MAXSYSLOGTRIES 100# undef syslog# ifdef __STDC__hard_syslog(int pri, char *msg, ...)# elsehard_syslog(pri, msg, va_alist) int pri; char *msg; va_dcl# endif{ int i; char buf[SYSLOG_BUFSIZE * 2]; VA_LOCAL_DECL; VA_START(msg); vsprintf(buf, msg, ap); VA_END; for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, "%s", buf) < 0; ) continue;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -