2014-02-13 3 views
1

터미널에서 사용자가 입력 한 명령을 실행할 수있는 셸을 만들고 있습니다. 또한 역사 기능이 있습니다.if-else 문과 함께 여러 execvp 호출을 사용하는 방법은 무엇입니까?

모든 것이 현재 정상적으로 작동합니다. 내가 붙어있는 유일한 부분은 사용자가 "!!" 가장 최근의 명령은 실행되어야하며 사용자가 "! n"을 입력하면 n 번째 명령이 실행되어야합니다. 그러나, 내가 그것을 실행할 때, 아무것도 그 명령을 입력하면 실행되지 않습니다.

get_recent_command() 및 search_in_list_for_n() 함수는 올바른 명령을 반환하지만 "args [0]"이 execvp() 호출에 있어야하는 위치에 해당 함수의 결과를 넣으면 아무 일도 발생하지 않습니다.

확실하지 않습니다. 미리 감사드립니다! 명령을 목록에 추가하기 전에 null을 시도했지만 여전히 작동하지 않았습니다. 내가 뭘 할 수 있는지 잘 모르겠다 ... 미리 감사드립니다!

참고 : 사이트에서 다시 링크 된 목록 코드 : http://www.thegeekstuff.com/2012/08/c-linked-list-example/

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <string.h> 
#include <stdbool.h> 

#define MAX_LINE 80 //Maximum number of characters for a commandline 

struct test_struct 
{ 
    char *str; 
    struct test_struct *next; 
}; 

struct test_struct *head = NULL; 
struct test_struct *curr = NULL; 

struct test_struct* create_list(char * str) 
{ 
    printf("\n creating list with headnode as %s\n",str); 
    struct test_struct *ptr = (struct test_struct*)malloc(sizeof(struct test_struct)); 
    if(NULL == ptr) 
    { 
     printf("\n Node creation failed \n"); 
     return NULL; 
    } 
    ptr->str = str; 
    ptr->next = NULL; 

    head = curr = ptr; 
    return ptr; 
} 

struct test_struct* add_to_list(char * str, bool add_to_end) 
{ 
    if(NULL == head) 
    { 
     return (create_list(str)); 
    } 

    if(add_to_end) 
     printf("\n Adding node to end of list with value %s\n",str); 
    else 
     printf("\n Adding node to beginning of list with value %s\n",str); 

    struct test_struct *ptr = (struct test_struct*)malloc(sizeof(struct test_struct)); 
    if(NULL == ptr) 
    { 
     printf("\n Node creation failed \n"); 
     return NULL; 
    } 
    ptr->str = str; 
    ptr->next = NULL; 

    if(add_to_end) 
    { 
     curr->next = ptr; 
     curr = ptr; 
    } 
    else 
    { 
     ptr->next = head; 
     head = ptr; 
    } 

    return ptr; 
} 

struct test_struct* search_in_list(char * str, struct test_struct **prev) 
{ 
    struct test_struct *ptr = head; 
    struct test_struct *tmp = NULL; 
    bool found = false; 

    printf("\n Searching the list for value [%s] \n",str); 

    while(ptr != NULL) 
    { 
     if(ptr->str == str) 
     { 
      found = true; 
      break; 
     } 
     else 
     { 
      tmp = ptr; 
      ptr = ptr->next; 
     } 
    } 

    if(true == found) 
    { 
     if(prev) 
     *prev = tmp; 
     return ptr; 
    } 
    else 
    { 
     return NULL; 
    } 
} 

int countList(void) 
{ 
    struct test_struct *ptr = head; 
    int i = 0; 
    while(ptr != NULL) 
    { 
     i++; 
     ptr = ptr->next; 
    } 

    return i; 
} 

