操作系统"UNIX外壳项目":简易命令行实现(执行命令+历史功能)

发布时间 2023-03-23 15:57:45作者: Bai_huasheng

运行环境Ubuntu-Linux

代码如下:

  1 #include <unistd.h>
  2 #include <string.h>
  3 #include <stdio.h>
  4 #include <wait.h>
  5 #include <stdlib.h>
  6 #define MAX_LINE 80
  7 typedef struct hst{
  8     int number;
  9     char *hst_cmd[MAX_LINE/2 + 1];
 10     int len;
 11     struct hst *next;
 12 
 13 }HstList;
 14 void outHst(HstList *p);
 15 void reLoad(int n, char *a[], HstList *p, int *num);
 16 int main(void){
 17     char *args[MAX_LINE/2 + 1];
 18     int should_run = 1;
 19     int waitFlag = 1;//flag of wait, 1 represent the father need to wait
 20     int retype = 0;//flag of retype command
 21     int hst_num = 1;//init the HstList
 22     HstList *head, *node, *end, *latest;
 23     head = (HstList*)malloc(sizeof(HstList));
 24     head->number = 0;
 25     end = head;
 26     latest = head;
 27     end->next = NULL;
 28 
 29     while(should_run){
 30         printf("myCommand(input 'exit' to exit)>>");
 31         fflush(stdout);
 32         
 33         //read every input
 34         int num = 0;
 35         while(1){
 36             char *tmp = (char*)malloc(50*sizeof(char));
 37             if((scanf("%s", tmp)) == EOF || getchar() == '\n'){
 38                 args[num] = tmp;
 39                 if(strcmp(args[num], "!!") == 0){
 40                     if(latest->number == 0) printf("***you have not input any command recently!***:(\n");
 41                     else{
 42                         reLoad(end->number, args, head, &num);
 43                         break;
 44                     }
 45                     retype = 1;
 46                     break;
 47                 }
 48                 if(args[num][0] == '!' && args[num][1] != '!'){
 49                     char *n = &args[num][1];
 50                     int index = atoi(n);
 51                     if( index < head->number || index > end->number) printf("***the command not found!***:(\n");
 52                     else{
 53                         reLoad(index, args, head, &num);
 54                         break;
 55                     }
 56                     retype = 1;
 57                     break;
 58                 }
 59 
 60                 if(strcmp(args[num], "history") == 0){
 61                     if(latest->number == 0) printf("***you have not input any command!***:(\n");
 62                     else{
 63                         while(latest != NULL){
 64                             outHst(latest);
 65                             latest = latest->next;
 66                         }
 67                         latest = head->next;//when it print out the history, it should be reset
 68                     }
 69                     retype = 1;
 70                     break;
 71                 }
 72                 if(strcmp(args[num], "&") == 0){
 73                     args[num] = NULL;
 74                     waitFlag = 0;
 75                     break;
 76                 }
 77                 if(strcmp(args[num], "exit") == 0){//set the flag of end
 78                     should_run = 0;
 79                     break;
 80                 }
 81                 args[++num] = NULL;//the end of args should be NULL
 82                 break;
 83             }//for delay to close input
 84             args[num] = tmp;
 85             num++;
 86         }
 87         if(retype == 1){
 88             retype = 0;
 89             continue;
 90         }
 91         if(should_run == 0) break;//stop run
 92 
 93         //put the command into history
 94         node = (HstList*)malloc(sizeof(HstList));
 95         end->next = node;
 96         end = node;
 97         end->next = NULL;
 98         node->number = hst_num;
 99         node->len = num;
100         hst_num++;
101         for(int i = 0;i <= node->number;i++) node->hst_cmd[i] = args[i];
102         int i;
103         latest = head;
104         for(i = 0;i < 10;i++){
105             if((end->number - i) > 1) continue;
106                    else{
107                        latest = head->next;
108                 break;
109             }
110         }
111         if(i == 10)//latest point to the latest 10 history command
112             while(latest->number != (end->number - 9))
113                 latest = latest->next;
114 
115         //fork a process and insert a program into it
116         int pid;
117         pid = fork();
118         if(pid < 0){
119             printf("***process creation failed!***:(\n");
120         }
121         else if(pid == 0){
122                execvp(args[0], args);
123                printf("***command execution failed!***:(\n");//if the command execute successfully,there will not be returned value, or error occurred
124                exit(1);
125         }
126         else{
127             if(waitFlag == 1){
128                        wait(NULL);
129                 sleep(1);
130             }
131             printf("***parent program finished!***:)\n");
132         }
133         
134     }
135     return 0;
136 }
137 
138 void outHst(HstList *p){
139     printf("%d  ", p->number);
140     for(int i = 0;i < p->len;i++)
141         printf("%s ", p->hst_cmd[i]);
142     printf("\n");
143 }
144 void reLoad(int n, char *a[], HstList *p, int *num){
145     while(p->number != n) p = p->next;
146     for(int i = 0;i <= p->len;i++){
147         a[i] = p->hst_cmd[i];
148     }
149     *num = p->len;
150 }