commit f36fd90a2e6ab101692fba0fa643aec5035597cd from: Omar Polo date: Sat Jul 09 09:52:38 2022 UTC use (a modified version of) kristaps' oconfigure see GitHub issue #1 commit - c2f554ff612cef4c72eea5a7da22d508b8c36d3c commit + f36fd90a2e6ab101692fba0fa643aec5035597cd blob - 3fdff78bcab1fcf6493998cb99b64ff5a5da4f63 blob + abf3c24bc711201666a48e52c79d2bdde00dea31 --- .gitignore +++ .gitignore @@ -1,2 +1,10 @@ +Makefile.configure +amused +config.h +config.h.old +config.log +config.log.old +**/*.d +**/*.o **/obj **/tags blob - 5a598e37a5ea16dd8da1dc46006c6e7595d42ad7 blob + b209c639fe00cd307f6816a5e1c56083e45f7cce --- Makefile +++ Makefile @@ -1,47 +1,104 @@ -PROG= amused -SRCS= amused.c control.c log.c xmalloc.c player.c ctl.c playlist.c \ - player_flac.c player_123.c player_opus.c player_oggvorbis.c +.PHONY: all clean distclean install -.include "amused-version.mk" +VERSION = 0.10 -CPPFLAGS += -I/usr/local/include -I/usr/local/include/opus +PROG = amused -LDADD = -levent -lm -lsndio -lutil \ - -L/usr/local/lib -lmpg123 -lvorbisfile -lopusfile -lFLAC -DPADD = ${LIBEVENT} ${LIBM} ${LIBSNDIO} ${LIBUTIL} +SOURCES = amused.c \ + compats.c \ + control.c \ + ctl.c \ + log.c \ + player.c \ + player_123.c \ + player_flac.c \ + player_oggvorbis.c \ + player_opus.c \ + playlist.c \ + xmalloc.c -.if "${AMUSED_RELEASE}" == "Yes" -PREFIX ?= /usr/local -BINDIR ?= ${PREFIX}/bin -MANDIR ?= ${PREFIX}/man/man -.else -NOMAN = Yes -CFLAGS += -Werror -Wall -Wstrict-prototypes -Wunused-variable -PREFIX ?= ${HOME} -BINDIR ?= ${PREFIX}/bin -BINOWN ?= ${USER} -.if !defined(BINGRP) -BINGRP != id -g -n -.endif -DEBUG = -O0 -g -.endif +OBJS = ${SOURCES:.c=.o} -release: clean - sed -i -e 's/_RELEASE=No/_RELEASE=Yes/' amused-version.mk - ${MAKE} dist - sed -i -e 's/_RELEASE=Yes/_RELEASE=No/' amused-version.mk +HEADERS = amused.h \ + control.h \ + log.h \ + playlist.h \ + xmalloc.h -dist: clean - mkdir /tmp/amused-${AMUSED_VERSION} - pax -rw * /tmp/amused-${AMUSED_VERSION} - find /tmp/amused-${AMUSED_VERSION} -type d -name obj -delete - rm /tmp/amused-${AMUSED_VERSION}/amused-dist.txt - tar -C /tmp -zcf amused-${AMUSED_VERSION}.tar.gz amused-${AMUSED_VERSION} - rm -rf /tmp/amused-${AMUSED_VERSION} - tar -ztf amused-${AMUSED_VERSION}.tar.gz | \ - sed -e 's/^amused-${AMUSED_VERSION}//' | \ - sort > amused-dist.txt.new - diff -u amused-dist.txt{,.new} - rm amused-dist.txt.new +DISTFILES = CHANGES \ + LICENSE \ + Makefile \ + README.md \ + amused.1 \ + configure \ + configure.local.example \ + imsg.h \ + queue.h \ + tests.c \ + ${HEADERS} \ + ${SOURCES} -.include +all: ${PROG} + +Makefile.configure config.h: configure tests.c + @echo "$@ is out of date; please run ./configure" + @exit 1 + +include Makefile.configure + +# -- targets -- + +${PROG}: ${OBJS} + ${CC} -o $@ ${OBJS} ${LDFLAGS} ${LDADD} + +clean: + rm -f ${OBJS} ${PROG} + +distclean: clean + rm -f Makefile.configure config.h config.h.old config.log config.log.old + +install: + mkdir -p ${DESTDIR}${BINDIR} + mkdir -p ${DESTDIR}${MANDIR}/man1 + ${INSTALL_PROGRAM} ${PROG} ${DESTDIR}${BINDIR} + ${INSTALL_MAN} amused.1 ${DESTDIR}${MANDIR}/man1/${PROG}.1 + +install-local: + mkdir -p ${HOME}/bin + ${INSTALL_PROGRAM} ${PROG} ${HOME}/bin + +uninstall: + rm ${DESTDIR}${BINDIR}/${PROG} + rm ${DESTDIR}${MANDIR}/man1/${PROG}.1 + +# --- maintainer targets --- + +dist: ${PROG}-${VERSION}.sha256 + +${PROG}-${VERSION}.sha256: ${PROG}-${VERSION}.tar.gz + sha256 ${PROG}-${VERSION}.tar.gz > $@ + +${PROG}-${VERSION}.tar.gz: ${DISTFILES} + mkdir -p .dist/${PROG}-${VERSION} + ${INSTALL} -m 0644 ${DISTFILES} .dist/${PROG}-${VERSION} + cd .dist/${PROG}-${VERSION} && chmod 755 configure + cd .dist && tar zcf ../$@ ${PROG}-${VERSION} + rm -rf .dist/ + +# --- dependency management --- + +# these .d files are produced during the first build if the compiler +# supports it. + +-include amused.d +-include compats.d +-include control.d +-include ctl.d +-include log.d +-include player.d +-include player_123.d +-include player_flac.d +-include player_oggvorbis.d +-include player_opus.d +-include playlist.d +-include xmalloc.d blob - 1b2a36f67a77108d86f6f486789032bfd5b6bc5f (mode 644) blob + /dev/null --- amused-dist.txt +++ /dev/null @@ -1,23 +0,0 @@ - -/CHANGES -/LICENSE -/Makefile -/README.md -/amused-version.mk -/amused.1 -/amused.c -/amused.h -/control.c -/control.h -/ctl.c -/log.c -/log.h -/player.c -/player_123.c -/player_flac.c -/player_oggvorbis.c -/player_opus.c -/playlist.c -/playlist.h -/xmalloc.c -/xmalloc.h blob - 1a4652276f1281058098b73a5b88aa9ddadecb69 (mode 644) blob + /dev/null --- amused-version.mk +++ /dev/null @@ -1,8 +0,0 @@ -AMUSED_RELEASE=No -AMUSED_VERSION_NUMBER=0.10 - -.if ${AMUSED_RELEASE} == Yes -AMUSED_VERSION=${AMUSED_VERSION_NUMBER} -.else -AMUSED_VERSION=${AMUSED_VERSION_NUMBER}-current -.endif blob - 238295db07b7cbc0d8793381b38d5936f4dec604 blob + bf368c371689924a2eaedfb47abd27af8a2f6db4 --- amused.c +++ amused.c @@ -14,14 +14,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include +#include "config.h" + #include #include -#include #include -#include #include #include #include @@ -32,7 +30,6 @@ #include #include #include -#include #include "amused.h" #include "control.h" blob - /dev/null blob + a402eb60f55fb2b692600268f4b7d5cdebce55e5 (mode 644) --- /dev/null +++ compats.c @@ -0,0 +1,1545 @@ +#include "config.h" +#if !HAVE_ERR +/* + * Copyright (c) 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. + * 3. 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. + */ + +#include +#include +#include +#include +#include + +void +vwarnx(const char *fmt, va_list ap) +{ + fprintf(stderr, "%s: ", getprogname()); + if (fmt != NULL) + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); +} + +void +vwarnc(int code, const char *fmt, va_list ap) +{ + fprintf(stderr, "%s: ", getprogname()); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + fprintf(stderr, "%s\n", strerror(code)); +} + +void +vwarn(const char *fmt, va_list ap) +{ + int sverrno; + + sverrno = errno; + fprintf(stderr, "%s: ", getprogname()); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + fprintf(stderr, "%s\n", strerror(sverrno)); +} + +void +verrc(int eval, int code, const char *fmt, va_list ap) +{ + fprintf(stderr, "%s: ", getprogname()); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + fprintf(stderr, "%s\n", strerror(code)); + exit(eval); +} + +void +verrx(int eval, const char *fmt, va_list ap) +{ + fprintf(stderr, "%s: ", getprogname()); + if (fmt != NULL) + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + exit(eval); +} + +void +verr(int eval, const char *fmt, va_list ap) +{ + int sverrno; + + sverrno = errno; + fprintf(stderr, "%s: ", getprogname()); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + fprintf(stderr, "%s\n", strerror(sverrno)); + exit(eval); +} + +void +err(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + verr(eval, fmt, ap); + va_end(ap); +} + +void +errc(int eval, int code, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + verrc(eval, code, fmt, ap); + va_end(ap); +} + +void +errx(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + verrx(eval, fmt, ap); + va_end(ap); +} + +void +warn(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarn(fmt, ap); + va_end(ap); +} + +void +warnc(int code, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarnc(code, fmt, ap); + va_end(ap); +} + +void +warnx(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarnx(fmt, ap); + va_end(ap); +} +#endif /* !HAVE_ERR */ +#if !HAVE_FLOCK +#include +#include +#include + +/* + * flock(2) emulation on top of fcntl advisory locks. This is "good + * enough" for amused, not a _real_ emulation. flock and fcntl locks + * have subtly different behaviours! + */ +int +flock(int fd, int op) +{ + struct flock l; + int cmd; + + memset(&l, 0, sizeof(l)); + l.l_whence = SEEK_SET; + + if (op & LOCK_SH) + l.l_type = F_RDLCK; + else if (op & LOCK_EX) + l.l_type = F_WRLCK; + else { + errno = EINVAL; + return -1; + } + + cmd = F_SETLKW; + if (op & LOCK_NB) + cmd = F_SETLK; + + return fcntl(fd, cmd, &l); +} +#endif /* HAVE_FLOCK */ +#if !HAVE_FREEZERO +#include +#include + +void +freezero(void *ptr, size_t len) +{ + if (ptr == NULL) + return; + memset(ptr, 0, len); + free(ptr); +} +#endif /* HAVE_FREEZERO */ +#if !HAVE_EXPLICIT_BZERO +/* OPENBSD ORIGINAL: lib/libc/string/explicit_bzero.c */ +/* + * Public domain. + * Written by Ted Unangst + */ + +#include + +/* + * explicit_bzero - don't let the compiler optimize away bzero + */ + +#if HAVE_MEMSET_S + +void +explicit_bzero(void *p, size_t n) +{ + if (n == 0) + return; + (void)memset_s(p, n, 0, n); +} + +#else /* HAVE_MEMSET_S */ + +#include + +/* + * Indirect memset through a volatile pointer to hopefully avoid + * dead-store optimisation eliminating the call. + */ +static void (* volatile ssh_memset)(void *, int, size_t) = memset; + +void +explicit_bzero(void *p, size_t n) +{ + if (n == 0) + return; + /* + * clang -fsanitize=memory needs to intercept memset-like functions + * to correctly detect memory initialisation. Make sure one is called + * directly since our indirection trick above sucessfully confuses it. + */ +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + memset(p, 0, n); +# endif +#endif + + ssh_memset(p, 0, n); +} + +#endif /* HAVE_MEMSET_S */ +#endif /* !HAVE_EXPLICIT_BZERO */ +#if !HAVE_GETPROGNAME +/* + * Copyright (c) 2016 Nicholas Marriott + * Copyright (c) 2017 Kristaps Dzonsons + * Copyright (c) 2020 Stephen Gregoratto + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#if HAVE_GETEXECNAME +#include +const char * +getprogname(void) +{ + return getexecname(); +} +#elif HAVE_PROGRAM_INVOCATION_SHORT_NAME +const char * +getprogname(void) +{ + return (program_invocation_short_name); +} +#elif HAVE___PROGNAME +const char * +getprogname(void) +{ + extern char *__progname; + + return (__progname); +} +#else +#warning No getprogname available. +const char * +getprogname(void) +{ + return ("amused"); +} +#endif +#endif /* !HAVE_GETPROGNAME */ +#if !HAVE_IMSG +/* $OpenBSD: imsg-buffer.c,v 1.13 2021/03/31 17:42:24 eric Exp $ */ +/* $OpenBSD: imsg.c,v 1.17 2022/01/28 10:41:44 claudio Exp $ */ + +/* + * Copyright (c) 2003, 2004 Henning Brauer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "imsg.h" + +static int ibuf_realloc(struct ibuf *, size_t); +static void ibuf_enqueue(struct msgbuf *, struct ibuf *); +static void ibuf_dequeue(struct msgbuf *, struct ibuf *); + +struct ibuf * +ibuf_open(size_t len) +{ + struct ibuf *buf; + + if ((buf = calloc(1, sizeof(struct ibuf))) == NULL) + return (NULL); + if ((buf->buf = malloc(len)) == NULL) { + free(buf); + return (NULL); + } + buf->size = buf->max = len; + buf->fd = -1; + + return (buf); +} + +struct ibuf * +ibuf_dynamic(size_t len, size_t max) +{ + struct ibuf *buf; + + if (max < len) + return (NULL); + + if ((buf = ibuf_open(len)) == NULL) + return (NULL); + + if (max > 0) + buf->max = max; + + return (buf); +} + +static int +ibuf_realloc(struct ibuf *buf, size_t len) +{ + unsigned char *b; + + /* on static buffers max is eq size and so the following fails */ + if (buf->wpos + len > buf->max) { + errno = ERANGE; + return (-1); + } + + b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1); + if (b == NULL) + return (-1); + buf->buf = b; + buf->size = buf->wpos + len; + + return (0); +} + +int +ibuf_add(struct ibuf *buf, const void *data, size_t len) +{ + if (buf->wpos + len > buf->size) + if (ibuf_realloc(buf, len) == -1) + return (-1); + + memcpy(buf->buf + buf->wpos, data, len); + buf->wpos += len; + return (0); +} + +void * +ibuf_reserve(struct ibuf *buf, size_t len) +{ + void *b; + + if (buf->wpos + len > buf->size) + if (ibuf_realloc(buf, len) == -1) + return (NULL); + + b = buf->buf + buf->wpos; + buf->wpos += len; + return (b); +} + +void * +ibuf_seek(struct ibuf *buf, size_t pos, size_t len) +{ + /* only allowed to seek in already written parts */ + if (pos + len > buf->wpos) + return (NULL); + + return (buf->buf + pos); +} + +size_t +ibuf_size(struct ibuf *buf) +{ + return (buf->wpos); +} + +size_t +ibuf_left(struct ibuf *buf) +{ + return (buf->max - buf->wpos); +} + +void +ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf) +{ + ibuf_enqueue(msgbuf, buf); +} + +int +ibuf_write(struct msgbuf *msgbuf) +{ + struct iovec iov[IOV_MAX]; + struct ibuf *buf; + unsigned int i = 0; + ssize_t n; + + memset(&iov, 0, sizeof(iov)); + TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { + if (i >= IOV_MAX) + break; + iov[i].iov_base = buf->buf + buf->rpos; + iov[i].iov_len = buf->wpos - buf->rpos; + i++; + } + +again: + if ((n = writev(msgbuf->fd, iov, i)) == -1) { + if (errno == EINTR) + goto again; + if (errno == ENOBUFS) + errno = EAGAIN; + return (-1); + } + + if (n == 0) { /* connection closed */ + errno = 0; + return (0); + } + + msgbuf_drain(msgbuf, n); + + return (1); +} + +void +ibuf_free(struct ibuf *buf) +{ + if (buf == NULL) + return; + freezero(buf->buf, buf->size); + free(buf); +} + +void +msgbuf_init(struct msgbuf *msgbuf) +{ + msgbuf->queued = 0; + msgbuf->fd = -1; + TAILQ_INIT(&msgbuf->bufs); +} + +void +msgbuf_drain(struct msgbuf *msgbuf, size_t n) +{ + struct ibuf *buf, *next; + + for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; + buf = next) { + next = TAILQ_NEXT(buf, entry); + if (buf->rpos + n >= buf->wpos) { + n -= buf->wpos - buf->rpos; + ibuf_dequeue(msgbuf, buf); + } else { + buf->rpos += n; + n = 0; + } + } +} + +void +msgbuf_clear(struct msgbuf *msgbuf) +{ + struct ibuf *buf; + + while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL) + ibuf_dequeue(msgbuf, buf); +} + +int +msgbuf_write(struct msgbuf *msgbuf) +{ + struct iovec iov[IOV_MAX]; + struct ibuf *buf, *buf0 = NULL; + unsigned int i = 0; + ssize_t n; + struct msghdr msg; + struct cmsghdr *cmsg; + union { + struct cmsghdr hdr; + char buf[CMSG_SPACE(sizeof(int))]; + } cmsgbuf; + + memset(&iov, 0, sizeof(iov)); + memset(&msg, 0, sizeof(msg)); + memset(&cmsgbuf, 0, sizeof(cmsgbuf)); + TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { + if (i >= IOV_MAX) + break; + if (i > 0 && buf->fd != -1) + break; + iov[i].iov_base = buf->buf + buf->rpos; + iov[i].iov_len = buf->wpos - buf->rpos; + i++; + if (buf->fd != -1) + buf0 = buf; + } + + msg.msg_iov = iov; + msg.msg_iovlen = i; + + if (buf0 != NULL) { + msg.msg_control = (caddr_t)&cmsgbuf.buf; + msg.msg_controllen = sizeof(cmsgbuf.buf); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *)CMSG_DATA(cmsg) = buf0->fd; + } + +again: + if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) { + if (errno == EINTR) + goto again; + if (errno == ENOBUFS) + errno = EAGAIN; + return (-1); + } + + if (n == 0) { /* connection closed */ + errno = 0; + return (0); + } + + /* + * assumption: fd got sent if sendmsg sent anything + * this works because fds are passed one at a time + */ + if (buf0 != NULL) { + close(buf0->fd); + buf0->fd = -1; + } + + msgbuf_drain(msgbuf, n); + + return (1); +} + +static void +ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf) +{ + TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry); + msgbuf->queued++; +} + +static void +ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf) +{ + TAILQ_REMOVE(&msgbuf->bufs, buf, entry); + + if (buf->fd != -1) + close(buf->fd); + + msgbuf->queued--; + ibuf_free(buf); +} + +/* imsg.c */ + +int imsg_fd_overhead = 0; + +static int imsg_get_fd(struct imsgbuf *); + +void +imsg_init(struct imsgbuf *ibuf, int fd) +{ + msgbuf_init(&ibuf->w); + memset(&ibuf->r, 0, sizeof(ibuf->r)); + ibuf->fd = fd; + ibuf->w.fd = fd; + ibuf->pid = getpid(); + TAILQ_INIT(&ibuf->fds); +} + +ssize_t +imsg_read(struct imsgbuf *ibuf) +{ + struct msghdr msg; + struct cmsghdr *cmsg; + union { + struct cmsghdr hdr; + char buf[CMSG_SPACE(sizeof(int) * 1)]; + } cmsgbuf; + struct iovec iov; + ssize_t n = -1; + int fd; + struct imsg_fd *ifd; + + memset(&msg, 0, sizeof(msg)); + memset(&cmsgbuf, 0, sizeof(cmsgbuf)); + + iov.iov_base = ibuf->r.buf + ibuf->r.wpos; + iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = &cmsgbuf.buf; + msg.msg_controllen = sizeof(cmsgbuf.buf); + + if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) + return (-1); + +again: + if (getdtablecount() + imsg_fd_overhead + + (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int)) + >= getdtablesize()) { + errno = EAGAIN; + free(ifd); + return (-1); + } + + if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) { + if (errno == EINTR) + goto again; + goto fail; + } + + ibuf->r.wpos += n; + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) { + int i; + int j; + + /* + * We only accept one file descriptor. Due to C + * padding rules, our control buffer might contain + * more than one fd, and we must close them. + */ + j = ((char *)cmsg + cmsg->cmsg_len - + (char *)CMSG_DATA(cmsg)) / sizeof(int); + for (i = 0; i < j; i++) { + fd = ((int *)CMSG_DATA(cmsg))[i]; + if (ifd != NULL) { + ifd->fd = fd; + TAILQ_INSERT_TAIL(&ibuf->fds, ifd, + entry); + ifd = NULL; + } else + close(fd); + } + } + /* we do not handle other ctl data level */ + } + +fail: + free(ifd); + return (n); +} + +ssize_t +imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) +{ + size_t av, left, datalen; + + av = ibuf->r.wpos; + + if (IMSG_HEADER_SIZE > av) + return (0); + + memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr)); + if (imsg->hdr.len < IMSG_HEADER_SIZE || + imsg->hdr.len > MAX_IMSGSIZE) { + errno = ERANGE; + return (-1); + } + if (imsg->hdr.len > av) + return (0); + datalen = imsg->hdr.len - IMSG_HEADER_SIZE; + ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE; + if (datalen == 0) + imsg->data = NULL; + else if ((imsg->data = malloc(datalen)) == NULL) + return (-1); + + if (imsg->hdr.flags & IMSGF_HASFD) + imsg->fd = imsg_get_fd(ibuf); + else + imsg->fd = -1; + + if (datalen != 0) + memcpy(imsg->data, ibuf->r.rptr, datalen); + + if (imsg->hdr.len < av) { + left = av - imsg->hdr.len; + memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left); + ibuf->r.wpos = left; + } else + ibuf->r.wpos = 0; + + return (datalen + IMSG_HEADER_SIZE); +} + +int +imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid, + int fd, const void *data, uint16_t datalen) +{ + struct ibuf *wbuf; + + if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) + return (-1); + + if (imsg_add(wbuf, data, datalen) == -1) + return (-1); + + wbuf->fd = fd; + + imsg_close(ibuf, wbuf); + + return (1); +} + +int +imsg_composev(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid, + int fd, const struct iovec *iov, int iovcnt) +{ + struct ibuf *wbuf; + int i, datalen = 0; + + for (i = 0; i < iovcnt; i++) + datalen += iov[i].iov_len; + + if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) + return (-1); + + for (i = 0; i < iovcnt; i++) + if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1) + return (-1); + + wbuf->fd = fd; + + imsg_close(ibuf, wbuf); + + return (1); +} + +/* ARGSUSED */ +struct ibuf * +imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid, + uint16_t datalen) +{ + struct ibuf *wbuf; + struct imsg_hdr hdr; + + datalen += IMSG_HEADER_SIZE; + if (datalen > MAX_IMSGSIZE) { + errno = ERANGE; + return (NULL); + } + + hdr.type = type; + hdr.flags = 0; + hdr.peerid = peerid; + if ((hdr.pid = pid) == 0) + hdr.pid = ibuf->pid; + if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) { + return (NULL); + } + if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1) + return (NULL); + + return (wbuf); +} + +int +imsg_add(struct ibuf *msg, const void *data, uint16_t datalen) +{ + if (datalen) + if (ibuf_add(msg, data, datalen) == -1) { + ibuf_free(msg); + return (-1); + } + return (datalen); +} + +void +imsg_close(struct imsgbuf *ibuf, struct ibuf *msg) +{ + struct imsg_hdr *hdr; + + hdr = (struct imsg_hdr *)msg->buf; + + hdr->flags &= ~IMSGF_HASFD; + if (msg->fd != -1) + hdr->flags |= IMSGF_HASFD; + + hdr->len = (uint16_t)msg->wpos; + + ibuf_close(&ibuf->w, msg); +} + +void +imsg_free(struct imsg *imsg) +{ + freezero(imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE); +} + +static int +imsg_get_fd(struct imsgbuf *ibuf) +{ + int fd; + struct imsg_fd *ifd; + + if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL) + return (-1); + + fd = ifd->fd; + TAILQ_REMOVE(&ibuf->fds, ifd, entry); + free(ifd); + + return (fd); +} + +int +imsg_flush(struct imsgbuf *ibuf) +{ + while (ibuf->w.queued) + if (msgbuf_write(&ibuf->w) <= 0) + return (-1); + return (0); +} + +void +imsg_clear(struct imsgbuf *ibuf) +{ + int fd; + + msgbuf_clear(&ibuf->w); + while ((fd = imsg_get_fd(ibuf)) != -1) + close(fd); +} +#endif /* HAVE_IMSG */ +#if !HAVE_MEMMEM +/*- + * Copyright (c) 2005 Pascal Gloor + * + * 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * 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. + */ +/* + * Find the first occurrence of the byte string s in byte string l. + */ +void * +memmem(const void *l, size_t l_len, const void *s, size_t s_len) +{ + const char *cur, *last; + const char *cl = l; + const char *cs = s; + + /* a zero length needle should just return the haystack */ + if (l_len == 0) + return (void *)cl; + + /* "s" must be smaller or equal to "l" */ + if (l_len < s_len) + return NULL; + + /* special case where s_len == 1 */ + if (s_len == 1) + return memchr(l, *cs, l_len); + + /* the last position where its possible to find "s" in "l" */ + last = cl + l_len - s_len; + + for (cur = cl; cur <= last; cur++) + if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) + return (void *)cur; + + return NULL; +} +#endif /* !HAVE_MEMMEM */ +#if !HAVE_MEMRCHR +/* + * Copyright (c) 2007 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include + +/* + * Reverse memchr() + * Find the last occurrence of 'c' in the buffer 's' of size 'n'. + */ +void * +memrchr(const void *s, int c, size_t n) +{ + const unsigned char *cp; + + if (n != 0) { + cp = (unsigned char *)s + n; + do { + if (*(--cp) == (unsigned char)c) + return((void *)cp); + } while (--n != 0); + } + return(NULL); +} +#endif /* !HAVE_MEMRCHR */ +#if !HAVE_OPTRESET +/* + * Copyright (c) 1987, 1993, 1994 + * 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. + * 3. 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/getopt.c */ + +#include +#include +#include + +int BSDopterr = 1, /* if error message should be printed */ + BSDoptind = 1, /* index into parent argv vector */ + BSDoptopt, /* character checked for validity */ + BSDoptreset; /* reset getopt */ +char *BSDoptarg; /* argument associated with option */ + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +/* + * getopt -- + * Parse argc/argv argument vector. + */ +int +BSDgetopt(int nargc, char *const *nargv, const char *ostr) +{ + static const char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + + if (ostr == NULL) + return (-1); + + if (BSDoptreset || !*place) { /* update scanning pointer */ + BSDoptreset = 0; + if (BSDoptind >= nargc || *(place = nargv[BSDoptind]) != '-') { + place = EMSG; + return (-1); + } + if (place[1] && *++place == '-') { /* found "--" */ + if (place[1]) + return (BADCH); + ++BSDoptind; + place = EMSG; + return (-1); + } + } /* option letter okay? */ + if ((BSDoptopt = (int)*place++) == (int)':' || + !(oli = strchr(ostr, BSDoptopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if (BSDoptopt == (int)'-') + return (-1); + if (!*place) + ++BSDoptind; + if (BSDopterr && *ostr != ':') + (void)fprintf(stderr, + "%s: unknown option -- %c\n", getprogname(), + BSDoptopt); + return (BADCH); + } + if (*++oli != ':') { /* don't need argument */ + BSDoptarg = NULL; + if (!*place) + ++BSDoptind; + } + else { /* need an argument */ + if (*place) /* no white space */ + BSDoptarg = (char *)place; + else if (nargc <= ++BSDoptind) { /* no arg */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (BSDopterr) + (void)fprintf(stderr, + "%s: option requires an argument -- %c\n", + getprogname(), BSDoptopt); + return (BADCH); + } + else /* white space */ + BSDoptarg = nargv[BSDoptind]; + place = EMSG; + ++BSDoptind; + } + return (BSDoptopt); /* dump back option letter */ +} +#endif +#if !HAVE_REALLOCARRAY +/* + * Copyright (c) 2008 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void * +reallocarray(void *optr, size_t nmemb, size_t size) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return realloc(optr, size * nmemb); +} +#endif /* !HAVE_REALLOCARRAY */ +#if !HAVE_RECALLOCARRAY +/* + * Copyright (c) 2008, 2017 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */ + +#include +#include +#include +#include +#include + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void * +recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size) +{ + size_t oldsize, newsize; + void *newptr; + + if (ptr == NULL) + return calloc(newnmemb, size); + + if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + newnmemb > 0 && SIZE_MAX / newnmemb < size) { + errno = ENOMEM; + return NULL; + } + newsize = newnmemb * size; + + if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + oldnmemb > 0 && SIZE_MAX / oldnmemb < size) { + errno = EINVAL; + return NULL; + } + oldsize = oldnmemb * size; + + /* + * Don't bother too much if we're shrinking just a bit, + * we do not shrink for series of small steps, oh well. + */ + if (newsize <= oldsize) { + size_t d = oldsize - newsize; + + if (d < oldsize / 2 && d < (size_t)getpagesize()) { + memset((char *)ptr + newsize, 0, d); + return ptr; + } + } + + newptr = malloc(newsize); + if (newptr == NULL) + return NULL; + + if (newsize > oldsize) { + memcpy(newptr, ptr, oldsize); + memset((char *)newptr + oldsize, 0, newsize - oldsize); + } else + memcpy(newptr, ptr, newsize); + + explicit_bzero(ptr, oldsize); + free(ptr); + + return newptr; +} +#endif /* !HAVE_RECALLOCARRAY */ +#if !HAVE_SETPROCTITLE +/* + * Copyright (c) 2016 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +# if HAVE_PR_SET_NAME +#include +#include +#include +#include +#include +void +setproctitle(const char *fmt, ...) +{ + char title[16], name[16], *cp; + va_list ap; + int used; + + va_start(ap, fmt); + vsnprintf(title, sizeof(title), fmt, ap); + va_end(ap); + + used = snprintf(name, sizeof(name), "%s: %s", getprogname(), title); + if (used >= (int)sizeof(name)) { + cp = strrchr(name, ' '); + if (cp != NULL) + *cp = '\0'; + } + prctl(PR_SET_NAME, name); +} +# else +void +setproctitle(const char *fmt, ...) +{ + return; +} +# endif +#endif /* !HAVE_SETPROCTITLE */ +#if !HAVE_STRLCAT +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} +#endif /* !HAVE_STRLCAT */ +#if !HAVE_STRLCPY +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} +#endif /* !HAVE_STRLCPY */ +#if !HAVE_STRNDUP +/* $OpenBSD$ */ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +char * +strndup(const char *str, size_t maxlen) +{ + char *copy; + size_t len; + + len = strnlen(str, maxlen); + copy = malloc(len + 1); + if (copy != NULL) { + (void)memcpy(copy, str, len); + copy[len] = '\0'; + } + + return copy; +} +#endif /* !HAVE_STRNDUP */ +#if !HAVE_STRNLEN +/* $OpenBSD$ */ + +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +size_t +strnlen(const char *str, size_t maxlen) +{ + const char *cp; + + for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--) + ; + + return (size_t)(cp - str); +} +#endif /* !HAVE_STRNLEN */ +#if !HAVE_STRTONUM +/* + * Copyright (c) 2004 Ted Unangst and Todd Miller + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#define INVALID 1 +#define TOOSMALL 2 +#define TOOLARGE 3 + +long long +strtonum(const char *numstr, long long minval, long long maxval, + const char **errstrp) +{ + long long ll = 0; + int error = 0; + char *ep; + struct errval { + const char *errstr; + int err; + } ev[4] = { + { NULL, 0 }, + { "invalid", EINVAL }, + { "too small", ERANGE }, + { "too large", ERANGE }, + }; + + ev[0].err = errno; + errno = 0; + if (minval > maxval) { + error = INVALID; + } else { + ll = strtoll(numstr, &ep, 10); + if (numstr == ep || *ep != '\0') + error = INVALID; + else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) + error = TOOSMALL; + else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) + error = TOOLARGE; + } + if (errstrp != NULL) + *errstrp = ev[error].errstr; + errno = ev[error].err; + if (error) + ll = 0; + + return (ll); +} +#endif /* !HAVE_STRTONUM */ blob - /dev/null blob + 979457af0604a374897fc0ff068d7dde6bc7aa18 (mode 755) --- /dev/null +++ configure @@ -0,0 +1,941 @@ +#! /bin/sh +# +# Copyright (c) 2014, 2015, 2016 Ingo Schwarze +# Copyright (c) 2017, 2018 Kristaps Dzonsons +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +OCONFIGURE_VERSION="0.3.8" + +# +# This script outputs two files: config.h and Makefile.configure. +# It tries to read from configure.local, which contains predefined +# values we won't autoconfigure. +# +# If you want to use configure with your project, have your GNUmakefile +# or BSDmakefile---whichever---try to import/include Makefile.configure +# at the beginning of the file. +# +# Like so (note no quotes, no period, etc.): +# +# include Makefile.configure +# +# If it exists, configure was run; otherwise, it wasn't. +# +# You'll probably want to change parts of this file. I've noted the +# parts that you'll probably change in the section documentation. +# +# See https://github.com/kristapsdz/oconfigure for more. + +set -e + +# try to be helpful +case "$1" in +--help|-h) + cat < config.log +echo "config.log: writing..." + +# GNU submake prints different output if invoked recursively, which +# messes up CC and CFLAGS detection. Pass --no-print-directory if +# we have a MAKELEVEL (GNU and FreeBSD make) and the argument is +# allowed. + +MAKE_FLAGS="" + +if [ -n "${MAKELEVEL}" ]; then + if [ "${MAKELEVEL}" -gt 0 ] ; then + MAKE_FLAGS="--no-print-directory" + echo "all:" | make ${MAKE_FLAGS} -sf - 2>/dev/null || MAKE_FLAGS="" + fi +fi + +if [ -n "$MAKE_FLAGS" ]; then + echo "GNU submake detected: using --no-print-directory" 1>&2 + echo "GNU submake detected: using --no-print-directory" 1>&3 +fi + +#---------------------------------------------------------------------- +# Initialize all variables here such that nothing can leak in from the +# environment except for CC and CFLAGS, which we might have passed in. +#---------------------------------------------------------------------- + +CC=`printf "all:\\n\\t@echo \\\$(CC)\\n" | make ${MAKE_FLAGS} -sf -` +CFLAGS=`printf "all:\\n\\t@echo \\\$(CFLAGS)\\n" | make ${MAKE_FLAGS} -sf -` +CFLAGS="${CFLAGS} -g -W -Wall -Wmissing-prototypes -Wstrict-prototypes" +CFLAGS="${CFLAGS} -Wmissing-declarations -Wno-unused-parameter" +CFLAGS="${CFLAGS} -Wno-sign-compare" +LDADD= +LDADD_IMSG= +LDADD_LIBEVENT= +LDADD_LIBEVENT2= +LDADD_LIB_FLAC= +LDADD_LIB_MPG123= +LDADD_LIB_VORBISFILE= +LDADD_LIB_SNDIO= +LDADD_LIB_SOCKET= +LDADD_STATIC= +CPPFLAGS= +LDFLAGS= +DESTDIR= +PREFIX="/usr/local" +BINDIR= +SBINDIR= +INCLUDEDIR= +LIBDIR= +MANDIR= +SHAREDIR= +INSTALL="install" +INSTALL_PROGRAM= +INSTALL_LIB= +INSTALL_MAN= +INSTALL_DATA= +PKG_CONFIG= + +# SunOS sets "cc", but this doesn't exist. +# It does have gcc, so try that instead. +# Prefer clang, though. + +command -v ${CC} 2>/dev/null 1>&2 || { + echo "${CC} not found: trying clang" 1>&2 + echo "${CC} not found: trying clang" 1>&3 + CC=clang + command -v ${CC} 2>/dev/null 1>&2 || { + echo "${CC} not found: trying gcc" 1>&2 + echo "${CC} not found: trying gcc" 1>&3 + CC=gcc + command -v ${CC} 2>/dev/null 1>&2 || { + echo "gcc not found: giving up" 1>&2 + echo "gcc not found: giving up" 1>&3 + exit 1 + } + } +} + +command -v pkg-config 2>/dev/null 1>&2 && { + PKG_CONFIG=pkg-config + echo "pkg-config found" 1>&2 + echo "pkg-config found" 1>&3 +} || { + echo "pkg-config not found" 1>&2 + echo "pkg-config not found" 1>&3 +} + +#---------------------------------------------------------------------- +# Allow certain variables to be overriden on the command line. +#---------------------------------------------------------------------- + +while [ $# -gt 0 ]; do + key=${1%%=*} + val=${1#*=} + + if [ "$key" = "--prefix" ]; then + key=PREFIX + if [ "$1" = "--prefix" ]; then + if ! shift 2>&1 >/dev/null; then + echo "$0: missing value for --prefix" 1>&2 + exit 1 + fi + val="$1" + fi + fi + + if [ "$1" = "$key" ]; then + echo "$0: invalid key-value: $1" 1>&2 + exit 1 + fi + + shift + + case "$key" in + LDADD) + LDADD="$val" ;; + LDADD_IMSG) + LDADD_IMSG="$val" ;; + LDADD_LIBEVENT) + LDADD_LIBEVENT="$val" ;; + LDADD_LIBEVENT2) + LDADD_LIBEVENT2="$val" ;; + LDADD_LIBFLAC) + LDADD_LIBFLAC="$val" ;; + LDADD_LIBMPG123) + LDADD_LIBMPG123="$val" ;; + LDADD_LIBOPUSFILE) + LDADD_LIBOPUSFILE="$val" ;; + LDADD_LIBVORBISFILE) + LDADD_LIBVORBISFILE="$val" ;; + LDADD_SNDIO) + LDADD_SNDIO="$val" ;; + LDADD_LIBSOCKET) + LDADD_LIBSOCKET="$val" ;; + LDFLAGS) + LDFLAGS="$val" ;; + CPPFLAGS) + CPPFLAGS="$val" ;; + DESTDIR) + DESTDIR="$val" ;; + PREFIX) + PREFIX="$val" ;; + MANDIR) + MANDIR="$val" ;; + LIBDIR) + LIBDIR="$val" ;; + BINDIR) + BINDIR="$val" ;; + SHAREDIR) + SHAREDIR="$val" ;; + SBINDIR) + SBINDIR="$val" ;; + INCLUDEDIR) + INCLUDEDIR="$val" ;; + PKG_CONFIG) + PKG_CONFIG="$val" ;; + *) + echo "$0: invalid key: $key" 1>&2 + exit 1 + esac +done + + +#---------------------------------------------------------------------- +# These are the values that will be pushed into config.h after we test +# for whether they're supported or not. +# Each of these must have a runtest(), below. +# Please sort by alpha, for clarity. +# You WANT to change this. +#---------------------------------------------------------------------- + +HAVE_CAPSICUM= +HAVE_ERR= +HAVE_EXPLICIT_BZERO= +HAVE_FLOCK= +HAVE_FREEZERO= +HAVE_GETDTABLECOUNT= +HAVE_GETEXECNAME= +HAVE_GETPROGNAME= +HAVE_INFTIM= +HAVE_IMSG= +HAVE_LANDLOCK= +HAVE_LIBEVENT= +HAVE_LIBEVENT2=0 # may not be checked, set to zero +HAVE_LIB_FLAC= +HAVE_LIB_MPG123= +HAVE_LIB_OPUSFILE= +HAVE_LIB_VORBISFILE= +HAVE_LIB_SNDIO= +HAVE_LIB_SOCKET= +HAVE_MEMMEM= +HAVE_MEMRCHR= +HAVE_MEMSET_S= +HAVE_OPTRESET= +HAVE_PATH_MAX= +HAVE_PLEDGE= +HAVE_PROGRAM_INVOCATION_SHORT_NAME= +HAVE_PR_SET_NAME= +HAVE_REALLOCARRAY= +HAVE_RECALLOCARRAY= +HAVE_SANDBOX_INIT= +HAVE_SETPROCTITLE= +HAVE_SIO_FLUSH= +HAVE_SOCK_NONBLOCK= +HAVE_STRLCAT= +HAVE_STRLCPY= +HAVE_STRNDUP= +HAVE_STRNLEN= +HAVE_STRTONUM= +HAVE_SYS_FILE= +HAVE_SYS_QUEUE= +HAVE_SYSTRACE=0 +HAVE_UNVEIL= +HAVE___PROGNAME= + +#---------------------------------------------------------------------- +# Allow configure.local to override all variables, default settings, +# command-line arguments, and tested features, above. +# You PROBABLY DO NOT want to change this. +#---------------------------------------------------------------------- + +if [ -r ./configure.local ]; then + echo "configure.local: reading..." 1>&2 + echo "configure.local: reading..." 1>&3 + cat ./configure.local 1>&3 + . ./configure.local +else + echo "configure.local: no (fully automatic configuration)" 1>&2 + echo "configure.local: no (fully automatic configuration)" 1>&3 +fi + +echo 1>&3 + +#---------------------------------------------------------------------- +# Infrastructure for running tests. +# These consists of a series of functions that will attempt to run the +# given test file and record its exit into a HAVE_xxx variable. +# You DO NOT want to change this. +#---------------------------------------------------------------------- + +COMP="${CC} ${CFLAGS} ${CPPFLAGS} -Wno-unused -Werror" + +# Check whether this HAVE_ setting is manually overridden. +# If yes, use the override, if no, do not decide anything yet. +# Arguments: lower-case test name, manual value + +ismanual() { + [ -z "${3}" ] && return 1 + echo "${1}: manual (HAVE_${2}=${3})" 1>&2 + echo "${1}: manual (HAVE_${2}=${3})" 1>&3 + echo 1>&3 + return 0 +} + +# Run a single autoconfiguration test. +# In case of success, enable the feature. +# In case of failure, do not decide anything yet. +# Arguments: lower-case test name, upper-case test name, additional +# CFLAGS, additional LIBS. + +singletest() { + extralib="" + pkgcfs="" + pkglib="" + + cat 1>&3 << __HEREDOC__ +${1}: testing... +${COMP} -DTEST_${2} ${3} -o test-${1} tests.c ${LDFLAGS} ${4} +__HEREDOC__ + if ${COMP} -DTEST_${2} ${3} -o "test-${1}" tests.c ${LDFLAGS} ${4} 1>&3 2>&3; then + echo "${1}: ${CC} succeeded" 1>&3 + else + if [ -n "${5}" ] ; then + echo "${1}: ${CC} failed with $? (retrying)" 1>&3 + cat 1>&3 << __HEREDOC__ +${1}: testing... +${COMP} -DTEST_${2} ${3} -o test-${1} tests.c ${LDFLAGS} ${5} +__HEREDOC__ + if ${COMP} -DTEST_${2} ${3} -o "test-${1}" tests.c ${LDFLAGS} ${5} 1>&3 2>&3; then + echo "${1}: ${CC} succeeded" 1>&3 + extralib="(with ${5})" + else + test -n "${PKG_CONFIG}" -a -n "${6}" && ${PKG_CONFIG} "$6" + if [ $? -eq 0 ]; then + echo "${1}: ${CC} failed with $? (retrying)" 1>&3 + pkgcfs=$($PKG_CONFIG --cflags "${6}") + pkglib=$($PKG_CONFIG --libs "${6}") + cat 1>&3 << __HEREDOC__ +${1}: testing... +${COMP} -DTEST_${2} ${3} ${pkgcfs} -o test-${1} tests.c ${LDFLAGS} ${pkglib} +__HEREDOC__ + if ${COMP} -DTEST_${2} ${3} ${pkgcfs} -o test-${1} tests.c ${LDFLAGS} ${pkglib} 1>&3 2>&3; then + echo "${1}: ${CC} succeeded" 1>&3 + extralib="(with ${pkgcfs} ${pkglib})" + else + echo "${1}: ${CC} failed with $?" 1>&3 + echo 1>&3 + return 1 + fi + else + echo "${1}: ${CC} failed with $?" 1>&3 + echo 1>&3 + return 1 + fi + fi + else + echo "${1}: ${CC} failed with $?" 1>&3 + echo 1>&3 + return 1 + fi + fi + + if [ -n "${pkgcfs}" -o -n "${pkglib}" ] + then + CFLAGS="${CFLAGS} ${pkgcfs}" + eval "LDADD_${2}=\"${pkglib}\"" + elif [ -n "${extralib}" ] + then + eval "LDADD_${2}=\"${5}\"" + elif [ -n "${4}" ] + then + eval "LDADD_${2}=\"${4}\"" + fi + + echo "${1}: yes ${extralib}" 1>&2 + echo "${1}: yes ${extralib}" 1>&3 + echo 1>&3 + eval HAVE_${2}=1 + rm "test-${1}" + return 0 +} + +# Run a complete autoconfiguration test, including the check for +# a manual override and disabling the feature on failure. +# Arguments: lower case name, upper case name, additional CFLAGS, +# additional LDADD, alternative LDADD, pkg-config name. + +runtest() { + eval _manual=\${HAVE_${2}} + ismanual "${1}" "${2}" "${_manual}" && return 0 + singletest "${1}" "${2}" "${3}" "${4}" "${5}" "${6}" && return 0 + echo "${1}: no" 1>&2 + eval HAVE_${2}=0 + return 1 +} + +#---------------------------------------------------------------------- +# Begin running the tests themselves. +# All of your tests must be defined here. +# Please sort as the HAVE_xxxx values were defined. +# You WANT to change this. +# It consists of the following columns: +# runtest +# (1) test file +# (2) macro to set +# (3) argument to cc *before* -o +# (4) argument to cc *after* +# (5) alternative argument to cc *after* +# (6) name for pkg-config auto-discovery +#---------------------------------------------------------------------- + +if runtest -MMD _MMD -MMD; then + CFLAGS="${CFLAGS} -MMD" + echo "adding -MMD to CFLAGS" 1>&2 + echo "adding -MMD to CFLAGS" 1>&3 +fi + +runtest capsicum CAPSICUM || true +runtest err ERR || true +runtest explicit_bzero EXPLICIT_BZERO || true +runtest flock FLOCK || true +runtest freezero FREEZERO || true +runtest getdtablecount GETDTABLECOUNT || true +runtest getexecname GETEXECNAME || true +runtest getprogname GETPROGNAME || true +runtest imsg IMSG "" "" "-lutil" || true +runtest INFTIM INFTIM || true +runtest landlock LANDLOCK || true + +runtest libevent LIBEVENT "" "" "-levent" || \ +runtest libevent2 LIBEVENT2 "" "" "-levent_extra -levent_core" "libevent" || true + +runtest lib_flac LIB_FLAC "" "" "-lFLAC" "flac" || true +runtest lib_mpg123 LIB_MPG123 "" "" "-lmpg123" "libmpg123" || true +runtest lib_opusfile LIB_OPUSFILE "" "" "-lopusfile" "opusfile" || true +runtest lib_vorbisfile LIB_VORBISFILE "" "" "-lvorbisfile" "vorbisfile" || true + +runtest lib_sndio LIB_SNDIO "" "" "-lsndio" "sndio" || true +runtest lib_socket LIB_SOCKET "" "" "-lsocket -lnsl" || true +runtest memmem MEMMEM || true +runtest memrchr MEMRCHR || true +runtest memset_s MEMSET_S || true +runtest optreset OPTRESET || true +runtest PATH_MAX PATH_MAX || true +runtest pledge PLEDGE || true +runtest program_invocation_short_name PROGRAM_INVOCATION_SHORT_NAME || true +runtest PR_SET_NAME PR_SET_NAME || true +runtest reallocarray REALLOCARRAY || true +runtest recallocarray RECALLOCARRAY || true +runtest sandbox_init SANDBOX_INIT "-Wno-deprecated" || true +runtest setproctitle SETPROCTITLE || true +runtest sio_flush SIO_FLUSH "" "" "${LDADD_LIB_SNDIO}" || true +runtest SOCK_NONBLOCK SOCK_NONBLOCK || true +runtest static STATIC "" "-static" || true +runtest strlcat STRLCAT || true +runtest strlcpy STRLCPY || true +runtest strndup STRNDUP || true +runtest strnlen STRNLEN || true +runtest strtonum STRTONUM || true +runtest sys_queue SYS_QUEUE || true +runtest sys_file SYS_FILE || true +runtest unveil UNVEIL || true +runtest __progname __PROGNAME || true + +if [ "${HAVE_LIBEVENT}" -eq 0 -a "${HAVE_LIBEVENT2}" -eq 0 ]; then + echo "Fatal: missing libevent" 1>&2 + echo "Fatal: missing libevent" 1>&3 + exit 1 +fi + +if [ "${HAVE_LIB_FLAC}" -eq 0 -o \ + "${HAVE_LIB_MPG123}" -eq 0 -o \ + "${HAVE_LIB_OPUSFILE}" -eq 0 -o \ + "${HAVE_LIB_VORBISFILE}" -eq 0 ]; then + echo "Fatal: missing required audio libraries" 1>&2 + echo "Fatal: missing required audio libraries" 1>&3 + exit 1 +fi + +if [ "${HAVE_LIB_SNDIO}" -eq 0 ]; then + echo "Fatal: missing libsndio" 1>&2 + echo "Fatal: missing libsndio" 1>&3 + exit 1 +fi + +#---------------------------------------------------------------------- +# Output writing: generate the config.h file. +# This file contains all of the HAVE_xxxx variables necessary for +# compiling your source. +# You must include "config.h" BEFORE any other variables. +# You WANT to change this. +#---------------------------------------------------------------------- + +exec > config.h + +# Start with prologue. + +cat << __HEREDOC__ +#ifndef OCONFIGURE_CONFIG_H +#define OCONFIGURE_CONFIG_H + +#ifdef __cplusplus +# error "Do not use C++: this is a C application." +#endif +#if !defined(__GNUC__) || (__GNUC__ < 4) +# define __attribute__(x) +#endif +#if defined(__linux__) || defined(__MINT__) +# define _GNU_SOURCE /* memmem, memrchr, setresuid... */ +# define _DEFAULT_SOURCE /* le32toh, crypt, ... */ +#endif +#if defined(__NetBSD__) +# define _OPENBSD_SOURCE /* reallocarray, etc. */ +#endif +#if defined(__sun) +# ifndef _XOPEN_SOURCE /* SunOS already defines */ +# define _XOPEN_SOURCE /* XPGx */ +# endif +# define _XOPEN_SOURCE_EXTENDED 1 /* XPG4v2 */ +# ifndef __EXTENSIONS__ /* SunOS already defines */ +# define __EXTENSIONS__ /* reallocarray, etc. */ +# endif +#endif +#if !defined(__BEGIN_DECLS) +# define __BEGIN_DECLS +#endif +#if !defined(__END_DECLS) +# define __END_DECLS +#endif + +__HEREDOC__ + +# This is just for size_t, mode_t, and dev_t. +# Most of these functions, in the real world, pull in or +# someting that pulls in support for size_t. +# Our function declarations are standalone, so specify them here. + +if [ ${HAVE_IMSG} -eq 0 -o \ + ${HAVE_MEMMEM} -eq 0 -o \ + ${HAVE_MEMRCHR} -eq 0 -o \ + ${HAVE_REALLOCARRAY} -eq 0 -o \ + ${HAVE_RECALLOCARRAY} -eq 0 -o \ + ${HAVE_STRLCAT} -eq 0 -o \ + ${HAVE_STRLCPY} -eq 0 -o \ + ${HAVE_STRNDUP} -eq 0 -o \ + ${HAVE_STRNLEN} -eq 0 ] +then + echo "#include /* size_t, mode_t, dev_t */ " + echo +fi + +if [ ${HAVE_FLOCK} -eq 0 ]; then + if [ ${HAVE_SYS_FILE} -eq 0 ]; then + HAVE_FLOCK=1 + echo "#include " + echo + else + echo "int flock(int, int);" + echo "#define LOCK_SH 0x1" + echo "#define LOCK_EX 0x2" + echo "#define LOCK_NB 0x4" + echo + fi +fi + +if [ ${HAVE_ERR} -eq 0 ]; then + echo "#include /* err(3) */" + echo +else + echo "#include " + echo +fi + +if [ ${HAVE_PLEDGE} -eq 0 ]; then + echo "#define pledge(p, e) (0)" + echo +else + echo "#include " + echo +fi + +# Now we handle our HAVE_xxxx values. +# Most will just be defined as 0 or 1. + +if [ ${HAVE_PATH_MAX} -eq 0 ] +then + echo "#define PATH_MAX 4096" + echo +fi + +if [ ${HAVE_INFTIM} -eq 0 ] +then + echo "#define INFTIM (-1) /* poll.h */" + echo +fi + +cat << __HEREDOC__ +/* + * Results of configuration feature-testing. + */ +#define HAVE_CAPSICUM ${HAVE_CAPSICUM} +#define HAVE_ERR ${HAVE_ERR} +#define HAVE_EXPLICIT_BZERO ${HAVE_EXPLICIT_BZERO} +#define HAVE_FLOCK ${HAVE_FLOCK} +#define HAVE_FREEZERO ${HAVE_FREEZERO} +#define HAVE_GETDTABLECOUNT ${HAVE_GETDTABLECOUNT} +#define HAVE_GETEXECNAME ${HAVE_GETEXECNAME} +#define HAVE_GETPROGNAME ${HAVE_GETPROGNAME} +#define HAVE_INFTIM ${HAVE_INFTIM} +#define HAVE_LANDLOCK ${HAVE_LANDLOCK} +#define HAVE_MEMMEM ${HAVE_MEMMEM} +#define HAVE_MEMRCHR ${HAVE_MEMRCHR} +#define HAVE_MEMSET_S ${HAVE_MEMSET_S} +#define HAVE_OPTRESET ${HAVE_OPTRESET} +#define HAVE_PATH_MAX ${HAVE_PATH_MAX} +#define HAVE_PLEDGE ${HAVE_PLEDGE} +#define HAVE_PROGRAM_INVOCATION_SHORT_NAME ${HAVE_PROGRAM_INVOCATION_SHORT_NAME} +#define HAVE_PR_SET_NAME ${HAVE_PR_SET_NAME} +#define HAVE_REALLOCARRAY ${HAVE_REALLOCARRAY} +#define HAVE_RECALLOCARRAY ${HAVE_RECALLOCARRAY} +#define HAVE_SANDBOX_INIT ${HAVE_SANDBOX_INIT} +#define HAVE_SETPROCTITLE ${HAVE_SETPROCTITLE} +#define HAVE_SIO_FLUSH ${HAVE_SIO_FLUSH} +#define HAVE_SOCK_NONBLOCK ${HAVE_SOCK_NONBLOCK} +#define HAVE_STRLCAT ${HAVE_STRLCAT} +#define HAVE_STRLCPY ${HAVE_STRLCPY} +#define HAVE_STRNDUP ${HAVE_STRNDUP} +#define HAVE_STRNLEN ${HAVE_STRNLEN} +#define HAVE_STRTONUM ${HAVE_STRTONUM} +#define HAVE_SYS_FILE ${HAVE_SYS_FILE} +#define HAVE_SYS_QUEUE ${HAVE_SYS_QUEUE} +#define HAVE_SYSTRACE ${HAVE_SYSTRACE} +#define HAVE_UNVEIL ${HAVE_UNVEIL} +#define HAVE___PROGNAME ${HAVE___PROGNAME} + +__HEREDOC__ + +# Now we do our function declarations for missing functions. + +[ ${HAVE_ERR} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility functions for err(3). + */ +extern void err(int, const char *, ...) __attribute__((noreturn)); +extern void errc(int, int, const char *, ...) __attribute__((noreturn)); +extern void errx(int, const char *, ...) __attribute__((noreturn)); +extern void verr(int, const char *, va_list) __attribute__((noreturn)); +extern void verrc(int, int, const char *, va_list) __attribute__((noreturn)); +extern void verrx(int, const char *, va_list) __attribute__((noreturn)); +extern void warn(const char *, ...); +extern void warnx(const char *, ...); +extern void warnc(int, const char *, ...); +extern void vwarn(const char *, va_list); +extern void vwarnc(int, const char *, va_list); +extern void vwarnx(const char *, va_list); +__HEREDOC__ + +[ ${HAVE_EXPLICIT_BZERO} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for explicit_bzero(3). + */ +extern void explicit_bzero(void *, size_t); + +__HEREDOC__ + +[ ${HAVE_FREEZERO} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for freezero(3). + */ +extern void freezero(void *, size_t); + +__HEREDOC__ + +[ ${HAVE_MEMMEM} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for memmem(3). + */ +void *memmem(const void *, size_t, const void *, size_t); + +__HEREDOC__ + +[ ${HAVE_MEMRCHR} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for memrchr(3). + */ +void *memrchr(const void *b, int, size_t); + +__HEREDOC__ + +[ ${HAVE_GETPROGNAME} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for getprogname(3). + */ +extern const char *getprogname(void); + +__HEREDOC__ + +[ ${HAVE_REALLOCARRAY} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for reallocarray(3). + */ +extern void *reallocarray(void *, size_t, size_t); + +__HEREDOC__ + +[ ${HAVE_RECALLOCARRAY} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for recallocarray(3). + */ +extern void *recallocarray(void *, size_t, size_t, size_t); + +__HEREDOC__ + +[ ${HAVE_SETPROCTITLE} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for setproctitle(3). + */ +extern void setproctitle(const char *, ...); + +__HEREDOC__ + +[ ${HAVE_STRLCAT} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for strlcat(3). + */ +extern size_t strlcat(char *, const char *, size_t); + +__HEREDOC__ + +[ ${HAVE_STRLCPY} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for strlcpy(3). + */ +extern size_t strlcpy(char *, const char *, size_t); + +__HEREDOC__ + +[ ${HAVE_STRNDUP} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for strndup(3). + */ +extern char *strndup(const char *, size_t); + +__HEREDOC__ + +[ ${HAVE_STRNLEN} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for strnlen(3). + */ +extern size_t strnlen(const char *, size_t); + +__HEREDOC__ + +[ ${HAVE_STRTONUM} -eq 0 ] && \ + cat << __HEREDOC__ +/* + * Compatibility for strotnum(3). + */ +extern long long strtonum(const char *, long long, long long, const char **); + +__HEREDOC__ + +if [ ${HAVE_SYS_QUEUE} -eq 0 ]; then + cat << __HEREDOC__ +#include "queue.h" +__HEREDOC__ +else + echo "#include " + echo +fi + +echo "#include " +echo "#include " +if [ ${HAVE_IMSG} -eq 0 ]; then + echo "#include \"imsg.h\"" +else + echo "#include " +fi +echo + +if [ "${HAVE_LIBEVENT2}" -eq 1 ]; then + cat << __HEREDOC__ +#include +#include +#include +#include +#include +#include +#include +#include + +__HEREDOC__ +elif [ "${HAVE_LIBEVENT}" -eq 1 ]; then + cat << __HEREDOC__ +#include + +__HEREDOC__ +fi + +cat << __HEREDOC__ +#ifndef __dead +# define __dead __attribute__((noreturn)) +#endif + +#if !HAVE_SIO_FLUSH +#define sio_flush(hdl) (sio_stop(hdl)) +#endif + +#if !HAVE_GETDTABLECOUNT +/* XXX: on linux it should be possible to inspect /proc/self/fd/ */ +#define getdtablecount() (0) +#endif + +#if !HAVE_OPTRESET +/* replace host' getopt with OpenBSD' one */ +#define opterr BSDopterr +#define optind BSDoptind +#define optopt BSDoptopt +#define optreset BSDoptreset +#define optarg BSDoptarg +#define getopt BSDgetopt + +extern int BSDopterr, BSDoptind, BSDoptopt, BSDoptreset; +extern char *BSDoptarg; +#endif + +#endif /*!OCONFIGURE_CONFIG_H*/ +__HEREDOC__ + +echo "config.h: written" 1>&2 +echo "config.h: written" 1>&3 + +#---------------------------------------------------------------------- +# Now we go to generate our Makefile.configure. +# This file is simply a bunch of Makefile variables. +# They'll work in both GNUmakefile and BSDmakefile. +# You MIGHT want to change this. +#---------------------------------------------------------------------- + +exec > Makefile.configure + +[ -z "${BINDIR}" ] && BINDIR="${PREFIX}/bin" +[ -z "${SBINDIR}" ] && SBINDIR="${PREFIX}/sbin" +[ -z "${INCLUDEDIR}" ] && INCLUDEDIR="${PREFIX}/include" +[ -z "${LIBDIR}" ] && LIBDIR="${PREFIX}/lib" +[ -z "${MANDIR}" ] && MANDIR="${PREFIX}/man" +[ -z "${SHAREDIR}" ] && SHAREDIR="${PREFIX}/share" + +[ -z "${INSTALL_PROGRAM}" ] && INSTALL_PROGRAM="${INSTALL} -m 0555" +[ -z "${INSTALL_LIB}" ] && INSTALL_LIB="${INSTALL} -m 0444" +[ -z "${INSTALL_MAN}" ] && INSTALL_MAN="${INSTALL} -m 0444" +[ -z "${INSTALL_DATA}" ] && INSTALL_DATA="${INSTALL} -m 0444" + +cat << __HEREDOC__ +CC = ${CC} +CFLAGS = ${CFLAGS} +CPPFLAGS = ${CPPFLAGS} +LDADD = ${LDADD} ${LDADD_IMSG} ${LDADD_LIB_FLAC} ${LDADD_LIB_MPG123} \ + ${LDADD_LIB_OPUSFILE} ${LDADD_LIB_VORBISFILE} ${LDADD_LIB_SOCKET} \ + ${LDADD_LIBEVENT} ${LDADD_LIBEVENT2} ${LDADD_LIB_SNDIO} +LDADD_STATIC = ${LDADD_STATIC} +LDFLAGS = ${LDFLAGS} +STATIC = ${STATIC} +PREFIX = ${PREFIX} +BINDIR = ${BINDIR} +SHAREDIR = ${SHAREDIR} +SBINDIR = ${SBINDIR} +INCLUDEDIR = ${INCLUDEDIR} +LIBDIR = ${LIBDIR} +MANDIR = ${MANDIR} +INSTALL = ${INSTALL} +INSTALL_PROGRAM = ${INSTALL_PROGRAM} +INSTALL_LIB = ${INSTALL_LIB} +INSTALL_MAN = ${INSTALL_MAN} +INSTALL_DATA = ${INSTALL_DATA} +__HEREDOC__ + +echo "Makefile.configure: written" 1>&2 +echo "Makefile.configure: written" 1>&3 + +exit 0 blob - 889149e7a82ddf07e0169a50cf1563f629f8d7ca blob + abf505eaf22728d250eee8a0e5d0aab25d7b86fa --- control.c +++ control.c @@ -15,19 +15,17 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include + +#include "config.h" + #include #include -#include #include #include #include #include -#include -#include #include #include #include blob - /dev/null blob + b03d0f3b83d875fd587fbb0a0d05344efbc8e130 (mode 644) --- /dev/null +++ configure.local.example @@ -0,0 +1,91 @@ +# +# Copyright (c) 2022 Omar Polo +# Copyright (c) 2014-2022 Ingo Schwarze +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# For all settings documented in this file, there are reasonable +# defaults and/or the ./configure script attempts autodetection. +# Consequently, you only need to create a file ./configure.local +# and put any of these settings into it if ./configure autodetection +# fails or if you want to make different choices for other reasons. + +# If autodetection fails, please tell . + +# We recommend that you write ./configure.local from scratch and +# only put the lines there you need. This file contains examples. +# It is not intended as a template to be copied as a whole. + +# Some systems may want to set additional linker flags for all the +# binaries, for example for hardening options. + +LDFLAGS="-Wl,-z,relro" + +# It may be needed to change the flags for the individual libraries. + +LDADD_IMSG="-limsg" +LDADD_LIBEVENT2="-L/opt/lib/ -levent_extra -levent_core" +LDADD_LIB_FLAC= +LDADD_LIB_MPG123= +LDADD_LIB_VORBISFILE= +LDADD_LIB_SNDIO= +LDADD_LIB_SOCKET= + +# To disable the autoconfiguration via pkg-config set PKG_CONFIG to +# the empty string: + +PKG_CONFIG= + +# It is possible to change the utility program used for installation +# and the modes files are installed with. The defaults are: + +INSTALL="install" +INSTALL_PROGRAM="${INSTALL} -m 0555" +INSTALL_LIB="${INSTALL} -m 0444" +INSTALL_MAN="${INSTALL} -m 0444" +INSTALL_DATA="${INSTALL} -m 0444" + +# In rare cases, it may be required to skip individual automatic tests. +# Each of the following variables can be set to 0 (test will not be run +# and will be regarded as failed) or 1 (test will not be run and will +# be regarded as successful). + +HAVE_CAPSICUM=0 +HAVE_ERR=0 +HAVE_EXPLICIT_BZERO=0 +HAVE_GETEXECNAME=0 +HAVE_GETPROGNAME=0 +HAVE_IMSG=0 +HAVE_LANDLOCK=0 +HAVE_LIBEVENT=0 +HAVE_LIBEVENT2=0 +HAVE_LIB_FLAC=0 +HAVE_LIB_MPG123=0 +HAVE_LIB_OPUSFILE=0 +HAVE_LIB_VORBISFILE=0 +HAVE_MEMMEM=0 +HAVE_MEMRCHR=0 +HAVE_PATH_MAX=0 +HAVE_PLEDGE=0 +HAVE_PROGRAM_INVOCATION_SHORT_NAME=0 +HAVE_REALLOCARRAY=0 +HAVE_RECALLOCARRAY=0 +HAVE_SANDBOX_INIT=0 +HAVE_STRLCAT=0 +HAVE_STRLCPY=0 +HAVE_STRNDUP=0 +HAVE_STRNLEN=0 +HAVE_STRTONUM=0 +HAVE_SYS_QUEUE=0 +HAVE_UNVEIL=0 +HAVE___PROGNAME=0 blob - 6956d3da03063292f2b60ea8d676994887cf70dc blob + c4629edaa511ae2d9c584c4d1ac6c9458242e1ee --- ctl.c +++ ctl.c @@ -15,14 +15,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include "config.h" + #include -#include -#include #include #include -#include #include #include #include @@ -31,7 +29,6 @@ #include #include #include -#include #include "amused.h" #include "log.h" blob - 179235943ad862e0426e472d7b0922bf3fef0371 blob + 852ef4b4d7bb5f4041ef126c2db5bde8213e8c5c --- log.c +++ log.c @@ -16,6 +16,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "config.h" + #include #include #include blob - /dev/null blob + 5b092cfcfd53b5b09a2d5932010f421d6795e0aa (mode 644) --- /dev/null +++ imsg.h @@ -0,0 +1,113 @@ +/* $OpenBSD: imsg.h,v 1.5 2019/01/20 02:50:03 bcook Exp $ */ + +/* + * Copyright (c) 2006, 2007 Pierre-Yves Ritschard + * Copyright (c) 2006, 2007, 2008 Reyk Floeter + * Copyright (c) 2003, 2004 Henning Brauer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _IMSG_H_ +#define _IMSG_H_ + +#include + +#define IBUF_READ_SIZE 65535 +#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr) +#define MAX_IMSGSIZE 16384 + +struct ibuf { + TAILQ_ENTRY(ibuf) entry; + unsigned char *buf; + size_t size; + size_t max; + size_t wpos; + size_t rpos; + int fd; +}; + +struct msgbuf { + TAILQ_HEAD(, ibuf) bufs; + uint32_t queued; + int fd; +}; + +struct ibuf_read { + unsigned char buf[IBUF_READ_SIZE]; + unsigned char *rptr; + size_t wpos; +}; + +struct imsg_fd { + TAILQ_ENTRY(imsg_fd) entry; + int fd; +}; + +struct imsgbuf { + TAILQ_HEAD(, imsg_fd) fds; + struct ibuf_read r; + struct msgbuf w; + int fd; + pid_t pid; +}; + +#define IMSGF_HASFD 1 + +struct imsg_hdr { + uint32_t type; + uint16_t len; + uint16_t flags; + uint32_t peerid; + uint32_t pid; +}; + +struct imsg { + struct imsg_hdr hdr; + int fd; + void *data; +}; + + +/* buffer.c */ +struct ibuf *ibuf_open(size_t); +struct ibuf *ibuf_dynamic(size_t, size_t); +int ibuf_add(struct ibuf *, const void *, size_t); +void *ibuf_reserve(struct ibuf *, size_t); +void *ibuf_seek(struct ibuf *, size_t, size_t); +size_t ibuf_size(struct ibuf *); +size_t ibuf_left(struct ibuf *); +void ibuf_close(struct msgbuf *, struct ibuf *); +int ibuf_write(struct msgbuf *); +void ibuf_free(struct ibuf *); +void msgbuf_init(struct msgbuf *); +void msgbuf_clear(struct msgbuf *); +int msgbuf_write(struct msgbuf *); +void msgbuf_drain(struct msgbuf *, size_t); + +/* imsg.c */ +void imsg_init(struct imsgbuf *, int); +ssize_t imsg_read(struct imsgbuf *); +ssize_t imsg_get(struct imsgbuf *, struct imsg *); +int imsg_compose(struct imsgbuf *, uint32_t, uint32_t, pid_t, int, + const void *, uint16_t); +int imsg_composev(struct imsgbuf *, uint32_t, uint32_t, pid_t, int, + const struct iovec *, int); +struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, uint16_t); +int imsg_add(struct ibuf *, const void *, uint16_t); +void imsg_close(struct imsgbuf *, struct ibuf *); +void imsg_free(struct imsg *); +int imsg_flush(struct imsgbuf *); +void imsg_clear(struct imsgbuf *); + +#endif blob - 0686e1258936c821114600db32ee00b4d1a7f0fa blob + 25f2a3acd47767a1524498b0ea97d08b54ae2ee6 --- player.c +++ player.c @@ -14,22 +14,18 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include +#include "config.h" #include #include #include -#include #include #include #include #include #include #include -#include #include #include #include blob - ddf86c28d7b98f0a796b5ffa55cd87f02b4c673b blob + 020ef8df21b9634a7671a55b57e93507a59c6114 --- player_123.c +++ player_123.c @@ -14,16 +14,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "config.h" + #include #include -#include -#include -#include -#include -#include #include -#include #include #include blob - fb7d7f6e5fb27589c7b28218ed1c71c88c7091f6 blob + 7df1d378d1b826a3bab7a241cf6c9d7f257c9b0f --- player_flac.c +++ player_flac.c @@ -14,19 +14,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include +#include "config.h" -#include -#include #include #include #include #include #include #include -#include #include blob - a2263c30c54ee0d24dcd7a852cfeb7f91a4211cd blob + e287375ce6df3b24e132769563a7bcabe2403f4e --- player_oggvorbis.c +++ player_oggvorbis.c @@ -14,19 +14,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include +#include "config.h" -#include -#include #include #include #include #include #include #include -#include #include #include blob - 2a20b6840acc75e98eab54cbc2c4ffe84faeafe2 blob + 7e291f0c988483c73189fce7d8bab69f7cd10fdf --- player_opus.c +++ player_opus.c @@ -14,19 +14,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include +#include "config.h" -#include -#include #include #include #include #include #include #include -#include #include #include blob - f2821ef2c9500cc78ba6202d4a4a171047d46fd4 blob + bf38c046e3d2ddc87a94439913eed4bea6109160 --- playlist.c +++ playlist.c @@ -14,6 +14,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "config.h" + #include #include blob - f05ceadf51129ffe6559594eeea12fa517db5f69 blob + aeb15eb2aa91cbb4d041a78af3a54eab3c8c9de7 --- xmalloc.c +++ xmalloc.c @@ -13,6 +13,8 @@ * called by a name other than "ssh" or "Secure Shell". */ +#include "config.h" + #include #include #include blob - /dev/null blob + 9cd9aad01fe0196eb6bb233493e4dabc0dc20625 (mode 644) --- /dev/null +++ queue.h @@ -0,0 +1,619 @@ +/* + * A compatible version of OpenBSD . + */ +/* + * Copyright (c) 1991, 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. + * 3. 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. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +/* OPENBSD ORIGINAL: sys/sys/queue.h */ + +/* + * Require for OS/X and other platforms that have old/broken/incomplete + * . + */ + +#undef LIST_EMPTY +#undef LIST_END +#undef LIST_ENTRY +#undef LIST_FIRST +#undef LIST_FOREACH +#undef LIST_FOREACH_SAFE +#undef LIST_HEAD +#undef LIST_HEAD_INITIALIZER +#undef LIST_INIT +#undef LIST_INSERT_AFTER +#undef LIST_INSERT_BEFORE +#undef LIST_INSERT_HEAD +#undef LIST_NEXT +#undef LIST_REMOVE +#undef LIST_REPLACE +#undef SIMPLEQ_CONCAT +#undef SIMPLEQ_EMPTY +#undef SIMPLEQ_END +#undef SIMPLEQ_ENTRY +#undef SIMPLEQ_FIRST +#undef SIMPLEQ_FOREACH +#undef SIMPLEQ_FOREACH_SAFE +#undef SIMPLEQ_HEAD +#undef SIMPLEQ_HEAD_INITIALIZER +#undef SIMPLEQ_INIT +#undef SIMPLEQ_INSERT_AFTER +#undef SIMPLEQ_INSERT_HEAD +#undef SIMPLEQ_INSERT_TAIL +#undef SIMPLEQ_NEXT +#undef SIMPLEQ_REMOVE_AFTER +#undef SIMPLEQ_REMOVE_HEAD +#undef SLIST_EMPTY +#undef SLIST_END +#undef SLIST_ENTRY +#undef SLIST_FIRST +#undef SLIST_FOREACH +#undef SLIST_FOREACH_SAFE +#undef SLIST_HEAD +#undef SLIST_HEAD_INITIALIZER +#undef SLIST_INIT +#undef SLIST_INSERT_AFTER +#undef SLIST_INSERT_HEAD +#undef SLIST_NEXT +#undef SLIST_REMOVE +#undef SLIST_REMOVE_AFTER +#undef SLIST_REMOVE_HEAD +#undef TAILQ_CONCAT +#undef TAILQ_EMPTY +#undef TAILQ_END +#undef TAILQ_ENTRY +#undef TAILQ_FIRST +#undef TAILQ_FOREACH +#undef TAILQ_FOREACH_REVERSE +#undef TAILQ_FOREACH_REVERSE_SAFE +#undef TAILQ_FOREACH_SAFE +#undef TAILQ_HEAD +#undef TAILQ_HEAD_INITIALIZER +#undef TAILQ_INIT +#undef TAILQ_INSERT_AFTER +#undef TAILQ_INSERT_BEFORE +#undef TAILQ_INSERT_HEAD +#undef TAILQ_INSERT_TAIL +#undef TAILQ_LAST +#undef TAILQ_NEXT +#undef TAILQ_PREV +#undef TAILQ_REMOVE +#undef TAILQ_REPLACE +#undef XSIMPLEQ_EMPTY +#undef XSIMPLEQ_END +#undef XSIMPLEQ_ENTRY +#undef XSIMPLEQ_FIRST +#undef XSIMPLEQ_FOREACH +#undef XSIMPLEQ_FOREACH_SAFE +#undef XSIMPLEQ_HEAD +#undef XSIMPLEQ_INIT +#undef XSIMPLEQ_INSERT_AFTER +#undef XSIMPLEQ_INSERT_HEAD +#undef XSIMPLEQ_INSERT_TAIL +#undef XSIMPLEQ_NEXT +#undef XSIMPLEQ_REMOVE_AFTER +#undef XSIMPLEQ_REMOVE_HEAD +#undef XSIMPLEQ_XOR + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues and XOR simple queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * An XOR simple queue is used in the same way as a regular simple queue. + * The difference is that the head structure also includes a "cookie" that + * is XOR'd with the queue pointer (first, last or next) to generate the + * real pointer value. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) +#define _Q_INVALID ((void *)-1) +#define _Q_INVALIDATE(a) (a) = _Q_INVALID +#else +#define _Q_INVALIDATE(a) +#endif + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = SLIST_FIRST(head); \ + (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST(head); \ + (var) && ((tvar) = SLIST_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) { \ + SLIST_FIRST(head) = SLIST_END(head); \ +} + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->slh_first; \ + \ + while (curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ + _Q_INVALIDATE((elm)->field.sle_next); \ +} while (0) + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods. + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \ + for((var) = LIST_FIRST(head); \ + (var)!= LIST_END(head); \ + (var) = LIST_NEXT(var, field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST(head); \ + (var) && ((tvar) = LIST_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * List functions. + */ +#define LIST_INIT(head) do { \ + LIST_FIRST(head) = LIST_END(head); \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ +} while (0) + +#define LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ +} while (0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for((var) = SIMPLEQ_FIRST(head); \ + (var) != SIMPLEQ_END(head); \ + (var) = SIMPLEQ_NEXT(var, field)) + +#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SIMPLEQ_FIRST(head); \ + (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ + == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_CONCAT(head1, head2) do { \ + if (!SIMPLEQ_EMPTY((head2))) { \ + *(head1)->sqh_last = (head2)->sqh_first; \ + (head1)->sqh_last = (head2)->sqh_last; \ + SIMPLEQ_INIT((head2)); \ + } \ +} while (0) + +/* + * XOR Simple queue definitions. + */ +#define XSIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqx_first; /* first element */ \ + struct type **sqx_last; /* addr of last next element */ \ + unsigned long sqx_cookie; \ +} + +#define XSIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqx_next; /* next element */ \ +} + +/* + * XOR Simple queue access methods. + */ +#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \ + (unsigned long)(ptr))) +#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) +#define XSIMPLEQ_END(head) NULL +#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) +#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) + + +#define XSIMPLEQ_FOREACH(var, head, field) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) != XSIMPLEQ_END(head); \ + (var) = XSIMPLEQ_NEXT(head, var, field)) + +#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ + (var) = (tvar)) + +/* + * XOR Simple queue functions. + */ +#define XSIMPLEQ_INIT(head) do { \ + arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ +} while (0) + +#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqx_next = (head)->sqx_first) == \ + XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ +} while (0) + +#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ + *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ +} while (0) + +#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \ + XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ +} while (0) + +#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqx_first = XSIMPLEQ_XOR(head, \ + (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ +} while (0) + +#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ + (elm)->field.sqx_next)->field.sqx_next) \ + == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = \ + XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ +} while (0) + + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * Tail queue access methods. + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) NULL +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) \ + (TAILQ_FIRST(head) == TAILQ_END(head)) + +#define TAILQ_FOREACH(var, head, field) \ + for((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head) && \ + ((tvar) = TAILQ_NEXT(var, field), 1); \ + (var) = (tvar)) + + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_PREV(var, headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head) && \ + ((tvar) = TAILQ_PREV(var, headname, field), 1); \ + (var) = (tvar)) + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + _Q_INVALIDATE((elm)->field.tqe_prev); \ + _Q_INVALIDATE((elm)->field.tqe_next); \ +} while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.tqe_prev); \ + _Q_INVALIDATE((elm)->field.tqe_next); \ +} while (0) + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + } \ +} while (0) blob - /dev/null blob + ab9a2cfc5f1241b1c375cc1e3fc555c5fc35a06a (mode 644) --- /dev/null +++ tests.c @@ -0,0 +1,955 @@ +#if TEST__MMD +int +main(void) +{ + return 0; +} +#endif /* TEST_NOOP */ +#if TEST___PROGNAME +int +main(void) +{ + extern char *__progname; + + return !__progname; +} +#endif /* TEST___PROGNAME */ +#if TEST_ARC4RANDOM +#include + +int +main(void) +{ + return (arc4random() + 1) ? 0 : 1; +} +#endif /* TEST_ARC4RANDOM */ +#if TEST_B64_NTOP +#include +#include + +int +main(void) +{ + const char *src = "hello world"; + char output[1024]; + + return b64_ntop((const unsigned char *)src, 11, output, sizeof(output)) > 0 ? 0 : 1; +} +#endif /* TEST_B64_NTOP */ +#if TEST_CAPSICUM +#include + +int +main(void) +{ + cap_enter(); + return(0); +} +#endif /* TEST_CAPSICUM */ +#if TEST_CRYPT +#if defined(__linux__) +# define _GNU_SOURCE /* old glibc */ +# define _DEFAULT_SOURCE /* new glibc */ +#endif +#if defined(__sun) +# ifndef _XOPEN_SOURCE /* SunOS already defines */ +# define _XOPEN_SOURCE /* XPGx */ +# endif +# define _XOPEN_SOURCE_EXTENDED 1 /* XPG4v2 */ +# ifndef __EXTENSIONS__ /* SunOS already defines */ +# define __EXTENSIONS__ /* reallocarray, etc. */ +# endif +#endif +#include + +int main(void) +{ + char *v; + + v = crypt("this_is_a_key", "123455"); + return v == NULL; +} +#endif /* TEST_CRYPT */ +#if TEST_CRYPT_NEWHASH +#include /* _PASSWORD_LEN */ +#include + +int +main(void) +{ + const char *v = "password"; + char hash[_PASSWORD_LEN]; + + if (crypt_newhash(v, "bcrypt,a", hash, sizeof(hash)) == -1) + return 1; + if (crypt_checkpass(v, hash) == -1) + return 1; + + return 0; +} +#endif /* TEST_CRYPT_NEWHASH */ +#if TEST_ENDIAN_H +#ifdef __linux__ +# define _DEFAULT_SOURCE +#endif +#include + +int +main(void) +{ + return !htole32(23); +} +#endif /* TEST_ENDIAN_H */ +#if TEST_ERR +/* + * Copyright (c) 2015 Ingo Schwarze + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +int +main(void) +{ + warnx("%d. warnx", 1); + warnc(ENOENT, "%d. warn", ENOENT); + warn("%d. warn", 2); + err(0, "%d. err", 3); + errx(0, "%d. err", 3); + errc(0, ENOENT, "%d. err", 3); + /* NOTREACHED */ + return 1; +} +#endif /* TEST_ERR */ +#if TEST_EXPLICIT_BZERO +#include + +int +main(void) +{ + char foo[10]; + + explicit_bzero(foo, sizeof(foo)); + return(0); +} +#endif /* TEST_EXPLICIT_BZERO */ +#if TEST_FLOCK +#include + +int +main(void) +{ + flock(0, LOCK_SH|LOCK_NB); + return 0; +} +#endif /* TEST_FLOCK */ +#if TEST_FREEZERO +#include + +int +main(void) +{ + freezero(NULL, 0); + return 0; +} +#endif /* TEST_FREEZERO */ +#if TEST_FTS +#include +#include +#include +#include + +int +main(void) +{ + const char *argv[2]; + FTS *ftsp; + FTSENT *entry; + + argv[0] = "."; + argv[1] = (char *)NULL; + + ftsp = fts_open((char * const *)argv, + FTS_PHYSICAL | FTS_NOCHDIR, NULL); + + if (ftsp == NULL) + return 1; + + entry = fts_read(ftsp); + + if (entry == NULL) + return 1; + + if (fts_set(ftsp, entry, FTS_SKIP) != 0) + return 1; + + if (fts_close(ftsp) != 0) + return 1; + + return 0; +} +#endif /* TEST_FTS */ +#if TEST_GETEXECNAME +#include + +int +main(void) +{ + const char * progname; + + progname = getexecname(); + return progname == NULL; +} +#endif /* TEST_GETEXECNAME */ +#if TEST_GETPROGNAME +#include + +int +main(void) +{ + const char * progname; + + progname = getprogname(); + return progname == NULL; +} +#endif /* TEST_GETPROGNAME */ +#if TEST_IMSG +#include +#include +#include +#include +#include + +int +main(void) +{ + struct imsgbuf ibuf; + + imsg_init(&ibuf, 3); + imsg_clear(&ibuf); + return 0; +} +#endif /* TEST_IMSG */ +#if TEST_INFTIM +/* + * Linux doesn't (always?) have this. + */ + +#include +#include + +int +main(void) +{ + printf("INFTIM is defined to be %ld\n", (long)INFTIM); + return 0; +} +#endif /* TEST_INFTIM */ +#if TEST_LANDLOCK +#include +#include +#include +#include +#include +#include +#include + +#ifndef landlock_create_ruleset +static inline int landlock_create_ruleset(const struct landlock_ruleset_attr *const attr, + const size_t size, const __u32 flags) +{ + return syscall(__NR_landlock_create_ruleset, attr, size, flags); +} +#endif + +#ifndef landlock_restrict_self +static inline int landlock_restrict_self(const int ruleset_fd, + const __u32 flags) +{ + return syscall(__NR_landlock_restrict_self, ruleset_fd, flags); +} +#endif + +int +main(void) +{ + uint64_t mask = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE; + struct landlock_ruleset_attr rules = { + .handled_access_fs = mask + }; + int fd = landlock_create_ruleset(&rules, sizeof(rules), 0); + + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) + return 1; + return landlock_restrict_self(fd, 0) ? 1 : 0; +} +#endif /* TEST_LANDLOCK */ +#if TEST_LIB_SOCKET +#include + +int +main(void) +{ + int fds[2], c; + + c = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); + return c == -1; +} +#endif /* TEST_LIB_SOCKET */ +#if TEST_MD5 +#include +#include + +int main(void) +{ + MD5_CTX ctx; + char result[MD5_DIGEST_STRING_LENGTH]; + + MD5Init(&ctx); + MD5Update(&ctx, (const unsigned char *)"abcd", 4); + MD5End(&ctx, result); + + return 0; +} +#endif /* TEST_MD5 */ +#if TEST_MEMMEM +#define _GNU_SOURCE +#include + +int +main(void) +{ + char *a = memmem("hello, world", strlen("hello, world"), "world", strlen("world")); + return(NULL == a); +} +#endif /* TEST_MEMMEM */ +#if TEST_MEMRCHR +#if defined(__linux__) || defined(__MINT__) +#define _GNU_SOURCE /* See test-*.c what needs this. */ +#endif +#include + +int +main(void) +{ + const char *buf = "abcdef"; + void *res; + + res = memrchr(buf, 'a', strlen(buf)); + return(NULL == res ? 1 : 0); +} +#endif /* TEST_MEMRCHR */ +#if TEST_MEMSET_S +#include + +int main(void) +{ + char buf[10]; + memset_s(buf, 0, 'c', sizeof(buf)); + return 0; +} +#endif /* TEST_MEMSET_S */ +#if TEST_MKFIFOAT +#include +#include + +int main(void) { + mkfifoat(AT_FDCWD, "this/path/should/not/exist", 0600); + return 0; +} +#endif /* TEST_MKFIFOAT */ +#if TEST_MKNODAT +#include +#include + +int main(void) { + mknodat(AT_FDCWD, "this/path/should/not/exist", S_IFIFO | 0600, 0); + return 0; +} +#endif /* TEST_MKNODAT */ +#if TEST_OPTRESET +#include + +int +main(int argc, char **argv) +{ + optreset = 1; + getopt(argc, argv, ""); + return 0; +} +#endif /* TEST_OPTRESET */ +#if TEST_OSBYTEORDER_H +#include + +int +main(void) +{ + return !OSSwapHostToLittleInt32(23); +} +#endif /* TEST_OSBYTEORDER_H */ +#if TEST_PATH_MAX +/* + * POSIX allows PATH_MAX to not be defined, see + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html; + * the GNU Hurd is an example of a system not having it. + * + * Arguably, it would be better to test sysconf(_SC_PATH_MAX), + * but since the individual *.c files include "config.h" before + * , overriding an excessive value of PATH_MAX from + * "config.h" is impossible anyway, so for now, the simplest + * fix is to provide a value only on systems not having any. + * So far, we encountered no system defining PATH_MAX to an + * impractically large value, even though POSIX explicitly + * allows that. + * + * The real fix would be to replace all static buffers of size + * PATH_MAX by dynamically allocated buffers. But that is + * somewhat intrusive because it touches several files and + * because it requires changing struct mlink in mandocdb.c. + * So i'm postponing that for now. + */ + +#include +#include + +int +main(void) +{ + printf("PATH_MAX is defined to be %ld\n", (long)PATH_MAX); + return 0; +} +#endif /* TEST_PATH_MAX */ +#if TEST_PLEDGE +#include + +int +main(void) +{ + return !!pledge("stdio", NULL); +} +#endif /* TEST_PLEDGE */ +#if TEST_PROGRAM_INVOCATION_SHORT_NAME +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include + +int +main(void) +{ + + return !program_invocation_short_name; +} +#endif /* TEST_PROGRAM_INVOCATION_SHORT_NAME */ +#if TEST_PR_SET_NAME +#include + +int +main(void) +{ + prctl(PR_SET_NAME, "foo"); + return 0; +} +#endif /* TEST_PR_SET_NAME */ +#if TEST_READPASSPHRASE +#include +#include + +int +main(void) +{ + return !!readpassphrase("prompt: ", NULL, 0, 0); +} +#endif /* TEST_READPASSPHRASE */ +#if TEST_REALLOCARRAY +#ifdef __NetBSD__ +# define _OPENBSD_SOURCE +#endif +#include + +int +main(void) +{ + return !reallocarray(NULL, 2, 2); +} +#endif /* TEST_REALLOCARRAY */ +#if TEST_RECALLOCARRAY +#include + +int +main(void) +{ + return !recallocarray(NULL, 0, 2, 2); +} +#endif /* TEST_RECALLOCARRAY */ +#if TEST_SANDBOX_INIT +#include + +int +main(void) +{ + char *ep; + int rc; + + rc = sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, &ep); + if (-1 == rc) + sandbox_free_error(ep); + return(-1 == rc); +} +#endif /* TEST_SANDBOX_INIT */ +#if TEST_SETPROCTITLE +#include + +int +main(void) +{ + setproctitle("#%d test program", 7); + return 0; +} +#endif +#if TEST_SIO_FLUSH +#include + +int +main(void) +{ + struct sio_hdl *hdl; + hdl = sio_open(SIO_DEVANY, SIO_PLAY, 1); + sio_flush(hdl); + sio_close(hdl); +} +#endif /* TEST_SIO_FLUSH */ +#if TEST_SCAN_SCALED +#include + +int +main(void) +{ + char *cinput = (char *)"1.5K", buf[FMT_SCALED_STRSIZE]; + long long ninput = 10483892, result; + return scan_scaled(cinput, &result) == 0; +} +#endif /* TEST_SCAN_SCALED */ +#if TEST_SECCOMP_FILTER +#include +#include +#include + +int +main(void) +{ + + prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, 0); + return(EFAULT == errno ? 0 : 1); +} +#endif /* TEST_SECCOMP_FILTER */ +#if TEST_SETRESGID +#define _GNU_SOURCE /* linux */ +#include +#include + +int +main(void) +{ + return setresgid(-1, -1, -1) == -1; +} +#endif /* TEST_SETRESGID */ +#if TEST_SETRESUID +#define _GNU_SOURCE /* linux */ +#include +#include + +int +main(void) +{ + return setresuid(-1, -1, -1) == -1; +} +#endif /* TEST_SETRESUID */ +#if TEST_SHA2 +#include +#include + +int main(void) +{ + SHA2_CTX ctx; + char result[SHA256_DIGEST_STRING_LENGTH]; + + SHA256Init(&ctx); + SHA256Update(&ctx, (const unsigned char *)"abcd", 4); + SHA256End(&ctx, result); + + return 0; +} +#endif /* TEST_SHA2 */ +#if TEST_SOCK_NONBLOCK +/* + * Linux doesn't (always?) have this. + */ + +#include + +int +main(void) +{ + int fd[2]; + socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK, 0, fd); + return 0; +} +#endif /* TEST_SOCK_NONBLOCK */ +#if TEST_STATIC +int +main(void) +{ + return 0; /* not meant to do anything */ +} +#endif /* TEST_STATIC */ +#if TEST_STRLCAT +#include + +int +main(void) +{ + char buf[3] = "a"; + return ! (strlcat(buf, "b", sizeof(buf)) == 2 && + buf[0] == 'a' && buf[1] == 'b' && buf[2] == '\0'); +} +#endif /* TEST_STRLCAT */ +#if TEST_STRLCPY +#include + +int +main(void) +{ + char buf[2] = ""; + return ! (strlcpy(buf, "a", sizeof(buf)) == 1 && + buf[0] == 'a' && buf[1] == '\0'); +} +#endif /* TEST_STRLCPY */ +#if TEST_STRNDUP +#include + +int +main(void) +{ + const char *foo = "bar"; + char *baz; + + baz = strndup(foo, 1); + return(0 != strcmp(baz, "b")); +} +#endif /* TEST_STRNDUP */ +#if TEST_STRNLEN +#include + +int +main(void) +{ + const char *foo = "bar"; + size_t sz; + + sz = strnlen(foo, 1); + return(1 != sz); +} +#endif /* TEST_STRNLEN */ +#if TEST_STRTONUM +/* + * Copyright (c) 2015 Ingo Schwarze + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef __NetBSD__ +# define _OPENBSD_SOURCE +#endif +#include + +int +main(void) +{ + const char *errstr; + + if (strtonum("1", 0, 2, &errstr) != 1) + return 1; + if (errstr != NULL) + return 2; + if (strtonum("1x", 0, 2, &errstr) != 0) + return 3; + if (errstr == NULL) + return 4; + if (strtonum("2", 0, 1, &errstr) != 0) + return 5; + if (errstr == NULL) + return 6; + if (strtonum("0", 1, 2, &errstr) != 0) + return 7; + if (errstr == NULL) + return 8; + return 0; +} +#endif /* TEST_STRTONUM */ +#if TEST_SYS_BYTEORDER_H +#include + +int +main(void) +{ + return !LE_32(23); +} +#endif /* TEST_SYS_BYTEORDER_H */ +#if TEST_SYS_ENDIAN_H +#include + +int +main(void) +{ + return !htole32(23); +} +#endif /* TEST_SYS_ENDIAN_H */ +#if TEST_SYS_MKDEV_H +#include +#include + +int +main(void) +{ + return !minor(0); +} +#endif /* TEST_SYS_MKDEV_H */ +#if TEST_SYS_FILE +#include + +int +main(void) +{ + flock(0, LOCK_SH|LOCK_NB); + return 0; +} +#endif /* TEST_SYS_FILE */ +#if TEST_SYS_QUEUE +#include +#include + +struct foo { + int bar; + TAILQ_ENTRY(foo) entries; +}; + +TAILQ_HEAD(fooq, foo); + +int +main(void) +{ + struct fooq foo_q, bar_q; + struct foo *p, *tmp; + int i = 0; + + TAILQ_INIT(&foo_q); + TAILQ_INIT(&bar_q); + + /* + * Use TAILQ_FOREACH_SAFE because some systems (e.g., Linux) + * have TAILQ_FOREACH but not the safe variant. + */ + + TAILQ_FOREACH_SAFE(p, &foo_q, entries, tmp) + p->bar = i++; + + /* Test for newer macros as well. */ + + TAILQ_CONCAT(&foo_q, &bar_q, entries); + return 0; +} +#endif /* TEST_SYS_QUEUE */ +#if TEST_SYS_SYSMACROS_H +#include + +int +main(void) +{ + return !minor(0); +} +#endif /* TEST_SYS_SYSMACROS_H */ +#if TEST_SYS_TREE +#include +#include + +struct node { + RB_ENTRY(node) entry; + int i; +}; + +static int +intcmp(struct node *e1, struct node *e2) +{ + return (e1->i < e2->i ? -1 : e1->i > e2->i); +} + +RB_HEAD(inttree, node) head = RB_INITIALIZER(&head); +RB_PROTOTYPE(inttree, node, entry, intcmp) +RB_GENERATE(inttree, node, entry, intcmp) + +int testdata[] = { + 20, 16, 17, 13, 3, 6, 1, 8, 2, 4 +}; + +int +main(void) +{ + size_t i; + struct node *n; + + for (i = 0; i < sizeof(testdata) / sizeof(testdata[0]); i++) { + if ((n = malloc(sizeof(struct node))) == NULL) + return 1; + n->i = testdata[i]; + RB_INSERT(inttree, &head, n); + } + + return 0; +} + +#endif /* TEST_SYS_TREE */ +#if TEST_UNVEIL +#include + +int +main(void) +{ + return -1 != unveil(NULL, NULL); +} +#endif /* TEST_UNVEIL */ +#if TEST_WAIT_ANY +#include + +int +main(void) +{ + int st; + + return waitpid(WAIT_ANY, &st, WNOHANG) != -1; +} +#endif /* TEST_WAIT_ANY */ +#if TEST_LIBEVENT +#include + +int +main(void) +{ + struct event ev; + + event_set(&ev, 0, EV_READ, NULL, NULL); + event_add(&ev, NULL); + event_del(&ev); + return 0; +} +#endif /* TEST_LIBEVENT */ +#if TEST_LIBEVENT2 +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(void) +{ + struct event ev; + + event_set(&ev, 0, EV_READ, NULL, NULL); + event_add(&ev, NULL); + event_del(&ev); + return 0; +} +#endif /* TEST_LIBEVENT2 */ +#if TEST_LIB_FLAC +#include + +int +main(void) +{ + FLAC__StreamDecoder *decoder = NULL; + FLAC__StreamDecoderInitStatus init_status; + + decoder = FLAC__stream_decoder_new(); + FLAC__stream_decoder_delete(decoder); + return 0; +} +#endif /* TEST_LIB_FLAC */ +#if TEST_LIB_MPG123 +#include + +int +main(void) +{ + mpg123_handle *mh; + + mh = mpg123_new(NULL, NULL); + mpg123_delete(mh); + return 0; +} +#endif/* TEST_LIB_MPG123 */ +#if TEST_LIB_OPUSFILE +#include +#include + +int +main(void) +{ + FILE *f; + OggOpusFile *of; + OpusFileCallbacks cb = {NULL, NULL, NULL, NULL}; + int r; + + f = op_fdopen(&cb, 0, "r"); + of = op_open_callbacks(f, &cb, NULL, 0, &r); + op_free(of); + return 0; +} +#endif /* TEST_LIB_OPUSFILE */ +#if TEST_LIB_VORBISFILE +#include +#include + +int +main(void) +{ + OggVorbis_File vf; + + ov_open_callbacks(stdin, &vf, NULL, 0, OV_CALLBACKS_NOCLOSE); + ov_clear(&vf); + return 0; +} +#endif /* TEST_LIB_VORBISFILE */ +#if TEST_LIB_SNDIO +#include + +int +main(void) +{ + struct sio_hdl *hdl; + hdl = sio_open(SIO_DEVANY, SIO_PLAY, 1); + sio_close(hdl); +} +#endif /* TEST_LIB_SNDIO */