void print_list(void) 
{ 
    int i = 1; 
    int listCount = 0; 
    struct test_struct *ptr = head; 

    listCount = countList(); 
    printf("\n -------HISTORY START------- \n"); 
    while(ptr != NULL && i < 11) 
    { 
     printf("\n %i %s \n", listCount, ptr->str); 
     ptr = ptr->next; 
     i++; 
     listCount--; 
    } 
    printf("\n -------HISTORY END------- \n"); 

    countList(); 
    i = 0; 
    return; 
} 

char* get_recent_command(void) 
{ 
    int listCount = 0; 
    int i = 0; 
    listCount = countList(); 

    if(listCount > 1) 
    { 
     struct test_struct *ptr = head; 
     while(ptr != NULL && i < 1) 
     { 
      i++; 
      ptr= ptr->next; 
     } 
     return ptr->str; 
    } 
    else 
    { 
     printf("No recent commands entered yet\n"); 
     return NULL; 
    } 
} 

char* search_in_list_for_n(int n, struct test_struct **prev) 
{ 
    int i = 0; 
    int listCount = 0; 
    int tempCount = 0; 
    listCount = countList(); 
    tempCount = countList(); 

    if(listCount >= n) 
    { 
     struct test_struct *ptr = head; 
     struct test_struct *tmp = NULL; 
     bool found = false; 

     while(tempCount != n) 
     { 
      i++; 
      ptr = ptr->next; 
      tempCount--; 
     } 
     return ptr->str; 
    } 
    else 
    { 
     printf("No such command found"); 
     return NULL; 
    } 
} 

//Sets up shell function 
void shellInput(char userInput[], char *args[], int ampersand); 

int main(void) 
{ 
char *str = " "; 
char *str2 = " "; 
char *str3 = " "; 
struct test_struct *ptr = NULL; 
int count = 0; 

char *args[MAX_LINE/2 + 1]; //Holds individual arguments 
int shouldRun = 1; //While loop continues to run if this equals 1 
char userInput[MAX_LINE]; //Stores each character from user input 
int ampersand; //Represents ampersand from commandline 
pid_t pid; 
pid_t pid2; 
int n; 

while(shouldRun) 
{ 
    ampersand = 0; //If ampersand equals 1 at any point, the user entered an ampersand, so the parent will run concurrently 
    printf("\nosh>"); 
    fflush(stdout); 

    shellInput(userInput, args, ampersand); //Initiates shell 
    count++; 

    pid = fork(); 

    if(pid == 0) 
    { 
     if (args[1]) 
     { 
      n = atoi(args[1]); 
     } 
     if(!(strncmp(args[0], "history", 7))) 
     { 

      print_list(); 
     } 
     else if(!(strncmp(args[0], "!!", 2))) 
     { 
      str = get_recent_command(); 
      printf("str %s", str); 

      if(execvp(str, args) < 0) 
      { 
       printf("execvp failed"); 
       exit(1); 
      } 
      else 
      { 
       printf("executing..."); 
       fflush(stdout); 
       execvp(str, args); 
      } 
     } 
     else if(!(strncmp(args[0], "!", 1))) 
     { 
      str3 = search_in_list_for_n(n,NULL); 
      printf("search_in_list_for_n: %s", search_in_list_for_n(n,NULL)); 
      execvp(str3, args); 
     } 
     else 
     { 
      printf("executing..."); 
      fflush(stdout); 
      execvp(args[0], args); 
     } 
     exit(0); 
    } 
    else if(ampersand == 0) 
    { 
     wait(&pid); 
    } 
    } 
free(str); 
return 0; 
} 

