tom@puff.wisc.edu (Thomas Scott Christiansen) (01/24/86)
> 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 */