util: remove ring.[ch] + pty.[ch] and tests
authorLennart Poettering <lennart@poettering.net>
Fri, 11 Sep 2015 14:26:31 +0000 (16:26 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 11 Sep 2015 16:28:29 +0000 (18:28 +0200)
This was used by consoled, which was removed, let's remove this too now.

Makefile.am
src/basic/ring.c [deleted file]
src/basic/ring.h [deleted file]
src/shared/pty.c [deleted file]
src/shared/pty.h [deleted file]
src/test/test-pty.c [deleted file]
src/test/test-ring.c [deleted file]

index 0583742..c395840 100644 (file)
@@ -865,8 +865,6 @@ libbasic_la_SOURCES = \
        src/basic/xml.h \
        src/basic/json.c \
        src/basic/json.h \
-       src/basic/ring.c \
-       src/basic/ring.h \
        src/basic/barrier.c \
        src/basic/barrier.h \
        src/basic/async.c \
@@ -954,8 +952,6 @@ libshared_la_SOURCES = \
        src/shared/ima-util.h \
        src/shared/ptyfwd.c \
        src/shared/ptyfwd.h \
-       src/shared/pty.c \
-       src/shared/pty.h \
        src/shared/base-filesystem.c \
        src/shared/base-filesystem.h \
        src/shared/uid-range.c \
@@ -1402,9 +1398,7 @@ tests += \
        test-process-util \
        test-terminal-util \
        test-path-lookup \
-       test-ring \
        test-barrier \
-       test-pty \
        test-tmpfiles \
        test-namespace \
        test-date \
@@ -1721,24 +1715,12 @@ test_socket_util_SOURCES = \
 test_socket_util_LDADD = \
        libshared.la
 
-test_ring_SOURCES = \
-       src/test/test-ring.c
-
-test_ring_LDADD = \
-       libshared.la
-
 test_barrier_SOURCES = \
        src/test/test-barrier.c
 
 test_barrier_LDADD = \
        libshared.la
 
-test_pty_SOURCES = \
-       src/test/test-pty.c
-
-test_pty_LDADD = \
-       libcore.la
-
 test_tmpfiles_SOURCES = \
        src/test/test-tmpfiles.c
 
diff --git a/src/basic/ring.c b/src/basic/ring.c
deleted file mode 100644 (file)
index 6814918..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/uio.h>
-#include "macro.h"
-#include "ring.h"
-
-#define RING_MASK(_r, _v) ((_v) & ((_r)->size - 1))
-
-void ring_flush(Ring *r) {
-        assert(r);
-
-        r->start = 0;
-        r->used = 0;
-}
-
-void ring_clear(Ring *r) {
-        assert(r);
-
-        free(r->buf);
-        zero(*r);
-}
-
-/*
- * Get data pointers for current ring-buffer data. @vec must be an array of 2
- * iovec objects. They are filled according to the data available in the
- * ring-buffer. 0, 1 or 2 is returned according to the number of iovec objects
- * that were filled (0 meaning buffer is empty).
- *
- * Hint: "struct iovec" is defined in <sys/uio.h> and looks like this:
- *     struct iovec {
- *         void *iov_base;
- *         size_t iov_len;
- *     };
- */
-size_t ring_peek(Ring *r, struct iovec *vec) {
-        assert(r);
-
-        if (r->used == 0) {
-                return 0;
-        } else if (r->start + r->used <= r->size) {
-                if (vec) {
-                        vec[0].iov_base = &r->buf[r->start];
-                        vec[0].iov_len = r->used;
-                }
-                return 1;
-        } else {
-                if (vec) {
-                        vec[0].iov_base = &r->buf[r->start];
-                        vec[0].iov_len = r->size - r->start;
-                        vec[1].iov_base = r->buf;
-                        vec[1].iov_len = r->used - (r->size - r->start);
-                }
-                return 2;
-        }
-}
-
-/*
- * Copy data from the ring buffer into the linear external buffer @buf. Copy
- * at most @size bytes. If the ring buffer size is smaller, copy less bytes and
- * return the number of bytes copied.
- */
-size_t ring_copy(Ring *r, void *buf, size_t size) {
-        size_t l;
-
-        assert(r);
-        assert(buf);
-
-        if (size > r->used)
-                size = r->used;
-
-        if (size > 0) {
-                l = r->size - r->start;
-                if (size <= l) {
-                        memcpy(buf, &r->buf[r->start], size);
-                } else {
-                        memcpy(buf, &r->buf[r->start], l);
-                        memcpy((uint8_t*)buf + l, r->buf, size - l);
-                }
-        }
-
-        return size;
-}
-
-/*
- * Resize ring-buffer to size @nsize. @nsize must be a power-of-2, otherwise
- * ring operations will behave incorrectly.
- */
-static int ring_resize(Ring *r, size_t nsize) {
-        uint8_t *buf;
-        size_t l;
-
-        assert(r);
-        assert(nsize > 0);
-
-        buf = malloc(nsize);
-        if (!buf)
-                return -ENOMEM;
-
-        if (r->used > 0) {
-                l = r->size - r->start;
-                if (r->used <= l) {
-                        memcpy(buf, &r->buf[r->start], r->used);
-                } else {
-                        memcpy(buf, &r->buf[r->start], l);
-                        memcpy(&buf[l], r->buf, r->used - l);
-                }
-        }
-
-        free(r->buf);
-        r->buf = buf;
-        r->size = nsize;
-        r->start = 0;
-
-        return 0;
-}
-
-/*
- * Resize ring-buffer to provide enough room for @add bytes of new data. This
- * resizes the buffer if it is too small. It returns -ENOMEM on OOM and 0 on
- * success.
- */
-static int ring_grow(Ring *r, size_t add) {
-        size_t need;
-
-        assert(r);
-
-        if (r->size - r->used >= add)
-                return 0;
-
-        need = r->used + add;
-        if (need <= r->used)
-                return -ENOMEM;
-        else if (need < 4096)
-                need = 4096;
-
-        need = ALIGN_POWER2(need);
-        if (need == 0)
-                return -ENOMEM;
-
-        return ring_resize(r, need);
-}
-
-/*
- * Push @len bytes from @u8 into the ring buffer. The buffer is resized if it
- * is too small. -ENOMEM is returned on OOM, 0 on success.
- */
-int ring_push(Ring *r, const void *u8, size_t size) {
-        int err;
-        size_t pos, l;
-
-        assert(r);
-        assert(u8);
-
-        if (size == 0)
-                return 0;
-
-        err = ring_grow(r, size);
-        if (err < 0)
-                return err;
-
-        pos = RING_MASK(r, r->start + r->used);
-        l = r->size - pos;
-        if (l >= size) {
-                memcpy(&r->buf[pos], u8, size);
-        } else {
-                memcpy(&r->buf[pos], u8, l);
-                memcpy(r->buf, (const uint8_t*)u8 + l, size - l);
-        }
-
-        r->used += size;
-
-        return 0;
-}
-
-/*
- * Remove @len bytes from the start of the ring-buffer. Note that we protect
- * against overflows so removing more bytes than available is safe.
- */
-void ring_pull(Ring *r, size_t size) {
-        assert(r);
-
-        if (size > r->used)
-                size = r->used;
-
-        r->start = RING_MASK(r, r->start + size);
-        r->used -= size;
-}
diff --git a/src/basic/ring.h b/src/basic/ring.h
deleted file mode 100644 (file)
index dbd6296..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-
-typedef struct Ring Ring;
-
-struct Ring {
-        uint8_t *buf;           /* buffer or NULL */
-        size_t size;            /* actual size of @buf */
-        size_t start;           /* start position of ring */
-        size_t used;            /* number of actually used bytes */
-};
-
-/* flush buffer so it is empty again */
-void ring_flush(Ring *r);
-
-/* flush buffer, free allocated data and reset to initial state */
-void ring_clear(Ring *r);
-
-/* get pointers to buffer data and their length */
-size_t ring_peek(Ring *r, struct iovec *vec);
-
-/* copy data into external linear buffer */
-size_t ring_copy(Ring *r, void *buf, size_t size);
-
-/* push data to the end of the buffer */
-int ring_push(Ring *r, const void *u8, size_t size);
-
-/* pull data from the front of the buffer */
-void ring_pull(Ring *r, size_t size);
-
-/* return size of occupied buffer in bytes */
-static inline size_t ring_get_size(Ring *r) {
-        return r->used;
-}
diff --git a/src/shared/pty.c b/src/shared/pty.c
deleted file mode 100644 (file)
index 35d9ff5..0000000
+++ /dev/null
@@ -1,633 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-/*
- * PTY
- * A PTY object represents a single PTY connection between a master and a
- * child. The child process is fork()ed so the caller controls what program
- * will be run.
- *
- * Programs like /bin/login tend to perform a vhangup() on their TTY
- * before running the login procedure. This also causes the pty master
- * to get a EPOLLHUP event as long as no client has the TTY opened.
- * This means, we cannot use the TTY connection as reliable way to track
- * the client. Instead, we _must_ rely on the PID of the client to track
- * them.
- * However, this has the side effect that if the client forks and the
- * parent exits, we loose them and restart the client. But this seems to
- * be the expected behavior so we implement it here.
- *
- * Unfortunately, epoll always polls for EPOLLHUP so as long as the
- * vhangup() is ongoing, we will _always_ get EPOLLHUP and cannot sleep.
- * This gets worse if the client closes the TTY but doesn't exit.
- * Therefore, the fd must be edge-triggered in the epoll-set so we
- * only get the events once they change.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/epoll.h>
-#include <sys/ioctl.h>
-#include <sys/uio.h>
-#include <sys/wait.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "barrier.h"
-#include "macro.h"
-#include "ring.h"
-#include "util.h"
-#include "signal-util.h"
-#include "pty.h"
-
-#define PTY_BUFSIZE 4096
-
-enum {
-        PTY_ROLE_UNKNOWN,
-        PTY_ROLE_PARENT,
-        PTY_ROLE_CHILD,
-};
-
-struct Pty {
-        unsigned long ref;
-        Barrier barrier;
-        int fd;
-        pid_t child;
-        sd_event_source *fd_source;
-        sd_event_source *child_source;
-
-        char in_buf[PTY_BUFSIZE];
-        Ring out_buf;
-
-        pty_event_t event_fn;
-        void *event_fn_userdata;
-
-        bool needs_requeue : 1;
-        unsigned int role : 2;
-};
-
-int pty_new(Pty **out) {
-        _pty_unref_ Pty *pty = NULL;
-        int r;
-
-        assert_return(out, -EINVAL);
-
-        pty = new0(Pty, 1);
-        if (!pty)
-                return -ENOMEM;
-
-        pty->ref = 1;
-        pty->fd = -1;
-        pty->barrier = (Barrier) BARRIER_NULL;
-
-        pty->fd = posix_openpt(O_RDWR | O_NOCTTY | O_CLOEXEC | O_NONBLOCK);
-        if (pty->fd < 0)
-                return -errno;
-
-        /*
-         * The slave-node is initialized to uid/gid of the caller of
-         * posix_openpt(). Only if devpts is mounted with fixed uid/gid this is
-         * skipped. In that case, grantpt() can overwrite these, but then you
-         * have to be root to use chown() (or a pt_chown helper has to be
-         * present). In those cases grantpt() really does something,
-         * otherwise it's a no-op. We call grantpt() here to try supporting
-         * those cases, even though no-one uses that, I guess. If you need other
-         * access-rights, set them yourself after this call returns (no, this is
-         * not racy, it looks racy, but races regarding your own UID are never
-         * important as an attacker could ptrace you; and the slave-pty is also
-         * still locked).
-         */
-        r = grantpt(pty->fd);
-        if (r < 0)
-                return -errno;
-
-        r = barrier_create(&pty->barrier);
-        if (r < 0)
-                return r;
-
-        *out = pty;
-        pty = NULL;
-        return 0;
-}
-
-Pty *pty_ref(Pty *pty) {
-        if (!pty || pty->ref < 1)
-                return NULL;
-
-        ++pty->ref;
-        return pty;
-}
-
-Pty *pty_unref(Pty *pty) {
-        if (!pty || pty->ref < 1 || --pty->ref > 0)
-                return NULL;
-
-        pty_close(pty);
-        pty->child_source = sd_event_source_unref(pty->child_source);
-        barrier_destroy(&pty->barrier);
-        ring_clear(&pty->out_buf);
-        free(pty);
-
-        return NULL;
-}
-
-Barrier *pty_get_barrier(Pty *pty) {
-        assert(pty);
-        return &pty->barrier;
-}
-
-bool pty_is_unknown(Pty *pty) {
-        return pty && pty->role == PTY_ROLE_UNKNOWN;
-}
-
-bool pty_is_parent(Pty *pty) {
-        return pty && pty->role == PTY_ROLE_PARENT;
-}
-
-bool pty_is_child(Pty *pty) {
-        return pty && pty->role == PTY_ROLE_CHILD;
-}
-
-bool pty_has_child(Pty *pty) {
-        return pty_is_parent(pty) && pty->child > 0;
-}
-
-pid_t pty_get_child(Pty *pty) {
-        return pty_has_child(pty) ? pty->child : -ECHILD;
-}
-
-bool pty_is_open(Pty *pty) {
-        return pty && pty->fd >= 0;
-}
-
-int pty_get_fd(Pty *pty) {
-        assert_return(pty, -EINVAL);
-
-        return pty_is_open(pty) ? pty->fd : -EPIPE;
-}
-
-int pty_make_child(Pty *pty) {
-        _cleanup_free_ char *slave_name = NULL;
-        int r, fd;
-
-        assert_return(pty, -EINVAL);
-        assert_return(pty_is_unknown(pty), -EALREADY);
-
-        r = ptsname_malloc(pty->fd, &slave_name);
-        if (r < 0)
-                return -errno;
-
-        fd = open(slave_name, O_RDWR | O_CLOEXEC | O_NOCTTY);
-        if (fd < 0)
-                return -errno;
-
-        safe_close(pty->fd);
-        pty->fd = fd;
-        pty->child = getpid();
-        pty->role = PTY_ROLE_CHILD;
-        barrier_set_role(&pty->barrier, BARRIER_CHILD);
-
-        return 0;
-}
-
-int pty_make_parent(Pty *pty, pid_t child) {
-        assert_return(pty, -EINVAL);
-        assert_return(pty_is_unknown(pty), -EALREADY);
-
-        pty->child = child;
-        pty->role = PTY_ROLE_PARENT;
-
-        return 0;
-}
-
-int pty_unlock(Pty *pty) {
-        assert_return(pty, -EINVAL);
-        assert_return(pty_is_unknown(pty) || pty_is_parent(pty), -EINVAL);
-        assert_return(pty_is_open(pty), -ENODEV);
-
-        return unlockpt(pty->fd) < 0 ? -errno : 0;
-}
-
-int pty_setup_child(Pty *pty) {
-        struct termios attr;
-        pid_t pid;
-        int r;
-
-        assert_return(pty, -EINVAL);
-        assert_return(pty_is_child(pty), -EINVAL);
-        assert_return(pty_is_open(pty), -EALREADY);
-
-        r = reset_signal_mask();
-        if (r < 0)
-                return r;
-
-        r = reset_all_signal_handlers();
-        if (r < 0)
-                return r;
-
-        pid = setsid();
-        if (pid < 0 && errno != EPERM)
-                return -errno;
-
-        r = ioctl(pty->fd, TIOCSCTTY, 0);
-        if (r < 0)
-                return -errno;
-
-        r = tcgetattr(pty->fd, &attr);
-        if (r < 0)
-                return -errno;
-
-        /* erase character should be normal backspace, PLEASEEE! */
-        attr.c_cc[VERASE] = 010;
-        /* always set UTF8 flag */
-        attr.c_iflag |= IUTF8;
-
-        r = tcsetattr(pty->fd, TCSANOW, &attr);
-        if (r < 0)
-                return -errno;
-
-        if (dup2(pty->fd, STDIN_FILENO) != STDIN_FILENO ||
-            dup2(pty->fd, STDOUT_FILENO) != STDOUT_FILENO ||
-            dup2(pty->fd, STDERR_FILENO) != STDERR_FILENO)
-                return -errno;
-
-        /* only close FD if it's not a std-fd */
-        pty->fd = (pty->fd > 2) ? safe_close(pty->fd) : -1;
-
-        return 0;
-}
-
-void pty_close(Pty *pty) {
-        if (!pty_is_open(pty))
-                return;
-
-        pty->fd_source = sd_event_source_unref(pty->fd_source);
-        pty->fd = safe_close(pty->fd);
-}
-
-/*
- * Drain input-queue and dispatch data via the event-handler. Returns <0 on
- * error, 0 if queue is empty and 1 if we couldn't empty the input queue fast
- * enough and there's still data left.
- */
-static int pty_dispatch_read(Pty *pty) {
-        unsigned int i;
-        ssize_t len;
-        int r;
-
-        /*
-         * We're edge-triggered, means we need to read the whole queue. This,
-         * however, might cause us to stall if the writer is faster than we
-         * are. Therefore, try reading as much as 8 times (32KiB) and only
-         * bail out then.
-         */
-
-        for (i = 0; i < 8; ++i) {
-                len = read(pty->fd, pty->in_buf, sizeof(pty->in_buf) - 1);
-                if (len < 0) {
-                        if (errno == EINTR)
-                                continue;
-
-                        return (errno == EAGAIN) ? 0 : -errno;
-                } else if (len == 0)
-                        continue;
-
-                /* set terminating zero for debugging safety */
-                pty->in_buf[len] = 0;
-                r = pty->event_fn(pty, pty->event_fn_userdata, PTY_DATA, pty->in_buf, len);
-                if (r < 0)
-                        return r;
-        }
-
-        /* still data left, make sure we're queued again */
-        pty->needs_requeue = true;
-
-        return 1;
-}
-
-/*
- * Drain output-queue by writing data to the pty. Returns <0 on error, 0 if the
- * output queue is empty now and 1 if we couldn't empty the output queue fast
- * enough and there's still data left.
- */
-static int pty_dispatch_write(Pty *pty) {
-        struct iovec vec[2];
-        unsigned int i;
-        ssize_t len;
-        size_t num;
-
-        /*
-         * Same as pty_dispatch_read(), we're edge-triggered so we need to call
-         * write() until either all data is written or it returns EAGAIN. We
-         * call it twice and if it still writes successfully, we reschedule.
-         */
-
-        for (i = 0; i < 2; ++i) {
-                num = ring_peek(&pty->out_buf, vec);
-                if (num < 1)
-                        return 0;
-
-                len = writev(pty->fd, vec, (int)num);
-                if (len < 0) {
-                        if (errno == EINTR)
-                                continue;
-
-                        return (errno == EAGAIN) ? 1 : -errno;
-                } else if (len == 0)
-                        continue;
-
-                ring_pull(&pty->out_buf, (size_t)len);
-        }
-
-        /* still data left, make sure we're queued again */
-        if (ring_get_size(&pty->out_buf) > 0) {
-                pty->needs_requeue = true;
-                return 1;
-        }
-
-        return 0;
-}
-
-static int pty_fd_fn(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
-        Pty *pty = userdata;
-        int r_hup = 0, r_write = 0, r_read = 0, r;
-
-        /*
-         * Whenever we encounter I/O errors, we have to make sure to drain the
-         * input queue first, before we handle any HUP. A child might send us
-         * a message and immediately close the queue. We must not handle the
-         * HUP first or we loose data.
-         * Therefore, if we read a message successfully, we always return
-         * success and wait for the next event-loop iteration. Furthermore,
-         * whenever there is a write-error, we must try reading from the input
-         * queue even if EPOLLIN is not set. The input might have arrived in
-         * between epoll_wait() and write(). Therefore, write-errors are only
-         * ever handled if the input-queue is empty. In all other cases they
-         * are ignored until either reading fails or the input queue is empty.
-         */
-
-        if (revents & (EPOLLHUP | EPOLLERR))
-                r_hup = -EPIPE;
-
-        if (revents & EPOLLOUT)
-                r_write = pty_dispatch_write(pty);
-
-        /* Awesome! Kernel signals HUP without IN but queues are not empty.. */
-        if ((revents & EPOLLIN) || r_hup < 0 || r_write < 0) {
-                r_read = pty_dispatch_read(pty);
-                if (r_read > 0)
-                        return 0; /* still data left to fetch next round */
-        }
-
-        if (r_hup < 0 || r_write < 0 || r_read < 0) {
-                /* PTY closed and input-queue drained */
-                pty_close(pty);
-                r = pty->event_fn(pty, pty->event_fn_userdata, PTY_HUP, NULL, 0);
-                if (r < 0)
-                        return r;
-        }
-
-        return 0;
-}
-
-static int pty_fd_prepare_fn(sd_event_source *source, void *userdata) {
-        Pty *pty = userdata;
-        int r;
-
-        if (pty->needs_requeue) {
-                /*
-                 * We're edge-triggered. In case we couldn't handle all events
-                 * or in case new write-data is queued, we set needs_requeue.
-                 * Before going asleep, we set the io-events *again*. sd-event
-                 * notices that we're edge-triggered and forwards the call to
-                 * the kernel even if the events didn't change. The kernel will
-                 * check the events and re-queue us on the ready queue in case
-                 * an event is pending.
-                 */
-                r = sd_event_source_set_io_events(source, EPOLLHUP | EPOLLERR | EPOLLIN | EPOLLOUT | EPOLLET);
-                if (r >= 0)
-                        pty->needs_requeue = false;
-        }
-
-        return 0;
-}
-
-static int pty_child_fn(sd_event_source *source, const siginfo_t *si, void *userdata) {
-        Pty *pty = userdata;
-        int r;
-
-        pty->child = 0;
-
-        r = pty->event_fn(pty, pty->event_fn_userdata, PTY_CHILD, si, sizeof(*si));
-        if (r < 0)
-                return r;
-
-        return 0;
-}
-
-int pty_attach_event(Pty *pty, sd_event *event, pty_event_t event_fn, void *event_fn_userdata) {
-        int r;
-
-        assert_return(pty, -EINVAL);
-        assert_return(event, -EINVAL);
-        assert_return(event_fn, -EINVAL);
-        assert_return(pty_is_parent(pty), -EINVAL);
-
-        pty_detach_event(pty);
-
-        if (pty_is_open(pty)) {
-                r = sd_event_add_io(event,
-                                    &pty->fd_source,
-                                    pty->fd,
-                                    EPOLLHUP | EPOLLERR | EPOLLIN | EPOLLOUT | EPOLLET,
-                                    pty_fd_fn,
-                                    pty);
-                if (r < 0)
-                        goto error;
-
-                r = sd_event_source_set_prepare(pty->fd_source, pty_fd_prepare_fn);
-                if (r < 0)
-                        goto error;
-        }
-
-        if (pty_has_child(pty)) {
-                r = sd_event_add_child(event,
-                                       &pty->child_source,
-                                       pty->child,
-                                       WEXITED,
-                                       pty_child_fn,
-                                       pty);
-                if (r < 0)
-                        goto error;
-        }
-
-        pty->event_fn = event_fn;
-        pty->event_fn_userdata = event_fn_userdata;
-
-        return 0;
-
-error:
-        pty_detach_event(pty);
-        return r;
-}
-
-void pty_detach_event(Pty *pty) {
-        if (!pty)
-                return;
-
-        pty->child_source = sd_event_source_unref(pty->child_source);
-        pty->fd_source = sd_event_source_unref(pty->fd_source);
-        pty->event_fn = NULL;
-        pty->event_fn_userdata = NULL;
-}
-
-int pty_write(Pty *pty, const void *buf, size_t size) {
-        bool was_empty;
-        int r;
-
-        assert_return(pty, -EINVAL);
-        assert_return(pty_is_open(pty), -ENODEV);
-        assert_return(pty_is_parent(pty), -ENODEV);
-
-        if (size < 1)
-                return 0;
-
-        /*
-         * Push @buf[0..@size] into the output ring-buffer. In case the
-         * ring-buffer wasn't empty beforehand, we're already waiting for
-         * EPOLLOUT and we're done. If it was empty, we have to re-queue the
-         * FD for EPOLLOUT as we're edge-triggered and wouldn't get any new
-         * EPOLLOUT event.
-         */
-
-        was_empty = ring_get_size(&pty->out_buf) < 1;
-
-        r = ring_push(&pty->out_buf, buf, size);
-        if (r < 0)
-                return r;
-
-        if (was_empty)
-                pty->needs_requeue = true;
-
-        return 0;
-}
-
-int pty_signal(Pty *pty, int sig) {
-        assert_return(pty, -EINVAL);
-        assert_return(pty_is_open(pty), -ENODEV);
-        assert_return(pty_is_parent(pty), -ENODEV);
-
-        return ioctl(pty->fd, TIOCSIG, sig) < 0 ? -errno : 0;
-}
-
-int pty_resize(Pty *pty, unsigned short term_width, unsigned short term_height) {
-        struct winsize ws = {
-                .ws_col = term_width,
-                .ws_row = term_height,
-        };
-
-        assert_return(pty, -EINVAL);
-        assert_return(pty_is_open(pty), -ENODEV);
-        assert_return(pty_is_parent(pty), -ENODEV);
-
-        /*
-         * This will send SIGWINCH to the pty slave foreground process group.
-         * We will also get one, but we don't need it.
-         */
-        return ioctl(pty->fd, TIOCSWINSZ, &ws) < 0 ? -errno : 0;
-}
-
-pid_t pty_fork(Pty **out, sd_event *event, pty_event_t event_fn, void *event_fn_userdata, unsigned short initial_term_width, unsigned short initial_term_height) {
-        _pty_unref_ Pty *pty = NULL;
-        int r;
-        pid_t pid;
-
-        assert_return(out, -EINVAL);
-        assert_return((event && event_fn) || (!event && !event_fn), -EINVAL);
-
-        r = pty_new(&pty);
-        if (r < 0)
-                return r;
-
-        r = pty_unlock(pty);
-        if (r < 0)
-                return r;
-
-        pid = fork();
-        if (pid < 0)
-                return -errno;
-
-        if (pid == 0) {
-                /* child */
-
-                r = pty_make_child(pty);
-                if (r < 0)
-                        _exit(-r);
-
-                r = pty_setup_child(pty);
-                if (r < 0)
-                        _exit(-r);
-
-                /* sync with parent */
-                if (!barrier_place_and_sync(&pty->barrier))
-                        _exit(1);
-
-                /* fallthrough and return the child's PTY object */
-        } else {
-                /* parent */
-
-                r = pty_make_parent(pty, pid);
-                if (r < 0)
-                        goto parent_error;
-
-                r = pty_resize(pty, initial_term_width, initial_term_height);
-                if (r < 0)
-                        goto parent_error;
-
-                if (event) {
-                        r = pty_attach_event(pty, event, event_fn, event_fn_userdata);
-                        if (r < 0)
-                                goto parent_error;
-                }
-
-                /* sync with child */
-                if (!barrier_place_and_sync(&pty->barrier)) {
-                        r = -ECHILD;
-                        goto parent_error;
-                }
-
-                /* fallthrough and return the parent's PTY object */
-        }
-
-        *out = pty;
-        pty = NULL;
-        return pid;
-
-parent_error:
-        barrier_abort(&pty->barrier);
-        waitpid(pty->child, NULL, 0);
-        pty->child = 0;
-        return r;
-}
diff --git a/src/shared/pty.h b/src/shared/pty.h
deleted file mode 100644 (file)
index 63c7db2..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-#include <unistd.h>
-
-#include "barrier.h"
-#include "macro.h"
-#include "sd-event.h"
-
-typedef struct Pty Pty;
-
-enum {
-        PTY_CHILD,
-        PTY_HUP,
-        PTY_DATA,
-};
-
-typedef int (*pty_event_t) (Pty *pty, void *userdata, unsigned int event, const void *ptr, size_t size);
-
-int pty_new(Pty **out);
-Pty *pty_ref(Pty *pty);
-Pty *pty_unref(Pty *pty);
-
-#define _pty_unref_ _cleanup_(pty_unrefp)
-DEFINE_TRIVIAL_CLEANUP_FUNC(Pty*, pty_unref);
-
-Barrier *pty_get_barrier(Pty *pty);
-
-bool pty_is_unknown(Pty *pty);
-bool pty_is_parent(Pty *pty);
-bool pty_is_child(Pty *pty);
-bool pty_has_child(Pty *pty);
-pid_t pty_get_child(Pty *pty);
-
-bool pty_is_open(Pty *pty);
-int pty_get_fd(Pty *pty);
-
-int pty_make_child(Pty *pty);
-int pty_make_parent(Pty *pty, pid_t child);
-int pty_unlock(Pty *pty);
-int pty_setup_child(Pty *pty);
-void pty_close(Pty *pty);
-
-int pty_attach_event(Pty *pty, sd_event *event, pty_event_t event_fn, void *event_fn_userdata);
-void pty_detach_event(Pty *pty);
-
-int pty_write(Pty *pty, const void *buf, size_t size);
-int pty_signal(Pty *pty, int sig);
-int pty_resize(Pty *pty, unsigned short term_width, unsigned short term_height);
-
-pid_t pty_fork(Pty **out, sd_event *event, pty_event_t event_fn, void *event_fn_userdata, unsigned short initial_term_width, unsigned short initial_term_height);
diff --git a/src/test/test-pty.c b/src/test/test-pty.c
deleted file mode 100644 (file)
index fbab3d4..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <locale.h>
-#include <string.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "pty.h"
-#include "util.h"
-#include "signal-util.h"
-
-static const char sndmsg[] = "message\n";
-static const char rcvmsg[] = "message\r\n";
-static char rcvbuf[128];
-static size_t rcvsiz = 0;
-static sd_event *event;
-
-static void run_child(Pty *pty) {
-        ssize_t r, l;
-        char buf[512];
-
-        r = read(0, buf, sizeof(buf));
-        assert_se((size_t)r == strlen(sndmsg));
-        assert_se(!strncmp(buf, sndmsg, r));
-
-        l = write(1, buf, r);
-        assert_se(l == r);
-}
-
-static int pty_fn(Pty *pty, void *userdata, unsigned int ev, const void *ptr, size_t size) {
-        switch (ev) {
-        case PTY_DATA:
-                assert_se(rcvsiz < strlen(rcvmsg) * 2);
-                assert_se(rcvsiz + size < sizeof(rcvbuf));
-
-                memcpy(&rcvbuf[rcvsiz], ptr, size);
-                rcvsiz += size;
-
-                if (rcvsiz >= strlen(rcvmsg) * 2) {
-                        assert_se(rcvsiz == strlen(rcvmsg) * 2);
-                        assert_se(!memcmp(rcvbuf, rcvmsg, strlen(rcvmsg)));
-                        assert_se(!memcmp(&rcvbuf[strlen(rcvmsg)], rcvmsg, strlen(rcvmsg)));
-                }
-
-                break;
-        case PTY_HUP:
-                /* This is guaranteed to appear _after_ the input queues are
-                 * drained! */
-                assert_se(rcvsiz == strlen(rcvmsg) * 2);
-                break;
-        case PTY_CHILD:
-                /* this may appear at any time */
-                break;
-        default:
-                assert_se(0);
-                break;
-        }
-
-        /* if we got HUP _and_ CHILD, exit */
-        if (pty_get_fd(pty) < 0 && pty_get_child(pty) < 0)
-                sd_event_exit(event, 0);
-
-        return 0;
-}
-
-static void run_parent(Pty *pty) {
-        int r;
-
-        /* write message to pty, ECHO mode guarantees that we get it back
-         * twice: once via ECHO, once from the run_child() fn */
-        assert_se(pty_write(pty, sndmsg, strlen(sndmsg)) >= 0);
-
-        r = sd_event_loop(event);
-        assert_se(r >= 0);
-}
-
-static void test_pty(void) {
-        pid_t pid;
-        Pty *pty = NULL;
-
-        rcvsiz = 0;
-        zero(rcvbuf);
-
-        assert_se(sd_event_default(&event) >= 0);
-
-        pid = pty_fork(&pty, event, pty_fn, NULL, 80, 25);
-        assert_se(pid >= 0);
-
-        if (pid == 0) {
-                /* child */
-                run_child(pty);
-                exit(0);
-        }
-
-        /* parent */
-        run_parent(pty);
-
-        /* Make sure the PTY recycled the child; yeah, this is racy if the
-         * PID was already reused; but that seems fine for a test. */
-        assert_se(waitpid(pid, NULL, WNOHANG) < 0 && errno == ECHILD);
-
-        pty_unref(pty);
-        sd_event_unref(event);
-}
-
-int main(int argc, char *argv[]) {
-        unsigned int i;
-
-        log_parse_environment();
-        log_open();
-
-        assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
-
-        /* Oh, there're ugly races in the TTY layer regarding HUP vs IN. Turns
-         * out they appear only 10% of the time. I fixed all of them and
-         * don't see them, anymore. But let's be safe and run this 1000 times
-         * so we catch any new ones, in case they appear again. */
-        for (i = 0; i < 1000; ++i)
-                test_pty();
-
-        return 0;
-}
diff --git a/src/test/test-ring.c b/src/test/test-ring.c
deleted file mode 100644 (file)
index cb8a5d4..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <string.h>
-
-#include "def.h"
-#include "ring.h"
-
-static void test_ring(void) {
-        static const char buf[8192];
-        Ring r;
-        size_t l;
-        struct iovec vec[2];
-        int s;
-
-        zero(r);
-
-        l = ring_peek(&r, vec);
-        assert_se(l == 0);
-
-        s = ring_push(&r, buf, 2048);
-        assert_se(!s);
-        assert_se(ring_get_size(&r) == 2048);
-
-        l = ring_peek(&r, vec);
-        assert_se(l == 1);
-        assert_se(vec[0].iov_len == 2048);
-        assert_se(!memcmp(vec[0].iov_base, buf, vec[0].iov_len));
-        assert_se(ring_get_size(&r) == 2048);
-
-        ring_pull(&r, 2048);
-        assert_se(ring_get_size(&r) == 0);
-
-        l = ring_peek(&r, vec);
-        assert_se(l == 0);
-        assert_se(ring_get_size(&r) == 0);
-
-        s = ring_push(&r, buf, 2048);
-        assert_se(!s);
-        assert_se(ring_get_size(&r) == 2048);
-
-        l = ring_peek(&r, vec);
-        assert_se(l == 1);
-        assert_se(vec[0].iov_len == 2048);
-        assert_se(!memcmp(vec[0].iov_base, buf, vec[0].iov_len));
-        assert_se(ring_get_size(&r) == 2048);
-
-        s = ring_push(&r, buf, 1);
-        assert_se(!s);
-        assert_se(ring_get_size(&r) == 2049);
-
-        l = ring_peek(&r, vec);
-        assert_se(l == 2);
-        assert_se(vec[0].iov_len == 2048);
-        assert_se(vec[1].iov_len == 1);
-        assert_se(!memcmp(vec[0].iov_base, buf, vec[0].iov_len));
-        assert_se(!memcmp(vec[1].iov_base, buf, vec[1].iov_len));
-        assert_se(ring_get_size(&r) == 2049);
-
-        ring_pull(&r, 2048);
-        assert_se(ring_get_size(&r) == 1);
-
-        l = ring_peek(&r, vec);
-        assert_se(l == 1);
-        assert_se(vec[0].iov_len == 1);
-        assert_se(!memcmp(vec[0].iov_base, buf, vec[0].iov_len));
-        assert_se(ring_get_size(&r) == 1);
-
-        ring_pull(&r, 1);
-        assert_se(ring_get_size(&r) == 0);
-
-        s = ring_push(&r, buf, 2048);
-        assert_se(!s);
-        assert_se(ring_get_size(&r) == 2048);
-
-        s = ring_push(&r, buf, 2049);
-        assert_se(!s);
-        assert_se(ring_get_size(&r) == 4097);
-
-        l = ring_peek(&r, vec);
-        assert_se(l == 1);
-        assert_se(vec[0].iov_len == 4097);
-        assert_se(!memcmp(vec[0].iov_base, buf, vec[0].iov_len));
-        assert_se(ring_get_size(&r) == 4097);
-
-        ring_pull(&r, 1);
-        assert_se(ring_get_size(&r) == 4096);
-
-        s = ring_push(&r, buf, 4096);
-        assert_se(!s);
-        assert_se(ring_get_size(&r) == 8192);
-
-        l = ring_peek(&r, vec);
-        assert_se(l == 2);
-        assert_se(vec[0].iov_len == 8191);
-        assert_se(vec[1].iov_len == 1);
-        assert_se(!memcmp(vec[0].iov_base, buf, vec[0].iov_len));
-        assert_se(!memcmp(vec[1].iov_base, buf, vec[1].iov_len));
-        assert_se(ring_get_size(&r) == 8192);
-
-        ring_clear(&r);
-        assert_se(ring_get_size(&r) == 0);
-}
-
-int main(int argc, char *argv[]) {
-        log_parse_environment();
-        log_open();
-
-        test_ring();
-
-        return 0;
-}