Irfan
Irfan

Reputation: 1768

Using IPC to redirect stdin within a while loop

I'm trying to write a string to clipboard on linux with C. I plan to use xsel -ib (takes a string from standard input and sets it as the current clipboard content). For example, in bash, doing echo Hello world | xsel -ib would set "Hello World" into the clipbord.

My code consists of a simple IPC that works well when my program (parent) finishes execution, but it doesn't work if I wrap the IPC inside a while loop.

#include<unistd.h>
void main()
{
    while (1) { // 1
        int pipes[2] = { 0 };
        pipe(pipes);
        if (fork()) {
            close(pipes[0]);
            write(pipes[1], "hello world", sizeof("hello world"));
        } else {
            close(0);
            dup2(pipes[0], STDIN_FILENO);
            close(pipes[1]);
            execl("/usr/bin/xsel", "xsel", "-ib", NULL);
        }
        printf("\nTesting..");
        sleep(3); // 2
    } // 3
}

If I remove the lines commented by "1", "2" and "3", it works fine. But having a while loop is essential for me to be able to output different strings to the clipboard every now and then. How do I do this without terminating my program.

Upvotes: 0

Views: 206

Answers (1)

user3185968
user3185968

Reputation:

Here are a few small changes that should make the program more debuggable, and fix at least some of the issues.

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
int main() /*correct declaration is int main()...*/
{
    while (1) { // 1
        int pipes[2] = { 0 };
        if (pipe(pipes)){
            perror("pipe() failed");
            exit(EXIT_FAILURE);
        }
        pid_t pid = fork();
        if (pid == -1){
            perror("fork() failed");
            exit(EXIT_FAILURE);
        }
        if (pid) {
            close(pipes[0]);
            write(pipes[1], "hello world", sizeof("hello world"));
            close(pipes[1]);
/*prevents file descriptor leak, also causes a read() to signal EOF rather than block indefinitely*/
            int status;
            wait(&status); /*prevents child zombification*/

        } else {
            close(0);
            dup2(pipes[0], STDIN_FILENO);
            close(pipes[1]);
            execl("/usr/bin/xsel", "xsel", "-ib", NULL);
        }
        printf("\nTesting..");
        sleep(3); // 2
    } // 3
}

Upvotes: 1

Related Questions