/*++ /* NAME /* sys_compat 3 /* SUMMARY /* compatibility routines /* SYNOPSIS /* #include /* /* void closefrom(int lowfd) /* int lowfd; /* /* const char *strerror(err) /* int err; /* /* int setenv(name, value, clobber) /* const char *name; /* const char *value; /* int clobber; /* /* int unsetenv(name) /* const char *name; /* /* int seteuid(euid) /* uid_t euid; /* /* int setegid(egid) /* gid_t euid; /* /* int mkfifo(path, mode) /* char *path; /* int mode; /* /* int waitpid(pid, statusp, options) /* int pid; /* WAIT_STATUS_T *statusp; /* int options; /* /* int setsid() /* /* void dup2_pass_on_exec(int oldd, int newd) /* /* char *inet_ntop(af, src, dst, size) /* int af; /* const void *src; /* char *dst; /* SOCKADDR_SIZE size; /* /* int inet_pton(af, src, dst) /* int af; /* const char *src; /* void *dst; /* DESCRIPTION /* These routines are compiled for platforms that lack the functionality /* or that have broken versions that we prefer to stay away from. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* /* Wietse Venema /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA /*--*/ /* System library. */ #include "sys_defs.h" /* * ANSI strerror() emulation */ #ifdef MISSING_STRERROR extern int errno; extern char *sys_errlist[]; extern int sys_nerr; #include /* strerror - print text corresponding to error */ const char *strerror(int err) { static VSTRING *buf; if (err < 0 || err >= sys_nerr) { if (buf == 0) buf = vstring_alloc(10); vstring_sprintf(buf, "Unknown error %d", err); return (vstring_str(buf)); } else { return (sys_errlist[errno]); } } #endif /* * setenv() emulation on top of putenv(). */ #ifdef MISSING_SETENV #include #include #include /* setenv - update or insert environment (name,value) pair */ int setenv(const char *name, const char *value, int clobber) { char *cp; if (clobber == 0 && getenv(name) != 0) return (0); if ((cp = malloc(strlen(name) + strlen(value) + 2)) == 0) return (1); sprintf(cp, "%s=%s", name, value); return (putenv(cp)); } /* unsetenv - remove all instances of the name */ int unsetenv(const char *name) { extern char **environ; ssize_t name_len = strlen(name); char **src_pp; char **dst_pp; for (dst_pp = src_pp = environ; *src_pp; src_pp++, dst_pp++) { if (strncmp(*src_pp, name, name_len) == 0 && *(*src_pp + name_len) == '=') { dst_pp--; } else if (dst_pp != src_pp) { *dst_pp = *src_pp; } } *dst_pp = 0; return (0); } #endif /* * seteuid() and setegid() emulation, the HP-UX way */ #ifdef MISSING_SETEUID #ifdef HAVE_SETRESUID #include int seteuid(uid_t euid) { return setresuid(-1, euid, -1); } #else #error MISSING_SETEUID #endif #endif #ifdef MISSING_SETEGID #ifdef HAVE_SETRESGID #include int setegid(gid_t egid) { return setresgid(-1, egid, -1); } #else #error MISSING_SETEGID #endif #endif /* * mkfifo() emulation - requires superuser privileges */ #ifdef MISSING_MKFIFO #include int mkfifo(char *path, int mode) { return mknod(path, (mode & ~_S_IFMT) | _S_IFIFO, 0); } #endif /* * waitpid() emulation on top of Berkeley UNIX wait4() */ #ifdef MISSING_WAITPID #ifdef HAS_WAIT4 #include #include int waitpid(int pid, WAIT_STATUS_T *status, int options) { if (pid == -1) pid = 0; return wait4(pid, status, options, (struct rusage *) 0); } #else #error MISSING_WAITPID #endif #endif /* * setsid() emulation, the Berkeley UNIX way */ #ifdef MISSING_SETSID #include #include #include #include #ifdef TIOCNOTTY #include int setsid(void) { int p = getpid(); int fd; if (setpgrp(p, p)) return -1; fd = open("/dev/tty", O_RDONLY, 0); if (fd >= 0 || errno != ENXIO) { if (fd < 0) { msg_warn("open /dev/tty: %m"); return -1; } if (ioctl(fd, TIOCNOTTY, 0)) { msg_warn("ioctl TIOCNOTTY: %m"); return -1; } close(fd); } return 0; } #else #error MISSING_SETSID #endif #endif /* * dup2_pass_on_exec() - dup2() and clear close-on-exec flag on the result */ #ifdef DUP2_DUPS_CLOSE_ON_EXEC #include "iostuff.h" int dup2_pass_on_exec(int oldd, int newd) { int res; if ((res = dup2(oldd, newd)) >= 0) close_on_exec(newd, PASS_ON_EXEC); return res; } #endif #ifndef HAS_CLOSEFROM #include #include #include /* closefrom() - closes all file descriptors from the given one up */ int closefrom(int lowfd) { int fd_limit = open_limit(0); int fd; /* * lowfrom does not have an easy to determine upper limit. A process may * have files open that were inherited from a parent process with a less * restrictive resource limit. */ if (lowfd < 0) { errno = EBADF; return (-1); } if (fd_limit > 500) fd_limit = 500; for (fd = lowfd; fd < fd_limit; fd++) (void) close(fd); return (0); } #endif #ifdef MISSING_INET_NTOP #include #include #include #include #include #include #include /* inet_ntop - convert binary address to printable address */ const char *inet_ntop(int af, const void *src, char *dst, SOCKADDR_SIZE size) { const unsigned char *addr; char buffer[sizeof("255.255.255.255")]; int len; if (af != AF_INET) { errno = EAFNOSUPPORT; return (0); } addr = (const unsigned char *) src; #if (CHAR_BIT > 8) sprintf(buffer, "%d.%d.%d.%d", addr[0] & 0xff, addr[1] & 0xff, addr[2] & 0xff, addr[3] & 0xff); #else sprintf(buffer, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); #endif if ((len = strlen(buffer)) >= size) { errno = ENOSPC; return (0); } else { memcpy(dst, buffer, len + 1); return (dst); } } #endif #ifdef MISSING_INET_PTON #include #include #include #include #include #include #ifndef INADDR_NONE #define INADDR_NONE 0xffffffff #endif /* inet_pton - convert printable address to binary address */ int inet_pton(int af, const char *src, void *dst) { struct in_addr addr; /* * inet_addr() accepts a wider range of input formats than inet_pton(); * the former accepts 1-, 2-, or 3-part dotted addresses, while the * latter requires dotted quad form. */ if (af != AF_INET) { errno = EAFNOSUPPORT; return (-1); } else if ((addr.s_addr = inet_addr(src)) == INADDR_NONE && strcmp(src, "255.255.255.255") != 0) { return (0); } else { memcpy(dst, (void *) &addr, sizeof(addr)); return (1); } } #endif