写shell时指针指向错误的问题

软件和网站开发以及相关技术探讨
回复
Feiurk
帖子: 6
注册时间: 2016-10-17 8:56

写shell时指针指向错误的问题

#1

帖子 Feiurk » 2016-10-31 18:59

最后想实现的功能是按下ctrl+c后显示出最近10个命令,想法是用queue来实现,但是好像指针有问题,导致输入第二个命令时,queue里的第一个命令会变为第二个命令。
比如先输入date,queue: date
再输入cal,queue:cal,cal

因此最后queue里所有的命令都是相同的,是最新的命令。请问如何修改?

代码: 全选

#include <signal.h>
// #include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
// #include <sys/wait.h>
#include <queue>
using namespace std;
#define BUFFER_SIZE 50
#define MAX_LINE 80 /* 80 chars per line, per command, should be enough. */


struct mes{//用于保存命令的参数,参数个数,是否并发执行,执行后是否错误
    char* _args[MAX_LINE/2+1];//参数,arg[0]为命令本身
    int len;//参数个数
    int bg;//是否并发
    int erno;//执行后是否错误

    mes(){
        len = 0;
        bg = false;
        memset(_args,0,sizeof(_args));
    }

    mes(char* new_args[],int _len,int _bg){
        len = _len;
        bg = _bg;

        for(int i = 0; i < len; ++i){
            _args[i] = new_args[i];
        }
        _args[len] = NULL;
        
    }

    void show(){//打印命令
        // cout<<"show";
        if(erno==-1) cout<<"ERROR:";
        // cout<<"show:"<<args[len - 1]<<endl;
        for(int i=0;i<len;i++) 
            cout<<_args[i]<<" ";
        if(bg) cout<<"&"<<endl;
        else cout<<endl;
    }

    ~mes(){
        memset(_args,0,sizeof(_args));
        // for(int i=0; i<len && args[i]; i++){
        //     delete args[i];
        //     args[i]=NULL;
        // }
        // delete[] args;
        // args=NULL;
    }
};

queue <mes*> rec, quetmp;
static int reclen = 0;
static int totlen = 0;

void readSplit(char inputBuffer[], char *args[], int * background){
    int length, /* # of characters in the command line */
        i,      /* loop index for accessing inputBuffer array */
        start,  /* index where beginning of next command parameter is */
        ct;     /* index of where to place the next parameter into args[] */
    ct = 0;
    
    /* read what the user enters on the command line */
    length = read(STDIN_FILENO, inputBuffer, MAX_LINE);

    start = -1;
    if (length == 0){
        // write(STDOUT_FILENO,inputBuffer,strlen(inputBuffer));//write the last instruction
        exit(0);            /* ^d was entered, end of user command stream */
    }
    if (length < 0){
        perror("error reading the command");
        exit(-1);           /* terminate with error code of -1 */
    }

    /* examine every character in the inputBuffer */
    for (i=0;i<length;i++) { 
        switch (inputBuffer[i]){
        case ' ':
        case '\t' :               /* argument separators */
            if(start != -1){
                args[ct] = &inputBuffer[start];    /* set up pointer */
                ct++;
            }
            inputBuffer[i] = '\0'; /* add a null char; make a C string */
            start = -1;
            break;

        case '\n':                 /* should be the final char examined */
            if (start != -1){
                args[ct] = &inputBuffer[start];     
                ct++;
            }
                    inputBuffer[i] = '\0';
                    args[ct] = NULL; /* no more arguments to this command */
            break;

        default :             /* some other character */
            if (start == -1)
                start = i;
                if (inputBuffer[i] == '&'){
                    *background  = 1;
                    inputBuffer[i] = '\0';
                }
        } 
    }

    args[ct] = NULL; /* just in case the input line was > 80 */
    // mes* pmes = new mes(args, ct, *background);
    cout<<"readSplit end"<<endl;
}



/**
 * setup() reads in the next command line, separating it into distinct tokens
 * using whitespace as delimiters. setup() sets the args parameter as a 
 * null-terminated string.
 */
