2016-12-08 7 views
0

Ich schreibe ein Mini-Shell-Programm. Es gibt mir Seg-Fehler in der Zeile "args = my_str2vect (line);". Die "my_str2vect" -Funktion funktioniert gut, aber auch die Funktion my_strncpy und my_strlen (gibt die Länge des char-Arrays zurück). Also, was stimmt nicht mit dieser Linie?Empfangen Seg Fehler für meine Minishell-Programm

#define _POSIX_SOURCE 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/types.h> 
#include <signal.h> 
#include "../../include/my.h" 




pid_t pid; 
int childrunning = 0; 
void minishell_loop(); 

/* 
    Your shell must also support CTRL+C by using UNIX signals. 
    If you type CTRL+C your prompt must not exit 
    and instead kill the currently running process (or do nothing if there is none). 
*/ 

void int_handler(int sig){ 
    if(childrunning == 1){ 
    kill(pid, SIGUSR2); 
    }else{ 
    my_str("\n"); 
    minishell_loop(); 
    } 
} 

void killkillkill(int sig){ 
    exit(0); 
} 
/* 
    Function Declarations for builtin shell commands: 
*/ 
int minishell_cd(char **args); 
int minishell_help(char **args); 
int minishell_exit(char **args); 

/* 
    List of builtin commands, followed by their corresponding functions. 
*/ 
char *builtin_str[] = { 
    "cd", 
    "help", 
    "exit" 
}; 

int (*builtin_func[]) (char **) = { 
    &minishell_cd, 
    &minishell_help, 
    &minishell_exit 
}; 

int minishell_mum_bultins() { 
    return sizeof(builtin_str)/sizeof(char *); 
} 

/* 
    Builtin function implementations. 
*/ 

/** 
    @brief Bultin command: change directory. 
    @param args List of args. args[0] is "cd". args[1] is the directory. 
    @return Always returns 1, to continue executing. 
*/ 
int minishell_cd(char **args) 
{ 
    if (args[1] == NULL) { 
    fprintf(stderr, "minishell: expected argument to \"cd\"\n"); 
    } else { 
    if (chdir(args[1]) != 0) { 
     perror("minishell"); 
    } 
    } 
    return 1; 
} 

/** 
    @brief Builtin command: print help. 
    @param args List of args. Not examined. 
    @return Always returns 1, to continue executing. 
*/ 
int minishell_help(char **args) 
{ 
    int i; 
    printf("Tianwei's minishell, version 1.01\n"); 
    printf("These shell commands are defined internally.\n"); 

    for (i = 0; i < minishell_mum_bultins(); i++) { 
    printf(" %s\n", builtin_str[i]); 
    } 
    return 1; 
} 

/** 
    @brief Builtin command: exit. 
    @param args List of args. Not examined. 
    @return Always returns 0, to terminate execution. 
*/ 
int minishell_exit(char **args) 
{ 
    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 minishell_launch(char **args) 
{ 
    signal(SIGUSR2, killkillkill); 
    int status; 

    pid = fork(); 
    if (pid == 0) { 
    // Child process 
    childrunning = 1; 
    if (execvp(args[0], args) == -1) { 
     perror("minishell"); 
    } 
    exit(EXIT_FAILURE); 
    } else if (pid < 0) { 
    // Error forking 
    perror("minishell"); 
    } 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 minishell_execute(char **args) 
{ 
    int i; 
    my_str(args[0]); 
    if (args[0] == NULL) { 
    my_str("args[0] is NULL\n"); 
    // An empty command was entered. 
    return 1; 
    } 
    for (i = 0; i < minishell_mum_bultins(); i++) { 
    if (strcmp(args[0], builtin_str[i]) == 0) { 
     my_str("1\n"); 
     return (*builtin_func[i])(args); 
    } 
    } 
    my_str("0\n"); 
    return minishell_launch(args); 
} 

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

    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) { 
     fprintf(stderr, "minishell: Command line too long!\n"); 
     exit(EXIT_FAILURE); 
    } 
    } 
} 


