⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 c实现模拟终端输入功能可以实现自动输入密码和其他命令的功能。
💻 C
字号:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <netdb.h>
#include <fcntl.h>
#include <time.h>
#include    <grp.h>
#include <ctype.h>
#include <dirent.h>

#include <sys/time.h>
#include <sys/wait.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <net/if.h>
	
#include <sys/stat.h>
#include <sys/types.h>
#include <termios.h>
#include <sys/ioctl.h>    /* 44BSD requires this too */
#include    <errno.h>        /* for definition of errno */
#include    <stdarg.h>        /* ANSI C header file */
#ifndef    TIOCGWINSZ
#include    <sys/ioctl.h>    /* 44BSD requires this too */
#endif

#define    BUFFSIZE    4096*10
#define    MAXLINE    4096   

static void    sig_term(int);
static volatile sig_atomic_t    sigcaught;    /* set by signal handler */
static void    set_noecho(int);    /* at the end of this file */
void        do_driver(char *);    /* in the file driver.c */
void        loop(int, int);        /* in the file loop.c */
void err_sys(const char *fmt, ...);
void tty_atexit(void);
void err_quit(const char *fmt, ...);
int tty_raw(int fd);
int s_pipe(int fd[2]);
int ptys_open(int fdm, char *pts_name);
int ptym_open(char *pts_name);
int tty_reset(int fd) ;
ssize_t writen(int fd, const void *vptr, size_t n);

typedef    void    Sigfunc(int);    /* for signal handlers */
void signal_intr(int signo, Sigfunc *func);
#if    defined(SIG_IGN) && !defined(SIG_ERR)
#define    SIG_ERR    ((Sigfunc *)-1)
#endif
static int                ttysavefd = -1;
static struct termios    save_termios;
static enum { RESET, RAW, CBREAK }    ttystate = RESET;

char passwd[1024]={0};

int main(int argc, char *argv[])
{
    int                fdm, c, ignoreeof, interactive, noecho, verbose;
    pid_t            pid;
    char            *driver, slave_name[20];
    struct termios    orig_termios;
    struct winsize    size;

    interactive = isatty(STDIN_FILENO);
    ignoreeof = 0;
    noecho = 0;
    verbose = 0;
    driver = NULL;

    opterr = 0;        /* don't want getopt() writing to stderr */
    while ( (c = getopt(argc, argv, "d:einvp:")) != EOF) {
        switch (c) {
        case 'd':        /* driver for stdin/stdout */
            driver = optarg;
            break;

        case 'e':        /* noecho for slave pty's line discipline */
            noecho = 1;
            break;

        case 'i':        /* ignore EOF on standard input */
            ignoreeof = 1;
            break;
        case 'n':        /* not interactive */
            interactive = 0;
            break;

        case 'v':        /* verbose */
            verbose = 1;
            break;
        case 'p':        /* verbose */
            strncpy(passwd,optarg,1023);
            break;

        case '?':
            err_quit("unrecognized option: -%c", optopt);
        }
    }
    if (optind >= argc)
        err_quit("usage: pty [ -d driver -einv -p passwd] program [ arg ... ]");

    if (interactive) {    /* fetch current termios and window size */
        if (tcgetattr(STDIN_FILENO, &orig_termios) < 0)
            err_sys("tcgetattr error on stdin");
        if (ioctl(STDIN_FILENO, TIOCGWINSZ, (char *) &size) < 0)
            err_sys("TIOCGWINSZ error");
        pid = pty_fork(&fdm, slave_name, &orig_termios, &size);

    } else
        pid = pty_fork(&fdm, slave_name, NULL, NULL);

    if (pid < 0)
        err_sys("fork error");

    else if (pid == 0) {        /* child */
        if (noecho)
            set_noecho(STDIN_FILENO);    /* stdin is slave pty */

        if (execvp(argv[optind], &argv[optind]) < 0)
            err_sys("can't execute: %s", argv[optind]);
    }

    if (verbose) {
        fprintf(stderr, "slave name = %s\n", slave_name);
        if (driver != NULL)
            fprintf(stderr, "driver = %s\n", driver);
    }

    if (interactive && driver == NULL) {
        if (tty_raw(STDIN_FILENO) < 0)    /* user's tty to raw mode */
            err_sys("tty_raw error");
        if (atexit(tty_atexit) < 0)        /* reset user's tty on exit */
            err_sys("atexit error");
    }

    if (driver)
        do_driver(driver);    /* changes our stdin/stdout */

    loop(fdm, ignoreeof);    /* copies stdin -> ptym, ptym -> stdout */

    exit(0);
}
static void set_noecho(int fd)        /* turn off echo (for slave pty) */
{
    struct termios    stermios;

    if (tcgetattr(fd, &stermios) < 0)
        err_sys("tcgetattr error");

    stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
    stermios.c_oflag &= ~(ONLCR);
            /* also turn off NL to CR/NL mapping on output */

    if (tcsetattr(fd, TCSANOW, &stermios) < 0)
        err_sys("tcsetattr error");
}

