diff options
author | Lennart Poettering <lennart@poettering.net> | 2004-01-14 21:51:32 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2004-01-14 21:51:32 +0000 |
commit | 2187fc7c62ffad7cb514d061899d57cfd95438dc (patch) | |
tree | 417667f8ef1175f703d6b86f73bdd9094187d51e | |
parent | 973391053d38096aa05933a61885c67cc07adbe6 (diff) |
Add UUCP locking
Add documentation
git-svn-id: file:///home/lennart/svn/public/bidilink/trunk@7 9cde1c1d-e4d0-0310-8a68-bf217395ea82
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | doc/Makefile.am | 36 | ||||
-rw-r--r-- | doc/README.html.in | 139 | ||||
-rw-r--r-- | doc/style.css | 32 | ||||
-rw-r--r-- | src/client-tty.c | 150 |
6 files changed, 360 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am index 87d73dc..dd5befa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,14 +17,14 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. EXTRA_DIST=bootstrap.sh README LICENSE -SUBDIRS=src # doc man +SUBDIRS=src doc # man MAINTAINERCLEANFILES = README noinst_DATA = README README: rm -f README -#$(MAKE) -C doc README + $(MAKE) -C doc README cd $(srcdir) && ln -s doc/README README homepage: diff --git a/configure.ac b/configure.ac index b676d4f..ad456aa 100644 --- a/configure.ac +++ b/configure.ac @@ -98,5 +98,5 @@ fi AM_CONDITIONAL([USE_XMLTOMAN], [test "x$xmltoman" = xyes]) -AC_CONFIG_FILES([src/Makefile Makefile]) # doc/Makefile man/Makefile doc/README.html]) +AC_CONFIG_FILES([src/Makefile Makefile doc/Makefile doc/README.html]) # man/Makefile ]) AC_OUTPUT diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..33b29a7 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,36 @@ +# $Id$ + +# This file is part of bidilink. +# +# bidilink is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# bidilink 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with bidilink; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +noinst_DATA = README.html README +EXTRA_DIST = $(noinst_DATA) style.css README.html.in + +MAINTAINERCLEANFILES = README README.html +CLEANFILES = + +if USE_LYNX +README: README.html + lynx --dump $^ | sed 's,file://localhost/.*/doc/README.html,README,' > $@ + +CLEANFILES += README +endif + +tidy: README.html + tidy -e < README.html + +.PHONY: tidy + diff --git a/doc/README.html.in b/doc/README.html.in new file mode 100644 index 0000000..f9f2cc2 --- /dev/null +++ b/doc/README.html.in @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="iso-8859-1"?> <!-- -*-html-helper-*- --> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + +<head> +<title>bidilink @PACKAGE_VERSION@</title> +<link rel="stylesheet" type="text/css" href="style.css" /> +</head> + +<body> +<h1><a name="top">bidilink @PACKAGE_VERSION@</a></h1> + +<p><i>Copyright 2003 Lennart Poettering <@PACKAGE_BUGREPORT@></i></p> + +<ul class="toc"> + <li><a href="#license">License</a></li> + <li><a href="#news">News</a></li> + <li><a href="#overview">Overview</a></li> + <li><a href="#status">Status</a></li> + <li><a href="#documentation">Documentation</a></li> + <li><a href="#requirements">Requirements</a></li> + <li><a href="#installation">Installation</a></li> + <li><a href="#acks">Acknowledgements</a></li> + <li><a href="#download">Download</a></li> +</ul> + +<h2><a name="license">License</a></h2> + +<p>This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version.</p> + +<p>This program 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 +General Public License for more details.</p> + +<p>You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.</p> + +<h2><a name="news">News</a></h2> + +<div class="news-date">Wed Jan 14 2004: </div> + +<p class="news-text"><a href="@PACKAGE_URL@bidilink-0.1.tar.gz">Version 0.1</a> released, initial release.</p> + +<h2><a name="overview">Overview</a></h2> + +<p><tt>bidilink</tt> is a general purpose Unix tool for linking two +bidirectional data streams together. It extends the standard Unix +"filter" paradigma to bidrectional streams.</p> + +<h2><a name="status">Status</a></h2> + +<p>Version @PACKAGE_VERSION@ is more or less stable. Its has the following stream drivers:</p> + +<ul> + <li><tt>std:</tt> - <tt>STDIN</tt>, <tt>STDOUT</tt> of the process</li> + <li><tt>exec:PROGRAM</tt> - <tt>fork()</tt> off a process and use its <tt>STDIN</tt> and <tt>STDOUT</tt></li> + <li><tt>tty:TTYDEVICE</tt> - Open a TTY device (like a serial port) as client</li> + <li><tt>pty:PTYNAME</tt> - Allocate a pseudo TTY device as master</li> + <li><tt>tcp-client:HOSTNAME:PORT</tt> - Connect to another or the local host via TCP/IP</li> + <li><tt>tcp-server:[IPADDRESS:]PORT</tt> - Listen on a local port and wait for an incoming connection</li> + <li><tt>unix-client:SOCKNAME</tt> - Connect to a local Unix domain socket</li> + <li><tt>unix-server:SOCKNAME</tt> - Listen on a local Unix domain socket</li> +</ul> + +<p>More drivers are planned, including:</p> + +<ul> + <li><tt>dsp:</tt> - Full duplex audio with OSS (Open Sound System)</li> + <li><tt>tun:</tt> - Raw network access using the TUN subsystem</li> + <li><tt>tap:</tt> - Raw network access using the TAP subsystem</li> + </ul> + +<h2><a name="documentation">Documentation</a></h2> + +<p>Have a look on the man page <a href="@PACKAGE_URL@bidilink.1.xml"><tt>bidilink(1)</tt></a>. (An XSLT capable browser is required)</p> + +<h3>Usage examples</h3> + +<p>Forward a serial port of another machine to a local pseudo TTY, which is compatible with <tt>pppd</tt> and <tt>minicom</tt>:</p> + +<pre>bidilink "exec:ssh OTHERMACHINE bidilink tty:/dev/ttyS0" pty:/dev/rmodem</pre> + +<p><i>This will create a symbolic link <tt>/dev/rmodem</tt> to the +allocated pseudo TTY device. Point your application to the device to +use the forwarded port. This requires that <tt>bidilink</tt> is +installed on both the local machine and the remote machine.</i></p> + +<p>Bind a local serial port to a local TCP port:</p> + +<pre>bidilink tty:/dev/ttyS0 tcp-server:4711</pre> + +<p><i>Use <tt>telnet localhost 4711</tt> to connect to the device</i></p> + +<p>Bind a remote serial port to a local pseudo TTY:</p> + +<pre>bidilink pty:/dev/rmodem tcp-client:OTHERMACHINE:4711</pre> + +<p><i>This may be used as client to the server trick descibed above.</i></p> + +<p>Open a local Unix socket (<tt>SOCK_STREAM</tt>) to the Internet:</p> + +<pre>bidilink tcp-server:4711 unix-client:/tmp/.esd/socket</pre> + +<h2><a name="requirements">Requirements</a></h2> + +<p>A recent Linux distribution. Probably, it is simple to port <tt>bidilink</tt> to other platforms, but this has not been done yet.</p> + +<h2><a name="installation">Installation</a></h2> + +<p>As this package is made with the GNU <tt>autotools</tt> you should run +<tt>./configure</tt> inside the distribution directory for configuring +the source tree. After that you should run <tt>make</tt> for +compilation and <tt>make install</tt> (as root) for installation of +<tt>bidilink</tt>.</p> + +<h2><a name="acks">Acknowledgements</a></h2> + +<p>None so far</p> + +<h2><a name="download">Download</a></h2> + +<p>The newest release is always available from <a href="@PACKAGE_URL@">@PACKAGE_URL@</a></p> + +<p>The current release is <a href="@PACKAGE_URL@bidilink-@PACKAGE_VERSION@.tar.gz">@PACKAGE_VERSION@</a></p> + +<p>Get <tt>bidilink</tt>'s development sources from the <a href="http://subversion.tigris.org/">Subversion</a> <a href="https://seth.intheinter.net:8081/svn/bidilink/">repository</a>.</p> + +<hr/> +<address class="grey">Lennart Poettering <@PACKAGE_BUGREPORT@>, January 2004</address> + +<div class="grey"><i>$Id$</i></div> + +</body> +</html> diff --git a/doc/style.css b/doc/style.css new file mode 100644 index 0000000..3605d6e --- /dev/null +++ b/doc/style.css @@ -0,0 +1,32 @@ +/* $Id$ */ + +/*** + * This file is part of bidilink. + * + * bidilink is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * bidilink 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with bidilink; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + ***/ + +body { color: black; background-color: white; margin: 0.5cm; } +a:link, a:visited { color: #900000; } +p { margin-left: 0.5cm; margin-right: 0.5cm; } +div.news-date { margin-left: 0.5cm; font-size: 80%; color: #4f0000; } +p.news-text { margin-left: 1cm; } +h1 { color: #00009F; } +h2 { color: #00009F; } +h3 { color: #00004F; margin-left: 0.5cm; } +ul { margin-left: .5cm; } +ol { margin-left: .5cm; } +pre { margin-left: .5cm; background-color: #f0f0f0; padding: 0.4cm;} +.grey { color: #afafaf; } diff --git a/src/client-tty.c b/src/client-tty.c index 5f31249..59ddec5 100644 --- a/src/client-tty.c +++ b/src/client-tty.c @@ -30,17 +30,165 @@ #include <string.h> #include <errno.h> #include <assert.h> +#include <limits.h> +#include <sys/stat.h> +#include <inttypes.h> +#include <sys/types.h> +#include <signal.h> +#include <pwd.h> #include "client-tty.h" +#define LOCKDIR "/var/lock" + +static const char *lockfile(const char *dev) { + static char lockfile[PATH_MAX]; + char *p = strrchr(dev, '/'); + if (p) + p++; + else + p = (char*) dev; + + snprintf(lockfile, sizeof(lockfile), "%s/LCK..%s", LOCKDIR, p); + return lockfile; +} + +static const char *tempfile(const char *path) { + static char t[PATH_MAX]; + snprintf(t, sizeof(t), "%s.tmp.%lu", path, (unsigned long) getpid()); + return t; +} + +static int device_lock(const char *dev) { + struct stat st; + int fd; + const char *path, *temp; + char buf[100]; + char uidbuf[32]; + + if (stat(LOCKDIR, &st) != 0 || !S_ISDIR(st.st_mode)) { + fprintf(stderr, "Failed to lock device, directory "LOCKDIR" not existent.\n"); + return -1; + } + + path = lockfile(dev); + temp = tempfile(path); + + for (;;) { + mode_t u; + struct passwd* pw; + char *username; + + if ((fd = open(path, O_RDONLY)) < 0) { + if (errno != ENOENT) { + fprintf(stderr, "Failed to open lock file: %s\n", strerror(errno)); + return -1; + } + } + + if (fd >= 0) { + ssize_t n; + + n = read(fd, buf, sizeof(buf) - 1); + close(fd); + + if (n < 0) { + close(fd); + fprintf(stderr, "Failed to read from lock file: %s\n", strerror(errno)); + return -1; + } + + if (n > 0) { + pid_t pid; + + if (n == 4) + pid = (pid_t) *((uint32_t*) buf); + else { + unsigned long v; + buf[n] = 0; + sscanf(buf, "%lu", &v); + pid = (pid_t) v; + } + + if (pid > 0) { + if (kill(pid, 0) < 0 && errno == ESRCH) { + fprintf(stderr, "Lockfile is stale. Overriding it.\n"); + /* Yes, here is a race condition */ + unlink(path); + } else + return 1; + } + } + } + + u = umask(0033); + fd = open(temp, O_WRONLY | O_CREAT | O_EXCL, 0666); + umask(u); + + if (fd < 0) { + fprintf(stderr, "Failed to create temporary lock file: %s\n", strerror(errno)); + return -1; + } + + if ((pw = getpwuid(getuid()))) + username = pw->pw_name; + else + snprintf(username = uidbuf, sizeof(uidbuf), "%lu", (unsigned long) getuid()); + + snprintf(buf, sizeof(buf), "%10lu %s %.20s\n", (unsigned long) getpid(), "bidilink", username); + if (write(fd, buf, strlen(buf)) < 0) { + fprintf(stderr, "Failed to write to temporary lock file: %s\n", strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + if (link(temp, path) < 0) { + if (errno == EEXIST) + continue; + + fprintf(stderr, "Failed to link temporary lock file: %s\n", strerror(errno)); + } + + unlink(temp); + + return 0; + } +} + +static int device_unlock(const char *dev) { + if (unlink(lockfile(dev)) < 0) { + fprintf(stderr, "Failed to remove lock file: %s\n", strerror(errno)); + return -1; + } + + return 0; +} + +static void destruct(struct stream *s) { + assert(s && s->user); + + device_unlock((char*) s->user); + free(s->user); +} + struct stream* stream_client_tty(const char *args) { struct stream *s = NULL; struct termios ts; int fd = -1; + int r; s = malloc(sizeof(struct stream)); assert(s); memset(s, 0, sizeof(struct stream)); + + if ((r = device_lock(args)) != 0) { + if (r > 0) + fprintf(stderr, "Device locked.\n"); + goto fail; + } + if ((fd = open(args, O_RDWR|O_NOCTTY)) < 0) { fprintf(stderr, "open('%s', O_RDWR|O_NOCTTY): %s\n", args, strerror(errno)); @@ -67,6 +215,8 @@ struct stream* stream_client_tty(const char *args) { goto fail; } + s->user = strdup(args); + s->destruct = destruct; s->input_fd = s->output_fd = fd; return s; |