簡體   English   中英

為什么我不能在busybox中用'\\ t'模擬自動完成

[英]Why can't I simulate auto-completion with '\t' in busybox

我想通過利用busybox中的自動補全功能來使用“ yp \\ t \\ n \\ 0”運行“ ypdomainname”命令,但是失敗了。 我的代碼和結果如下:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>

#define DEFAULT_BUSYBOX_PATH "/bin/busybox"
#define MAX_BUF 1000

int main()
{
    int fd[2];
    pid_t pid;
    FILE *file;
    int status;

    if(pipe(fd) < 0){
        fprintf(stderr, "pipe error!\n");
        return -1;
    }

    if((pid = fork()) < 0){
        fprintf(stderr, "pipe error!\n");
    }else if(pid == 0){     //child
        close(fd[1]);

        int fd_output;
        fd_output = open("result", O_CREAT | O_RDWR, 777);

        if(fd_output != STDOUT_FILENO){
            if(dup2(fd_output, STDOUT_FILENO) != STDOUT_FILENO)
                fprintf(stderr, "dup2 error to stdout\n");
        }

        if(fd[0] != STDIN_FILENO){
            if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
                fprintf(stderr, "dup2 error to stdin\n");
        }
        execl(DEFAULT_BUSYBOX_PATH, DEFAULT_BUSYBOX_PATH, "ash", NULL);
        close(fd[0]);
        close(fd_output);
        return 0;
    }else{                  //parent
        close(fd[0]);

        char buf[MAX_BUF] = "yp";
        buf[2] = '\t';
        buf[3] = '\n';
        buf[4] = '\0';

        write(fd[1], buf, strlen(buf));

        close(fd[1]);
        return 0;
    }

}

我的代碼的結果

讓我感到困惑的是,該字符未在文件lineedit.c中的函數lineedit_read_key()中更改,並且當字符為'\\ t'時它將運行函數input_tab() 當字符為'\\ t'時,將執行input_tab

最近,我花了一些時間來學習有關終端的模擬自動完成功能,但是我仍然失敗了。 我的代碼如下:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <signal.h>
#include <pty.h>

#define DEFAULT_BUSYBOX_PATH "/bin/busybox"
#define MAX_BUF 1000
#define BUFFSIZE 512

typedef void Sigfunc(int);

static void sig_term(int);
static volatile sig_atomic_t sigcaught;

ssize_t writen(int fd, const void *ptr, size_t n){
    size_t nleft;
    ssize_t nwritten;

    nleft = n;
    while(nleft > 0){
        if((nwritten = write(fd, ptr, nleft)) < 0){
            if(nleft == n){
                return(-1); 
            }else{
                break; 
            }
        }else if(nwritten == 0) {
            break;
        }
        nleft -= nwritten;
        ptr += nwritten;
    }
    return(n - nleft);
}

Sigfunc *signal_intr(int signo, Sigfunc *func){
    struct sigaction act;
    struct sigaction oact;

    act.sa_handler = func;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
#ifdef  SA_INTERRUPT
    act.sa_flags |= SA_INTERRUPT;
#endif
    if (sigaction(signo, &act, &oact) < 0)
        return(SIG_ERR);
    return(oact.sa_handler);
}

int ptym_open(char *pts_name, int pts_namesz)
{
    char ptr[50];
    int fdm;
    int err;

    if((fdm = posix_openpt(O_RDWR)) < 0){
        return(-1);
    }   
    if(grantpt(fdm) < 0){ 
        goto errout;
    }           
    if(unlockpt(fdm) < 0){  
        goto errout;
    }       

    if(ptsname_r(fdm, ptr, 50) != 0){
        goto errout;
    }

    strncpy(pts_name, ptr, pts_namesz);
    pts_name[pts_namesz - 1] = '\0';
    return(fdm);            /* return fd of master */
errout:
    err = errno;
    close(fdm);
    errno = err;
    return(-1);
}

int ptys_open(char *pts_name){
    int fds;

    if((fds = open(pts_name, O_RDWR)) < 0)
        return(-1);

    return(fds);
}

