Need Non-Blocking Terminal Input Function For Berkeley 4.2
Thomas Scott Christiansen
tom at puff.wisc.edu
Fri Jan 24 23:26:56 AEST 1986
> Does anyone know of a way to do read from a terminal under Berkeley 4.2 UNIX
> so that after a specified number of seconds control is returned to the
> program if there is no response? Right now I'm forking off of the main
> program, and having the child process do the read, with the parent setting
> an alarm to interrupt the child after a certain number of seconds. This
> works, but it's devilishly difficult to debug using dbx. Alternate
> techniques would be appreciated.
Yes the read will restart, *IF* you return to it. The trick is not
to return to it. You should use setjmp() to remember where you were.
The following module should do what you want. It contains the function
readt() which works just as read does except that it accepts a fourth
argument indicating the number of seconds at which a timeout is to be
triggered. If this does occur, errno will contain EINTR.
A sample main() is included to test the function. I have tested it
on a Gould under 4.2, a Pyramid under 4.2/SYSV, and a Vax 780 under 4.3.
-----------------------------------------------------------------------
#include <setjmp.h>
#include <signal.h>
#include <errno.h>
#define reg register
#define global
#define local static
#define ERROR (-1)
local jmp_buf Context;
local int timetrap();
extern int alarm();
extern int errno;
/*
* readt(): a read function that accepts a
* fourth parm indicating the number of seconds
* at which to trigger the timeout. other parms are
* the same as read.
*
* returns number of bytes read or -1 on error.
* a timeout causes errno to be set to EINTR.
*/
global int
readt ( channel, buffer, count, timeout )
reg int channel, count;
reg unsigned timeout;
reg char *buffer;
{
reg int retval;
reg int (*alrm_vec)();
alrm_vec = signal (SIGALRM, timetrap);
(void) alarm ( timeout );
retval = setjmp (Context)
? (errno = EINTR, ERROR)
: read ( channel, buffer, count );
(void) alarm ( 0 );
(void) signal (SIGALRM, alrm_vec);
return retval;
}
local int
timetrap() {
longjmp ( Context, 1 );
}
#include <stdio.h>
#define TIMEOUT 3
main() {
char line[100];
printf ("string (no timeout): ");
fflush (stdout);
if ( read (fileno(stdin), line, sizeof(line)) < 0)
perror("read");
else
printf ( "The string was %s",line);
printf ("string (timeout == %d): ",TIMEOUT);
fflush (stdout);
if ( readt (fileno(stdin), line, sizeof(line), TIMEOUT) < 0)
perror("readt");
else
printf ( "The string was %s",line);
}
/* lint output:
/usr/staff/tom/src/readt.c:
fflush returns value which is always ignored
*/
More information about the Comp.unix
mailing list