手把手带你写一个minishell
先解释一下Shell : Shell是一个功能为命令行解释器的应用程序,连接了用户和Linux内核,让我们能高效和安全地使用Linux内核。
要写一个minishell,我们要先理解它的过程:
读取输入->>命令解析->>创建子进程->>(子进程)程序替换->>(父进程)进程等待
代码及注释如下:
//minishell:
//命令行解释器:
//从标准输入读取数据(scanf) ls -l -a
//ls----运行ls命令----ls命令是一个外部程序
//创建一个进程,让这个进程运行ls程序(程序替换)
//读取输入->>命令解析->>创建子进程->>程序替换->>(父进程)进程等待
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<ctype.h>
#include<errno.h>
#include<string.h>
#include<fcntl.h>
#include<sys/wait.h> void Minishell()
{
//循环执行
while(){ //启动格式
printf("minishell:");
fflush(stdout);
char str[]={}; //1.读取输入 ls -a
//需要解决的问题: 空格不截断输入
//scanf返回值:成功:赋值数量,失败:EOF
// %[^\n]---^代表非 []代表字符集,接收所有在\n之前的任意字符
// %*c---*表示不读入(直接取出缓冲区的下一个字符),%*c的作用是为了丢掉\n
if(scanf("%[^\n]%*c",str)!=)
{
getchar(); //接收失败,吸收返回的EOF
}
// printf("cmd:[%s]\n",str); //2.解析命令
//需要解决的问题:命令分割,存储位置
//空格分割命令,模拟命令行参数存储命令
char* p = str;
char* argv[] = {NULL};
int argc = ;
while(*p!='\0')
{
if(*p!=)
{
//存入一个命令
argv[argc]=p;
argc++;
//走到空格
while(*p != && *p!='\0')
{
p++;
}
continue;
}
//遇到空格,分割,加结束标志
else
{
*p='\0';
p++;
}
}
//查看解析
/*int i=0;
for(i;i<argc;i++)
{
printf("argv[%d]--%s\n",i,argv[i]);
}
*/ //3.创建子进程
int pid=fork();
if(pid<)
{
perror("pid error");
exit(-);
}
//4.程序替换
else if(pid==)
{
//功能 : 重定向 -- 使用dup2改变数据流向
int i;
for(i=;i<argc;i++)
{
//> 将原本要写入到终端显示的数据,写入到指定的文件中,并清空文件原有内容
if(strcmp(argv[i],">")==)
{
close();
//打开该文件
int fd = open(argv[argc-],O_CREAT | O_TRUNC | O_RDWR,);
if(fd<)
{
perror("open error\n");
return;
} dup2(fd,);
//直接写入数据
int len;
for(len=;len<i;++len)
{
printf("%s ",argv[len]);
}
printf("\n"); close(fd);
return;
}
//>> 将原本要写入到终端显示的数据,追加写入到指定的文件中
if(strcmp(argv[i],">>")==)
{
close();
//打开文件
int fd = open(argv[argc-],O_CREAT | O_APPEND | O_RDWR,);
if(fd<)
{
perror("open error\n");
return;
}
dup2(fd,);
//直接写入数据
int len;
for(len=;len<i;len++)
{
printf("%s ",argv[len]);
}
printf("\n");
close(fd);
return;
}
}
//非重定向直接程序替换
execvp(argv[],argv);
exit(-);
}
//5.父进程等待子进程退出
waitpid(pid,NULL,); }
} int main()
{
Minishell();
return ;
}
运行结果展示 :
手把手带你写一个minishell的更多相关文章
- 手把手带你做一个超炫酷loading成功动画view Android自定义view
写在前面: 本篇可能是手把手自定义view系列最后一篇了,实际上我也是一周前才开始真正接触自定义view,通过这一周的练习,基本上已经熟练自定义view,能够应对一般的view需要,那么就以本篇来结尾 ...
- 只有20行Javascript代码!手把手教你写一个页面模板引擎
http://www.toobug.net/article/how_to_design_front_end_template_engine.html http://barretlee.com/webs ...
- 手把手带你画一个动态错误提示 Android自定义view
嗯..再差1篇就可以获得持之以恒徽章了,今天带大家画一个比较简单的view. 转载请注明出处:http://blog.csdn.net/wingichoy/article/details/504771 ...
- 手把手用Monkey写一个压测脚本
版权声明: 本账号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影所有. 允许有条件转载,转载请附带底部二维码. 一.为什么需要一个测试脚本? 昨天讲解了Android Monkey命 ...
- 手把手教你写一个java的orm(五)
生成sql:where 上一篇里我们实现了生成insert的sql,下面要开始实现update,delete,select的sql语句了.但是这些语句有一个比较麻烦的地方是:它们一般后面都会有wher ...
- 手把手教你写一个java的orm(一)
写之前的说明 其实吧. 这个东西已经写好了,地址在:https://github.com/hjx601496320/JdbcPlus 这系列文章算是我写的过程的总结吧.(恩系列,说明我可能会写好久,╮ ...
- 手把手教你写一个RPC
1.1 RPC 是什么 定义:RPC(Remote Procedure Call Protocol)--远程过程调用协议 ,RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数 ...
- 让我手把手教你写一个强大、方便使用的 IOC 容器
一.介绍 1.介绍 最近无聊,也没什么事做,没事做总是要给自己找点事情做吧,毕竟人的生活在与折腾.于是,决定自己手动写一个 IOC 的框架.我们知道在 NetCore 的版本里面已经内置了 IOC 容 ...
- 手把手教你写一个RN小程序!
时间过得真快,眨眼已经快3年了! 1.我的第一个App 还记得我14年初写的第一个iOS小程序,当时是给别人写的一个单机的相册,也是我开发的第一个完整的app,虽然功能挺少,但是耐不住心中的激动啊,现 ...
随机推荐
- C语言博客06-结构体
1.本章学习总结 1.1 学习内容总结 结构体如何定义.成员如何赋值 1.结构体的一般形式为: struct 结构体名 { 数据类型 成员名1: 数据类型 成员名2: : 数据类型 成员名n: }: ...
- (11)Go方法/接收者
方法和接收者 Go语言中的方法(Method)是一种作用于特定类型变量的函数.这种特定类型变量叫做接收者(Receiver).接收者的概念就类似于其他语言中的this或者 self. 方法的定义格式如 ...
- (15)Go错误处理
1.erro(一般错误) package main import ( "errors" "fmt" ) func div(a, b int) (res int) ...
- solr(一) 单节点安装部署
一.solr简介 1.什么是solr? Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口.用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件 ...
- 卷积神经网络CNN学习笔记
CNN的基本结构包括两层: 特征提取层:每个神经元的输入与前一层的局部接受域相连,并提取该局部的特征.一旦该局部特征被提取后,它与其它特征间的位置关系也随之确定下来: 特征映射层:网络的每个计算层由多 ...
- Cloudera-Manager(一) —— 基本概念及使用
概念 Cloudera Manager(简称CM)是Cloudera公司开发的一款大数据集群安装部署利器,这款利器具有集群自动化安装.中心化管理.集群监控.报警等功能,极大的提高集群管理的效率. AP ...
- uploadifive 1.1.2 动态传参
之前用过Flash版本的uploadify,写过一篇关于uploadify动态传参的文章(点击打开链接).后来有了HTML5版本的上传控件,叫uploadifive,测试着用了一下,效果还不错.这里主 ...
- Android - Button(按钮)的响应点击事件的4种写法
Button控件setOnclickListener(View.OnClickListener listener)来接收一个点击事件的监听器 自定义一个点击事件监听器类让其实现View.OnClick ...
- rrr
# coding:utf-8 import pika username = 'feng' password = 'nihao' host = '192.168.1.144' credentials = ...
- Android 多用户
下面几篇介绍的不错,推荐看看 https://www.jianshu.com/p/3ad2163f7d34 Android 9.x 多用户机制 1 #Profile user创建过程 https: ...