summaryrefslogtreecommitdiffstats
path: root/call
diff options
context:
space:
mode:
authorThomas Osterried <thomas@osterried.de>2009-08-24 21:13:18 +0000
committerThomas Osterried <thomas@osterried.de>2009-08-24 21:13:18 +0000
commit235fa050403c7335fb2287a280dc6ea8d2d7183b (patch)
tree6d052365eda6fd7f2919d7f217df85c75bdf59f6 /call
parentf49602e6c64ec74c4a4d23b5babd1cdb8d7d829b (diff)
fix: on read through closed pipe, call did endless select(),
read() = 0, wht consumed 100% CPU power. New options: -W: waits after EOF on stdin. Useful for scripting, for waiting for data coming via fd 3 (ax25 connection) -T secs: idle timout after secs seconds.
Diffstat (limited to 'call')
-rw-r--r--call/call.18
-rw-r--r--call/call.c75
2 files changed, 66 insertions, 17 deletions
diff --git a/call/call.1 b/call/call.1
index a10465b..2786975 100644
--- a/call/call.1
+++ b/call/call.1
@@ -4,7 +4,7 @@ call \- make an AX.25, NET/ROM or Rose connection.
.SH SYNOPSIS
For AX.25
.br
-.B call [-b l|e] [-d] [-h] [-m s|e] [-p paclen] [-s mycall] [-r] [-t] [-v] [-w window] port callsign [[via] digipeaters.....]
+.B call [-b l|e] [-d] [-h] [-m s|e] [-p paclen] [-s mycall] [-r] [-t] [-T timeout] [-v] [-w window] [-W] port callsign [[via] digipeaters.....]
.sp 1
For NET/ROM
.br
@@ -74,6 +74,9 @@ Connect using the specified source call (you may need to be root).
.BI \-S
Be silent. Useful for using call in shellscripts (together with option \-r) in order to be really transparent.
.TP 10
+.BI "\-T timeout"
+Set idle timeout seconds after a connection will be closed automaticaly when there's no data being transferred (in- and outbound). If timeout is set to 3600, the connection will close after 1h inactivity. A value of 0.5 is 500ms.
+.TP 10
.BI \-r
Selects Raw mode.
.TP 10
@@ -85,6 +88,9 @@ Display the version.
.TP 10
.BI "\-w window"
Specify a specific AX.25 window for this connection. Only valid in AX.25 mode.
+.TP 10
+.BI "\-W"
+Wait for remote disconnect even if stdin is closed. Normaly, "echo q | call ax0 db0fhn" closes immediately after "echo q" terminates; thus we never see the greeting from db0fhn. With the -W option, call waits until the ax25-connection is disconnected (i.e. db0fhn disconnects after "q" command). Very useful for scripting. You might like to combine it with the -T option.
.LP
The call program interprets lines beginning with a '~' specially.
The following '~' escapes are available.
diff --git a/call/call.c b/call/call.c
index db76545..7b3aa03 100644
--- a/call/call.c
+++ b/call/call.c
@@ -83,6 +83,10 @@ int interrupted = FALSE;
int paclen = 0;
int fd;
+int wait_for_remote_disconnect = FALSE;
+static struct timeval inactivity_timeout;
+int inactivity_timeout_is_set = FALSE;
+
#define GP_FILENAME_SIZE 255
typedef struct {
char file_name[GP_FILENAME_SIZE];
@@ -109,7 +113,7 @@ typedef struct {
void usage(void)
{
- fprintf(stderr, "usage: call [-b l|e] [-d] [-h] [-m s|e] [-p paclen] [-r] [-s mycall] [-t] [-v] [-w window] port callsign [[via] digipeaters...]\n");
+ fprintf(stderr, "usage: call [-b l|e] [-d] [-h] [-m s|e] [-p paclen] [-r] [-s mycall] [-t] [-T timeout] [-v] [-w window] [-W] port callsign [[via] digipeaters...]\n");
exit(1);
}
@@ -1537,6 +1541,7 @@ int cmd_call(char *call[], int mode)
int crc = 0;
char s[80];
int flags = 0;
+ int EOF_on_STDIN = FALSE;
init_crc();
@@ -1575,29 +1580,43 @@ int cmd_call(char *call[], int mode)
while (TRUE) {
struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 10;
-
+ if (inactivity_timeout_is_set == TRUE && uploadfile == -1 && downloadfile == -1) {
+ tv.tv_sec = inactivity_timeout.tv_sec;
+ tv.tv_usec = inactivity_timeout.tv_usec;
+ } else {
+ tv.tv_sec = 0;
+ tv.tv_usec = 10;
+ }
FD_ZERO(&sock_read);
- FD_SET(STDIN_FILENO, &sock_read);
+ if (EOF_on_STDIN == FALSE)
+ FD_SET(STDIN_FILENO, &sock_read);
FD_SET(fd, &sock_read);
FD_ZERO(&sock_write);
if (uploadfile != -1)
FD_SET(fd, &sock_write);
- if (select(fd + 1, &sock_read, &sock_write, NULL, (uploadfile == -1 && downloadfile == -1) ? NULL : &tv) == -1) {
- if (!interrupted && errno == EAGAIN)
+ if (select(fd + 1, &sock_read, &sock_write, NULL, (uploadfile == -1 && downloadfile == -1 && inactivity_timeout_is_set == FALSE) ? NULL : &tv) == -1) {
+ if (!interrupted && errno == EAGAIN) {
+ usleep(100000);
continue;
+ }
if (!interrupted)
perror("select");
break;
}
+ if (inactivity_timeout_is_set == TRUE && !FD_ISSET(fd, &sock_read) && !FD_ISSET(STDIN_FILENO, &sock_read)) {
+ if (!be_silent) {
+ printf("*** Inactivity timeout reached. Terminating..\n");
+ fflush(stdout);
+ }
+ break;
+ }
if (FD_ISSET(fd, &sock_read)) {
/* bytes = read(fd, buf, 511); */
bytes = read(fd, buf, sizeof(buf));
if (bytes == 0) {
- /* read EOF on stdin */
+ /* read EOF on connection */
/* cause program to terminate */
flags &= ~FLAG_RECONNECT;
break;
@@ -2053,14 +2072,22 @@ int cmd_call(char *call[], int mode)
}
/* if (bytes == -1 && errno != EWOULDBLOCK && errno != EAGAIN) */
/* if ((bytes == 0 && (mode & (TALKMODE|SLAVEMODE)) == 0) || (bytes == -1 && errno != EWOULDBLOCK && errno != EAGAIN)) */
- if (interrupted
- || (bytes == -1 && errno != EWOULDBLOCK
- && errno != EAGAIN)) {
- if (!interrupted)
- perror("input");
+
+ if (interrupted)
break;
- }
- if (bytes > 0) {
+ if (bytes == -1) {
+ if (errno != EWOULDBLOCK && errno != EAGAIN) {
+ perror("input");
+ EOF_on_STDIN = TRUE;
+ }
+ usleep(100);
+ } else if (bytes == 0) {
+ /* select() indicated that there is data to
+ * read, but read() returned 0 bytes.
+ * -> terminate normaly
+ */
+ EOF_on_STDIN = TRUE;
+ } else if (bytes > 0) {
unsigned long offset = 0L;
int err = 0;
@@ -2089,6 +2116,8 @@ int cmd_call(char *call[], int mode)
if (err)
break;
}
+ if (EOF_on_STDIN == TRUE && wait_for_remote_disconnect == FALSE)
+ break;
}
if (uploadfile != -1) {
if (uplsize == 0) {
@@ -2203,7 +2232,7 @@ int main(int argc, char **argv)
setlinebuf(stdin);
- while ((p = getopt(argc, argv, "b:dhm:p:rs:Stvw:")) != -1) {
+ while ((p = getopt(argc, argv, "b:dhm:p:rs:StT:vw:W")) != -1) {
switch (p) {
case 'b':
if (*optarg != 'e' && *optarg != 'l') {
@@ -2248,6 +2277,17 @@ int main(int argc, char **argv)
case 'S':
be_silent = 1;
break;
+ case 'T':
+ { double f = atof(optarg);
+ inactivity_timeout.tv_sec = ((time_t) f) & 0x7fffffff;
+ inactivity_timeout.tv_usec = (time_t ) (f - (double ) (time_t ) f);
+ if (f < 0.001 || f > (double) (0x7fffffff) || (inactivity_timeout.tv_sec == 0 && inactivity_timeout.tv_usec == 0)) {
+ fprintf(stderr, "call: option '-T' must be > 0.001 (1ms) and < 69 years\n");
+ return 1;
+ }
+ inactivity_timeout_is_set = TRUE;
+ }
+ break;
case 't':
mode = TALKMODE;
break;
@@ -2274,6 +2314,9 @@ int main(int argc, char **argv)
}
}
break;
+ case 'W':
+ wait_for_remote_disconnect = TRUE;
+ break;
case '?':
case ':':
usage();