diff options
Diffstat (limited to 'ax25')
-rw-r--r-- | ax25/.gitignore | 1 | ||||
-rw-r--r-- | ax25/Makefile.am | 4 | ||||
-rw-r--r-- | ax25/ax25d.8 | 1 | ||||
-rw-r--r-- | ax25/ax25d.conf.5 | 1 | ||||
-rw-r--r-- | ax25/axwrapper.8 | 25 | ||||
-rw-r--r-- | ax25/axwrapper.c | 225 |
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; +} |