Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

getchar with timeout?

2,822 views
Skip to first unread message

Donald Arseneau

unread,
Mar 6, 2000, 3:00:00 AM3/6/00
to
I'm wondering if anyone has pointers to a simple getchar() with
a timeout. Curses has a good getch and timeout, but I don't want
to use ncurses screen management or cooked escape sequences.

I tried something based on the example in the select(2) man
page, but that only signals once for every escape sequence or
text-paste. Is there a way to see how many characters are
available?

I'm using Linux/gcc but the more general the solution, the better.
(A fortran version would also be useful.) I figure there must be
something very standard for this that I'm overlooking.

Thanks,
Donald Arseneau as...@triumf.ca

David T. Blake

unread,
Mar 6, 2000, 3:00:00 AM3/6/00
to
Donald Arseneau <as...@erich.triumf.ca> wrote:
> I'm wondering if anyone has pointers to a simple getchar() with
> a timeout. Curses has a good getch and timeout, but I don't want
> to use ncurses screen management or cooked escape sequences.
>
> I tried something based on the example in the select(2) man
> page, but that only signals once for every escape sequence or
> text-paste. Is there a way to see how many characters are
> available?

You could, for example, read the entire stream into an array
until you read EOF signalling the end of available input,
and then count the number of characters read.

I am not up on my functions for checking size of input streams
with any higher level funcs than that.

--
Dave Blake
dbl...@phy.ucsf.edu

nightstalker

unread,
Mar 6, 2000, 3:00:00 AM3/6/00
to
Donald Arseneau wrote:

> I'm wondering if anyone has pointers to a simple getchar() with
> a timeout. Curses has a good getch and timeout, but I don't want
> to use ncurses screen management or cooked escape sequences.
>
> I tried something based on the example in the select(2) man
> page, but that only signals once for every escape sequence or
> text-paste. Is there a way to see how many characters are
> available?
>

> I'm using Linux/gcc but the more general the solution, the better.
> (A fortran version would also be useful.) I figure there must be
> something very standard for this that I'm overlooking.
>
> Thanks,
> Donald Arseneau as...@triumf.ca

you can do it with 'signal's or in particular 'alarm'

here's the code for a small program i made:

/* test using alarm */

#include <stdio.h>
#include <unistd.h>
#include <signal.h>


/* alarm signal handler */
void alarm_func()
{
printf("\n20 second time-out reached ... aborting !\n");
exit(0);
}

int main( int argc, char **argv )
{
char name[31];
signal( SIGALRM, alarm_func );
printf("\nenter your name : ");
alarm(20);
gets(name,30,stdin);
alarm(0);
printf("\nname entered : %s", name );
return 0;
}

i hope this helps :)

Juergen Heinzl

unread,
Mar 6, 2000, 3:00:00 AM3/6/00
to
In article <38C3ECCB...@tvd.be>, nightstalker wrote:
>Donald Arseneau wrote:
>
>> I'm wondering if anyone has pointers to a simple getchar() with
>> a timeout. Curses has a good getch and timeout, but I don't want
>> to use ncurses screen management or cooked escape sequences.

http://www.monocerus.demon.co.uk/httpd-server/juergen/code/c/unix/getch.html
[...]


>you can do it with 'signal's or in particular 'alarm'
>
>here's the code for a small program i made:
>
>/* test using alarm */
>
>#include <stdio.h>
>#include <unistd.h>
>#include <signal.h>
>
>
>/* alarm signal handler */
>void alarm_func()
>{
> printf("\n20 second time-out reached ... aborting !\n");
> exit(0);
>}

Ouch ... alarm_func() can be called at any time, means you cannot
say which state the application is in, so neither printf() and one
should not call exit() either.

In addition you presume SIGALRM would interrupt system calls, which
might or might not be the case; see the info documentation for the
current C library for more 8-/
[...]

Cheers,
Juergen

--
\ Real name : Jürgen Heinzl \ no flames /
\ EMail Private : jue...@monocerus.demon.co.uk \ send money instead /

Paul D. Boyle

unread,
Mar 6, 2000, 3:00:00 AM3/6/00
to
Donald Arseneau (as...@erich.triumf.ca) wrote:
: I'm wondering if anyone has pointers to a simple getchar() with
: a timeout. Curses has a good getch and timeout, but I don't want
: to use ncurses screen management or cooked escape sequences.

: I tried something based on the example in the select(2) man


: page, but that only signals once for every escape sequence or
: text-paste. Is there a way to see how many characters are
: available?

Yes, use ioctl(2) with the FIONREAD request. For example, on file
descriptor 'fd':

int ret, n_to_read;

