20165223 《信息安全系统设计基础》 实现mybash
一、了解 mybash
1. 简介
bash 是 Bourne Again Shell 的缩写,是linux默认的标准shell(也是大家常说的系统内核),bash也是Unix/Linux上常见的Shell脚本解释器,既然bash是标准的shell,那么就有非标准的sh,csh,ksh等等,我们常说有多少种Shell,其实说的是Shell脚本解释器,Shell是一种脚本语言,那么,就必须有解释器来执行这些脚本,bash是基于Bourne shell创建的,并且吸收了C shell和Korn shell的一些特性,而且bash完全兼容sh,也就是说,用sh写的脚本可以不加修改的在bash中执行。
——摘自《Unix/Linux里面的bash是什么》
- 通常shell中执行命令的流程都是bash进程创建了一个子进程,然后子进程进程替换,替换为可执行的命令文件。
- bash shell是sh shell的增强版本,目前linux大部分(默认)使用的都是bash shell。
2. mybash 输出信息格式
- [用户名@主机名所在文件]$(root用户:[用户名@主机名所在文件]#)
- 当所在文件就是当前用户的home目录时显示“~”
二、研究 mybash 实现需要的系统调用
(1)fork()
fork() 函数通过系统调用创建一个与原来进程几乎完全相同的进程,每个进程都启动一个从代码的同一位置开始执行的线程,父子两个进程中的线程能同时执行不同的指令要求。
(1)当调用fork()函数时,在该位置进程一分为二,一个是父进程,一个是子进程。
(2)若调用成功返回的是两个值:父进程返回的值为子进程标志;子进程返回的值为0,不成功返回为-1。
- 使用
man fork
查看
- 找到需要的头文件和函数参数
#include <unistd.h>
pid_t fork(void);
(2)exec()
系统调用 execv() 对当前进程进行替换,替换者为一个指定的可执行程序,其参数包括文件名(filename)、参数列表(argv) 以及环境变量 (envp) 。exec函数族不止一个,但它们大致相同,在 Linux 中,它们分别是:execl,execlp,execle,execv,execve 和 execvp 。
- 使用
man exec
查看
- 找到需要的头文件和函数参数
#include <unistd.h>
int execv(const char *path, char *const argv[]);
(3)wait()
wait() 函数用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或者该进程接收到了一个指定的信号为止。若该父进程没有子进程或者它的子进程已经结束,wait() 函数就会立即返回。
waitpid() 的作用和 wait() 一样,但它并不一定要等待第一个终止的子进程(它可以指定需要等待终止的子进程),它还有若干选项,如可提供一个非阻塞版本的 wait() 功能,也能支持作业控制。实际上,wait() 函数只是 waitpid()函数的一个特例,在 Linux 内部实现 wait() 函数时直接调用的就是 waitpid() 函数。
- 使用
man wait
查看
- 找到需要的头文件和函数参数
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
三、实现 mybash 的伪代码
(1)读取用户输入的指令
(2)调用fork函数生成一个子进程,并将fork返回的pid值赋给父进程fpid
(3)调用wait函数,传入参数NULL
(4)判断fpid是否为0
(5)若为0,则调用execvp函数,将用户输入的指令传进去,实现功能
(6)若不为0,则提示错误,并返回(1)等待用户下一个指令
四、实现 mybash
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <pwd.h>
#include <sys/wait.h>
#define LEN 10
char* Cmd[LEN] = {0};
int count = 0;
char OLDPWD[1024] = {0};
void out_flag()
{
char flag = '$';
struct passwd *pw = getpwuid(getuid());
if(getuid() == 0)
{
flag = '#';
}
struct utsname host;
uname(&host);
char *hostname = strtok(host.nodename, ".");
char path[128] = {0};
getcwd(path, 127);//获取当前目录的绝对路径
char *p = strtok(path, "/");
char *nowdir = NULL;
while(p!= NULL)
{
nowdir = p;
p = strtok(NULL, "/");
}
if(nowdir == NULL)
{
nowdir = "/";
}
if(strcmp(nowdir, pw->pw_name) == 0)
{
nowdir = "~";
}
printf("[%s@%s %s]mybash%c ", pw->pw_name, hostname, nowdir, flag);
fflush(stdout);
}
void cut_cmd(char *cmd)
{
char *p = strtok(cmd, " ");
while(p != NULL)
{
Cmd[count++] = p;
p = strtok(NULL, " ");
}
}
int special_cmd()
{
//cd exit
if(strncmp("cd", Cmd[0], 2) == 0)
{
if(Cmd[1] == NULL || strncmp(Cmd[1], "~", 1) == 0)
{
//切换到家目录
struct passwd *pw = getpwuid(getuid());
Cmd[1] = pw->pw_dir;
}
else if(strncmp(Cmd[1], "-", 1) == 0)
{
//切换到家目录到上一次所在目录
if(strlen(OLDPWD) == 0)
{
printf("mybash: cd :: OLDPWD not set\n");
return 1;
}
Cmd[1] = OLDPWD;
printf("%s\n", Cmd[1]);
}
char str[1024] = {0};
getcwd(str, 1023);
chdir(Cmd[1]); // 切换路径
strcpy(OLDPWD, str);
return 1;
}
if(strncmp("exit", Cmd[0], 4) == 0)
{
exit(0);
}
return 0;
}
void clear_cmd()
{
int i = 0;
for(;i < count; ++i)
{
Cmd[i] = 0;
}
count = 0;
}
void main()
{
while(1)
{
out_flag();
char cmd[128] = {0};
fgets(cmd, 128, stdin); //获取命令
cmd[strlen(cmd) - 1] = 0; //去掉最后一个回车符
if(strlen(cmd) == 0) // 判别用户的无效输入
{
continue;
}
cut_cmd(cmd); // 切割cmd
int res = special_cmd(); // 判别是否是需要集成到bash中的特殊命令
if(res == 1)
{
clear_cmd(); //清空全局的指针数组,并将count归0
continue;
}
pid_t pid = fork();
assert(pid != -1);
if(pid == 0)
{
// 用命令的可执行文件(./mypwd)替换当前进程
char path[1024] = "/home/20165223cn/week9/mypwd/";
if(strstr(Cmd[0], "/") != NULL)
{
memset(path, 0, 1024);
}
strcat(path, Cmd[0]);
execv(path, Cmd);
printf("mybash: %s : command not found\n", Cmd[0]);
exit(0);
}
else
{
wait(NULL);
}
clear_cmd();
}
}
四、产品截图
- 测试 mybash
- 用可执行文件 ./mypwd 替代当前进程执行(实现mypwd)
20165223 《信息安全系统设计基础》 实现mybash的更多相关文章
- 2017-2018-1 20155306 《信息安全系统设计基础》Mybash的实现
2017-2018-1 20155306 <信息安全系统设计基础>Mybash的实现 要求: 使用fork,exec,wait实现mybash 写出伪代码,产品代码和测试代码 发表知识理解 ...
- 2017-2018-1 20155239 《信息安全系统设计基础》第五周学习总结+mybash的实现
2017-2018-1 20155239 <信息安全系统设计基础>第五周学习总结+mybash的实现 mybash的实现 使用fork,exec,wait实现mybash 写出伪代码,产品 ...
- # 2017-2018-1 20155337《信息安全系统设计基础》第5周学习总结+mybash
2017-2018-1 20155337<信息安全系统设计基础>第5周学习总结 教材学习内容总结 不论我们是在用C语言还是用JAVA或是其他的语言编程时,我们会被屏蔽了程序的机器级的实现. ...
- 2017-2018-1 20155338 《信息安全系统设计基础》第5周加分项Mybash的实现
2017-2018-1 20155338 <信息安全系统设计基础>第5周加分项Mybash的实现 使用fork,exec,wait实现mybash 一.fork函数 定义和理解:fork( ...
- 20155305《信息安全系统设计基础》10月18日课堂 fork,exic,wait
20155305<信息安全系统设计基础>10月18日课堂 fork,exic,wait fork()函数 1.fork函数作用 一般来讲, 我们编写1个普通的c程序, 运行这个程序直到程序 ...
- 20145213《信息安全系统设计基础》实验一 Linux开发环境的配置
北京电子科技学院(BESTI) 实 验 报 告 课程:信息安全系统设计基础 班级:1452 姓名: 黄亚奇 祁玮 学号:20145213 20145222 成绩: 指导教师:娄嘉鹏 实验日期:2016 ...
- 20145215&20145307《信息安全系统设计基础》实验二 固件设计
20145215&20145307<信息安全系统设计基础>实验二 固件设计 实验目的与要求 了解多线程程序设计的基本原理,学习 pthread 库函数的使用. 了解在 linux ...
- 20145215&20145307《信息安全系统设计基础》实验五 网络通信
小组成员:20145215卢肖明.20145307陈俊达 实验报告链接:信息安全系统设计基础--实验五实验报告
- 20145223《信息安全系统设计基础》 GDB调试汇编堆栈过程分析
20145223<信息安全系统设计基础> GDB调试汇编堆栈过程分析 分析的c语言源码 生成汇编代码--命令:gcc -g example.c -o example -m32 进入gdb调 ...
- 20145216 20145330 《信息安全系统设计基础》 实验五 简单嵌入式WEB 服务器实验
20145216 20145330 <信息安全系统设计基础> 实验五 简单嵌入式WEB 服务器实验 实验报告封面 实验步骤 1.阅读理解源码 进入/arm2410cl/exp/basic/ ...
随机推荐
- 想要在launcher中模拟按home键。
Intent mHomeIntent = new Intent(Intent.ACTION_MAIN); mHomeIntent.addCategory(Intent.CATEGORY_HOME); ...
- Broadcast发送广播
一.知识介绍 1.[广播分类] ①有序广播:接收者A收到广播传递给B,B传给C,有序传递.任何一个环节都可以终止广播,也可以修改广播中携带的数据. 发送的方式:sendOrderedBroadcast ...
- 使用synchronized的几种场景
1.修饰一个方法synchronized 修饰一个方法很简单,就是在方法的前面加synchronized,例如: public synchronized void method() { // todo ...
- Hasse神舟笔记本卡logo解决,刷BIOS方法,教你修复神船
我的电脑是神舟战神K660E i7 d7的,前两天装Windows10,Ubuntu,MAC OS Mojave,PE 一堆操作,使用bootice重建uefi引导,结果在前几天,我删了一个重复的ue ...
- Windows10系统无法更新
方法一: 1.先检查一下windows update服务是否开启,并禁用杀毒软件: 2.如果此服务已经启动,先尝试更换一下网络环境重新更新: 3.如果更换网络环境后依然无法更新,就删除windows ...
- 系统功能调用Windows操作系统原理实验
一.实验目的 1.熟悉操作系统的系统功能调用. 2.掌握用C语言实现系统功能调用的方法和步骤. 3.掌握利用10H号功能调用(BIOS的显示I/O功能调用)来实现对屏幕的操作与控制. 二.实验内容 1 ...
- Tmux 入门
什么是 Tmux Tmux 官方 Wiki 简单来说,Tmux 是一个能够让你一个窗口当多个窗口使用的终端模拟器.并且你还可以将它放到后台,等到想使用的时候再使用. 为什么要用 Tmux 在服务器上调 ...
- socket粘包问题解决
粘包client.send(data1)client.send(data2)这两次send紧挨在一起,处理的时候会放在一起发过去在Linux里每次都粘包,Windows里面某次会出现粘包在两次send ...
- audio元素和video元素在ios和andriod中无法自动播放
原因: 因为各大浏览器都为了节省流量,做出了优化,在用户没有行为动作时(交互)不予许自动播放: /音频,写法一 <audio src="music/bg.mp3" autop ...
- 干货:Vue粒子特效(vue-particles插件)
转:https://www.jianshu.com/p/53199b842d25 image.png 图上那些类似于星座图的点和线,是由vue-particles生成的,不仅自己动,而且能与用户鼠标事 ...