Subject: Re: alarm() does not work with tty read???
To: <>
From: Simon J. Gerraty <sjg@zen.void.oz.au>
List: current-users
Date: 12/07/1993 18:37:55
I wrote:
> I'm "porting" mgetty+sendfax. sendfax works more or less ok.
> mgetty gets stuck... it gets stuck because it tries to do a read from
> a tty device with and
>
> t->c_lflag &= ~ICANON;
> t->c_cc[VMIN] = 0;
> t->c_cc[VTIME]= 1;
>
> it should work, but the time out never happens.
> I modified mgetty to simply use
>
> alarm(1);
> read()
> alarm(0);
Ok so like an idiot, I keep forgetting I'm using BSD :-)
Simply using signal() is no good as the read is automagically restarted.
Modifying things to use sigaction and to specify no-retry works ok.
My initial question remains though... does NetBSD actually support
termios timed reads using c_cc[VTIME] as above. The modified test
prog below suggests not.
Compile it with just
cc -g -O -o chat.sigaction -static chat.c
and it works
cc -g -O -o chat.signal -DUSE_SIGNAL -static chat.c
does not (as expected) and nor does
cc -g -O -o chat.vtime -DUSE_VTIME -static chat.c
#include <stdio.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
volatile int timeout = 0;
void
alarm_catcher(int sig)
{
timeout++;
}
int
tty_open(char *name)
{
int fd = -1;
struct termios tio;
if ((fd = open(name, O_RDWR)) >= 0)
{
#ifdef USE_SIGNAL
signal(SIGALRM, alarm_catcher);
#else
struct sigaction sa;
sa.sa_handler = alarm_catcher;
sa.sa_flags = 0; /* no restart */
sigaction(SIGALRM, &sa, NULL);
#endif
}
return fd;
}
int
tty_read(int fd, char *buf, int nbytes, int secs)
{
int c;
#ifdef USE_VTIME
static struct termios t, old;
static int once = 0;
if (!once) {
once++;
tcgetattr(fd, &old);
}
t = old;
t.c_lflag &= ~( ICANON );
t.c_cc[VMIN] = 0;
t.c_cc[VTIME]= secs * 10;
tcsetattr(fd, TCSANOW, &t);
c = read(fd, buf, nbytes);
tcsetattr(fd, TCSANOW, &old);
#else
alarm(secs);
c = read(fd, buf, nbytes);
alarm(0);
#endif
return c;
}
int
wait_for(int fd, char *str)
{
char buf[128];
int c;
printf("looking for '%s', got: ", str);
fflush(stdout);
while ((c = tty_read(fd, buf, sizeof (buf) - 1, 5)) > 0)
{
buf[c] = '\0';
printf("%s", buf);
fflush(stdout);
if (strstr(buf, str))
return 1;
}
return 0;
}
void
do_chat(int fd, char **args)
{
int i = 0;
for (i = 0; args[i]; i += 2)
{
printf("send: '%s'\n", args[i]);
write(fd, args[i], strlen(args[i]));
write(fd, "\r", 1);
wait_for(fd, args[i + 1]);
printf("\n");
}
}
int
main(int argc, char **argv)
{
char *tty_dev = NULL;
int c, fd = -1;
while ((c = getopt(argc, argv, "l:")) != EOF)
{
switch (c)
{
case 'l':
tty_dev = optarg;
break;
}
}
if (tty_dev)
if ((fd = tty_open(tty_dev)) >= 0)
do_chat(fd, &argv[optind]);
return 0;
}
------------------------------------------------------------------------------