#c #shell #operating-system #fork
Вопрос:
Я пытаюсь реализовать простую оболочку с историей, которая принимает пакетные файлы процесса в качестве входных данных и выполняет их.
Мой файл заголовка head.h
выглядит так:
#include lt;stdlib.hgt; #include lt;stdio.hgt; #include lt;time.hgt; #include lt;unistd.hgt; #include lt;string.hgt; #include lt;sys/wait.hgt; typedef struct Process{ int index; char **args; } Proc_t; typedef struct historyNode{ Proc_t Process; struct historyNode *next; struct historyNode * prev; } his_t; //Function Prototypes his_t * createNode(his_t *head, Proc_t *Process); char** ParseString(char *buffer); void execProcess(his_t *head, Proc_t *Process); void HistoryBrief(his_t *head); void HistoryFull(his_t *head); void printProcess(Proc_t Process); void printProcessCmd(Proc_t Process); int isNumber(char *arg); Proc_t *get_Process(his_t *head, int index); Proc_t *existsInHistory(his_t *head, char **args);
Вот main.c
:
#include "head.h" his_t * head = NULL; int main(int argc, char ** argv) { int index = 1; for(int i = 1 ; ilt;argc;i ) { char buffer[1000]; // to store the command read from file FILE *f = fopen(argv[i],"r"); while(fgets(buffer,sizeof(buffer), f) != NULL) { char** currProcessArgs = ParseString(buffer); Proc_t *currProcess = (Proc_t *)malloc(sizeof(Proc_t)); currProcess-gt;index = index; //printf("index of currProcess: %dn",currProcess-gt;index); currProcess-gt;args = currProcessArgs; //printProcess(*currProcess); if(head == NULL) { head = createNode(head, currProcess); //printf("Process name:%s, head address:%pn", head, head-gt;Process.args[0]); } else { createNode(head, currProcess); //printf("Process name:%s, head address:%pn", head, head-gt;Process.args[0]); } printf("n%d index in loopn", index); index ; execProcess(head,currProcess); //index ; } // HistoryBrief(head); //HistoryFull(head); fclose(f); } //Ignore the while part for now while(1) { char inputBuffer[1000]; puts("Please enter a command!: "); scanf("%[^n]%*c", inputBuffer); //fflush(stdin); printf("inputBuffer: %sn",inputBuffer); char **userCmdArgs = ParseString(inputBuffer); if(strcmp(userCmdArgs[0],"EXEC")==0) { if(isNumber(userCmdArgs[1])==0) { Proc_t *userCmd = (Proc_t *)malloc(sizeof(Proc_t)); userCmd-gt;index=index; userCmd-gt;args = userCmdArgs 1; userCmd = existsInHistory(head, userCmd-gt;args); if(userCmd!=NULL) { puts("This Command Already exists in History!!"); // execProcess(userCmd); } else { puts("This Command doesn't exist in history. Adding it to the history"); createNode(head,userCmd); //execProcess(userCmd); } } else { Proc_t *userProcessWithIndex = get_Process(head, atoi(userCmdArgs[1])); if(userProcessWithIndex==NULL) { puts("Command with the given index doesn't exist!!n"); } else execProcess(head, userProcessWithIndex); } } else if(strcmp(userCmdArgs[0], "HISTORY")==0) { if(strcmp(userCmdArgs[1],"BRIEF")==0) { printProcess(head-gt;Process); HistoryBrief(head); } else { HistoryFull(head); } } else if(strcmp(userCmdArgs[0],"STOP")==0) { puts("Exiting Normally, Bye!!n"); break; } } return 0; }
here is history.c
#include "head.h" his_t *createNode(his_t *head, Proc_t *Process) { his_t * new_node = (his_t *) malloc(sizeof(his_t)); new_node-gt;Process = *Process; new_node-gt;next = NULL; new_node-gt;prev = NULL; if(head == NULL) { head = new_node; return head; } else { his_t * temp = head; while(temp-gt;next != NULL) { temp=temp-gt;next; } temp-gt;next=new_node; new_node-gt;prev=temp; return new_node; } } Proc_t *existsInHistory(his_t *head, char **args) { his_t *temp = head; int i = 0; int exists = 1; while(temp!=NULL) { while(args[i]!=NULL amp;amp; temp-gt;Process.args[i]!=NULL) { if(args[i]==temp-gt;Process.args[i]) exists=1; else { exists = 0; break; } } if(exists) { Proc_t *tempProc = (Proc_t *)malloc(sizeof(Proc_t)); tempProc = amp;(temp-gt;Process); return tempProc; } temp = temp-gt;next; return NULL; } } Proc_t *get_Process(his_t *head, int index) { his_t * temp = head; while(temp!=NULL) { if(temp-gt;Process.index == index) break; temp=temp-gt;next; } if(temp!=NULL) { Proc_t *procTemp = (Proc_t *)malloc(sizeof(Proc_t)); procTemp = amp;(temp-gt;Process); return procTemp; } else return NULL; } void HistoryBrief(his_t *head) { his_t * temp = head; while(temp-gt;next!=NULL) { printf("Address of head: %pn", temp); if(temp-gt;prev!=NULL) printProcessCmd(temp-gt;prev-gt;Process); printProcessCmd(temp-gt;Process); temp=temp-gt;next; } } void HistoryFull(his_t *head) { his_t *temp = head; while(temp-gt;next!=NULL) { printProcess(temp-gt;Process); temp = temp -gt; next; } } }
Here is process.c
#include "head.h" int isNumber(char *arg) { int i = 0; while(arg[i]!='') { if(isdigit(arg[i])==0) return 0; i ; } return 1; } char** ParseString(char *buffer) { int buff_size = strlen(buffer); if(buffer[buff_size-1]=='n') buffer[buff_size-1]=''; char **args =(char *)malloc(30*sizeof(char *));// array for storing arguments int i = 0; char *arg = strtok(buffer," "); while(arg !='') { args[i] = arg; arg = strtok(NULL," "); i ; } args[i] = ''; puts("n"); int k =0; while(args[k]!=NULL) { printf("%s ",args[k]); k ; } return args; } void printProcess(Proc_t Process) { printf("%d.",Process.index); puts("args: "); int i = 0; while(Process.args[i]!=NULL) { printf("%s ",Process.args[i]); i ; } puts("n"); } void printProcessCmd(Proc_t Process) { printf("%d.%sn",Process.index,Process.args[0]); } void execProcess(his_t *head,Proc_t *Process) { int pid = fork(); if(pid==0) { printf("Currently Executing: index:%d||command:%snn",Process-gt;index, Process-gt;args[0]); execvp(Process-gt;args[0],Process-gt;args); } else if(pid) { wait(NULL); (head-gt;Process.index) ; printf("index of head afgter returning to parent process: %dn",head-gt;Process.index); printf("%s, cmd of head process after returning to parentn",head-gt;Process.args[0]); } else return 0; }
Таким образом, в основном моя программа будет принимать входные данные в виде текстовых файлов, содержащих команды Linux. Каждая команда записывается в отдельной строке.
Пример файла —
ls -al echo Hello World touch newfile.c ps
Я создал двусвязный список для хранения истории команд. Когда я вызываю HistoryBrief()
его, он печатает 4 ps
вместо печати каждой команды. Кроме того, после вызова fork индекс меняется внутри родительского, но не дочернего элемента. Это почему??
Комментарии:
1. Вы продолжаете повторно использовать один и тот же массив для значений, на которые указывают массивы аргументов, которые вы храните.
2. @Шон, не могли бы вы уточнить, я не мог понять.
3. ‘if(args[i]==temp-gt;Process.args[i])’ — сравнение указателей вместо строк (та же проблема, что и выше, на самом деле).
4. @MartinJames Спасибо, что указали на ошибку, я буду использовать strcmp() вместо==, но дело в том, что я все еще не могу понять, где я повторно использую массивы аргументов. Не могли бы вы, пожалуйста, помочь?
5. Относительно:
Proc_t *procTemp = (Proc_t *)malloc(sizeof(Proc_t)); procTemp = amp;(temp-gt;Process);
Это объявление указателя, установка этого указателя на некоторую выделенную память, а затем наложение этого указателя (приводит к утечке памяти).