Subject: alarm() does not work with tty read???
To: None <current-users@sun-lamp.cs.berkeley.edu>
From: Simon J. Gerraty <sjg@zen.void.oz.au>
List: current-users
Date: 12/07/1993 17:01:25
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);
and even with root sending SIGALRM's at the process it does not return
from the read.... so I hacked up the trivial prog at the end of this
post to test in isolation. I was going to check various reading
approaches, but the first one using alarm() as above, did not work so
I'm pretty sure we have a bug...
com.c just calls the line discipline's read entry, but I'm not too
sure the standard line discipline is implemented. kern/tty.c does not
look enough (no mention of VMIN etc - indeed it only appears in
arch/i386/isa/cy.c) and speaks of line disciplines as though they are
implemented elsewhere... any clues appreciated.
Anyway here is the test prog. You can call it with
./chat -l /dev/tty01 send expect ...
It always adds a "\r" for you (I said this was trivial).
#include <stdio.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
int
tty_open(char *name)
{
int fd = -1;
struct termios tio;
if ((fd = open(name, O_RDWR)) >= 0)
{
/* hooks for later... */
}
return fd;
}
volatile int timeout = 0;
void
alarm_catcher(int sig)
{
timeout++;
}
int
tty_read(int fd, char *buf, int nbytes, int secs)
{
int c;
signal(SIGALRM, alarm_catcher);
alarm(secs);
#if 0
/* check that alarm() does work... */
strcpy(buf, "nothing");
sleep(100);
c = -1;
#else
c = read(fd, buf, nbytes);
#endif
alarm(0);
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;
}
------------------------------------------------------------------------------