简体   繁体   中英

Segmentation fault using strcmp and char *arr[]

I am working on creating a shell and I haven't use C for a while. I have the shell initizing properly but when I try to compare the user input to an array of strings I have I get a segmentation fault. I was planning on adding casce statements in a the for loop to initiate each of the processes once they are called by the user. I haven't included those since I have been trying to figure out how to get the user input to match with a value in my string array. Under debug I was only receiving the first character of the builtins[j] value which kind of makes since since it is a pointer right. However I am stuck and could use some ideas for why this isn't returning 0 when I input "exit". Thanks

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>

//This code is for creating a basic shell
void init_shell(int num, char *prompt[]){
    char s1[] = "-p"; 
    int result;
    if(num>1){
    result = strcmp(s1, prompt[1]);
        if(result==0){
            printf("%s>$", prompt[2]);

        }else{
        printf("308sh>$");
        }
    }
    //printf("%s\n %s\n %s\n %d\n", prompt[0], prompt[1], prompt[2], result);
    else{
        printf("308sh>$");
    }

}

//The infinite loop for accepting user input until it closes

int main(int argc, char *argv[]){


    const char *builtins[7];    
    builtins[0] = "exit\n";
    builtins[1] = "pid\n";
    builtins[2] = "ppid\n";
    builtins[3] = "cd\n";
    builtins[4] = "pwd\n";
    builtins[5] = "set\n";
    builtins[6] = "get\n";

    char usr_in[]="";
    char cmp[]="";
    while(1==1){
        init_shell(argc, argv);//intial prompt for the shell
        fgets(usr_in,100,stdin); 

    //Check for builtin Commands

        int cmds_size = 7;
        int j=0;
        int res;

        for(j; j<cmds_size; j++){

            res=strcmp(usr_in, hold);
            if(res==0){

            printf("Execucting\n");
            }
            else{
                printf("no command\n");
            }
        }

    }

    return(0);
}

The issue here is that you're writing the user's input to a buffer that isn't big enough to hold anything other than a null terminator.

char user_in[] = "";

The above line tells the C compiler that you need just enough space to store [ '\\0' ] , which is a single byte. The C compiler doesn't know that you may later write a 100-byte string to that buffer.

When you write to the buffer, the user's input overflows and will overwrite other values in your stack. Since the other values in your stack are pointers, what'll happen is you'll run into seg-faults, since you're writing character values into those bytes, but interpreting them as char pointers.

You are correctly limiting the size of the allowed input from the user to 100 characters, but you should make sure that your buffer is big enough to hold the value you're reading in:

char user_in[101];
for(int i = 0; i < sizeof(user_in) / sizeof(user_in[0]); i++) {
  user_in[i] = 0; // Since this is allocated on the stack *in main*, this
                  // shouldn't be necessary
}

Here's one example of how you can rewrite your main method:

#include <stdio.h>
#include <string.h>

typedef enum { false, true } bool; // If you don't have this
                                   // defined already

int main(int argc, char *argv[]) {

  const char *builtins[7];    
  builtins[0] = "exit\n";
  builtins[1] = "pid\n";
  builtins[2] = "ppid\n";
  builtins[3] = "cd\n";
  builtins[4] = "pwd\n";
  builtins[5] = "set\n";
  builtins[6] = "get\n";

  char user_in[101];
  for(int i = 0; i < sizeof(user_in) / sizeof(user_in[0]); i++) {
    user_in[i] = 0;
  }

  while(1) {
    printf("Enter a command: ");
    fgets(user_in, 100, stdin);

    bool found = false;
    for(int i = 0; i < sizeof(builtins) / sizeof(builtins[0]); i++) {
      if (!strcmp(user_in, builtins[i])) {
        printf("Found command %s", builtins[i]);
        found = true;
        break;
      }
    }

    if (!found) {
      printf("Didn't find command\n");
    }
  }

  return 0;
}

Also, regarding your function init_shell : you're checking to see if argc is greater than 1, but that only guarantees that argv[1] is defined; it doesn't guarantee that argv[2] is defined. (Remember, argc is the size of the argv array, where the first element is the name of the program being executed). You want to make sure that argc is at least 3 before checking for the prompt flag in the way you are.

It may be overkill for your use-case, but consider using the getopt function for getting a custom prompt value from the user. See http://man7.org/linux/man-pages/man3/getopt.3.html for documentation regarding that method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM