summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/ldattach/Makefile4
-rw-r--r--sbin/ldattach/atomicio.c130
-rw-r--r--sbin/ldattach/atomicio.h45
-rw-r--r--sbin/ldattach/ldattach.814
-rw-r--r--sbin/ldattach/ldattach.c102
5 files changed, 277 insertions, 18 deletions
diff --git a/sbin/ldattach/Makefile b/sbin/ldattach/Makefile
index 58d57e4925b..0b1225111df 100644
--- a/sbin/ldattach/Makefile
+++ b/sbin/ldattach/Makefile
@@ -1,9 +1,11 @@
-# $OpenBSD: Makefile,v 1.1.1.1 2007/11/03 15:22:54 mbalmer Exp $
+# $OpenBSD: Makefile,v 1.2 2008/06/09 21:06:10 mbalmer Exp $
PROG= ldattach
+SRCS= ldattach.c atomicio.c
MAN= ldattach.8
CFLAGS+= -Wall -Werror
+LDADD+= -lutil
BINDIR= /sbin
diff --git a/sbin/ldattach/atomicio.c b/sbin/ldattach/atomicio.c
new file mode 100644
index 00000000000..5adb7fd0597
--- /dev/null
+++ b/sbin/ldattach/atomicio.c
@@ -0,0 +1,130 @@
+/* $OpenBSD: atomicio.c,v 1.1 2008/06/09 21:06:10 mbalmer Exp $ */
+/*
+ * Copyright (c) 2006 Damien Miller. All rights reserved.
+ * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
+ * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 <sys/param.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <poll.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "atomicio.h"
+
+/*
+ * ensure all of data on socket comes through. f==read || f==vwrite
+ */
+size_t
+atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
+{
+ char *s = _s;
+ size_t pos = 0;
+ ssize_t res;
+ struct pollfd pfd;
+
+ pfd.fd = fd;
+ pfd.events = f == read ? POLLIN : POLLOUT;
+ while (n > pos) {
+ res = (f) (fd, s + pos, n - pos);
+ switch (res) {
+ case -1:
+ if (errno == EINTR)
+ continue;
+ if (errno == EAGAIN) {
+ (void)poll(&pfd, 1, -1);
+ continue;
+ }
+ return 0;
+ case 0:
+ errno = EPIPE;
+ return pos;
+ default:
+ pos += (size_t)res;
+ }
+ }
+ return (pos);
+}
+
+/*
+ * ensure all of data on socket comes through. f==readv || f==writev
+ */
+size_t
+atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
+ const struct iovec *_iov, int iovcnt)
+{
+ size_t pos = 0, rem;
+ ssize_t res;
+ struct iovec iov_array[IOV_MAX], *iov = iov_array;
+ struct pollfd pfd;
+
+ if (iovcnt > IOV_MAX) {
+ errno = EINVAL;
+ return 0;
+ }
+ /* Make a copy of the iov array because we may modify it below */
+ memcpy(iov, _iov, iovcnt * sizeof(*_iov));
+
+ pfd.fd = fd;
+ pfd.events = f == readv ? POLLIN : POLLOUT;
+ for (; iovcnt > 0 && iov[0].iov_len > 0;) {
+ res = (f) (fd, iov, iovcnt);
+ switch (res) {
+ case -1:
+ if (errno == EINTR)
+ continue;
+ if (errno == EAGAIN) {
+ (void)poll(&pfd, 1, -1);
+ continue;
+ }
+ return 0;
+ case 0:
+ errno = EPIPE;
+ return pos;
+ default:
+ rem = (size_t)res;
+ pos += rem;
+ /* skip completed iov entries */
+ while (iovcnt > 0 && rem >= iov[0].iov_len) {
+ rem -= iov[0].iov_len;
+ iov++;
+ iovcnt--;
+ }
+ /* This shouldn't happen... */
+ if (rem > 0 && (iovcnt <= 0 || rem > iov[0].iov_len)) {
+ errno = EFAULT;
+ return 0;
+ }
+ if (iovcnt == 0)
+ break;
+ /* update pointer in partially complete iov */
+ iov[0].iov_base = ((char *)iov[0].iov_base) + rem;
+ iov[0].iov_len -= rem;
+ }
+ }
+ return pos;
+}
diff --git a/sbin/ldattach/atomicio.h b/sbin/ldattach/atomicio.h
new file mode 100644
index 00000000000..3ff368a2cd0
--- /dev/null
+++ b/sbin/ldattach/atomicio.h
@@ -0,0 +1,45 @@
+/* $OpenBSD: atomicio.h,v 1.1 2008/06/09 21:06:10 mbalmer Exp $ */
+
+/*
+ * Copyright (c) 2006 Damien Miller. All rights reserved.
+ * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ */
+
+#ifndef _ATOMICIO_H
+#define _ATOMICIO_H
+
+/*
+ * Ensure all of data on socket comes through. f==read || f==vwrite
+ */
+size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
+
+#define vwrite (ssize_t (*)(int, void *, size_t))write
+
+/*
+ * ensure all of data on socket comes through. f==readv || f==writev
+ */
+size_t atomiciov(ssize_t (*)(int, const struct iovec *, int),
+ int, const struct iovec *, int);
+
+#endif /* _ATOMICIO_H */
diff --git a/sbin/ldattach/ldattach.8 b/sbin/ldattach/ldattach.8
index 4b784ed7bf6..478646738a8 100644
--- a/sbin/ldattach/ldattach.8
+++ b/sbin/ldattach/ldattach.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ldattach.8,v 1.10 2008/02/28 11:22:12 mbalmer Exp $
+.\" $OpenBSD: ldattach.8,v 1.11 2008/06/09 21:06:10 mbalmer Exp $
.\"
.\" Copyright (c) 2007, 2008 Marc Balmer <mbalmer@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: February 28 2008 $
+.Dd $Mdocdate: June 9 2008 $
.Dt LDATTACH 8
.Os
.Sh NAME
@@ -22,7 +22,7 @@
.Nd attach a line discipline to a serial line
.Sh SYNOPSIS
.Nm ldattach
-.Op Fl 27dehmo
+.Op Fl 27dehmop
.Op Fl s Ar baudrate
.Op Fl t Ar cond
.Ar discipline
@@ -59,6 +59,13 @@ Maintain modem control signals after closing the line.
Specifically, this disables HUPCL.
.It Fl o
Use odd parity.
+.It Fl p
+Pass the data received from
+.Ar device
+to the master device of a
+.Xr pty 4
+pair and vice versa.
+The name of the slave device is written to standard output.
.It Fl s Ar baudrate
Specifies the speed of the connection.
If not specified, the default of 9600 baud is used
@@ -153,6 +160,7 @@ tty01 "/sbin/ldattach nmea" unknown on softcar
.Sh SEE ALSO
.Xr msts 4 ,
.Xr nmea 4 ,
+.Xr pty 4 ,
.Xr sl 4 ,
.Xr tty 4 ,
.Xr ttys 5 ,
diff --git a/sbin/ldattach/ldattach.c b/sbin/ldattach/ldattach.c
index db3549e1a1e..32389611237 100644
--- a/sbin/ldattach/ldattach.c
+++ b/sbin/ldattach/ldattach.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldattach.c,v 1.5 2008/02/28 11:22:12 mbalmer Exp $ */
+/* $OpenBSD: ldattach.c,v 1.6 2008/06/09 21:06:10 mbalmer Exp $ */
/*
* Copyright (c) 2007, 2008 Marc Balmer <mbalmer@openbsd.org>
@@ -21,14 +21,18 @@
* the commandline or from init(8) (using entries in /etc/ttys).
*/
+#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/limits.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/ttycom.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
+#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -36,8 +40,12 @@
#include <syslog.h>
#include <termios.h>
#include <unistd.h>
+#include <util.h>
+
+#include "atomicio.h"
__dead void usage(void);
+void relay(int, int);
void coroner(int);
volatile sig_atomic_t dying = 0;
@@ -47,11 +55,53 @@ usage(void)
{
extern char *__progname;
- fprintf(stderr, "usage: %s [-27dehmo] [-s baudrate] "
+ fprintf(stderr, "usage: %s [-27dehmop] [-s baudrate] "
"[-t cond] discipline device\n", __progname);
exit(1);
}
+/* relay data between two file descriptors */
+void
+relay(int device, int pty)
+{
+ struct pollfd pfd[2];
+ int nfds, n, nread;
+ char buf[128];
+
+ pfd[0].fd = device;
+ pfd[0].events = POLLRDNORM;
+ pfd[1].fd = pty;
+ pfd[1].events = POLLRDNORM;
+
+ while (!dying) {
+ nfds = poll(pfd, 2, INFTIM);
+ if (nfds == -1) {
+ syslog(LOG_ERR, "polling error");
+ exit(1);
+ }
+ if (nfds == 0)
+ continue;
+
+ for (n = 0; n < 2; n++) {
+ if (!(pfd[n].revents & POLLRDNORM))
+ continue;
+
+ nread = read(pfd[n].fd, buf, sizeof(buf));
+ if (nread == -1) {
+ syslog(LOG_ERR, "error reading from %s: %m",
+ n ? "pty" : "device");
+ exit(1);
+ }
+ if (nread == 0) {
+ syslog(LOG_ERR, "eof during read from %s: %m",
+ n ? "pty" : "device");
+ exit(1);
+ }
+ atomicio(vwrite, pfd[1 - n].fd, buf, nread);
+ }
+ }
+}
+
int
main(int argc, char *argv[])
{
@@ -60,17 +110,17 @@ main(int argc, char *argv[])
const char *errstr;
sigset_t sigset;
pid_t ppid;
- int ch, fd, ldisc, nodaemon = 0;
- int bits = 0, parity = 0, stop = 0, flowcl = 0, hupcl = 1;
+ int ch, fd, master = -1, slave, pty = 0, ldisc, nodaemon = 0;
+ int bits = 0, parity = 0, stop = 0, flowcl = 0, hupcl = 1;
speed_t speed = 0;
- char devn[32], *dev, *disc;
+ char devn[32], ptyn[32], *dev, *disc;
tstamps.ts_set = tstamps.ts_clr = 0;
if ((ppid = getppid()) == 1)
nodaemon = 1;
- while ((ch = getopt(argc, argv, "27dehmos:t:")) != -1) {
+ while ((ch = getopt(argc, argv, "27dehmops:t:")) != -1) {
switch (ch) {
case '2':
stop = 2;
@@ -93,6 +143,9 @@ main(int argc, char *argv[])
case 'o':
parity = 'o';
break;
+ case 'p':
+ pty = 1;
+ break;
case 's':
speed = (speed_t)strtonum(optarg, 0, UINT_MAX, &errstr);
if (errstr) {
@@ -134,8 +187,7 @@ main(int argc, char *argv[])
disc = *argv++;
dev = *argv;
if (strncmp(_PATH_DEV, dev, sizeof(_PATH_DEV) - 1)) {
- (void)snprintf(devn, sizeof(devn),
- "%s%s", _PATH_DEV, dev);
+ (void)snprintf(devn, sizeof(devn), "%s%s", _PATH_DEV, dev);
dev = devn;
}
@@ -204,7 +256,7 @@ main(int argc, char *argv[])
if (ioctl(fd, TIOCSDTR, 0) < 0)
warn("TIOCSDTR");
if (ioctl(fd, TIOCSETD, &ldisc) < 0) {
- syslog(LOG_ERR, "can't set the %s line discipline on %s", disc,
+ syslog(LOG_ERR, "can't attach %s line discipline on %s", disc,
dev);
goto bail_out;
}
@@ -233,16 +285,38 @@ main(int argc, char *argv[])
goto bail_out;
}
- if (!nodaemon && daemon(0, 0))
- errx(1, "can't daemonize");
+ /*
+ * open a pty(4) pair to pass the data if the -p option has been
+ * given on the commandline.
+ */
+ if (pty) {
+ if (openpty(&master, &slave, ptyn, NULL, NULL))
+ errx(1, "can't open a pty");
+ close(slave);
+ printf("%s\n", ptyn);
+ }
+ if (nodaemon)
+ openlog("ldattach", LOG_PID | LOG_CONS | LOG_PERROR,
+ LOG_DAEMON);
+ else {
+ openlog("ldattach", LOG_PID | LOG_CONS, LOG_DAEMON);
+ if (daemon(0, 0))
+ errx(1, "can't daemonize");
+ }
syslog(LOG_INFO, "attach %s on %s", disc, dev);
signal(SIGHUP, coroner);
signal(SIGTERM, coroner);
- sigemptyset(&sigset);
- while (!dying)
- sigsuspend(&sigset);
+ if (master != -1) {
+ syslog(LOG_INFO, "passing data to %s", ptyn);
+ relay(fd, master);
+ } else {
+ sigemptyset(&sigset);
+
+ while (!dying)
+ sigsuspend(&sigset);
+ }
bail_out:
if (ppid == 1)