Linux编程实现一个简单的Shell
作者:网络转载 发布时间:[ 2014/3/3 13:57:10 ] 推荐标签:开发 操作系统
在linux中实现一个简单的命令解释程序,功能要求:
1)同时支持内部命令和外部命令,内部命令支持两个(cd、exit)
2)支持后台命令
首先解释一下上面的两个要求,实际上是三种情况:
1.如果是内部命令cd和exit,那么在父进程里直接分析执行
2.如果是外部命令,则创建一个子进程,再由子进程从path环境变量中查找相应的文件执行,此时shell会阻塞,等待子进程结束。
3.如果是后台命令,输入以&结束,它跟外部命令的大区别是,后台命令创建了子进程后不需要调用wait(*status),也是不用等待子进程结束,这样变成了后台进程。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
#define MAXLEN 80
char cwd[MAXLEN];//当前工作目录
char *prompt;
char* parseCmd(char* cmd, char** argarr, int* argc)
{
enum states {S_START, S_INTOKEN, S_INQUOTES};
int numArgs = 0;//参数数目
int loop = 1;//循环标志
enum states state = S_START;//当前状态
int lastch;
while(loop)
{
switch(state)
{
case S_START:
if(*cmd == '"')
{
*argarr++ = cmd + 1;
numArgs++;
state = S_INQUOTES;
}
else if(*cmd == 0 || *cmd == ';')
loop = 0;
else if(*cmd <= ' ')//忽略ascii码表中的空格符及空格符前面的字符
*cmd = 0;
else
{
*argarr++ = cmd;
numArgs++;
state = S_INTOKEN;
}
break;
case S_INTOKEN:
if(*cmd == 0 || *cmd == ';')
loop = 0;
else if(*cmd <= ' ')
{
*cmd = 0;
state = S_START;
}
break;
case S_INQUOTES:
if(*cmd == 0)
loop = 0;
else if(*cmd == '"')
{
*cmd = 0;
state = S_START;
}
break;
}
cmd++;//指向下一个字符
}
*argarr = NULL;//后一个参数指向空
if(argc != NULL) *argc = numArgs;
lastch = cmd[-1];
cmd[-1] = 0;
return lastch == ';' ? cmd : NULL;// 如果遇到分号则返回剩余的字符串作为下一条命令
}
int main(int argc, char** argv)
{
char cmd[80];
char* source = NULL;
char* arg[20];
int statval;
int numArgs;
while(1)
{
if(source == NULL)
{
getcwd(cwd,MAXLEN);
printf("%s$ ",cwd);
//读取命令
if((source = gets(cmd)) == NULL)
exit(0);
}
source = parseCmd(source, arg, &numArgs);
if(numArgs == 0) continue;
//是否退出程序
if(strcasecmp(arg[0], "exit") == 0)
{
exit(0);//不管exit后面是否还有参数,直接退出
}
if(!strcmp(arg[0],"cd"))//切换父进程的工作目录
{
chdir(arg[1]);
continue;
}
if(!strcmp(arg[numArgs-1],"&"))//后台命令
{
char* a[20];//临时变量
int k;
for(k=0;k<numArgs-1;k++)
{
a[k] = malloc(strlen(arg[k]) + 1);
strcpy(a[k],arg[k]);
//printf("%s ", a[k]);
}
a[k] = NULL;
if(fork() == 0)
{
if(execvp(a[0],a) == -1)// 执行失败
fprintf(stderr, "exec %s failed: %s
",argv[0],strerror(errno));
exit(1);//退出子进程
}
for(k=0;k<numArgs-1;k++);//释放内存
free(a[k]);
continue;
}
//创建子进程执行命令
if(fork() == 0)
{
if(execvp(arg[0],arg) == -1)// 执行失败
fprintf(stderr, "exec %s failed: %s
",argv[0],strerror(errno));
exit(1);//退出子进程
}
wait(&statval);
}
}
|
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
Linux下开源的DDR压力测试工具曝Linux恶意软件:让树莓派设备挖掘数字货币linux系统中不同颜色的文件夹及根目录介绍软件测试工程师必知必会Linux命令Linux下DNS服务器配置如何成为不可替代的Linux运维工程师?详解Linux进程(作业)的查看和杀死Linux 日志定时轮询流程详解比特币勒索病毒不只Windows系统有,Linux版的来了Linux日志定时轮询流程详解Linux iommu和vfio概念空间解构Linux系统如何低于TCP洪水攻击Linux无损调整分区大小Linux下防火墙配置实例Linux使用Jexus托管Asp.Net Core应用程序Linux中引号的那些事
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南