How do *nix pseudo-terminals work ? What's the master/slave channel? How do *nix pseudo-terminals work ? What's the master/slave channel? linux linux

How do *nix pseudo-terminals work ? What's the master/slave channel?


With respect to the master/slave part of your question, from the pty(4) man page (which is referenced from the openpty(3) man page on my system):

A pseudo terminal is a pair of character devices, a master device and a slave device. The slave device provides to a process an interface identical to that described in tty(4). However, whereas all other devices which provide the interface described in tty(4) have a hardware device of some sort behind them, the slave device has, instead, another process manipulating it through the master half of the pseudo terminal. That is, anything written on the master device is given to the slave device as input and anything written on the slave device is presented as input on the master device.

Man pages are your friends.


I just tried the examples found on this tutorial, they work very fine for me and I think they are an interesting starting point for the problem.

EDIT:The tutorial explain briefly the pseudo-terminals function. The explanation is done step by step and is followed by examples.

The following example show how to create a new pseudo-terminal, and fork the process in two parts, one writing on the master side of the pseudo-terminal, the other reading from the slave side of the pseudo-terminal.

#define _XOPEN_SOURCE 600 #include <stdlib.h> #include <fcntl.h> #include <errno.h> #include <unistd.h> #include <stdio.h> #define __USE_BSD #include <termios.h> int main(void) { int fdm, fds, rc; char input[150]; fdm = posix_openpt(O_RDWR); if (fdm < 0) { fprintf(stderr, "Error %d on posix_openpt()\n", errno); return 1; } rc = grantpt(fdm); if (rc != 0) { fprintf(stderr, "Error %d on grantpt()\n", errno); return 1; } rc = unlockpt(fdm); if (rc != 0) { fprintf(stderr, "Error %d on unlockpt()\n", errno); return 1; } // Open the slave PTYfds = open(ptsname(fdm), O_RDWR); printf("Virtual interface configured\n");printf("The master side is named : %s\n", ptsname(fdm));// Creation of a child processif (fork()) {   // Father   // Close the slave side of the PTY   close(fds);   while (1)   {     // Operator's entry (standard input = terminal)     write(1, "Input : ", sizeof("Input : "));     rc = read(0, input, sizeof(input));     if (rc > 0)     {      // Send the input to the child process through the PTY       write(fdm, input, rc);       // Get the child's answer through the PTY       rc = read(fdm, input, sizeof(input) - 1);       if (rc > 0)       {         // Make the answer NUL terminated to display it as a string        input[rc] = '\0';         fprintf(stderr, "%s", input);       }       else       {         break;       }     }     else     {       break;     }   } // End while } else { struct termios slave_orig_term_settings; // Saved terminal settings struct termios new_term_settings; // Current terminal settings   // Child  // Close the master side of the PTY   close(fdm);   // Save the default parameters of the slave side of the PTY   rc = tcgetattr(fds, &slave_orig_term_settings);   // Set raw mode on the slave side of the PTY  new_term_settings = slave_orig_term_settings;   cfmakeraw (&new_term_settings);   tcsetattr (fds, TCSANOW, &new_term_settings);   // The slave side of the PTY becomes the standard input and outputs of the child process   close(0); // Close standard input (current terminal)   close(1); // Close standard output (current terminal)   close(2); // Close standard error (current terminal)   dup(fds); // PTY becomes standard input (0)   dup(fds); // PTY becomes standard output (1)   dup(fds); // PTY becomes standard error (2)   while (1)   {     rc = read(fds, input, sizeof(input) - 1);     if (rc > 0)     {       // Replace the terminating \n by a NUL to display it as a string      input[rc - 1] = '\0';       printf("Child received : '%s'\n", input);     }     else     {       break;     }   } // End while } return 0; } // main