C programming question -- clearing keyboard buffer in linux

For a computer science class I’m taking, I have to write a simple shell on my Linux system, and one of the things required is to use alarm() to make the shell time out after 30 seconds and go to a lock screen, and you’re supposed to write a SIGALRM handler so that the user has to enter a username and password; if they enter the proper username and password, they’re supposed to return to the shell prompt.

But this has led me to two problems. The shell prompt is just a displayed string, followed by a gets() function to retrieve whatever string the user types in at the prompt. So gets() is interrupted when the alarm goes off and my SIGALRM handler takes over; thus, if the user enters the right username and password, it drops them back to the prompt – but what it actually returns to is the point where gets() is waiting for input, making it look like nothing has happened.

Well, I finally got around that by doing this:


signal(SIGALRM, alarm_handler);
siginterrupt(SIGALRM,1);

The first line sets my alarm_handler function to be used to handle the SIGALRM signal, and the siginterrupt line somehow interrupts the gets() function so it just drops back to the prompt instead of waiting for input before it displays the prompt again. So that pretty much fixed that.

But I still have another problem: if the user has typed anything at the prompt before the alarm kicks in and locks it, then the username prompt at the “shell locked, enter username and password to return” screen takes that as part of its input! So if the user had absently typed in, say, the letter p, and then the shell locks and displays the username prompt, and the person types in the correct username of “user1,” the gets() function for the username prompt actually takes in “puser1” as its input, even though it only displays “user1”.

Does anybody know how I can fix that? I’ve tried using other input functions like fgets and read, but they all do the same thing.

It’s classwork, so I feel bound to be a bit non-specific: You’ll likely find what you want in the man page for termios.

By the way, using gets() for anything is a really bad idea, although your teachers might let it slide.

Yeah, I realized that I changed that a while back; it’s actually using fgets() now.

Hey, thanks. I looked through it, and found:


int tcflush(int **fd**, int **queue_selector**);

tcflush() discards data written to the object referred to by fd but not
transmitted,  or  data received but not read, depending on the value of
queue_selector:

TCIFLUSH
     flushes data received but not read.

TCOFLUSH
     flushes data written but not transmitted.

TCIOFLUSH
     flushes both data received but not read, and  data  written  but
     not transmitted.

which sounded like what I needed. So right before my username: prompt, I did:

tcflush(0,TCIFLUSH);

0 for stidin, and TCIFLUSH to “flush data received but not read.” And that seems to have taken care of it!

Incidentally, I had sort-of gotten it to work before by doing this:



for(i=0;i<255;i++)
   ioctl(0,TIOCSTI,"\b");


Which basically stuffs 255 backspace characters into the keyboard buffer, but that still could have failed if the user had more than 255 characters waiting at the prompt, and it didn’t really feel like a proper solution anyway. Thanks for pointing me to the termios functions, Kyrie Eleison.

Oh, and just FYI, it

… forgot to finish that. I was going to say that the part I’m asking about isn’t really schoolwork – it’s not part of the requirements we’re graded on. It’s just something that was bothering me. Thanks for helping.