一个简单的shell实现
什么是内建命令
内建命令是由shell本身提供的命令,而不是通过外部程序(如位于/bin
、/usr/bin
等目录下的可执行文件)来执行的命令。这些命令在shell启动的时候就加载到内存中,执行效率相对较高。
常见的内建命令有:cd
,pwd
,echo
。
什么是当前路径
本质就是进程的工作目录,默认是进程在哪个目录底下执行,它的工作目录就是这个目录。
那这个工作目录可以更改吗?答案是可以的,使用chdir()
函数就可以更改当前进程的工作目录。
在我们自己实现一个简单的shell,执行cd命令的时候,你会发现路径没有变化。那是因为在执行命令的时候,我们是使用fork()出来的子进程来执行的cd,子进程有自己的工作目录(一般和父进程的工作目录相同),当执行cd的时候,更改的是子进程的目录,子进程执行完毕,什么都没了,继续用的是父进程,即shell。
简单的shell实现
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define NUM 1024
#define OP_NUM 64
char command[NUM];
char *myargv[OP_NUM];
int lastCode = 0;
int lastSig = 0;
int main()
{
while (1)
{
char *user = getenv("USER");
char *host = getenv("HOSTNAME");
printf("%s@%s 当前路径#", user, host);
fflush(stdout);
char *s = fgets(command, sizeof(command) -1, stdin);//获取命令行的输入
assert(s != NULL);
(void)s;
//清除用户按下的回车
command[strlen(command) - 1] = 0;
//字符串切割
myargv[0] = strtok(command, " ");
int i = 1;
//显示颜色
if (myargv[0] != NULL && strcmp(myargv[0], "ls") == 0)
{
myargv[i++] = (char*)"--color=auto";
}
//myargv[] 必须以NULL结尾,而strtok函数结束的时候返回NULL
//strtok()中的NULL表示从上次结束的位置继续查找下一个子串
while (myargv[i++] = strtok(NULL, " ")) {}
//不需要创建子进程,让shell自己执行对应的命令
if (myargv[0] != NULL && strcmp(myargv[0], "cd") == 0)
{
if (myargv[1] != NULL) chdir(myargv[1]);
continue;
}
if (myargv[0] != NULL && myargv[1] != NULL && strcmp(myargv[0], "echo") == 0)
{
if (strcmp(myargv[1], "$?") == 0) printf("%d, %d\n", lastCode, lastSig);
else printf("%s\n", myargv[1]);
continue;
}
//创建子进程
pid_t id = fork();
assert(id != -1);
if (id == 0)
{
//程序替换
execvp(myargv[0], myargv);
exit(1);
}
int status = 0;
pid_t ret = waitpid(id, &status, 0);
assert(ret > 0);
(void)ret;
lastCode = WEXITSTATUS(status);
lastSig = WIFEXITED(status);
}
}
标签:shell,Linux,NULL,简单,进程,myargv,include,目录
From: https://www.cnblogs.com/wzhiheng/p/18568477