summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-01-14 21:51:32 +0000
committerLennart Poettering <lennart@poettering.net>2004-01-14 21:51:32 +0000
commit2187fc7c62ffad7cb514d061899d57cfd95438dc (patch)
tree417667f8ef1175f703d6b86f73bdd9094187d51e
parent973391053d38096aa05933a61885c67cc07adbe6 (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.am4
-rw-r--r--configure.ac2
-rw-r--r--doc/Makefile.am36
-rw-r--r--doc/README.html.in139
-rw-r--r--doc/style.css32
-rw-r--r--src/client-tty.c150
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 &lt;@PACKAGE_BUGREPORT@&gt;</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 &lt;@PACKAGE_BUGREPORT@&gt;, 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;