pid_t pty_fork(int *ptrfdm, char *slave_name, int slave_namesz, 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, sizeof(pts_name))) < 0){
        fprintf(stderr, "can't open master pty: %s, error %d", pts_name, fdm);
    }   

    if(slave_name != NULL) {
        strncpy(slave_name, pts_name, slave_namesz);
        slave_name[slave_namesz - 1] = '\0';
    }

    if((pid = fork()) < 0) {
        return(-1);
    }else if (pid == 0) {       /* child */
        if(setsid() < 0){
            fprintf(stderr, "setsid error");
        }

        if((fds = ptys_open(pts_name)) < 0){
            fprintf(stderr, "can't open slave pty");
        }
        close(fdm);     

        if(slave_termios != NULL) {
            if (tcsetattr(fds, TCSANOW, slave_termios) < 0)
                fprintf(stderr, "tcsetattr error on slave pty");
        }
        if(slave_winsize != NULL) {
            if (ioctl(fds, TIOCSWINSZ, slave_winsize) < 0)
                fprintf(stderr, "TIOCSWINSZ error on slave pty");
        }

        if(dup2(fds, STDIN_FILENO) != STDIN_FILENO){
            fprintf(stderr, "dup2 error to stdin");
        }
        if(dup2(fds, STDOUT_FILENO) != STDOUT_FILENO){
            fprintf(stderr, "dup2 error to stdout");
        }
        if(dup2(fds, STDERR_FILENO) != STDERR_FILENO){
            fprintf(stderr, "dup2 error to stderr");
        }
        if(fds != STDIN_FILENO && fds != STDOUT_FILENO && fds != STDERR_FILENO){
            close(fds);
        }
        return(0);      
    } else {                    /* parent */
        *ptrfdm = fdm;  
        return(pid);    
    }
}

void loop(int ptym, int ignoreeof)
{
    pid_t   child;
    int     nread;
    char    buf[BUFFSIZE];

    if((child = fork()) < 0) {
        fprintf(stderr, "fork error");
    }else if(child == 0) {  
        /*for ( ; ; ){
            if((nread = read(STDIN_FILENO, buf, BUFFSIZE)) < 0){
                fprintf(stderr, "read error from stdin");
            }else if(nread == 0){
                break;
            }

            if(writen(ptym, buf, nread) != nread)
                fprintf(stderr, "writen error to master pty");
        }*/
        char *temp_buf = "yp\t\n";
        if(writen(ptym, temp_buf, strlen(temp_buf)) != strlen(temp_buf)){
            fprintf(stderr, "writen error to master pty");
        }

        if(ignoreeof == 0){
            kill(getppid(), SIGTERM);
        }

        exit(0);
    }

    if (signal_intr(SIGTERM, sig_term) == SIG_ERR)
        fprintf(stderr, "signal_intr error for SIGTERM");

    for( ; ; ){
        if ((nread = read(ptym, buf, BUFFSIZE)) <= 0){

        }
        //printf("nread = %d\n", nread);
        if (writen(STDOUT_FILENO, buf, nread) != nread){
            fprintf(stderr, "writen error to stdout");
        }
    }

    if (sigcaught == 0){
        printf("sigcaught == 0 and kill child\n");
        kill(child, SIGTERM);
    }   
}

static void sig_term(int signo)
{
    sigcaught = 1;      
}

int main(int argc, char *argv[]){
    int fd[2];
    pid_t pid;
    FILE *file;
    int status;
    int fdm;
    int ignoreeof;
    char slave_name[40];
    struct termios orig_termios;
    struct winsize size;

    pid = pty_fork(&fdm, slave_name, sizeof(slave_name), &orig_termios, &size);
    if(pid < 0){
        fprintf(stderr, "fork error!\n");
    }else if(pid == 0){  //child
        if(execl(DEFAULT_BUSYBOX_PATH, DEFAULT_BUSYBOX_PATH, "ash", NULL) < 0){
            fprintf(stderr, "can't execute: %s", DEFAULT_BUSYBOX_PATH);
        }
        /*if(execvp(argv[1], &argv[1]) < 0){
            fprintf(stderr, "can't execute: %s", argv[1]);
        }*/
    }

    loop(fdm, ignoreeof);
}

就像我第一次嘗試的結果一樣,結果是:ash:yp:not found。

您的代碼失敗,因為管道不是終端。 許多程序將使用isatty(3)等來檢測標准輸入是否已連接到終端並根據結果調整其行為。

您可以做的是使用openpty(3)打開一個偽終端對,並運行從屬設備復制到其標准輸入,輸出和錯誤描述符的命令,並使用主設備與之進行通信。 不幸的是,我現在沒有時間寫一個完整的解決方案,因為它相當復雜。 我曾經用Python完成過它,即使在那里也很棘手。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM