summaryrefslogtreecommitdiffstats
path: root/src/util/sys_compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/sys_compat.c')
-rw-r--r--src/util/sys_compat.c389
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