操作系统实验1实现简单的Shell(2020.10.6)
程序员文章站
2022-06-19 17:01:47
...
思路:
首先将用户输入的命令存储到 一维指针数组 *args[]中,整个args数组存储一条完整命令,并保存到二维指针数组 *str[][]中
然后通过循环数组,利用front 和rear实现记录最多十条的历史命令
源代码如下:
#include
<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
//the maximum length command
#define MAX_LINE 80
#define MAX_HIS 11
int main(void)
{
int should_run = 1;
char *args[MAX_LINE/2+1];//current command
char *str[MAX_HIS][MAX_LINE];// historical
command (whose maximun is 10 from 1 to 10)
int rear = 0;
int front = 0;
int sum = 0;//record the number of historical
commands at most 10
char judge[MAX_LINE];
while(should_run){
int label_w = 0;//decide whether to
wait
int label_h = 0;//decide whether to
execute the history
int label_hx = 0;//decide whether
to execute the !x
int label_h0 = 0; //decide whether
to execute the !!
printf("osh>");//print
the prompt
fflush(stdout);//clear the output
buffer
//get the args of the commmand one
line before the 'enter'
int i = 0;
char x;
do{
//get the args of the
commmand one line before the 'enter'
args[i] =
malloc(MAX_LINE*sizeof(char));
str[rear][i] =
malloc(MAX_LINE*sizeof(char));
scanf("%s",
args[i]);
strcpy(judge,
args[0]);
if(0 == strcmp(judge,
"!!"))
label_h0 = 1;
else if(0 ==
strcmp(judge, "history"))
label_h = 1;
else if(judge[0] ==
'!' && judge[1] != '!')
label_hx = 1;
else
strcpy(str[rear][i],
args[i]);
x = getchar();
++i;
}while(x != '\n');
//whether to rear++ and sum++
if(label_h0 == 0 &&
label_hx == 0 && label_h == 0)
{
if((rear+1)%11 ==
front)//the special situation
++front;
rear = (rear+1)%11;
if(10 > sum) ++sum;
}
args[i] = NULL;
str[rear][i] = NULL;
//printf("sum = %d :\n",
sum);//test
//judge whether the parent process
needs to wait
if(0 == strcmp(args[i-1],
"&"))
label_w = 1;
//judge whether invoke the latest
command
int irear = rear;//initial
int ifront = front;
if(1 == label_h0)
{
if(0 == sum) {printf("No
commands in history.\n"); continue;}
//h0
int itest = 0;
while(str[irear][itest] != NULL)
{
args[itest] = malloc(MAX_LINE*sizeof(char));//ready
strcpy(args[itest], str[irear-1][itest]);//ready
for the execvp
printf("%s ",
str[irear-1][itest]);
++itest;
}
printf("\n");
args[itest] = NULL;//ready for the
execvp
//h0
}
irear = rear;//initial
ifront = front;
//judge whether list the recent command
at most 10
if(1 == label_h)
{
int count = 1;
do{
printf("%d: ", count++);
//hcount
int itest = 0;
while(str[ifront][itest] != NULL)
{
printf("%s ",
str[ifront][itest]);
++itest;
}
printf("\n");
//hcount
ifront = (ifront+1)%MAX_HIS;
}while(sum != count-1);
}
irear = rear;//initial
ifront = front;
//judge whether list the specific
number command
if(1 == label_hx)
{///
int number = judge[1]-'0';
if('1' == judge[1]
&& '0' == judge[2]
&& '\0' ==
judge[3])//special sutuation
number = 10;
else if('1' <= judge[2]
&& '9' >= judge[2])
number = 99;
//printf("number = %d,
judge[2] = %c\n", number, judge[2]);
int count = 1;
do{
//when the his is empty
if(0 == sum) break;
//when the his is empty
if(count == number)
{
//hcount
int itest = 0;
while(str[ifront][itest]
!= NULL)
{
args[itest] =
malloc(MAX_LINE*sizeof(char));//ready
strcpy(args[itest],
str[ifront][itest]);//ready for the execvp
printf("%s
", str[ifront][itest]);
++itest;
}
printf("\n");
args[itest] =
NULL;//ready for the execvp
//hcount
++count;// easy to
ignore
break;
}
ifront = (ifront+1)%MAX_HIS;
++count;
}while(ifront != irear);
if(count <= number)
{printf("No such command in history.\n");
//printf("count = %d, number =
%d---for test---\n", count, number);
continue;}
}///
//printf("sum = %d---for
test---\n", sum);
//create the child process//
pid_t pid = fork();
if(0 == pid){
if(0 != strcmp(judge,
"exit")
&& 1 !=
label_h
)
execvp(args[0], args);
break;
}
else
{
if(0 == label_w)
wait(NULL);
//the followings
aren't going until the child ends without"&"
if(0 == strcmp(args[0],
"exit"))
should_run = 0;
fflush(stdin);
}
//create the child process//
}
return 0;
}
以后补充细节