Shell in C: Segmentation error and execve function, what’s wrong?

Asked

Viewed 131 times

0

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

void type_prompt(){
    printf("\n$~");
}


void read_command(char command[], char *parameters[]){
    char linha[100] = "";
    fgets(linha, 100, stdin);

    int i;
    int flag = 0;
    for (i = 0; i <= strlen(linha); i++){
        if (linha[i] == ' '){
            flag = 1;
            break;
        }
    }

    char *word = strtok(linha, " ");
    strcat(command, "/bin/");
    strcat(command, word);
    parameters[0] = word;

    if (flag == 1) command[strlen(command)] = '\0';
    else command[strlen(command) - 1] = '\0';

    if (flag == 1){
        while (word != NULL){
            word = strtok(NULL, " ");
            strcat(*parameters, word);
        }
    }
}

int main (){
    char command[] = {""};
    char *parameters[100] = {NULL}; //argv
    char *env[]={"PATH=/usr/local/sbin/:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games",NULL};
    int status;

    while (1){
        type_prompt();
        read_command(command, parameters);

        if (fork() != 0){
            command[0] = '\0';
            parameters[0] = '\0';
            waitpid(-1, &status, 0);
        }

        else {  
            execve(command, parameters, env);
            command[0] = '\0';
            parameters[0] = '\0';
            printf("Erro execve %d: %s\n", errno, strerror(errno));
        }
    }
}
  • Describe your error better and point out exactly the relevant code snippet to the problem.

  • The purpose of the code is to simulate a shell. However, I believe the problem lies in the read_command function. Because commands without spaces work normally, such as "ps", but when placing "ps aux", there is a segmentation error.

1 answer

0


There are several errors, the basic problem is that you are manipulating the Parameters vector in the wrong way, and also throwing in it snippets of "line" string, which is a variable that disappears as soon as the read_command() function returns.

Below is a "diff" of lines I changed to make it work. The program is not yet perfect, because strdup() allocates memory in the heap and repeated execution will leak memory because new parameters are played in "Parameters" without destroying the old ones, but at least the program does not break anymore, and works as expected.

-void read_command(char command[], char *parameters[]){
-    char linha[100] = "";
+void read_command(char command[], char **parameters){
+    char linha[100];
+    linha[0] = '\0';
     fgets(linha, 100, stdin);

+    // remove o "enter"
+    linha[strlen(linha) - 1] = '\0';
+
+    printf("compr linha %d\n", strlen(linha));
+    if (strlen(linha) < 1) {
+        printf("saindo\n");
+        exit(0);
+    }
+
     int i;
     int flag = 0;
     for (i = 0; i <= strlen(linha); i++){
@@ -27,22 +37,24 @@
     char *word = strtok(linha, " ");
     strcat(command, "/bin/");
     strcat(command, word);
-    parameters[0] = word;
-
-    if (flag == 1) command[strlen(command)] = '\0';
-    else command[strlen(command) - 1] = '\0';
+    *parameters = strdup(command);
+    printf("comando: '%s'\n", command);

     if (flag == 1){
         while (word != NULL){
             word = strtok(NULL, " ");
-            strcat(*parameters, word);
+            if (word) {
+           printf("parametro: '%s'\n", word);
+                *(++parameters) = strdup(word);
+            }
         }
     }
+    *(++parameters) = NULL;
 }

 int main (){
     char command[] = {""};
-    char *parameters[100] = {NULL}; //argv
+    char *parameters[100];
     char *env[]={"PATH=/usr/local/sbin/:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games",NULL};
     int status;

@@ -52,14 +64,12 @@

         if (fork() != 0){
             command[0] = '\0';
-            parameters[0] = '\0';
             waitpid(-1, &status, 0);
         }

         else {  
             execve(command, parameters, env);
             command[0] = '\0';
-            parameters[0] = '\0';
             printf("Erro execve %d: %s\n", errno, strerror(errno));
         }
     } 
  • That’s exactly it! Thank you, it worked, you are amazing. As you said, I was not knowing how to properly manipulate the "Parameters". I’ll review that, thanks again for the help!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.