summaryrefslogtreecommitdiffstats
path: root/ax25
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2015-05-25 20:57:47 +0200
committerRalf Baechle <ralf@linux-mips.org>2015-05-25 21:02:13 +0200
commit6911c1b1acd455e514de2fc88b3eaf0a23cabdd6 (patch)
tree4bcb25b6fd2e2374f66b5000b5ff12b6f7240ddf /ax25
parent4984e59635ed76196dc5f9a18ae8118be4853758 (diff)
Add Tomi Manninen OH2BNS's axwrapper program.
Axwrapper first creates a pipe and then forks and execs the program <server-program> with arguments given at the axwrapper command line. The argv[0] argument is mandatory; further arguments are optional. The parent process then sits and waits for any I/O to and from the user and converts any carriage return characters from the user to line feeds and any line feeds from the program to carriage returns. This is useful when starting non-AX.25-aware programs from ax25d. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'ax25')
-rw-r--r--ax25/.gitignore1
-rw-r--r--ax25/Makefile.am4
-rw-r--r--ax25/ax25d.81
-rw-r--r--ax25/ax25d.conf.51
-rw-r--r--ax25/axwrapper.825
-rw-r--r--ax25/axwrapper.c225
6 files changed, 256 insertions, 1 deletions
diff --git a/ax25/.gitignore b/ax25/.gitignore
index 00323ec..a925695 100644
--- a/ax25/.gitignore
+++ b/ax25/.gitignore
@@ -6,6 +6,7 @@ ax25d
axctl
axparms
axspawn
+axwrapper
beacon
bpqparms
mheard
diff --git a/ax25/Makefile.am b/ax25/Makefile.am
index 029217c..40eac38 100644
--- a/ax25/Makefile.am
+++ b/ax25/Makefile.am
@@ -16,7 +16,8 @@ installconf:
done
-sbin_PROGRAMS = ax25d axctl axparms axspawn beacon bpqparms mheardd rxecho
+sbin_PROGRAMS = ax25d axctl axparms axspawn axwrapper beacon bpqparms mheardd \
+ rxecho
bin_PROGRAMS = mheard
@@ -41,6 +42,7 @@ ax25d_SOURCES = ax25d.c
axctl_SOURCES = axctl.c
axparms_SOURCES = axparms.c
axspawn_SOURCES = axspawn.c axspawn.h access.c access.h md5.c md5.h
+axwrapper_SOURCES = axwrapper.c
beacon_SOURCES = beacon.c
bpqparms_SOURCES = bpqparms.c
mheard_SOURCES = mheard.c
diff --git a/ax25/ax25d.8 b/ax25/ax25d.8
index 96ceec4..8155c3c 100644
--- a/ax25/ax25d.8
+++ b/ax25/ax25d.8
@@ -37,6 +37,7 @@ Display the version.
.SH "SEE ALSO"
.BR kill (1),
.BR ax25 (4),
+.BR ax25wrapper (8),
.BR netrom (4),
.BR rose (4),
.BR ax25d.conf (5).
diff --git a/ax25/ax25d.conf.5 b/ax25/ax25d.conf.5
index 0fd80db..eeb26c2 100644
--- a/ax25/ax25d.conf.5
+++ b/ax25/ax25d.conf.5
@@ -282,6 +282,7 @@ or
/etc/ax25/ax25d.conf
.SH "SEE ALSO"
.BR ax25 (4),
+.BR ax25wrapper (8),
.BR netrom (4),
.BR rose (4),
.BR axports (5),
diff --git a/ax25/axwrapper.8 b/ax25/axwrapper.8
new file mode 100644
index 0000000..5372dd8
--- /dev/null
+++ b/ax25/axwrapper.8
@@ -0,0 +1,25 @@
+.TH AXWRAPPER 8 "25 May 2015" Linux "Linux System Managers Manual"
+.SH NAME
+axwrapper \- Run non-ax.25-aware programs from ax25d
+.SH SYNOPSIS
+.B axwrapper [ -p paclen ] server-program argv[0] ...
+.SH DESCRIPTION
+.LP
+.B Axwrapper
+first creates a pipe and then forks and execs the program <server-program> with
+arguments given at the axwrapper command line. The argv[0] argument is
+mandatory; further arguments are optional. The parent process then sits
+and waits for any I/O to and from the user and converts any carriage return
+characters from the user to line feeds and any line feeds from the program to
+carriage returns. This is useful when starting non-AX.25-aware programs from
+ax25d.
+.SH OPTIONS
+.BI "\-c paclen"
+.IP
+Specify a the size of the output buffer. The default length is 256 bytes.
+.SH FILES
+.SH "SEE ALSO"
+.BR ax25 (8)
+.BR ax25.conf (5)
+.SH AUTHOR
+Tomi Manninen OH2BNS <oh2bns@sral.fi>
diff --git a/ax25/axwrapper.c b/ax25/axwrapper.c
new file mode 100644
index 0000000..872932a
--- /dev/null
+++ b/ax25/axwrapper.c
@@ -0,0 +1,225 @@
+/*
+ * axwrapper.c - Convert end-of-line sequences for non-AX.25 aware programs -
+ * version 1.1
+ *
+ * Copyright (C) 1996-2001 Tomi Manninen, OH2BNS, <tomi.manninen@hut.fi>.
+ *
+ * Compile with: gcc -Wall -O6 -o axwrapper axwrapper.c
+ *
+ * Usage: axwrapper [-p <paclen>] <filename> <argv[0]> ...
+ *
+ * Axwrapper first creates a pipe and then forks and execs the program
+ * <filename> with arguments given at the axwrapper command line.
+ * The parent process then sits and waits for any I/O to and from the
+ * user and converts any <CR>'s from user to <NL>'s and any <NL>'s from
+ * the program to <CR>'s. This is useful when starting non-AX.25 aware
+ * programs from ax25d.
+ *
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <string.h>
+#include <errno.h>
+
+#define FLUSHTIMEOUT 500000 /* 0.5 sec */
+
+#define PERROR(s) fprintf(stderr, "*** %s: %s\r", (s), strerror(errno))
+#define USAGE() fputs("Usage: axwrapper [-p <paclen>] <filename> <argv[0]> ...\r", stderr)
+
+void sigchld_handler(int sig)
+{
+ /* fprintf(stderr, "Caught SIGCHLD, exiting...\r"); */
+ exit(0);
+}
+
+void convert_cr_lf(unsigned char *buf, int len)
+{
+ while (len-- > 0) {
+ if (*buf == '\r') *buf = '\n';
+ buf++;
+ }
+}
+
+void convert_lf_cr(unsigned char *buf, int len)
+{
+ while (len-- > 0) {
+ if (*buf == '\n') *buf = '\r';
+ buf++;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ unsigned char buf[4096], *stdoutbuf;
+ int pipe_in[2];
+ int pipe_out[2];
+ int pipe_err[2];
+ int len;
+ int pid;
+ int paclen = 256;
+ fd_set fdset;
+ struct timeval tv;
+
+ while ((len = getopt(argc, argv, "p:")) != -1) {
+ switch (len) {
+ case 'p':
+ paclen = atoi(optarg);
+ break;
+ case ':':
+ case '?':
+ USAGE();
+ exit(1);
+ }
+ }
+
+ if (argc - optind < 2) {
+ USAGE();
+ exit(1);
+ }
+
+ if ((stdoutbuf = malloc(paclen)) == NULL) {
+ PERROR("axwrapper: malloc");
+ exit(1);
+ }
+
+ setvbuf(stdout, stdoutbuf, _IOFBF, paclen);
+
+ if (pipe(pipe_in) == -1) {
+ PERROR("axwrapper: pipe");
+ exit(1);
+ }
+ if (pipe(pipe_out) == -1) {
+ PERROR("axwrapper: pipe");
+ exit(1);
+ }
+ if (pipe(pipe_err) == -1) {
+ PERROR("axwrapper: pipe");
+ exit(1);
+ }
+
+ /* signal(SIGCHLD, sigchld_handler); */
+ signal(SIGCHLD, SIG_IGN);
+
+ pid = fork();
+
+ if (pid == -1) {
+ /* fork error */
+ PERROR("axwrapper: fork");
+ exit(1);
+ }
+
+ if (pid == 0) {
+ /* child */
+ dup2(pipe_in[0], STDIN_FILENO);
+ close(pipe_in[1]);
+
+ dup2(pipe_out[1], STDOUT_FILENO);
+ close(pipe_out[0]);
+
+ dup2(pipe_err[1], STDERR_FILENO);
+ close(pipe_err[0]);
+
+ execve(argv[optind], argv + optind + 1, NULL);
+
+ /* execve() should not return */
+ perror("axwrapper: execve");
+ exit(1);
+ }
+
+ /* parent */
+
+ close(pipe_in[0]);
+ close(pipe_out[1]);
+ close(pipe_err[1]);
+
+ if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) == -1) {
+ perror("axwrapper: fcntl");
+ exit(1);
+ }
+ if (fcntl(pipe_out[0], F_SETFL, O_NONBLOCK) == -1) {
+ perror("axwrapper: fcntl");
+ exit(1);
+ }
+ if (fcntl(pipe_err[0], F_SETFL, O_NONBLOCK) == -1) {
+ perror("axwrapper: fcntl");
+ exit(1);
+ }
+
+ while (1) {
+ FD_ZERO(&fdset);
+ FD_SET(STDIN_FILENO, &fdset);
+ FD_SET(pipe_out[0], &fdset);
+ FD_SET(pipe_err[0], &fdset);
+ tv.tv_sec = 0;
+ tv.tv_usec = FLUSHTIMEOUT;
+
+ len = select(256, &fdset, 0, 0, &tv);
+ if (len == -1) {
+ perror("axwrapper: select");
+ exit(1);
+ }
+ if (len == 0) {
+ fflush(stdout);
+ }
+
+ if (FD_ISSET(STDIN_FILENO, &fdset)) {
+ len = read(STDIN_FILENO, buf, sizeof(buf));
+ if (len < 0 && errno != EAGAIN) {
+ perror("axwrapper: read");
+ break;
+ }
+ if (len == 0)
+ break;
+ convert_cr_lf(buf, len);
+ write(pipe_in[1], buf, len);
+ }
+ if (FD_ISSET(pipe_out[0], &fdset)) {
+ len = read(pipe_out[0], buf, sizeof(buf));
+ if (len < 0 && errno != EAGAIN) {
+ perror("axwrapper: read");
+ break;
+ }
+ if (len == 0)
+ break;
+ convert_lf_cr(buf, len);
+ fwrite(buf, 1, len, stdout);
+ }
+ if (FD_ISSET(pipe_err[0], &fdset)) {
+ len = read(pipe_err[0], buf, sizeof(buf));
+ if (len < 0 && errno != EAGAIN) {
+ perror("axwrapper: read");
+ break;
+ }
+ if (len == 0)
+ break;
+ convert_lf_cr(buf, len);
+ fwrite(buf, 1, len, stderr);
+ }
+ }
+
+ kill(pid, SIGTERM);
+ close(pipe_in[1]);
+ close(pipe_out[0]);
+ close(pipe_err[0]);
+ return 0;
+}