Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!burl!ulysses!bellcore!decvax!decwrl!amdcad!lll-crg!seismo!columbia!garfield!ji From: ji@garfield.columbia.edu (John Ioannidis) Newsgroups: net.unix-wizards,net.unix Subject: Re: Need Non-Blocking Terminal Input Function For Berkeley 4.2 Message-ID: <1381@garfield.columbia.edu> Date: Sat, 25-Jan-86 23:49:59 EST Article-I.D.: garfield.1381 Posted: Sat Jan 25 23:49:59 1986 Date-Received: Thu, 30-Jan-86 01:39:41 EST References: <482@kontron.UUCP> Distribution: net Organization: Columbia University Lines: 86 Xref: watmath net.unix-wizards:16570 net.unix:6958 In article <482@kontron.UUCP>, cramer@kontron.UUCP (Clayton Cramer) writes: > 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. > The idea is to use select(2) to do the waiting for you. The following program should be obvious. See the documentation for select(2) for more details. #include #include #define EVER ;; main() { int rfds, sret, c; struct timeval { long tv_sec; long tv_usec; } tout; struct sgttyb b; /* * Prepare tout structure, as required by select(2) */ printf( "Enter time to wait, in seconds: " ); scanf( "%d", &tout.tv_sec ); tout.tv_usec = 0; /* * Some cosmetics... */ ioctl( 0, TIOCGETP, &b ); b.sg_flags |= CBREAK; /* Turn on CBreak mode */ b.sg_flags &= ~ ECHO; /* Turn off echoing */ ioctl( 0, TIOCSETP, &b ); setbuf( stdout, NULL ); /* Used to avoid fflush(stdout) later */ for(EVER) { printf( "Press any key to continue..." ); rfds = 1 << 0; /* really 1 but shown for clarity */ if( ( sret=select( 20, &rfds, 0, 0, &tout ) ) > 0 ) { /* something was pressed */ c=getchar(); printf( "\tYou pressed %c\r\n\n", c ); } else if( sret==0 ) printf( "\t*TIMEOUT WARNING*\r\n\n" ); else perror( "\r\nselect" ); } } The code should be obvious :-) If you specify 0 seconds, select will timeout immediately. To 'block' if no input is available, specify (char *)0 instead of &tout in the select call. This is more elegant than using setjmp/sigalrm and far more elegant than spawning another process just to read! I hope this settles the question, #include VOICE: +1 212 280 5510 ARPA: ioannidis@cs.columbia.EDU USnail: John Ioannidis ji@garfield.columbia.EDU 450 Computer Science Columbia University, USENET: ...{seismo|topaz}! New York, NY 10027 columbia!garfield!ji ... It's all Greek to me!