将数组发送到 pipeline() 时出现 c 管道分段错误

发布于 2025-01-19 07:56:51 字数 2870 浏览 2 评论 0原文

该程序被设置为实现一个外壳。 首先,它从 user( 到 info[4]) 获取输入,然后指示输入是否包含管道,然后按照所需的步骤执行输入中的命令。 当我将 info[4] 初始化放在引号之间,并手动将命令放入 execlp 中时,它可以工作。但如果我不这样做,如果我的输入中甚至没有管道,则会出现分段错误。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include<readline/readline.h>
#include<readline/history.h>
#include <sys/wait.h>
#include <fcntl.h>
#define READ 0
#define WRITE 1
void printDir(){
    //display current directory
        char cwd[1024];
            getcwd(cwd, sizeof(cwd));
            printf("\nDir: %s>>", cwd);
}

void scanIn(char* str){
    char* buf;
    buf=readline(" ");
    if(strlen(buf)!=0){
        add_history(buf);
        strcpy(str,buf);
    }
}


int main(){
    pid_t childpid;
    char* cmdLine;
    int status;
    char* info[4];//0-first command,1-second command,2-first word of first command,3-first word of second command.
    int flag,i;
    char* token;
    int p[2];
    while(1){
        flag=0;
        i=0;
        printDir();//printing current directory
        scanIn(cmdLine);//scan input
        while(i<strlen(cmdLine)&&flag==0){//check if there's pipeline
            if(cmdLine[i]=='|'){
                flag++;
            }
            i++;
        }
        if(flag == 1){//if pipeline-split to two commands
            token=strtok(cmdLine,"|");
            if(token){
                info[0]=strdup(token);//store the first command
                token=strtok(NULL,"|");
                info[1]=strdup(token);//store the second command
            }
            info[2]=strdup(strtok(cmdLine," "));
            info[3]=strdup(strtok(token," "));
        }
        else{
            info[0]=strdup(cmdLine);//store the only command
            info[2]=strdup(strtok(cmdLine," "));//store the first word
        }
        if(strcmp(info[2],"exit")==0){//ip entered exit- then exit
            exit(0);
        }
        if(flag==0){/////////////////if no pipeline- fork once
            childpid=fork();
            if(childpid==0){
                execlp(info[2],info[0],NULL);
            }
            else{
                waitpid(childpid,&status,0);
            }
        }   
        else{///////////////////if pipeline- make 2 forks
            printf("p1_first:%s,p1:%s\n",info[2],info[0]);
            printf("p2_first:%s,p2:%s\n",info[3],info[1]);
            if(pipe(p)==-1){
                perror("pipe");
                exit(EXIT_FAILURE);
            }
            if(fork()==0){
                close(p[READ]);
                dup2(p[WRITE],WRITE);
                execlp(info[2],info[0],NULL);
            }
            if(fork()==0){
                close(p[WRITE]);
                dup2(p[READ],READ);
                execlp(info[3],info[1],NULL);
            }
            
        }
    }
    return 0;
}

the program is set to implement a shell.
At first, it takes input from user( to info[4]), then it indicates whether the input includes a pipe, and then it follows the needed steps to execute the commands from the input.
When I put the info[4] initiallization between quotes, and put the commands in execlp manually, it works. But if I dont, a segmentation error appears if I dont even have a pipeline in my input.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include<readline/readline.h>
#include<readline/history.h>
#include <sys/wait.h>
#include <fcntl.h>
#define READ 0
#define WRITE 1
void printDir(){
    //display current directory
        char cwd[1024];
            getcwd(cwd, sizeof(cwd));
            printf("\nDir: %s>>", cwd);
}

void scanIn(char* str){
    char* buf;
    buf=readline(" ");
    if(strlen(buf)!=0){
        add_history(buf);
        strcpy(str,buf);
    }
}


int main(){
    pid_t childpid;
    char* cmdLine;
    int status;
    char* info[4];//0-first command,1-second command,2-first word of first command,3-first word of second command.
    int flag,i;
    char* token;
    int p[2];
    while(1){
        flag=0;
        i=0;
        printDir();//printing current directory
        scanIn(cmdLine);//scan input
        while(i<strlen(cmdLine)&&flag==0){//check if there's pipeline
            if(cmdLine[i]=='|'){
                flag++;
            }
            i++;
        }
        if(flag == 1){//if pipeline-split to two commands
            token=strtok(cmdLine,"|");
            if(token){
                info[0]=strdup(token);//store the first command
                token=strtok(NULL,"|");
                info[1]=strdup(token);//store the second command
            }
            info[2]=strdup(strtok(cmdLine," "));
            info[3]=strdup(strtok(token," "));
        }
        else{
            info[0]=strdup(cmdLine);//store the only command
            info[2]=strdup(strtok(cmdLine," "));//store the first word
        }
        if(strcmp(info[2],"exit")==0){//ip entered exit- then exit
            exit(0);
        }
        if(flag==0){/////////////////if no pipeline- fork once
            childpid=fork();
            if(childpid==0){
                execlp(info[2],info[0],NULL);
            }
            else{
                waitpid(childpid,&status,0);
            }
        }   
        else{///////////////////if pipeline- make 2 forks
            printf("p1_first:%s,p1:%s\n",info[2],info[0]);
            printf("p2_first:%s,p2:%s\n",info[3],info[1]);
            if(pipe(p)==-1){
                perror("pipe");
                exit(EXIT_FAILURE);
            }
            if(fork()==0){
                close(p[READ]);
                dup2(p[WRITE],WRITE);
                execlp(info[2],info[0],NULL);
            }
            if(fork()==0){
                close(p[WRITE]);
                dup2(p[READ],READ);
                execlp(info[3],info[1],NULL);
            }
            
        }
    }
    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文