void do_driver(char *driver)
{
    pid_t    child;
    int        pipe[2];

        /* create a stream pipe to communicate with the driver */
    if (s_pipe(pipe) < 0)
        err_sys("can't create stream pipe");

    if ( (child = fork()) < 0)
        err_sys("fork error");

    else if (child == 0) {            /* child */
        close(pipe[1]);

                /* stdin for driver */
        if (dup2(pipe[0], STDIN_FILENO) != STDIN_FILENO)
            err_sys("dup2 error to stdin");

                /* stdout for driver */
        if (dup2(pipe[0], STDOUT_FILENO) != STDOUT_FILENO)
            err_sys("dup2 error to stdout");
        close(pipe[0]);

                /* leave stderr for driver alone */

        execlp(driver, driver, (char *) 0);
        err_sys("execlp error for: %s", driver);
    }

    close(pipe[0]);        /* parent */

    if (dup2(pipe[1], STDIN_FILENO) != STDIN_FILENO)
        err_sys("dup2 error to stdin");

    if (dup2(pipe[1], STDOUT_FILENO) != STDOUT_FILENO)
        err_sys("dup2 error to stdout");
    close(pipe[1]);

    /* Parent returns, but with stdin and stdout connected
       to the driver. */
}

pid_t pty_fork(int *ptrfdm, char *slave_name,
         const struct termios *slave_termios,
         const struct winsize *slave_winsize)
{
    int        fdm, fds;
    pid_t    pid;
    char    pts_name[20];

    if ( (fdm = ptym_open(pts_name)) < 0)
        err_sys("can't open master pty: %s", pts_name);

    if (slave_name != NULL)
        strcpy(slave_name, pts_name);    /* return name of slave */

    if ( (pid = fork()) < 0)
        return(-1);

    else if (pid == 0) {        /* child */
        if (setsid() < 0)
            err_sys("setsid error");

                    /* SVR4 acquires controlling terminal on open() */
        if ( (fds = ptys_open(fdm, pts_name)) < 0)
            err_sys("can't open slave pty");
        close(fdm);        /* all done with master in child */

#if    defined(TIOCSCTTY) && !defined(CIBAUD)
                /* 44BSD way to acquire controlling terminal */
                /* !CIBAUD to avoid doing this under SunOS */
        if (ioctl(fds, TIOCSCTTY, (char *) 0) < 0)
            err_sys("TIOCSCTTY error");
#endif
                /* set slave's termios and window size */
        if (slave_termios != NULL) {
            if (tcsetattr(fds, TCSANOW, slave_termios) < 0)
                err_sys("tcsetattr error on slave pty");
        }
        if (slave_winsize != NULL) {
            if (ioctl(fds, TIOCSWINSZ, slave_winsize) < 0)
                err_sys("TIOCSWINSZ error on slave pty");
        }
                /* slave becomes stdin/stdout/stderr of child */
        if (dup2(fds, STDIN_FILENO) != STDIN_FILENO)
            err_sys("dup2 error to stdin");
        if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO)
            err_sys("dup2 error to stdout");
        if (dup2(fds, STDERR_FILENO) != STDERR_FILENO)
            err_sys("dup2 error to stderr");
        if (fds > STDERR_FILENO)
            close(fds);
        return(0);        /* child returns 0 just like fork() */

    } else {                    /* parent */
        *ptrfdm = fdm;    /* return fd of master */
        return(pid);    /* parent returns pid of child */
    }
}

void loop(int ptym, int ignoreeof)
{
    pid_t    child;
    int        nread;
    char    buff[BUFFSIZE];
	char    tmp[1024];
	FILE 	*fp;

	long long 	i = 0;
	
    if ( (child = fork()) < 0) {
        err_sys("fork error");

    } else if (child == 0) {    /* child copies stdin to ptym */
        for ( ; ; ) {
            if ( (nread = read(STDIN_FILENO, buff, BUFFSIZE)) < 0)
                err_sys("read error from stdin");
            else if (nread == 0)
                break;        /* EOF on stdin means we're done */
			
            if (writen(ptym, buff, nread) != nread)
                err_sys("writen error to master pty");
        }

            /* We always terminate when we encounter an EOF on stdin,
               but we only notify the parent if ignoreeof is 0. */
        if (ignoreeof == 0)
            kill(getppid(), SIGTERM);    /* notify parent */
        exit(0);    /* and terminate; child can't return */
    }

        /* parent copies ptym to stdout */
    signal_intr(SIGTERM, sig_term);
	sleep(1);
    for ( ; ; ) {
        if ( (nread = read(ptym, buff, BUFFSIZE-4)) <= 0)
            break;        /* signal caught, error, or EOF */
		
        if(i < 10){
	    	if(strstr(buff,"password:")!= NULL){
	    		sprintf(tmp,"%s\n",passwd);
	    		writen(ptym, tmp, strlen(tmp));
	    	}
	    	if(strstr(buff,"Are you sure you want to continue connecting (yes/no)?"))
	    	{
	    		sprintf(tmp,"%s\n","yes");
	    		writen(ptym, tmp, strlen(tmp));
	    	}
	    }
        if (writen(STDOUT_FILENO, buff, nread) != nread)
            err_sys("writen error to stdout");
        memset(buff,0,BUFFSIZE);
        i++;
    }

    /* There are three ways to get here: sig_term() below caught the
     * SIGTERM from the child, we read an EOF on the pty master (which
     * means we have to signal the child to stop), or an error. */

    if (sigcaught == 0)    /* tell child if it didn't send us the signal */
        kill(child, SIGTERM);
    return;        /* parent returns to caller */
}
/* The child sends us a SIGTERM when it receives an EOF on
 * the pty slave or encounters a read() error. */

