/*
============================================================================
Name : MyShell.c
Author : Cloud(连云)
Version : 0.1
Copyright : This Program belong to Cloud.Only he has all rights to explain it.
This Program build by Eclipse in linux;
============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#define BUFFERSIZE 256
char buffer[BUFFERSIZE];
int pipel(char * input, int len);
/*处理管道的情况*/
int redirect(char * in, int len);
/*处理重定向的情况*/
int is_fileexist(char * comm);
/*判断是否存在所需的运行文件*/
int main(int argc,char *argv[]) {
char *path;
pid_t pid;
char lc_char;
int li_inputlen=0,status = 0;;
int is_bj=0,is_back=0;
char * arg[30];
/* is_bj是否为管道或者重定向程序,is_back:是否进行后台处理*/
int k,j,i,ok,p;
int size=0; /*存储,共有几个连续的后加;号的命令*/
int Inlen[30]; /*存储输入信号的长度*/
char *InputArrey[30]; /*当存在;号时,存储命令的信息*/
int ifquit=0;
while(ifquit==0) {
is_bj=0,is_back=0;
li_inputlen=0;
path=get_current_dir_name();
printf("Lianyun-SHELL@ %s > $", path);
/* 开始获取输入 */
while(((lc_char=getchar())!='\n') && li_inputlen < BUFFERSIZE) {
buffer[li_inputlen ++] = lc_char;
}
if(li_inputlen > BUFFERSIZE) {
printf("Your command too long ! Please reenter your command !\n");
li_inputlen = 0;
continue;
}
else
{
if(buffer[li_inputlen-1]==';')
{
buffer[li_inputlen-1] = '\0';
InputArrey[size]= (char *)malloc(sizeof(char) * (li_inputlen));
strcpy(InputArrey[size], buffer);
Inlen[size]=li_inputlen-1;
size++;
continue;
}
else
{
buffer[li_inputlen] = '\0'; /*加上串结束符,形成字符串*/
InputArrey[size]= (char *)malloc(sizeof(char) * (li_inputlen + 1));
strcpy(InputArrey[size], buffer);
Inlen[size]=li_inputlen;
}
}
for(p=0;p<=size;p++){
for(i=0,j=0,k=0; i<=Inlen[p]; i++) {
/*管道和重定向单独处理*/
if(InputArrey[p][i]=='<'|| InputArrey[p][i] =='>' || InputArrey[p][i] == '|') {
if(InputArrey[p][i] == '|'){
ok=pipel(InputArrey[p], Inlen[p]);
}
else{
ok=redirect(InputArrey[p], Inlen[p]);
}
is_bj =1;
break;
}
/*处理空格,TAB和结束符。不用处理’\n’,大家如果仔细分析前面的获取输入的程序的话,不难发现回车符并没有写入buffer*/
if((InputArrey[p][i]==' ')||(InputArrey[p][i] =='\t')||(InputArrey[p][i] == '\0')) {
if(j == 0) /*这个条件可以略去连在一起的多个空格或者TAB */
continue;
else {
buffer[j ++] = '\0';
arg[k] = (char *)malloc(sizeof(char) * j);
/* 将指令或参数从缓存拷贝到arg中*/
strcpy(arg[k], buffer);
j = 0; /* 准备去下一个参数*/
k ++;
}
}
else {
/* 如果字符串最后是 ‘&’,则置后台运行标记为 1 */
if(InputArrey[p][i]== '&' && InputArrey[p][i + 1] == '\0') {
is_back = 1;
continue;
}
buffer[j++] = InputArrey[p][i];
}
}
free(InputArrey[p]); /* 释放空间*/
/*如果输入的指令是leave则退出while,即退出程序*/
if(strcmp(arg[0],"Quit") == 0) {
ifquit =1;
printf("bye-bye\n");
break;
}
if(is_bj == 0) { /* 非管道、重定向指令*/
/* 在使用exec执行命令的时候,最后的参数必须是NULL指针,所以将最后一个参数置成空值*/
arg[k] = (char *)malloc(sizeof(char));
arg[k ++] = (char *)0;
/* 判断指令arg[0]是否存在*/
if(is_fileexist(arg[0]) == -1) {
printf("This is command is not founded ?!\n");
for(i = 0; i < k; i ++){
free(arg[i]);
}
continue;
}
if((pid = fork()) == 0){ /*子进程*/
execv(buffer, arg);
}
else /*父进程*/
if(is_back == 1) /* 并非后台执行指令*/
waitpid(pid, &status, 0);
}
for(i = 0; i < k; i ++) free(arg[i]); /* 释放申请的空间*/
}
size =0;
}
return EXIT_SUCCESS;
}
int is_fileexist(char * comm)
{
char * path, * p;
int i;
i = 0;
/* 使用getenv函数来获取系统环境变量,用参数PATH表示获取路径*/
path = getenv("PATH");
p = path;
while(*p != '\0') {
/* 路径列表使用“:”来分隔路径*/
if(*p != ':') buffer[i ++] = *p;
else {
buffer[i ++] = '/';
buffer[i] = '\0';
/* 将指令和路径合成,形成pathname,并使用access函数来判断该文件是否存在*/
strcat(buffer, comm);
if(access(buffer, F_OK) == 0) /* 文件被找到*/
return 0;
else /* 继续寻找其他路径*/
i = 0;
}
p ++;
}
/* 搜索完所有路径,依然没有找到则返回 –1*/
return -1;
}
int redirect(char * in, int len)
{
char * argv[30];
char * filename[2];
pid_t pid;
int I, j, k, fd_in, fd_out, is_in = -1, is_out = -1, num = 0;
int is_back = 0, status = 0;
/* 这里是重定向的命令解吸过程,其中filename用于存放重定向文件,is_in, is_out分别是输入重定向标记和输出重定向标记*/
for(I = 0, j = 0, k = 0; I <= len; I ++) {
if((in[I]==' ')||(in[I] =='\t')||(in[I] == '\0')|| (in[I] == '<') || (in[I] == '>')) {
if((in[I] == '>') || (in[I] == '<')) {
/* 重定向指令最多 ‘<’, ‘>’各出现一次,因此上num最大为2,否则认为命令输入错误*/
if(num < 3) {
num ++;
if(in[I] == '<'){
is_in=num-1;
}
else is_out = num-1;
/* 处理命令和重定向符号相连的情况,比如 ls > a*/
if(j > 0 && num == 1) {
buffer[j ++] = '\0';
argv[k] = (char *)malloc(sizeof(char) * j);
strcpy(argv[k], buffer);
k ++;
j = 0;
}
}
else {
printf("The format is error !\n");
return -1;
}
}
if(j == 0)
continue;
else {
buffer[j ++] = '\0';
/* 尚未遇到重定向符号,字符串时命令或参数*/
if(num == 0){
argv[k] = (char *)malloc(sizeof(char) * j);
strcpy(argv[k], buffer);
k ++;
}
/* 是重定向后符号的字符串,是文件名*/
else {
filename[status] = (char *)malloc(sizeof(char)*j);
strcpy(filename[status ++], buffer);
}
j = 0; /* Initiate */
}
}
else{
if(in[I] == '&' && in[I + 1] == '\0') {
is_back = 1;
continue;
}
buffer[j ++] = in[I];
}
}
argv[k] = (char *)malloc(sizeof(char));
argv[k ++] = (char *)0;
if(is_fileexist(argv[0]) == -1) {
printf("This command is not founded !\n");
for(I = 0; I < k; I ++) free(argv[I]);
return 0;
}
if((pid = fork()) == 0) {
/* 存在输出重定向*/
if(is_out != -1) {
if((fd_out = open(filename[is_out], O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR )) == -1) {
printf("Open out %s error \n", filename[is_out]);
return -1;
}
}
/* 存在输入重定向*/
if(is_in != -1) {
if((fd_in = open(filename[is_in], O_RDONLY, S_IRUSR|S_IWUSR)) == -1) {
printf("Open in %s error \n", filename[is_in]);
return -1;
}
}
if(is_out != -1) {
/* 使用dup2函数将标准输出重定向到fd_out上,dup2(int oldfd, int newfd)实现的是报oldfd所指的文件描述符复制到newfd。若newfd为已已打开的文件描述符,
* 则newfd所指的文件先会被关闭,dup2复制的文件描述符与原来的文件描述符共享各种文件状态*/
if(dup2(fd_out, STDOUT_FILENO) == -1) {
printf("Redirect Standard Out Error !\n");
exit(1);
linux下的自写shell与中断程序
2星 需积分: 22 60 浏览量
2011-07-17
17:33:47
上传
评论
收藏 79KB RAR 举报
行云cloud
- 粉丝: 0
- 资源: 1
最新资源
- Win64OpenSSL-3-3-0.exe
- 课高分程设计-基于C++实现的民航飞行与地图简易管理系统-南京航空航天大学
- 航天器遥测数据故障检测系统python源码+文档说明+数据库(课程设计)
- 北京航空航天大学操作系统课设+ppt+实验报告
- 基于Vue+Echarts实现风力发电机中传感器的数据展示监控可视化系统+源代码+文档说明(高分课程设计)
- 基于单片机的风力发电机转速控制源码
- 基于C++实现的风力发电气动平衡监测系统+源代码+测量数据(高分课程设计)
- 毕业设计- 基于STM32F103C8T6 单片机,物联网技术的太阳能发电装置+源代码+文档说明+架构图+界面截图
- 基于 LSTM(长短期记忆)(即改进的循环神经网络)预测风力发电厂中风力涡轮机产生的功率+源代码+文档说明
- 基于stm32f103+空心杯电机+oled按键+运动算法
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