Unix Technical Forum

ldattach(8), a better utility to attach line disciplines to a tty

This is a discussion on ldattach(8), a better utility to attach line disciplines to a tty within the mailing.openbsd.tech forums, part of the OpenBSD category; --> ldatttach(8) is meant as a replacement for slattach(8) and nmeaattach(8). It is a complete rewrite and provides the functionality ...


Go Back   Unix Technical Forum > Unix Operating Systems > OpenBSD > mailing.openbsd.tech

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-18-2008, 09:33 AM
Marc Balmer
 
Posts: n/a
Default ldattach(8), a better utility to attach line disciplines to a tty

ldatttach(8) is meant as a replacement for slattach(8) and
nmeaattach(8). It is a complete rewrite and provides the functionality
of the former two tools in one single executable and can easily be
extended to support more (e.g. newly developed) line disciplines.

For a line discipline to be in effect, a userland application must open
a tty device, e.g. /dev/cua00, then set the line discipline using an
ioctl(2) call _and_ then the utility must keep running.

Whereas the two old attachment programs are meant to be started from
/etc/rc, ldattach(8) is a bit different (and better): The line
discipline to be attached is specified on the command line, along with
the device name and any options. This allows ldattach(8) to interact
with init(8) and thus have line disciplines attached in /etc/ttys.

An example:

Assume you want to attach a UPS GPS receiver as a time source for
nmea(4) as the first USB tty device (and as this is a hotplug device
/dev/cuaU0 mnd /dev/ttyU0 may even not be configured at system startup
time. But this is no problem as you will see). To /etc/tty we add a
line like:

ttyU0 "/sbin/ldattach nmea" unknown on

and signal the running init process with a SIGHUP.

init(8) will now start the ldattach(8) utility on the specified USB TTY.
If our GPS unit is not yet plugged in, ldattach(8) will of course not be
able to attach the line discipline. _BUT_ ldattach(8) knows that it has
been started by init(8) and instead of immediately exiting, it will
sleep for 30 seconds. After 30 seconds, it terminates and will be
restarted by init(8). This goes on and on until you finally plug in the
USB GPS receiver, the nmea(4) line discipline will be attached within
30 seconds and moments later, a timedelta sensor will appear in the sensor
list. Since ldattach(8) mostly sleeps when the device is not there,
this does not consume mcuh ressources.

And if ntpd(8) has been configured to use timedelte sensors, it will
pick up the time information now.

Of course ldattach(8) can still be called from the command line or from
scripts like /etc/rc, but then the 30 seconds exit delay will of course
not happen.

I appreciate any feedback and comments on this.


