linux pty( 伪终端)案例

#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;
}
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值