How to programmatically send the Enter key in C - c

This is a C console/terminal program.
I would like to let the user wait for the program to do some background work until either the background work finishes or the user clicks on the <Enter> key. I do that with a statement:
getchar();
and I have another thread doing the background work.
When the thread is about to finish, I would like the thread to send programmatically the <Enter> key so that the control continues after the getchar() statement.
How is this possible?

The getchar() function will block until a character arrives. Though not standard C, you can use a select call in a loop to wait until a given file handle is readable, then read it. That would go something like the following demo code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
int main(void) {
fd_set rfds;
struct timeval tv;
int retval;
puts("Waiting for a character ...");
for (;;) {
FD_ZERO(&rfds);
FD_SET(0, &rfds);
tv.tv_sec = 1;
tv.tv_usec = 0;
if (select(1, &rfds, NULL, NULL, &tv) > 0) break;
puts("Delay over, doing some stuff, then waiting ...");
}
int ch = getchar();
printf("Character available, it was '%c'.\n", ch);
return 0;
}
In your particular case, I wouldn't have an infinite loop for(;;). Rather, I'd do something like:
int stillRunning = 1;
while (stillRunning) {
...
}
and then have the background task set stillRunning to zero to cause the loop to exit regardless of a keypress.

Related

C Ctrl+D redirection to do smtg else

I am writting a program that copy the bash behaviour,
I use a while loop that stop if a variable "stop" is filled.
I want to get the ctrl-D signal when I press Ctrl-D only to fill the variable stop instead of stopping everything, is it possible
#include <signal.h>
void sigint_do(int sig) //handle the crtl c signal
{
signal(SIGINT, sigint_do);
sig = sig;
fflush(stdout);
}
int main()
{
signal(SIGINT, sigint_do);
int stop = -1;
while (stop < 0)
//do smg
if (stop >= 0)
{
free all allocation needed;
exit(stop);
}
return 0;
}
i already use a signal handling for ctrl-C with signal.h but i don't understand how to do modify the variable "stop" in the signal handler function if the Ctrl-D is seen.
could you give me any tip please?
CTRL+D is not a signal. It is simply translated by the system to the EOF symbol.
You can detect it if the read() command returns 0 for example.
You can use readline(). It returns NULL when ctrl + D is pressed. (For me read worked not really well).
something like:
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
int main ( void )
{
char *line;
line = readline(":");
while(line)
{
line = readline(":");
}
return (0);
}

Read input from console without waiting unconditionally(Non waiting scanf)

I am trying to write a code to read input from the console continuously and update a variable in the application. But if we use scanf function, whenever the function hits it expects an input from the user through console and continues with further instruction only if it receives an input from the console, otherwise it waits unconditionally.
My code is something like
int x, y;
while(1)
{
scanf("%d", &x);
y = x;
----
----
//Remaining code for execution
}
My expectation is the application should not be waiting for input from the console. If the user enters some input in the console, it should read and use that input, otherwise even if no input is entered, the application should execute remaining instructions or it should use the old values. Is there any other way to write such code without using scanf? Thanks!
You can select()/epoll() function for taking input, if timeout occurs it will proceed further.
Since stdin is also an FD, you can register than FD for select to work on that given FD.
Refer : https://stackoverflow.com/a/21198059/6686352
You can use select() with a zero (not NULL) timeout to check if data is available, and only then call scanf.
Example (without correct error handling):
#include <stdio.h>
#include <unistd.h>
#include <sys/select.h>
int main()
{
int x;
fd_set fds;
struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
while (1) {
FD_ZERO(&fds);
FD_SET(0, &fds); // Watch stdin (fd 0)
if (select(1, &fds, NULL, NULL, &tv)) {
scanf("%d", &x);
printf("Got %d from stdin", x);
}
printf("Working..\n");
sleep(1);
}
}
You can set stdin to non-blocking with fcntl. This makes scanf return early with EAGAIN if it would otherwise have blocked.
Example (without correct error handling):
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
int x;
fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
while (1) {
int ret = scanf("%d", &x);
if (ret > 0)
printf("Got %d from stdin", x);
printf("Working..\n");
sleep(1);
}
}

Child operation with select() does not stop running after execvp()

