2017-03-25 2 views
0

자체 정의 함수를 수행하기위한 bulit-in 명령이있는 셸을 만듭니다. 그러나 동일한 명령을 두 번 호출하려고하면 문제가 발생합니다.자체 정의 함수를 실행하는 c - 쉘이 작동하지 않습니다.

내 함수가 올바르게 실행되면 문제없이 처음 실행됩니다. 그러나 첫 번째 실행이 끝난 후 다른 옵션 집합으로 해당 명령을 다시 실행하면 runALS print 문을 제외한 다른 명령은 실행되지 않습니다. 무슨 일이 일어나고 있고, 어떻게 해결할 수 있습니까?

를 실행하는 방법 : runALS -FCFS 또는 runALS -SJF 자기 한정 기능 : fcfs()sjf()

출력 :

 --WELCOME TO ALS-- 
Please enter: 
> runALS -FCFS 
runALS 
.... // normal output for fcfs() 
Please enter: 
> Please enter: 
> runALS -SJF 
runALS 
// no output for sjf() 

다른 실행 :

 --WELCOME TO ALS-- 
Please enter: 
> runALS -SJF 
runALS 
.... // normal output for sjf() 
Please enter: 
> Please enter: 
> runALS -FCFS 
runALS 
// no output for fcfs() 

현재 코드 :

,745,
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

/* 
    Function Declarations for builtin shell commands: 
*/ 
int lsh_addOrder(char **args); 
int lsh_runALS(char **args); 
int lsh_printSchedule(char **args); 
int lsh_printReport(char **args); 
int lsh_endProgram(char **args); 



char *builtin_str[] = { 
    "addOrder", 
    "runALS", 
    "printSchedule", 
    "printReport", 
    "endProgram" 
}; 

int (*builtin_func[]) (char **) = { 
    &lsh_addOrder, 
    &lsh_runALS, 
    &lsh_printSchedule, 
    &lsh_printReport, 
    &lsh_endProgram 
}; 

int lsh_num_builtins() { 
    return sizeof(builtin_str)/sizeof(char *); 
} 
/* 
    Builtin function implementations. 
*/ 

/** 
    @brief Bultin command: create order. 
    @param args List of args. args[0] is "addOrder". args[1] is the "R0001". args[2] is start date "D001". args[3] is finish date. args[4] is product name. args[5] is number of product ordered 
    @return Always returns 1, to continue executing. 
*/ 
int lsh_addOrder(char **args) 
{ 
    printf("addOrder\n"); 
    return 1; 
} 

int lsh_printSchedule(char **args) 
{ 
    printf("printSchedule\n"); 
    return 1; 
} 
int lsh_printReport(char **args) 
{ 
    printf("printReport\n"); 
    return 1; 
} 

/** 
    @brief Builtin command: print help. 
    @param args List of args. Not examined. 
    @return Always returns 1, to continue executing. 
*/ 
int lsh_runALS(char **args) 
{ 
    int i; 
    printf("runALS\n"); 
    //printf("Type program names and arguments, and hit enter.\n"); 
    //printf("The following are built in:\n"); 

    //for (i = 0; i < lsh_num_builtins(); i++) { 
    //printf(" %s\n", builtin_str[i]); 
    //} 
    int opt; 
    while ((opt = getopt(2, args, "F:S:")) != -1) { 
     switch (opt) { 
     case 'F': 
      fcfs(); 
      break; 
     case 'S': 
      sjf(); 
      break; 
     default: /* '?' */ 
      fprintf(stderr, "Unsupported option\n"); 
      exit(EXIT_FAILURE); 
     } 
    } 
    return 1; 
} 

/** 
    @brief Builtin command: exit. 
    @param args List of args. Not examined. 
    @return Always returns 0, to terminate execution. 
*/ 
int lsh_endProgram(char **args) 
{ 
    printf("Bye-bye!"); 
    return 0; 
} 

/** 
    @brief Launch a program and wait for it to terminate. 
    @param args Null terminated list of arguments (including program). 
    @return Always returns 1, to continue execution. 
*/ 
int lsh_launch(char **args) 
{ 
    pid_t pid; 
    int status; 

    pid = fork(); 
    if (pid == 0) { 
    // Child process 
    if (execvp(args[0], args) == -1) { 
     perror("lsh"); 
    } 
    exit(EXIT_FAILURE); 
    } else if (pid < 0) { 
    // Error forking 
    perror("lsh"); 
    } else { 
    // Parent process 
    do { 
     waitpid(pid, &status, WUNTRACED); 
    } while (!WIFEXITED(status) && !WIFSIGNALED(status)); 
    } 

    return 1; 
} 