//args end with NULL
//only deal with splitted command
void setup(char inputBuffer[], char *args[],int *background)
{
    if(!rec.empty()){
        cout<<"before read"<<endl;
        cout<<rec.front()->_args[0]<<endl;
    }
    readSplit(inputBuffer, args, background);
    if(!rec.empty()){
        cout<<"after read"<<endl;
        cout<<rec.front()->_args[0]<<endl;
    }
    int len = 0;
    while(args[len]) ++len;
    cout<<"new mess:"<<args[0]<<endl;
    mes* pmes = new mes(args, len, *background);

    // int * p_errno=(int*)mmap(NULL,sizeof(int)*2,PROT_READ|PROT_WRITE,\
        // MAP_SHARED|MAP_ANONYMOUS,-1,0);//共享内存以便传递子进程的执行结果
    int * p_errno;
    // int pid = fork();
    int pid = 0;
    // if(pid == 0){
        
    //     int erno = execvp(args[0], args);
    //     cout<<"setup test 1"<<endl;
    //     // *p_errno = erno;
        
    //     // _exit(0);
    // }
    // else{
    //     if(!(*background)){
    //         // waitpid(pid, NULL, 0);
    //     }
    // }
    pmes->erno = 1;
    // pmes->erno = *p_errno;
    cout<<"setup test"<<endl;
    if(!rec.empty()){
        cout<<"test"<<endl;
        cout<<"reclen"<<reclen<<endl;
        while(!rec.empty()){
            quetmp.push(rec.front());
            cout<<rec.front()->_args[0]<<endl;
            rec.pop();
        }
        cout<<"test end"<<endl;
        while(!quetmp.empty()){
            rec.push(quetmp.front());
            quetmp.pop();
        }

    }
    if(reclen < 10){
        cout<<"push"<<endl;
        rec.push(pmes);
        ++reclen;
        while(!rec.empty()){
            quetmp.push(rec.front());
            cout<<rec.front()->_args[0]<<endl;
            rec.pop();
        }
        cout<<"push end"<<endl;
        while(!quetmp.empty()){
            rec.push(quetmp.front());
            quetmp.pop();
        }
    }
    else{
        cout<<"pop"<<endl;
        rec.pop();
        rec.push(pmes);
    }
    ++totlen;
} 


// void handle_SIGINT(int sig){//历史缓存工具 ctrl+c
//     cout<<"this is ctrl+c"<<endl;  
//     int num = totlen - reclen, index = 0;
//     mes* ls[10];
//     cout<<endl;
//     while(!rec.empty()){
//         cout<<++num<<": ";
//         rec.front()->show();
//         quetmp.push(rec.front());
//         ls[index++] = rec.front();
//         rec.pop();
//     }
//     cout<<"rec.empty()"<<endl;
//     while(!quetmp.empty()){
//         rec.push(quetmp.front());
//         quetmp.pop();
//     }
//     cout<<"Exit record input \"q\", repeat command,\
// input \"r\" or \"r x\"(x is the prefix of command)"<<endl;

//     char buffer[MAX_LINE];
//     char *arguments[MAX_LINE/2+1];
//     int flag;
    
//     int exeNum = index - 1;
//     while(true){
//         readSplit(buffer, arguments, &flag);
//         int num_arg = 0;
//         while(arguments[num_arg]) ++num_arg;
//         if(num_arg == 0) continue;
//         if(strcmp(arguments[0], "p") == 0) break;
//         if(strcmp(arguments[0], "r") != 0){
//             cout<<"No such command"<<endl;
//             continue;
//         }

//         if(num_arg == 1){
//         }
//         else if(num_arg != 2 || strlen(arguments[1]) != 1){
//             cout<<"invalid input"<<endl;
//             continue;
//         }
//         else{
//             for(; exeNum >= 0; --exeNum){
//                 // char tmp = arguments[1][0];
//                 if(ls[exeNum]->args[0][0] == arguments[1][0]){
//                     break;
//                 }
//             }
//         }
//         if(exeNum >= 0){
//             ls[exeNum]->show();
//             if(ls[exeNum]->erno == -1){
//                 cout<<"It is an error command"<<endl;
//             }
//             else{
//                 setup(buffer, ls[exeNum]->args, & (ls[exeNum]->bg));
//             }
//         }
        
//     }

//     cout<<"record has quitted"<<endl;

// }

int main(void)
{
    char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */
    int background;             /* equals 1 if a command is followed by '&' */
    char *args[MAX_LINE/2+1];/* command line (of 80) has max of 40 arguments */
    
    // signal(SIGINT,handle_SIGINT);
    while (1){            /* Program terminates normally inside setup */
        background = 0;
        printf("COMMAND->");
        // printf("COMMAND->");
        // cout<<"COMMAND->";
        fflush(stdout);
        // readSplit(inputBuffer, args, &background);
        setup(inputBuffer,args,&background);       /* get next command */
    }
}
//date &->date blank  this is expected???
//date&->date
Feiurk
帖子: 6
注册时间: 2016-10-17 8:56

Re: 写shell时指针指向错误的问题

#2

帖子 Feiurk » 2016-10-31 19:29

打印测试后发现length = read(STDIN_FILENO, inputBuffer, MAX_LINE);之前queue的内容还是正常的,这之后queue里就全部变为最新命令了。
回复