#define _XOPEN_SOURCE 600
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include <pty.h>
#include <utmp.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <string.h>
#include <syslog.h>
int main(int argc, char *argv[])
{
int fdm, fds;
int rc;
char input[150];
char input_termail[150];
char fdsname[150];
// Check arguments
if (argc <= 1)
{
fprintf(stderr, "Usage: %s program_name [parameters]\n", argv[0]);
exit(1);
}
if (openpty(&fdm, &fds, fdsname, NULL, NULL) == -1)
{
fprintf(stderr, "error open pty pairs\n");
exit(1);
}
else
{
printf("the slave is %s\n", fdsname);
}
// Create the child process
if (fork())
{
// FATHER
// Close the slave side of the PTY
close(fds);
fd_set fd_in;
while (1)
{
// Wait for data from standard input and master side of PTY
FD_ZERO(&fd_in);
FD_SET(0, &fd_in);
FD_SET(fdm, &fd_in);
rc = select(fdm + 1, &fd_in, NULL, NULL, NULL);
switch (rc)
{
case -1:
{
fprintf(stderr, "Error %d on select()\n", errno);
exit(1);
}
default:
{
// If data on standard input
if (FD_ISSET(0, &fd_in))
{
memset(input, 0, sizeof(input));
rc = read(0, input, sizeof(input));
// printf("%s\n", input);
if (rc > 0)
{
// Send data on the master side of PTY
write(fdm, input, rc);
}
}
else
{
if (rc < 0)
{
fprintf(stderr, "Error %d on read standard input\n", errno);
exit(1);
}
}
// If data on master side of PTY
if (FD_ISSET(fdm, &fd_in))
{
memset(input_termail, 0, sizeof(input_termail));
rc = read(fdm, input_termail, sizeof(input_termail));
syslog(LOG_DEBUG, "input_termail = %s", input_termail);
if (rc > 0)
{
// Send data on standard output
write(1, input_termail, rc);
}
else
{
if (rc < 0)
{
fprintf(stderr, "Error %d on read master PTY\n", errno);
exit(1);
}
}
}
}
} // End switch
} // End while
}
else
{
// CHILD
// Close the master side of the PTY
close(fdm);
struct termios slave_orig_term_settings; // Saved terminal settings
struct termios new_term_settings; // Current terminal settings
// Save the defaults parameters of the slave side of the PTY
rc = tcgetattr(fds, &slave_orig_term_settings);
// Set RAW mode on slave side of PTY
new_term_settings = slave_orig_term_settings;
cfmakeraw(&new_term_settings);
tcsetattr(1, TCSAFLUSH, &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)
dup2(fds, 0);
dup2(fds, 1);
dup2(fds, 2);
// Now the original file descriptor is useless
close(fds);
// Make the current process a new session leader
setsid();
// As the child is a session leader, set the controlling terminal to be the slave side of the PTY
// (Mandatory for programs like the shell to make them manage correctly their outputs)
// ioctl(0, TIOCSCTTY, 1);
ioctl(0, TIOCSCTTY, 1);
// Execution of the program
{
char **child_av;
int i;
// Build the command line
child_av = (char **)malloc(argc * sizeof(char *));
for (i = 1; i < argc; i++)
{
child_av[i - 1] = strdup(argv[i]);
}
child_av[i - 1] = NULL;
rc = execvp(child_av[0], child_av);
}
// if Error...
return 1;
}
return 0;
}
linux pty( 伪终端)案例
最新推荐文章于 2024-03-06 19:04:31 发布