void shellInput(char userInput[], char *args[], int ampersand) 
{ 
int commLength; //Length of command 
int i; // Index for loop 
int inputIndex = -5; //Represents the first index of each command parameter 
int ParamCount = 0; //Number of parameters on command line (number of arguments) 
char str [MAX_LINE]; 
char str2 [MAX_LINE]; 
char test = ' '; 
char* temp; 
char testing [MAX_LINE]; 
testing [0] = '\0'; 
char *strTest = " "; 

strncpy(str2, &testing[0], 1); 

//Reads user input from command line 
commLength = read(0, userInput, MAX_LINE); 

for(int k = 0; k < commLength; k++) 
{ 
    strncpy(str, &userInput[k], 1); 
    strcat(str2, str); 
} 

strTest = (char *)malloc(MAX_LINE + 1); 
strcpy(strTest, str2); 
strTest[MAX_LINE] = '\0'; 
add_to_list(strTest, false); 
for(int q = 0; q < commLength; q++) 
{ 
    printf("%c",userInput[q]); 
} 

//if user presses ctrl + d, the shell will exit 
if (commLength == 0) 
{ 
    exit(0); 
} 

//Loops through every character in the userInput array 
for(i = 0; i < commLength; i++) 
{ 
    //Checks a character from userInput array 
    switch(userInput[i]) 
    { 
      //If there is a space character, the command parameter upto that space will be stored into args 
     case ' ': 
      if(inputIndex != -5) 
      { 
       args[ParamCount] = &userInput[inputIndex]; //stores parameter into args array 
       ParamCount++; //Increments number of arguments 
       inputIndex = -5; //Resets index for the next command 
       userInput[i] = '\0'; //Creates a C string 
      } 

      break; 

      //If there is a new line character no more parameters will be stored 
     case '\n': 
      if(inputIndex != -5) 
      { 
       args[ParamCount] = &userInput[inputIndex]; //Last parameter is stored 
       ParamCount++; 
       userInput[i] = '\0'; 
       args[ParamCount] = NULL;//Since this was the last command, everything after should be null 
      } 
      break; 

      //If there is a character besides space or newline (usually should be) 
     default: 
      if(inputIndex == -5) 
      { 
       inputIndex = i; //This occurs everytime a new command parameter has been found 
      } 

      if(userInput[i] == '&') 
      { 
       ampersand = 1; 
       userInput[i-1] = '\0'; //Makes the parameter before the ampersand into a C string 
      } 
      //*note*: This default case will not carry out a function inbetween when the first command parameter has been found and until the next is found 
    } 
} 

//Prints the arguments 
for(i = 0; i <= ParamCount; i++) 
{ 
    printf("args [%i]: %s\n", i, args[i]); 
} 
} 
+1

완전한 코드를 연결하면 도움이됩니다. 즉, 주 프로그램의 긴 스 니펫 대신 컴파일 할 수있는 코드입니다. – Tanaki

+1

죄송합니다. @Tanaki 저는 게시물을 편집하고 전체 코드를 추가했습니다. 정말 고맙습니다! – user3299553

답변

0

정보를 귀하의 부족은 나에게 다음과 같은 가정을 일으킬 것입니다 :

  • test_struct.str

    가에서 명령을 말한다 그 전체 "ls -la", "ps u". 당신이 print_recent_list()execvp를 통과하면
  • 당신은 당신이 인수를 포함하여 전체 명령을 전달하는, 목록

의 시작에 새로운 기록 항목을 추가합니다. man 페이지를 한눈에 보면 execvp()의 첫 번째 인수는 "새 프로세스 이미지 파일을 식별하는 경로 이름을 가리 킵니다"라는 것을 알 수 있습니다. 본질적으로, 당신은 ls -la이라는 프로세스를 찾고 있습니다. 명령은 단순히 ls입니다. 다시 얻은 문자열을 print_recent_list()에서 다시 토큰 화하고 args을 토큰 화의 결과로 바꾼 다음 else 경우와 마찬가지로 print_recent_list(args[0], args)을 호출해야합니다.

(과제가 완료되기 전날이 질문을하는 것이 좋습니다. 나는 녹스 박사에게 말하지 않을 것입니다.)

+0

감사합니다! strtok 함수를 사용하여 명령 문자열을 토큰 화했습니다. – user3299553