/** 
    @brief Loop getting input and executing it. 
*/ 
void minishell_loop(void) 
{ 
    signal(SIGINT, int_handler); 
    char* line; 
    char** args; 
    int status; 
    do { 
    printf("MINISHELL: /home/tianwei/$ "); 
    line = minishell_readln(); 
    my_str("0\n"); 
    my_str(line); 
    args = my_str2vect(line); 
    my_str(args[0]); 
    my_str("0\n"); 
    status = minishell_execute(args); 
    my_str("1\n"); 

    free(line); 
    free(*args); 
    free(args); 
    } while (status); 
} 

/** 
    @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. 
    // Run command loop. 
    minishell_loop(); 

    // Perform any shutdown/cleanup. 

    return EXIT_SUCCESS; 
} 

Dies ist der Code für my_str2vect Funktion

#include "../../include/my.h" 

char** my_str2vect(char* str){ 
// Takes a string 
// Allocates a new vector (array of string ended by a NULL), 
// Splits apart the input string x at each space character 
// Returns the newly allocated array of strings 
// Any number of ' ','\t', and '\n's can separate words. 
// I.e. "hello \t\t\n class,\nhow are you?" -> {"hello", "class,", "how", "are","you?", NULL} 
    int max_num_words = 0; 
    int a = 0; 
    int b = 0; 
    int max_num_char = 0; 
    while(str[a] != '\0'){ // find the number of words and the length of the longest word 
     if(str[a] != ' ' && str[a] != '\t' && str[a] != '\n'){ 
      ++max_num_words; 
      ++a; 
      ++b; 
      while((str[a] != ' ' && str[a] != '\t' && str[a] != '\n') && str[a] != '\0'){ 
       ++a; 
       ++b; 
      } 
      if(b > max_num_char){ 
       max_num_char = b; 
      } 
      b = 0; 
      while((str[a] == ' ' || str[a] == '\t' || str[a] == '\n') && str[a] != '\0'){ 
       ++a; 
      } 
     } 
    } 
    char** output = (char **)malloc(sizeof(char *) * (max_num_words + 1)); // Allocate a 2D array first. 
    for(int c = 0; c < max_num_words + 1; ++c){ 
     output[c] = (char *)malloc(sizeof(char) * (max_num_char + 1)); 
    } 
    int i = 0; 
    int j = 0; 
    while(i < my_strlen(str) && j < max_num_words){ // Put the characters into the 2D array. 
     int k = 0; 
     while(i < my_strlen(str) && (str[i] == ' ' || str[i] == '\t' || str[i] == '\n')){ 
      ++i; 
     } 
     while(i < my_strlen(str) && (!(str[i] == ' ' || str[i] == '\t' || str[i] == '\n'))){ 
      ++i; 
      ++k; 
     } 
     if(i-k < my_strlen(str) && j < max_num_words){ 
      my_strncpy(output[j], &str[i-k], k); 
     } 
     ++j; 
    } 
    output[j] = NULL; 
    return output; 
} 

Dies ist my_strncpy Funktion

#include "../../include/my.h" 


char *my_strncpy(char *dst, char *src, int n) 
{ 
    /* Same as my_strcpy except: 
    * Only copies n chars or until the end of src*/ 

    if(src != NULL && dst != NULL){ 
     int i = 0; 
     while(i < n && src[i] != '\0'){ 
      dst[i] = src[i]; 
      ++i; 
     } 
     dst[i] = '\0'; 
    } 
    return dst; 
} 
+0

'if (str [a] = '' || str [a] erleichtern ! = '\ t' || str [a]! = '\ n') {':' || '->' && 'und brauche 'str [a]! =' \ 0'' innerhalb der Schleife. – BLUEPIXY

+0

Thx, gerade behoben. @BLUEPIXY – Echo111

Antwort

0

ich nicht Ihren Code nicht versuchen auszuführen, aber hier ist das, was den ersten Blick an mir auffällt in der my_str2vect Funktion:

  • in der ersten while Schleife, a wird nur in der if inkrementiert. Sie werden wahrscheinlich eine Schleife für immer treffen, wenn Ihre Zeile mit einem Leerzeichen
  • in der zweiten while Schleife beginnt, überprüfen Sie nicht für das Ende der Zeichenfolge '\0'. Dies könnte der Grund für Ihren Absturz sein, aber es könnte auch andere geben.

PS: da Sie einen String parsen, Sie einen Blick auf strtok und sscanf nehmen sollten, würden sie Ihr Leben

Verwandte Themen