aboutsummaryrefslogtreecommitdiff
path: root/compat
diff options
context:
space:
mode:
Diffstat (limited to 'compat')
-rw-r--r--compat/closefrom.h53
-rw-r--r--compat/compat.h59
-rw-r--r--compat/endian.h113
-rw-r--r--compat/endian_enc.h150
-rw-r--r--compat/flopen.h103
-rw-r--r--compat/pidfile.h293
-rw-r--r--compat/vis.h188
7 files changed, 850 insertions, 109 deletions
diff --git a/compat/closefrom.h b/compat/closefrom.h
new file mode 100644
index 000000000000..b0545f352a8c
--- /dev/null
+++ b/compat/closefrom.h
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/compat/closefrom.h#1 $
+ */
+
+#ifndef _CLOSEFROM_H_
+#define _CLOSEFROM_H_
+
+#include <unistd.h>
+
+static void
+closefrom(int lowfd)
+{
+ int error, fd, maxfd;
+
+ error = errno;
+
+ maxfd = sysconf(_SC_OPEN_MAX);
+ if (maxfd < 0)
+ maxfd = 16384;
+ for (fd = lowfd; fd <= maxfd; fd++)
+ (void)close(fd);
+
+ errno = error;
+}
+
+#endif /* !_CLOSEFROM_H_ */
diff --git a/compat/compat.h b/compat/compat.h
new file mode 100644
index 000000000000..5cd7446e0a6c
--- /dev/null
+++ b/compat/compat.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/compat/compat.h#1 $
+ */
+
+#ifndef _COMPAT_H_
+#define _COMPAT_H_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+#ifndef __packed
+#define __packed __attribute__((__packed__))
+#endif
+
+#ifndef __dead2
+#define __dead2 __attribute__((__noreturn__))
+#endif
+
+#ifndef __printflike
+#define __printflike(fmtarg, firstvararg) \
+ __attribute__((__format__ (__printf__, fmtarg, firstvararg)))
+#endif
+
+#endif /* !_COMPAT_H_ */
diff --git a/compat/endian.h b/compat/endian.h
index 6ef1d15b3d54..d01c7d4b2340 100644
--- a/compat/endian.h
+++ b/compat/endian.h
@@ -25,7 +25,7 @@
* SUCH DAMAGE.
*
* Derived from FreeBSD src/sys/sys/endian.h:1.6.
- * $P4: //depot/projects/trustedbsd/openbsm/compat/endian.h#8 $
+ * $P4: //depot/projects/trustedbsd/openbsm/compat/endian.h#10 $
*/
#ifndef _COMPAT_ENDIAN_H_
@@ -116,6 +116,8 @@ bswap64(uint64_t int64)
#define _LITTLE_ENDIAN LITTLE_ENDIAN
#endif
+/* XXX: Hack. */
+#ifndef htobe16
/*
* Host to big endian, host to little endian, big endian to host, and little
* endian to host byte order functions as detailed in byteorder(9).
@@ -149,113 +151,6 @@ bswap64(uint64_t int64)
#define le32toh(x) bswap32((x))
#define le64toh(x) bswap64((x))
#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */
-
-/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
-
-static __inline uint16_t
-be16dec(const void *pp)
-{
- unsigned char const *p = (unsigned char const *)pp;
-
- return ((p[0] << 8) | p[1]);
-}
-
-static __inline uint32_t
-be32dec(const void *pp)
-{
- unsigned char const *p = (unsigned char const *)pp;
-
- return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
-}
-
-static __inline uint64_t
-be64dec(const void *pp)
-{
- unsigned char const *p = (unsigned char const *)pp;
-
- return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4));
-}
-
-static __inline uint16_t
-le16dec(const void *pp)
-{
- unsigned char const *p = (unsigned char const *)pp;
-
- return ((p[1] << 8) | p[0]);
-}
-
-static __inline uint32_t
-le32dec(const void *pp)
-{
- unsigned char const *p = (unsigned char const *)pp;
-
- return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
-}
-
-static __inline uint64_t
-le64dec(const void *pp)
-{
- unsigned char const *p = (unsigned char const *)pp;
-
- return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p));
-}
-
-static __inline void
-be16enc(void *pp, uint16_t u)
-{
- unsigned char *p = (unsigned char *)pp;
-
- p[0] = (u >> 8) & 0xff;
- p[1] = u & 0xff;
-}
-
-static __inline void
-be32enc(void *pp, uint32_t u)
-{
- unsigned char *p = (unsigned char *)pp;
-
- p[0] = (u >> 24) & 0xff;
- p[1] = (u >> 16) & 0xff;
- p[2] = (u >> 8) & 0xff;
- p[3] = u & 0xff;
-}
-
-static __inline void
-be64enc(void *pp, uint64_t u)
-{
- unsigned char *p = (unsigned char *)pp;
-
- be32enc(p, u >> 32);
- be32enc(p + 4, u & 0xffffffff);
-}
-
-static __inline void
-le16enc(void *pp, uint16_t u)
-{
- unsigned char *p = (unsigned char *)pp;
-
- p[0] = u & 0xff;
- p[1] = (u >> 8) & 0xff;
-}
-
-static __inline void
-le32enc(void *pp, uint32_t u)
-{
- unsigned char *p = (unsigned char *)pp;
-
- p[0] = u & 0xff;
- p[1] = (u >> 8) & 0xff;
- p[2] = (u >> 16) & 0xff;
- p[3] = (u >> 24) & 0xff;
-}
-
-static __inline void
-le64enc(void *pp, uint64_t u)
-{
- unsigned char *p = (unsigned char *)pp;
-
- le32enc(p, u & 0xffffffff);
- le32enc(p + 4, u >> 32);
-}
+#endif
#endif /* _COMPAT_ENDIAN_H_ */
diff --git a/compat/endian_enc.h b/compat/endian_enc.h
new file mode 100644
index 000000000000..9e671b766607
--- /dev/null
+++ b/compat/endian_enc.h
@@ -0,0 +1,150 @@
+/*-
+ * Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org>
+ * Copyright (c) 2005 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Derived from FreeBSD src/sys/sys/endian.h:1.6.
+ * $P4: //depot/projects/trustedbsd/openbsm/compat/endian_enc.h#1 $
+ */
+
+#ifndef _COMPAT_ENDIAN_ENC_H_
+#define _COMPAT_ENDIAN_ENC_H_
+
+/*
+ * Some systems will have the uint/int types defined here already, others
+ * will need stdint.h.
+ */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
+
+static __inline uint16_t
+be16dec(const void *pp)
+{
+ unsigned char const *p = (unsigned char const *)pp;
+
+ return ((p[0] << 8) | p[1]);
+}
+
+static __inline uint32_t
+be32dec(const void *pp)
+{
+ unsigned char const *p = (unsigned char const *)pp;
+
+ return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+}
+
+static __inline uint64_t
+be64dec(const void *pp)
+{
+ unsigned char const *p = (unsigned char const *)pp;
+
+ return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4));
+}
+
+static __inline uint16_t
+le16dec(const void *pp)
+{
+ unsigned char const *p = (unsigned char const *)pp;
+
+ return ((p[1] << 8) | p[0]);
+}
+
+static __inline uint32_t
+le32dec(const void *pp)
+{
+ unsigned char const *p = (unsigned char const *)pp;
+
+ return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
+}
+
+static __inline uint64_t
+le64dec(const void *pp)
+{
+ unsigned char const *p = (unsigned char const *)pp;
+
+ return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p));
+}
+
+static __inline void
+be16enc(void *pp, uint16_t u)
+{
+ unsigned char *p = (unsigned char *)pp;
+
+ p[0] = (u >> 8) & 0xff;
+ p[1] = u & 0xff;
+}
+
+static __inline void
+be32enc(void *pp, uint32_t u)
+{
+ unsigned char *p = (unsigned char *)pp;
+
+ p[0] = (u >> 24) & 0xff;
+ p[1] = (u >> 16) & 0xff;
+ p[2] = (u >> 8) & 0xff;
+ p[3] = u & 0xff;
+}
+
+static __inline void
+be64enc(void *pp, uint64_t u)
+{
+ unsigned char *p = (unsigned char *)pp;
+
+ be32enc(p, u >> 32);
+ be32enc(p + 4, u & 0xffffffff);
+}
+
+static __inline void
+le16enc(void *pp, uint16_t u)
+{
+ unsigned char *p = (unsigned char *)pp;
+
+ p[0] = u & 0xff;
+ p[1] = (u >> 8) & 0xff;
+}
+
+static __inline void
+le32enc(void *pp, uint32_t u)
+{
+ unsigned char *p = (unsigned char *)pp;
+
+ p[0] = u & 0xff;
+ p[1] = (u >> 8) & 0xff;
+ p[2] = (u >> 16) & 0xff;
+ p[3] = (u >> 24) & 0xff;
+}
+
+static __inline void
+le64enc(void *pp, uint64_t u)
+{
+ unsigned char *p = (unsigned char *)pp;
+
+ le32enc(p, u & 0xffffffff);
+ le32enc(p + 4, u >> 32);
+}
+
+#endif /* _COMPAT_ENDIAN_ENC_H_ */
diff --git a/compat/flopen.h b/compat/flopen.h
new file mode 100644
index 000000000000..c68f4a2aded8
--- /dev/null
+++ b/compat/flopen.h
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 2007 Dag-Erling Coïdan Smørgrav
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Derived from FreeBSD head/lib/libutil/flopen.c r193591
+ * $P4: //depot/projects/trustedbsd/openbsm/compat/flopen.h#1 $
+ */
+
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+static int
+flopen(const char *path, int flags, ...)
+{
+ int fd, operation, serrno, trunc;
+ struct stat sb, fsb;
+ mode_t mode;
+
+#ifdef O_EXLOCK
+ flags &= ~O_EXLOCK;
+#endif
+
+ mode = 0;
+ if (flags & O_CREAT) {
+ va_list ap;
+
+ va_start(ap, flags);
+ mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */
+ va_end(ap);
+ }
+
+ operation = LOCK_EX;
+ if (flags & O_NONBLOCK)
+ operation |= LOCK_NB;
+
+ trunc = (flags & O_TRUNC);
+ flags &= ~O_TRUNC;
+
+ for (;;) {
+ if ((fd = open(path, flags, mode)) == -1)
+ /* non-existent or no access */
+ return (-1);
+ if (flock(fd, operation) == -1) {
+ /* unsupported or interrupted */
+ serrno = errno;
+ (void)close(fd);
+ errno = serrno;
+ return (-1);
+ }
+ if (stat(path, &sb) == -1) {
+ /* disappeared from under our feet */
+ (void)close(fd);
+ continue;
+ }
+ if (fstat(fd, &fsb) == -1) {
+ /* can't happen [tm] */
+ serrno = errno;
+ (void)close(fd);
+ errno = serrno;
+ return (-1);
+ }
+ if (sb.st_dev != fsb.st_dev ||
+ sb.st_ino != fsb.st_ino) {
+ /* changed under our feet */
+ (void)close(fd);
+ continue;
+ }
+ if (trunc && ftruncate(fd, 0) != 0) {
+ /* can't happen [tm] */
+ serrno = errno;
+ (void)close(fd);
+ errno = serrno;
+ return (-1);
+ }
+ return (fd);
+ }
+}
diff --git a/compat/pidfile.h b/compat/pidfile.h
new file mode 100644
index 000000000000..c3a259ba0801
--- /dev/null
+++ b/compat/pidfile.h
@@ -0,0 +1,293 @@
+/*-
+ * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Derived from FreeBSD head/lib/libutil/pidfile.c r231938
+ * $P4: //depot/projects/trustedbsd/openbsm/compat/pidfile.h#1 $
+ */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <err.h>
+#include <errno.h>
+
+#include "flopen.h"
+
+struct pidfh {
+ int pf_fd;
+ char pf_path[MAXPATHLEN + 1];
+ dev_t pf_dev;
+ ino_t pf_ino;
+};
+
+static int _pidfile_remove(struct pidfh *pfh, int freeit);
+
+static int
+pidfile_verify(const struct pidfh *pfh)
+{
+ struct stat sb;
+
+ if (pfh == NULL || pfh->pf_fd == -1)
+ return (EINVAL);
+ /*
+ * Check remembered descriptor.
+ */
+ if (fstat(pfh->pf_fd, &sb) == -1)
+ return (errno);
+ if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino)
+ return (EINVAL);
+ return (0);
+}
+
+static int
+pidfile_read(const char *path, pid_t *pidptr)
+{
+ char buf[16], *endptr;
+ int error, fd, i;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ return (errno);
+
+ i = read(fd, buf, sizeof(buf) - 1);
+ error = errno; /* Remember errno in case close() wants to change it. */
+ close(fd);
+ if (i == -1)
+ return (error);
+ else if (i == 0)
+ return (EAGAIN);
+ buf[i] = '\0';
+
+ *pidptr = strtol(buf, &endptr, 10);
+ if (endptr != &buf[i])
+ return (EINVAL);
+
+ return (0);
+}
+
+static struct pidfh *
+pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
+{
+ struct pidfh *pfh;
+ struct stat sb;
+ int error, fd, len, count;
+ struct timespec rqtp;
+
+ if (pidptr != NULL)
+ *pidptr = -1;
+
+ if (path == NULL)
+ return (NULL);
+
+ pfh = malloc(sizeof(*pfh));
+ if (pfh == NULL)
+ return (NULL);
+
+ len = snprintf(pfh->pf_path, sizeof(pfh->pf_path),
+ "%s", path);
+ if (len >= (int)sizeof(pfh->pf_path)) {
+ free(pfh);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+
+ /*
+ * Open the PID file and obtain exclusive lock.
+ * We truncate PID file here only to remove old PID immediatelly,
+ * PID file will be truncated again in pidfile_write(), so
+ * pidfile_write() can be called multiple times.
+ */
+ fd = flopen(pfh->pf_path,
+#ifdef O_CLOEXEC
+ O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK | O_CLOEXEC, mode);
+#else
+ O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode);
+#endif
+ if (fd == -1) {
+ if (errno == EWOULDBLOCK && pidptr != NULL) {
+ count = 20;
+ rqtp.tv_sec = 0;
+ rqtp.tv_nsec = 5000000;
+ for (;;) {
+ errno = pidfile_read(pfh->pf_path, pidptr);
+ if (errno != EAGAIN || --count == 0)
+ break;
+ nanosleep(&rqtp, 0);
+ }
+ if (errno == EAGAIN)
+ *pidptr = -1;
+ if (errno == 0 || errno == EAGAIN)
+ errno = EEXIST;
+ }
+ free(pfh);
+ return (NULL);
+ }
+
+#ifndef O_CLOEXEC
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
+ error = errno;
+ unlink(pfh->pf_path);
+ close(fd);
+ free(pfh);
+ errno = error;
+ return (NULL);
+ }
+#endif
+
+ /*
+ * Remember file information, so in pidfile_write() we are sure we write
+ * to the proper descriptor.
+ */
+ if (fstat(fd, &sb) == -1) {
+ error = errno;
+ unlink(pfh->pf_path);
+ close(fd);
+ free(pfh);
+ errno = error;
+ return (NULL);
+ }
+
+ pfh->pf_fd = fd;
+ pfh->pf_dev = sb.st_dev;
+ pfh->pf_ino = sb.st_ino;
+
+ return (pfh);
+}
+
+static int
+pidfile_write(struct pidfh *pfh)
+{
+ char pidstr[16];
+ int error, fd;
+
+ /*
+ * Check remembered descriptor, so we don't overwrite some other
+ * file if pidfile was closed and descriptor reused.
+ */
+ errno = pidfile_verify(pfh);
+ if (errno != 0) {
+ /*
+ * Don't close descriptor, because we are not sure if it's ours.
+ */
+ return (-1);
+ }
+ fd = pfh->pf_fd;
+
+ /*
+ * Truncate PID file, so multiple calls of pidfile_write() are allowed.
+ */
+ if (ftruncate(fd, 0) == -1) {
+ error = errno;
+ _pidfile_remove(pfh, 0);
+ errno = error;
+ return (-1);
+ }
+
+ snprintf(pidstr, sizeof(pidstr), "%u", getpid());
+ if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
+ error = errno;
+ _pidfile_remove(pfh, 0);
+ errno = error;
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+pidfile_close(struct pidfh *pfh)
+{
+ int error;
+
+ error = pidfile_verify(pfh);
+ if (error != 0) {
+ errno = error;
+ return (-1);
+ }
+
+ if (close(pfh->pf_fd) == -1)
+ error = errno;
+ free(pfh);
+ if (error != 0) {
+ errno = error;
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+_pidfile_remove(struct pidfh *pfh, int freeit)
+{
+ int error;
+
+ error = pidfile_verify(pfh);
+ if (error != 0) {
+ errno = error;
+ return (-1);
+ }
+
+ if (unlink(pfh->pf_path) == -1)
+ error = errno;
+ if (close(pfh->pf_fd) == -1) {
+ if (error == 0)
+ error = errno;
+ }
+ if (freeit)
+ free(pfh);
+ else
+ pfh->pf_fd = -1;
+ if (error != 0) {
+ errno = error;
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+pidfile_remove(struct pidfh *pfh)
+{
+
+ return (_pidfile_remove(pfh, 1));
+}
+
+#if 0
+static int
+pidfile_fileno(const struct pidfh *pfh)
+{
+
+ if (pfh == NULL || pfh->pf_fd == -1) {
+ errno = EINVAL;
+ return (-1);
+ }
+ return (pfh->pf_fd);
+}
+#endif
diff --git a/compat/vis.h b/compat/vis.h
new file mode 100644
index 000000000000..c03177aa4a49
--- /dev/null
+++ b/compat/vis.h
@@ -0,0 +1,188 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Defived from FreeBSD head/lib/libc/gen/vis.c 165903, head/include/vis.h
+ * 203964.
+ */
+
+#include <sys/types.h>
+#include <limits.h>
+#include <ctype.h>
+#include <stdio.h>
+
+/*
+ * to select alternate encoding format
+ */
+#define VIS_OCTAL 0x01 /* use octal \ddd format */
+#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropriate */
+
+/*
+ * to alter set of characters encoded (default is to encode all
+ * non-graphic except space, tab, and newline).
+ */
+#define VIS_SP 0x04 /* also encode space */
+#define VIS_TAB 0x08 /* also encode tab */
+#define VIS_NL 0x10 /* also encode newline */
+#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
+#define VIS_SAFE 0x20 /* only encode "unsafe" characters */
+
+/*
+ * other
+ */
+#define VIS_NOSLASH 0x40 /* inhibit printing '\' */
+#define VIS_HTTPSTYLE 0x80 /* http-style escape % HEX HEX */
+#define VIS_GLOB 0x100 /* encode glob(3) magics */
+
+/*
+ * unvis return codes
+ */
+#define UNVIS_VALID 1 /* character valid */
+#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */
+#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */
+#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */
+#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */
+
+/*
+ * unvis flags
+ */
+#define UNVIS_END 1 /* no more characters */
+
+#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+
+/*
+ * vis - visually encode characters
+ */
+char *
+vis(dst, c, flag, nextc)
+ char *dst;
+ int c, nextc;
+ int flag;
+{
+ c = (unsigned char)c;
+
+ if (flag & VIS_HTTPSTYLE) {
+ /* Described in RFC 1808 */
+ if (!(isalnum(c) /* alpha-numeric */
+ /* safe */
+ || c == '$' || c == '-' || c == '_' || c == '.' || c == '+'
+ /* extra */
+ || c == '!' || c == '*' || c == '\'' || c == '('
+ || c == ')' || c == ',')) {
+ *dst++ = '%';
+ snprintf(dst, 4, (c < 16 ? "0%X" : "%X"), c);
+ dst += 2;
+ goto done;
+ }
+ }
+
+ if ((flag & VIS_GLOB) &&
+ (c == '*' || c == '?' || c == '[' || c == '#'))
+ ;
+ else if (isgraph(c) ||
+ ((flag & VIS_SP) == 0 && c == ' ') ||
+ ((flag & VIS_TAB) == 0 && c == '\t') ||
+ ((flag & VIS_NL) == 0 && c == '\n') ||
+ ((flag & VIS_SAFE) && (c == '\b' || c == '\007' || c == '\r'))) {
+ *dst++ = c;
+ if (c == '\\' && (flag & VIS_NOSLASH) == 0)
+ *dst++ = '\\';
+ *dst = '\0';
+ return (dst);
+ }
+
+ if (flag & VIS_CSTYLE) {
+ switch(c) {
+ case '\n':
+ *dst++ = '\\';
+ *dst++ = 'n';
+ goto done;
+ case '\r':
+ *dst++ = '\\';
+ *dst++ = 'r';
+ goto done;
+ case '\b':
+ *dst++ = '\\';
+ *dst++ = 'b';
+ goto done;
+ case '\a':
+ *dst++ = '\\';
+ *dst++ = 'a';
+ goto done;
+ case '\v':
+ *dst++ = '\\';
+ *dst++ = 'v';
+ goto done;
+ case '\t':
+ *dst++ = '\\';
+ *dst++ = 't';
+ goto done;
+ case '\f':
+ *dst++ = '\\';
+ *dst++ = 'f';
+ goto done;
+ case ' ':
+ *dst++ = '\\';
+ *dst++ = 's';
+ goto done;
+ case '\0':
+ *dst++ = '\\';
+ *dst++ = '0';
+ if (isoctal(nextc)) {
+ *dst++ = '0';
+ *dst++ = '0';
+ }
+ goto done;
+ }
+ }
+ if (((c & 0177) == ' ') || isgraph(c) || (flag & VIS_OCTAL)) {
+ *dst++ = '\\';
+ *dst++ = ((u_char)c >> 6 & 07) + '0';
+ *dst++ = ((u_char)c >> 3 & 07) + '0';
+ *dst++ = ((u_char)c & 07) + '0';
+ goto done;
+ }
+ if ((flag & VIS_NOSLASH) == 0)
+ *dst++ = '\\';
+ if (c & 0200) {
+ c &= 0177;
+ *dst++ = 'M';
+ }
+ if (iscntrl(c)) {
+ *dst++ = '^';
+ if (c == 0177)
+ *dst++ = '?';
+ else
+ *dst++ = c + '@';
+ } else {
+ *dst++ = '-';
+ *dst++ = c;
+ }
+done:
+ *dst = '\0';
+ return (dst);
+}