带有fork和exec的简单shell
我正在尝试制作一个简单的shell,从PATH运行任何命令,比如ls或pwd du gedit等。我在exec上遇到了问题。我要求如果我输入空格,什么都不会发生,如果我输入exit,它就会终止。任何帮助都是非常感谢的带有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
#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
等待(空);
}
}
}
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/。我编辑了我原来的帖子。