Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带有fork和exec的简单shell_C_Shell_Fork_Exec_Implementation - Fatal编程技术网

带有fork和exec的简单shell

带有fork和exec的简单shell,c,shell,fork,exec,implementation,C,Shell,Fork,Exec,Implementation,我正在尝试制作一个简单的shell,从PATH运行任何命令,比如ls或pwd du gedit等。我在exec上遇到了问题。我要求如果我输入空格,什么都不会发生,如果我输入exit,它就会终止。任何帮助都是非常感谢的 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <sys/types.h> #includ

我正在尝试制作一个简单的shell,从PATH运行任何命令,比如ls或pwd du gedit等。我在exec上遇到了问题。我要求如果我输入空格,什么都不会发生,如果我输入exit,它就会终止。任何帮助都是非常感谢的

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

#define BUFFER 1024

int main() {
    char line[BUFFER];
    char* args[100];
    char* path = "";
    char program[20];


while(1){
    printf("$ ");
         if(!fgets(line, BUFFER, stdin))
          break;
          size_t length = strlen(line);
         if (line[length - 1] == '\n')
         line[length - 1] = '\0';
     if(strcmp(line, "exit")==0)  break;
         strcpy(program,path);           
         strcat(program,line);
    int pid= fork();              //fork child

        if(pid==0){               //Child
        execlp(program,line,(char *)NULL);    
    }else{                    //Parent
        wait(NULL);
}
}
}   
#包括
#包括
#包括
#包括
#包括
#包括
#定义缓冲区1024
int main(){
字符行[缓冲区];
字符*args[100];
char*path=“”;
char程序[20];
而(1){
printf($);
如果(!fgets(行、缓冲区、标准输入))
打破
尺寸/长度=标准长度(直线);
如果(行[长度-1]='\n')
行[长度-1]='\0';
如果(strcmp(行,“退出”)==0)中断;
strcpy(程序、路径);
strcat(程序、行);
int pid=fork();//fork子级
如果(pid==0){//Child
execlp(程序,行,(字符*)NULL);
}else{//Parent
等待(空);
}
}
}   
  • 您有2个
    fgets()
    调用。移除第一个
    fgets(行、缓冲区、标准输入)

  • 如果缓冲区中有空间,
    fgets()
    将读取换行符。您需要删除它,因为当您输入
    exit
    时,实际上您将输入
    exit\n
    ,并且没有命令作为
    /bin/exit\n

  • 下面的代码演示如何删除换行符:

        if(!fgets(line, BUFFER, stdin))
            break;
        char *p = strchr(line, '\n');
        if (p) *p = 0;
    
  • 你的用法是错误的。检查
    execl
    的手册。您需要传递参数:
    execl(程序,行,(char*)NULL)
    注意最后一个参数
    NULL
    的强制转换。如果将
    NULL
    定义为
    0
    ,则需要强制转换,因为
    execl
    是一个可变函数

  • 使用
    execvp
    修改的示例:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <string.h>
    
    #define BUFFER 1024
    
    int main(void) {
        char line[BUFFER];
    
        while(1) {
            printf("$ ");
            if(!fgets(line, BUFFER, stdin)) break;
            char *p = strchr(line, '\n');
            if (p) *p = 0;
            if(strcmp(line, "exit")==0) break;
            char *args[] = {line, (char*)0};
            int pid= fork();              //fork child
            if(pid==0) {               //Child
                execvp(line, args);
                perror("exec");
                exit(1);
            } else {                    //Parent
                wait(NULL);
            }
        }
    
        return 0;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #定义缓冲区1024
    内部主(空){
    字符行[缓冲区];
    而(1){
    printf($);
    如果(!fgets(行、缓冲区、标准输入)中断;
    char*p=strchr(第“\n”行);
    如果(p)*p=0;
    如果(strcmp(行,“退出”)==0)中断;
    char*args[]={line,(char*)0};
    int pid=fork();//fork子级
    如果(pid==0){//Child
    execvp(行,args);
    perror(“执行董事”);
    出口(1);
    }else{//Parent
    等待(空);
    }
    }
    返回0;
    }
    
    您好,请参见下面我的更正以及我的评论

    int main() {
    char line[BUFFER];
    char* args[100];
    char* path = "/bin/";
    char program[20];
    char command[50];
    
    while(1){
        printf("$ ");
        if(!fgets(line, BUFFER, stdin))
            break;
        memset(command,0,sizeof(command));
        if(strncmp(line, "exit", (strlen(line)-1))==0)  break;
        strncpy(command,line,(strlen(line)-1));
        strcpy(program, path);
        strcat(program,command);
        int pid= fork();              //fork child
        if(pid==0){               //Child
            execl(program,command,NULL);
            exit(0);// you must exit from the child because now you are inside while loop of child. Otherwise you have to type exit twice to exit from the application. Because your while loop also became the part of every child and from the child again it will call fork and create a child again
        }else{
            wait(NULL);
        }
     }
    }
    

    还要支持所有命令执行,请参见函数
    execl
    如何传递其中的参数。因此,您需要拆分您的命令并为
    execl

    正确创建参数列表,谢谢您的帮助。但我只是看到我需要执行$PATH目录中的任何程序。你怎么能做到这一点?此外,我想退出,即使我键入exit(后面的任何空格),然后使用exec的“path”变体(
    execlp
    execvp
    ,或
    execvpe
    )来搜索命令路径。我已经更新了答案,其中显示了如何使用
    strchr()
    删除换行符。我使用了execlp,但du(磁盘使用)命令或gedit不起作用。如果我没有弄错usr/bin上的路径变量,并且代码开头的路径变量没有包含它,对吗?是的,如果使用路径变量,则不要预先添加
    /bin/
    (就像在代码中一样)。您可以使用shell命令
    找到实际路径,该命令
    。例如,运行
    哪个gedit
    ,它会告诉你位置。你能帮我如何编码吗?我搞不好。我是否在开始时移除垃圾箱?我也不能使用哪一个进入程序,我可以吗?我需要执行usr/bin或/bin/。提前感谢我如何让它运行$PATH中的任何程序(也可以说是usr/bin),而不仅仅是/bin/。我编辑了我原来的帖子。