--- /dev/null Sat Oct 13 14:48:08 2007
+++ sbin/ldattach/Makefile Sat Oct 13 14:37:18 2007
@@ -0,0 +1,8 @@
+# $OpenBSD: Makefile,v 1.1 2006/07/04 05:31:54 mbalmer Exp $
+
+PROG= ldattach
+MAN= ldattach.8
+
+BINDIR= /sbin
+
+.include <bsd.prog.mk>
--- /dev/null Sat Oct 13 14:48:08 2007
+++ sbin/ldattach/ldattach.c Sat Oct 13 14:41:55 2007
@@ -0,0 +1,192 @@
+/* $OpenBSD */
+
+/*
+ * Copyright (c) 2007 Marc Balmer <mbalmer@openbsd.org>
+ *
+ * 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.
+ */
+
+/*
+ * A replacement for slattach(8) and nmeaattach(8) that can be used from
+ * the commandline or from init(8) (using entries in /etc/ttys).
+ */
+
+#include <sys/ioctl.h>
+#include <sys/ttycom.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <termios.h>
+#include <unistd.h>
+
+__dead void usage(void);
+void coroner(int);
+
+volatile sig_atomic_t dying = 0;
+
+__dead void
+usage(void)
+{
+ extern char *__progname;
+
+ fprintf(stderr, "usage: %s [-dhm] [-s baudrate] [-t cond] discipline "
+ "device\n", __progname);
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct termios tty;
+ struct tstamps tstamps;
+ const char *errstr;
+ tcflag_t cflag = HUPCL;
+ sigset_t sigset;
+ pid_t ppid;
+ int ch, fd, ldisc, nodaemon = 0, speed = B4800;
+ char devname[32], *dev, *disc;
+
+ tstamps.ts_set = tstamps.ts_clr = 0;
+
+ if ((ppid = getppid()) == 1)
+ nodaemon = 1;
+
+ while ((ch = getopt(argc, argv, "dhms:t:")) != -1) {
+ switch (ch) {
+ case 'd':
+ nodaemon = 1;
+ break;
+ case 'h':
+ cflag |= CRTSCTS;
+ break;
+ case 'm':
+ cflag &= ~HUPCL;
+ break;
+ case 's':
+ speed = (int)strtonum(optarg, 50, 230400, &errstr);
+ if (errstr) {
+ if (ppid != 1)
+ errx(1, "speed is %s: %s", errstr,
+ optarg);
+ else
+ goto bail_out;
+ }
+ break;
+ case 't':
+ if (!strcasecmp(optarg, "dcd"))
+ tstamps.ts_set |= TIOCM_CAR;
+ else if (!strcasecmp(optarg, "!dcd"))
+ tstamps.ts_clr |= TIOCM_CAR;
+ else if (!strcasecmp(optarg, "cts"))
+ tstamps.ts_set |= TIOCM_CTS;
+ else if (!strcasecmp(optarg, "!cts"))
+ tstamps.ts_clr |= TIOCM_CTS;
+ else {
+ if (ppid != 1)
+ errx(1, "'%s' not supported for "
+ "timestamping", optarg);
+ else
+ goto bail_out;
+ }
+ break;
+ default:
+ if (ppid != -1)
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (ppid != 1 && argc != 2)
+ usage();
+
+ disc = *argv++;
+ dev = *argv;
+ if (strncmp(_PATH_DEV, dev, sizeof(_PATH_DEV) - 1)) {
+ (void)snprintf(devname, sizeof(devname),
+ "%s%s", _PATH_DEV, dev);
+ dev = devname;
+ }
+ syslog(LOG_INFO, "attach %s on %s", disc, dev);
+ if ((fd = open(dev, O_RDWR)) < 0)
+ goto bail_out;
+
+ if (!strcmp(disc, "slip"))
+ ldisc = SLIPDISC;
+ else if (!strcmp(disc, "nmea"))
+ ldisc = NMEADISC;
+ else {
+ syslog(LOG_ERR, "unknown line discipline %s", disc);
+ goto bail_out;
+ }
+
+ tty.c_cflag = CREAD | CS8 | cflag;
+ tty.c_iflag = 0;
+ tty.c_lflag = 0;
+ tty.c_oflag = 0;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VTIME] = 0;
+ cfsetspeed(&tty, speed);
+ if (tcsetattr(fd, TCSADRAIN, &tty) < 0) {
+ if (ppid != 1)
+ warnx("tcsetattr");
+ goto bail_out;
+ }
+
+ /* setup common to all line disciplines */
+ 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,
+ dev);
+ goto bail_out;
+ }
+
+ /* line discpline sepcific setup */
+ switch (ldisc) {
+ case NMEADISC:
+ if (ioctl(fd, TIOCSTSTAMP, &tstamps) < 0) {
+ warnx("TIOCSTSTAMP");
+ goto bail_out;
+ }
+ break;
+ }
+
+ if (!nodaemon && daemon(0, 0))
+ errx(1, "can't daemonize");
+
+ signal(SIGHUP, coroner);
+ signal(SIGTERM, coroner);
+
+ sigemptyset(&sigset);
+ while (!dying)
+ sigsuspend(&sigset);
+
+bail_out:
+ if (ppid == 1)
+ sleep(30); /* delay restart when called from init */
+}
+
+/* ARGSUSED */
+void
+coroner(int useless)
+{
+ dying = 1;
+}
--- /dev/null Sat Oct 13 14:48:08 2007
+++ sbin/ldattach/ldattach.8 Sat Oct 13 14:48:02 2007
@@ -0,0 +1,134 @@
+.\" $OpenBSD$
+.\"
+.\" Copyright (c) 2007 Marc Balmer <mbalmer@openbsd.org>
+.\"
+.\" 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.
+.\"
+.Dd May 31, 2007
+.Dt LDATTACH 8
+.Os
+.Sh NAME
+.Nm ldattach
+.Nd attach a line discipline to a serial line
+.Sh SYNOPSIS
+.Nm ldattach
+.Op Fl dhm
+.Op Fl s Ar baudrate
+.Op Fl t Ar cond
+.Ar discipline
+.Ar device
+.Sh DESCRIPTION
+.Nm
+is used to attach a line discipline to a serial line to allow for in-kernel
+processing of the received and/or sent data.
+Depending on the line discipline being attached, one or more otions may be
+applied.
+.Pp
+.Nm
+can be used in
+.Dq /etc/ttys
+entries to attach line disciplines at system startup time by having
+.Xr init 8
+start
+.Nm
+on the designated interface.
+.Pp
+The following operands are supported by
+.Nm ldattach :
+.Bl -tag -width Ar
+.It Fl d
+Do not daemonize.
+.It Fl h
+Turn on RTS/CTS flow control.
+By default, no flow control is done.
+.It Fl m
+Maintain modem control signals after closing the line.
+Specifically, this disables HUPCL.
+.It Fl s Ar baudrate
+Specifies the speed of the connection.
+If not specified, the default of 4800 baud is used.
+.It Fl t Ar cond
+.Xr nmea 4
+line discipline only.
+Chooses the condition which will cause the current system time to be
+immediately copied to the terminal timestamp storage for subsequent use by
+.Xr nmea 4 .
+Only one can be used.
+.Pp
+.Bl -tag -width DCDXX -offset indent -compact
+.It dcd
+Copy the timestamp when DCD is asserted.
+.It !dcd
+Copy the timestamp when DCD is deasserted.
+.It cts
+Copy the timestamp when CTS is asserted.
+.It !cts
+Copy the timestamp when CTS is deasserted.
+.El
+.Pp
+If no condition is specified, the
+.Xr nmea 4
+line discipline will timestamp on receiving the leading
+.Sq $
+character of each block of NMEA sentences.
+.It Ar discipline
+Specifies the name of the line discipline to be attached.
+.Pp
+.Bl -tag -width nmeaXX -offset -indet -compact
+.It nmea
+Attach the
+.Xr nmea 4
+line discipline.
+.It slip
+Attach the
+.Xr sl 4
+line discipline.
+.El
+.It Ar device
+Specifies the name of the serial line.
+.Ar device
+should be a string of the form
+.Dq cuaXX ,
+or
+.Dq /dev/cuaXX .
+.El
+.Pp
+If
+.Nm
+was not started by
+.Xr init 8
+you can kill off the
+.Nm
+process to detach the line discipline.
+.Sh EXAMPLES
+To start
+.Nm
+by
+.Xr init 8
+to attach the
+.Xr nmea 4
+line discipline to
+.Dq /dev/cuaU0
+add a line of the following form to
+.Dq /etc/ttys :
+.Pp
+cuaU0 "/sbin/ldattach nmea" unknown on
+.Sh SEE ALSO
+.Xr nmea 4 ,
+.Xr sl 4 ,
+.Xr tty 4
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Ox 4.3 .

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 08:53 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com