2

I googled a lot but haven't found any real solution satisfying my needs.

I need the forked child process to use the stdin and stdout of another terminal rather than the one that called it here an example of what I want to do

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

int main()
{
    pid_t pid;
    printf("process parent pid is %d\n",getpid());
    pid =fork();
    printf("process child pid is %d\n",pid);
    if(pid==0)
    {
        //int exit_status = system("gnome-terminal");
        char a[20];
        while(1)
        {
            scanf(" %s",a);
            printf("child %s \n",a);
        }
    }
    while(1)
    {
        char b[20];
        scanf(" %s",b);
        printf("parent  %s \n",b);
    }
}

I need the child for example to interact with the user through another terminal.

Mateusz Piotrowski
  • 8,029
  • 10
  • 53
  • 79
Mohammed Talat
  • 77
  • 2
  • 12
  • take a look at this link and see if that helps you along... http://stackoverflow.com/questions/15880196/keyboard-device-in-unix – Les Oct 15 '15 at 17:57
  • are you wanting to have your child process open its own "gnome-terminal"? – Les Oct 16 '15 at 00:53

2 Answers2

2

As I understand your question, you wish fork a child process that does all its interaction with the user through a virtual terminal, namely gnome-terminal. Then, first of all, read this article about the difference between terminals and shells. Then read this article about Unix Pseudo Terminals. Then read this one about the /dev/pts filesystem. This will give you the background for my answer.

Here is one way to create a child process that connects to a different terminal, a virtual terminal. I admit, I've not done this in a long time, and then it was with a physical TTY, not a pseudo-terminal. But the background information should help you get past any hangups you may run into.

The overall approach is to fork two child processes. One for the virtual terminal and one for the worker process. You will then exec the virtual terminal process in such a way that it does not shut down when the shell exits. You really don't even want it to launch a shell or any program for that matter, because you are going to be supplying the running process that will interact with it. With gnome-terminal, is not very easy to tell it to hang around after the process exits. You should read this to get suggestions on how to keep it around. An alternative would be to use "xterm" which has the "--hold" option which appears suited for that purpose. "xterm" also has the "-S" option which sounds exactly like what you need. To use the "-S" options, you will need to read about PTS

Since XTERM has the options you need, I will describe the approach based upon XTERM instead of gnome-terminal.

In your child program you will need to open /dev/ptmx to get a master pseudo-terminal file descriptor. You then call ptsname() on the FD to get the name of the PTS. You need the name to inform XTERM what slave PTS to use. You have to grant access and unlock the FD by calling grantpt() and unlockpt() on the master FD. Next, fork another process and exec() XTERM with the -S option, which takes the PTS name and file descriptor number in the form of "-S/dev/pts/123/42" or equivalently "-S123/42". In this case, I don't think you need the "--hold", but add it if it turns out that you do. (Refer to the XTERM man page for more information on using -S)

This establishes the terminal as the User I/O device on your child process's master pseuo-terminal file descriptor. So, next you would dup() the file descriptor onto fd 0 and fd 1 (and fd 2 if you want stderr to go there).

I am sorry this is so general. The approach should work, but you may have to tweak it for your specific flavor of Linux/Unix. Please let me know how you do, and if I get a chance, I will get a Linux up and try it out myself.

Community
  • 1
  • 1
Les
  • 10,335
  • 4
  • 40
  • 60
0

stdin is file descriptor 0. To attach to another file or stream (or device), your child process must first close file descriptor 0, then open another file (device). Open will return fd 0 (if successful) because it is now the first available. You can use dup() to do this atomically.

You will need permission to open the device.

For example, let's say your input device of interest is /dev/input/tty1...

if(childpid == 0)
{
    int fd = open("/dev/input/tty1", open_args);
    if(fd >= 0)
    {
        /* Close stdin, duplicate the fd just opened to stdin */
        dup2(0, fd);
        // etc...
Les
  • 10,335
  • 4
  • 40
  • 60
  • doing that will prevent the parent from accessing the stdin of the terminal isn't it? – Mohammed Talat Oct 15 '15 at 18:30
  • your answer seem to be good but i am having trouble understanding what you are trying to do. int open(const char *pathname, int flags); what /dev/input/tty1 has to do with the terminal what is tty1 sorry i am a little bit of newbie – Mohammed Talat Oct 15 '15 at 21:23
  • /dev/input/tty1 was an example device, your system probably doesn't have it. But to attach another terminal to your child process, you will have to know, or figure out, what is the device to use. – Les Oct 16 '15 at 00:44
  • i need to use a terminal to interact with the child process – Mohammed Talat Oct 16 '15 at 06:48