errno = 0;
ret = ioctl( fd, FIONREAD, &n_to_read );
if( -1 == ret ) {
fprintf( stderr, "%s:%d -- ioctl() : %s\n",
__FILE__, __LINE__, strerror(errno) );
}

printf( "%d bytes read to read on descriptor %d\n", n_to_read, fd );

: I'm using Linux/gcc but the more general the solution, the better.


: (A fortran version would also be useful.) I figure there must be
: something very standard for this that I'm overlooking.

Here is my getch which allows for a time out. With a little hacking
you could make it work for any file desriptor, not just the file descriptor
associated with stdin.


/* these functions control the behavior of the keyboard. */

#define _XOPEN_SOURCE
#include <sys/types.h>
#include <sys/time.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

/* static file scope variables. */
static struct termios initial;
static struct termios current;
static int fd = STDIN_FILENO;

#ifdef USE_TIMEOUT
#define DEFAULT_TIMEOUT 10.0 /*for p_getch() */
#endif

/* functions */
static int non_canonical_kybd( void )
{
int ret_val;
ret_val = tcgetattr( fd, &initial );
if( -1 == ret_val ) {
perror( "tcgetattr()" );
return ret_val;
}

current = initial;
current.c_lflag &= ~ICANON;
current.c_lflag &= ~ISIG;
current.c_cc[VMIN] = 0;
current.c_cc[VTIME] = 0;

ret_val = tcsetattr( fd, TCSANOW, &current );
if( -1 == ret_val ) {
perror( "tcsetattr()" );
return ret_val;
}

tcflush( fd, TCIFLUSH );
return 0;
}

/* restores keyboard to it's starting state. Can be used as a signal
* handler in case the progam terminates unexpectedly.
*/
void restore_kybd( void )
{

int ret_val;

current = initial;

ret_val = tcsetattr( fd, TCSANOW, &current );
if( -1 == ret_val ) {
perror( "tcsetattr()" );
exit( EXIT_FAILURE );
}

tcflush( fd, TCIFLUSH );
return;

}

/* Paul's getch() function. */

/* p_getch() detects that a key has been pressed and returns the character
* which has been pressed. If no key has been pressed within the timeout,
* 0 is returned.
*/

int p_getch( void )
{
int sel_ret_val;
int s_set = fd + 1;
ssize_t n_read;

int ch = 0;

fd_set keyboard;
struct timeval timeout;

#ifdef USE_TIMEOUT
timeout.tv_sec = DEFAULT_TIMEOUT;
timeout.tv_usec = 0;
#endif

if( 0 != non_canonical_kybd() )
return ch;

FD_ZERO( &keyboard );
FD_SET( fd, &keyboard );


#ifdef USE_TIMEOUT
if( (sel_ret_val = select(s_set, &keyboard, NULL, NULL, &timeout)) < 0 )

#else /* wait forever for user user input */
if( (sel_ret_val = select(s_set, &keyboard, NULL, NULL, NULL)) < 0 )
#endif
perror( "select()" );

if( FD_ISSET(fd, &keyboard) ) {
n_read = read( fd, &ch, 1 );

if( n_read < 0 )
perror( "read()" );

}
restore_kybd();
return ch;
}


--
Paul D. Boyle
bo...@laue.chem.ncsu.edu
North Carolina State University
http://laue.chem.ncsu.edu/web/xray.welcome.html

Donald Arseneau

unread,
Mar 7, 2000, 3:00:00 AM3/7/00
to
jue...@monocerus.demon.co.uk (Juergen Heinzl) writes:

> In article <38C3ECCB...@tvd.be>, nightstalker wrote:

> >Donald Arseneau wrote:
> >
> >> I'm wondering if anyone has pointers to a simple getchar() with
> >> a timeout. Curses has a good getch and timeout, but I don't want
> >> to use ncurses screen management or cooked escape sequences.
>

> http://www.monocerus.demon.co.uk/httpd-server/juergen/code/c/unix/getch.html

Thanks everybody. It is working fine now based on Juergen's
example. That piece is very well explained, and seems to be
careful about the details.

> >void alarm_func()
> >{
> > printf("\n20 second time-out reached ... aborting !\n");
> > exit(0);
> >}

Although nightstalker's alarm example worked as shown, I couldn't
convert it to getchar(), and I couldn't see how to do anything
less drastic than exit() (unless I forked to read each character!)


bo...@laue.chem.ncsu.edu (Paul D. Boyle) writes:

> Yes, use ioctl(2) with the FIONREAD request. For example, on file

> ret = ioctl( fd, FIONREAD, &n_to_read );

This example is like my almost-successful try, and I think it
will work; I haven't tried it yet though.

Thanks again.

Donald Arseneau as...@triumf.ca

0 new messages