diff options
Diffstat (limited to 'src/util/sys_compat.c')
-rw-r--r-- | src/util/sys_compat.c | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/src/util/sys_compat.c b/src/util/sys_compat.c new file mode 100644 index 0000000..8bf8e58 --- /dev/null +++ b/src/util/sys_compat.c @@ -0,0 +1,389 @@ +/*++ +/* NAME +/* sys_compat 3 +/* SUMMARY +/* compatibility routines +/* SYNOPSIS +/* #include <sys_defs.h> +/* +/* 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 <vstring.h> + +/* 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 <stdio.h> +#include <string.h> +#include <stdlib.h> + +/* 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 <unistd.h> + +int seteuid(uid_t euid) +{ + return setresuid(-1, euid, -1); +} + +#else +#error MISSING_SETEUID +#endif + +#endif + +#ifdef MISSING_SETEGID +#ifdef HAVE_SETRESGID +#include <unistd.h> + +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 <sys/stat.h> + +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 <sys/wait.h> +#include <errno.h> + +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 <sys/ioctl.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#ifdef TIOCNOTTY + +#include <msg.h> + +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 <unistd.h> +#include <errno.h> +#include <iostuff.h> + +/* 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 <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +/* 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 <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <string.h> +#include <errno.h> + +#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 |