/** 
    @brief Execute shell built-in or launch program. 
    @param args Null terminated list of arguments. 
    @return 1 if the shell should continue running, 0 if it should terminate 
*/ 
int lsh_execute(char **args) 
{ 
    int i; 

    if (args[0] == NULL) { 
    // An empty command was entered. 
    return 1; 
    } 

    for (i = 0; i < lsh_num_builtins(); i++) { 
    if (strcmp(args[0], builtin_str[i]) == 0) { 
     return (*builtin_func[i])(args); 
    } 
    } 

    return lsh_launch(args); 
} 

#define LSH_RL_BUFSIZE 1024 
/** 
    @brief Read a line of input from stdin. 
    @return The line from stdin. 
*/ 
char *lsh_read_line(void) 
{ 
    int bufsize = LSH_RL_BUFSIZE; 
    int position = 0; 
    char *buffer = malloc(sizeof(char) * bufsize); 
    int c; 

    if (!buffer) { 
    fprintf(stderr, "lsh: allocation error\n"); 
    exit(EXIT_FAILURE); 
    } 

    while (1) { 
    // Read a character 
    c = getchar(); 

    // If we hit EOF, replace it with a null character and return. 
    if (c == EOF || c == '\n') { 
     buffer[position] = '\0'; 
     return buffer; 
    } else { 
     buffer[position] = c; 
    } 
    position++; 

    // If we have exceeded the buffer, reallocate. 
    if (position >= bufsize) { 
     bufsize += LSH_RL_BUFSIZE; 
     buffer = realloc(buffer, bufsize); 
     if (!buffer) { 
     fprintf(stderr, "lsh: allocation error\n"); 
     exit(EXIT_FAILURE); 
     } 
    } 
    } 
} 

#define LSH_TOK_BUFSIZE 64 
#define LSH_TOK_DELIM " \t\r\n\a" 
/** 
    @brief Split a line into tokens (very naively). 
    @param line The line. 
    @return Null-terminated array of tokens. 
*/ 
char **lsh_split_line(char *line) 
{ 
    int bufsize = LSH_TOK_BUFSIZE, position = 0; 
    char **tokens = malloc(bufsize * sizeof(char*)); 
    char *token, **tokens_backup; 

    if (!tokens) { 
    fprintf(stderr, "lsh: allocation error\n"); 
    exit(EXIT_FAILURE); 
    } 

     token = strtok(line, LSH_TOK_DELIM); 
     while (token != NULL) { 
     tokens[position] = token; 
     position++; 

    if (position >= bufsize) { 
     bufsize += LSH_TOK_BUFSIZE; 
     tokens_backup = tokens; 
     tokens = realloc(tokens, bufsize * sizeof(char*)); 
     if (!tokens) { 
     free(tokens_backup); 
     fprintf(stderr, "lsh: allocation error\n"); 
     exit(EXIT_FAILURE); 
     } 
    } 

     token = strtok(NULL, LSH_TOK_DELIM); 
     } 
     tokens[position] = NULL; 
     return tokens; 
     } 

/** 
    @brief Loop getting input and executing it. 
*/ 
void lsh_loop(void) 
{ 
    char *line; 
    char **args; 
    int status; 

    do { 
    printf("Please enter:\n> "); 
    line = lsh_read_line(); 
    args = lsh_split_line(line); 
    status = lsh_execute(args); 

    free(line); 
    free(args); 
    } while (status); 
} 
int fcfs(){ 
... 
return 0; 
} 

int sjf(){ 
... 
return 0; 
} 
/** 
    @brief Main entry point. 
    @param argc Argument count. 
    @param argv Argument vector. 
    @return status code 
*/ 
int main(int argc, char **argv) 
{ 
    // Load config files, if any. 
    printf(" --WELCOME TO ALS-- \n"); 
    // Run command loop. 
    lsh_loop(); 

     // Perform any shutdown/cleanup. 

     return EXIT_SUCCESS; 
    } 

답변

1

getopt()은 동일한 문자열을 다시 구문 분석 할 수 있도록 재설정해야하는 일부 정적 변수를 사용합니다.

에서 [정적 가변 optind

는 ARGV 에서 처리 될 다음 요소의 인덱스이다. 시스템은이 값을 1로 초기화합니다. 호출자는 을 1로 재설정하여 동일한 argv의 스캔을 다시 시작하거나 새 인수 벡터를 스캔 할 수 있습니다.

그렇게 : 또한

extern int optind; 
.... 
optind= 1; 

참조 : http://man7.org/linux/man-pages/man3/getopt.3.html

+0

심지어 이것에 대해 생각했다! 고마워, 폴 +1 –

관련 문제