Running this snippet of code to experiment with piping and signals. I'm trying to learn how to properly utilize the select() function between pipes.
This process will fork. If there is something to be read from stdIn it is then written to the write end of the pipe. It is supposed to execute either a basic command entered via terminal, or it runs hard-coded commands in the code. (It's running hard code right now as "ls.")
When I run this snippet, it should quit and stop running completely when I press the letter "q" followed by ENTER, or it should quit after it runs its assigned process.
Instead, even after I hit "q" or run the process it won't stop the program completely. It is still waiting for input. It will stop running once I have hit ENTER, but it never even executes my process.
For example, if I compile and run this as "./test ls" or even just run "./test" (because ls is hard-coded in so that SHOULD just run I think), it will not run the command ls. And the program will continue to run until I've hit ENTER again.
I'm certain my rudimentary understanding of select() has to do with this issue. I'm pretty sure my select() statement needs to break at some point but I don't know what or how to check for this.
I was told that there is a method WIFEXITED() that might be able to help me but I'm just not sure how it applies in this context.
I also would like to know how to check if your pipes are empty!
I DO know that I want this to be able to both take input from the terminal and record it and also run built in functions.
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <stdio.h>
int main() {
int in[2]; // parent writes; child reads
pipe(in);
if (fork() == 0) {
// instantiate the values that will be execed
char *a[2];
//a[0] = "./test3";
a[0] = "ls";
a[1] = NULL;
// redirects what is being read from stdin to the pipe
//this redirection is for a separate test that is not included
close(in[1]);
close(0);
dup(in[0]);
close(in[0]); // close read
execvp(a[0], a);
}
else {
close(in[0]); // only want parent to write
// select() params
int nfds = 3;
int check = -1;
int done = 0;
fd_set readfds;
fd_set writefds;
FD_ZERO(&readfds); // set select params
FD_SET(0, &readfds);
FD_SET(in[1], &writefds);
while ((check = select(nfds, &readfds, &writefds, NULL, NULL)) > 0) {
int size = 0;
char buf[1000];
// write to pipe for child
if (FD_ISSET(0, &readfds) && FD_ISSET(in[1], &writefds)) {
while ((size = read(0, buf, sizeof(buf))) != 0) {
write(in[1], buf, size);
}
}
// reset
FD_ZERO(&readfds);
FD_SET(0, &readfds);
FD_SET(in[1], &writefds);
}
printf("%d --------------- %d\n", (FD_ISSET(in[1], &writefds)),
FD_ISSET(0, &readfds));
}
return 0;
}
Here is the potential set of test code that can be run with the above snipped if a[0] = ./test is uncommented and a[0] = ls is commented.
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
int main () {
int fd;
char buf[11];
int ret, sret;
int flag = 0;
fd = 0;
fd_set readfds;
struct timeval timeout;
while(1) {
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
timeout.tv_sec = 5;
timeout.tv_usec = 0;
sret = select(fd + 1, &readfds, NULL, NULL, NULL);
memset((void *) buf, 0, 11);
ret = read(fd, (void *) buf, 10);
flag = strcmp(buf, "q\n") == 0;
if (flag) {
return 0;
}
printf("ret = %d\n", ret);
if(ret != -1) {
printf(" buf = %s\n", buf);
}
}
return 0;
}

select() Blocks in a While Loop when I press Enter Twice

So, I want this program to wait for 5 seconds for an input. If there is no input it returns. If there is input, it renews the timer and starts the count again.
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
char buf[1024];
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait up to five seconds. */
do {
tv.tv_sec = 5;
tv.tv_usec = 0;
printf("Please enter a number: \n");
retval = select(1, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
if (retval == -1)
perror("select()");
else if (retval) {
scanf("%[^\n]%*c", buf);
}
else
printf("No data within five seconds.\n");
} while (tv.tv_sec != 0 && tv.tv_usec != 0);
exit(EXIT_SUCCESS);
}
It works fine with regular input, but when I press enter twice, it goes into infinite loop. Why? What is happening?
You need to put FD_SET(0, &rfds); within the loop...
... if it select times out, the rfds structure will be reset
as if FD_ZERO() had been called....
Additionally, I might suggest you change the scanf() to a more simple fgets() if moving the FD_SET() doesn't totally solve your problem (in any event, FD_SET needs to be moved).

Child process unable to read from created pseudo terminal

I'm trying to write an app that can login to SSH with a password, by using pseudo terminals. But if I write() to the master device then the data somehow does not appear in the slave device. Here's a simple test case:
#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#ifdef __linux__
#include <pty.h>
#else
#include <util.h>
#endif
int
main() {
int master;
pid_t pid = forkpty(&master, NULL, NULL, NULL);
if (pid == 0) {
int ch;
read(0, &ch, 1);
_exit(1);
} else {
printf("Press Enter to send a byte.\n");
getchar();
write(master, "1", 1);
printf("Done. Waiting for process to exit...\n");
waitpid(pid, NULL, 0);
return 0;
}
}
The app will first output "Press Enter to send a byte". After pressing Enter, I expect the child process's read() to return. But the read() there seems to block indefinitely even though the master's write() succeeds, so the master waits forever on the waitpid(). What's going on?
The problem is that you didn't modify the line discipline of the PTY. The default line discipline is line oriented, so no input will be sent to the slave process until a newline character is read. (You can see this by sending a "\n" to the slave, instead of just "1".) You can run the PTY in RAW mode by, in the child process, calling tcgetattr, cfmakeraw and tcsetattr, like follows:
if (pid == 0) {
int ch;
struct termios t;
tcgetattr(0, &t);
cfmakeraw(&t);
tcsetattr(0, TCSANOW, &t);
read(0, &ch, 1);
_exit(1);
} else {
This seems to work for me.
The example code at this blog post should probably be of help. The author has an update to his original problem (very similar to yours) with a usable spawn (char *argv[]); function given.

Resources