1 Star 0 Fork 0

suye/Linux入门到进阶

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
myshell.c 3.23 KB
一键复制 编辑 原始数据 按行查看 历史
suye 提交于 8个月前 . shell原理
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MARK ":"
#define LABLE "#"
#define DELIM " "
#define LINE_SIZE 1024
#define ARGC_SIZE 32
#define EXIT_CODE 44
int lastcode = 0;
int quit = 0;
extern char **environ;
char commandline[LINE_SIZE];
char *argv[ARGC_SIZE];
char myenv[LINE_SIZE];
char pwd[LINE_SIZE];
const char* getusername()
{
return getenv("USER");
}
const char* gethostname()
{
return getenv("HOSTNAME");
}
void getpwd()
{
getcwd(pwd, sizeof(pwd));
const char* home = getenv("HOME"); // 获取用户主目录
if (home != NULL && strcmp(pwd, home) == 0)
{
// 如果当前目录等于用户主目录,则返回 "~"
strcpy(pwd, "~");
}
else if (home != NULL && strncmp(pwd, home, strlen(home)) == 0) {
// 如果当前目录是用户主目录的子目录,则替换主目录部分为 "~"
static char relative_path[LINE_SIZE];
snprintf(relative_path, sizeof(relative_path), "~%s", pwd + strlen(home));
strcpy(pwd, relative_path);
}
}
void interact(char* cline, int size)
{
getpwd();
printf("%s@%s"MARK"%s"LABLE" ", getusername(), gethostname(), pwd);
char* s = fgets(cline, size, stdin);
assert(s);
// printf("echo: %s", s); // 验证能否接收命令以及命令行参数
cline[strlen(cline)-1] = '\0';
}
int splitstring(char* cline, char* _argv[])
{
int i = 0;
argv[i++] = strtok(cline, DELIM);
while(_argv[i++] = strtok(NULL, DELIM));
return i - 1;
}
int buildCommand(char* _argv[], int _argc)
{
if(_argc == 2 && strcmp(_argv[0], "cd") == 0)
{
getpwd();
chdir(_argv[1]);
sprintf(getenv("PWD"), "%s", pwd);
return 1;
}
else if(_argc == 2 && strcmp(_argv[0], "export") == 0)
{
strcpy(myenv, _argv[1]);
putenv(myenv);
return 1;
}
else if(_argc == 2 && strcmp(_argv[0], "echo") == 0)
{
if(strcmp(_argv[1], "$?") == 0)
{
printf("%d\n", lastcode);
lastcode = 0;
}
else if(*_argv[1] == '$')
{
char* val = getenv(_argv[1] + 1);
if(val) printf("%s\n", val);
}
else printf("%s\n", _argv[1]);
return 1;
}
if(strcmp(_argv[0], "ls") == 0)
{
_argv[_argc++] = "--color";
_argv[_argc] = NULL;
}
return 0;
}
void normalExcute(char* _argv[])
{
pid_t id = fork();
if(id < 0)
{
perror("fork");
return;
}
if(id == 0)
{
execvpe(_argv[0], _argv, environ);
exit(EXIT_CODE);
}
else
{
int status = 0;
int rid = waitpid(id, &status, 0);
if(id == rid) lastcode = WEXITSTATUS(status);
}
}
int main()
{
while(!quit)
{
// 1、交互获取命令行参数
interact(commandline, sizeof(commandline));
// 2、指令截取
int argc = splitstring(commandline, argv);
// 3、指令判断
if(argc == 0) continue;
// 4、执行内建命令
int n = buildCommand(argv, argc);
// 5、执行普通指令
if(!n) normalExcute(argv);
}
return 0;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/cdut_suye/linux.git
git@gitee.com:cdut_suye/linux.git
cdut_suye
linux
Linux入门到进阶
master

搜索帮助