操作系统实验1实现简单的Shell(2020.10.6)

    科技2023-11-05  102

    思路: 首先将用户输入的命令存储到 一维指针数组 *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; }

    以后补充细节

    Processed: 0.016, SQL: 8