static void sig_term(int signo)
{
    sigcaught = 1;        /* just set flag and return */
    return;                /* probably interrupts read() of ptym */
}
static void err_doit(int errnoflag, const char *fmt, va_list ap)
{
    int        errno_save;
    char    buf[MAXLINE];

    errno_save = errno;        /* value caller might want printed */
    vsprintf(buf, fmt, ap);
    if (errnoflag)
        sprintf(buf+strlen(buf), ": %s", strerror(errno_save));
    strcat(buf, "\n");
    fflush(stdout);        /* in case stdout and stderr are the same */
    fputs(buf, stderr);
    fflush(NULL);        /* flushes all stdio output streams */
    return;
}
void err_sys(const char *fmt, ...)
{
    va_list        ap;

    va_start(ap, fmt);
    err_doit(1, fmt, ap);
    va_end(ap);
    exit(1);
}
void tty_atexit(void)        /* can be set up by atexit(tty_atexit) */
{
    if (ttysavefd >= 0)
        tty_reset(ttysavefd);
}
void err_quit(const char *fmt, ...)
{
    va_list        ap;

    va_start(ap, fmt);
    err_doit(0, fmt, ap);
    va_end(ap);
    exit(1);
}

int tty_raw(int fd)        /* put terminal into a raw mode */
{
    struct termios    buf;

    if (tcgetattr(fd, &save_termios) < 0)
        return(-1);

    buf = save_termios;    /* structure copy */

    buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
                    /* echo off, canonical mode off, extended input
                       processing off, signal chars off */

    buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
                    /* no SIGINT on BREAK, CR-to-NL off, input parity
                       check off, don't strip 8th bit on input,
                       output flow control off */

    buf.c_cflag &= ~(CSIZE | PARENB);
                    /* clear size bits, parity checking off */
    buf.c_cflag |= CS8;
                    /* set 8 bits/char */

    buf.c_oflag &= ~(OPOST);
                    /* output processing off */

    buf.c_cc[VMIN] = 1;    /* Case B: 1 byte at a time, no timer */
    buf.c_cc[VTIME] = 0;

    if (tcsetattr(fd, TCSAFLUSH, &buf) < 0)
        return(-1);
    ttystate = RAW;
    ttysavefd = fd;
    return(0);
}

int s_pipe(int fd[2]) /* two file descriptors returned in fd[0] & fd[1] */
{
    return( pipe(fd) );
}
int ptym_open(char *pts_name)
{
    int        fdm;
    char    *ptr1, *ptr2;

    strcpy(pts_name, "/dev/ptyXY");
      /* array index: 0123456789 (for references in following code) */
    for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
        pts_name[8] = *ptr1;
        for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
            pts_name[9] = *ptr2;
//printf(pts_name);
                        /* try to open master */
            if ( (fdm = open(pts_name, O_RDWR)) < 0) {
                if (errno == ENOENT)    /* different from EIO */
                    return(-1);            /* out of pty devices */
                else
                    continue;            /* try next pty device */
            }

            pts_name[5] = 't';    /* change "pty" to "tty" */
            return(fdm);        /* got it, return fd of master */
        }
    }
    return(-1);        /* out of pty devices */
}

int ptys_open(int fdm, char *pts_name)
{
    struct group    *grptr;
    int                gid, fds;

    if ( (grptr = getgrnam("tty")) != NULL)
        gid = grptr->gr_gid;
    else
        gid = -1;        /* group tty is not in the group file */

            /* following two functions don't work unless we're root */
    chown(pts_name, getuid(), gid);
    chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP);

    if ( (fds = open(pts_name, O_RDWR)) < 0) {
        close(fdm);
        return(-1);
    }
    return(fds);
}
int tty_reset(int fd)        /* restore terminal's mode */
{
    if (ttystate != CBREAK && ttystate != RAW)
        return(0);

    if (tcsetattr(fd, TCSAFLUSH, &save_termios) < 0)
        return(-1);
    ttystate = RESET;
    return(0);
}
void signal_intr(int signo, Sigfunc *func)
{
    struct sigaction    act, oact;

    act.sa_handler = func;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;

    sigaction(signo, &act, &oact);
    return;
}
ssize_t writen(int fd, const void *vptr, size_t n)
{
    size_t        nleft, nwritten;
    const char    *ptr;

    ptr = vptr;    /* can't do pointer arithmetic on void* */
    nleft = n;
    while (nleft > 0) {
        if ( (nwritten = write(fd, ptr, nleft)) <= 0)
            return(nwritten);        /* error */

        nleft -= nwritten;
        ptr   += nwritten;
    }
    return(n);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -