Question

J'ai suivi un tutoriel sur la façon de créer mon propre shell mais je suis bloqué depuis quelques jours maintenant.

Deux choses:

  1. Lorsque ce code sera compilé et exécuté, il aura des erreurs de segmentation de manière aléatoire et je n'arrive pas à comprendre pourquoi.
  2. L'instruction if « if (ferror != 0) » semble toujours être vraie.ce qui est étrange car je ne comprends pas pourquoi fgets() est en échec dans le principal() fonction.

Toute information sur ces sujets (ou d'autres sujets sur la création de ce shell) serait grandement appréciée.

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

#define MAXSIZE 512

int parseCmd(char *cmd, char *args[])
{
    printf("LOGGER: parseCmd(cmd=%s, args=%p)\n", cmd, args);

    char cmdDelims[] = {' ','>'};

    char *cmdReader;
    cmdReader = strtok(cmd, cmdDelims);

    int i = 0;
    while (cmdReader != NULL)
    {       
        args[i] = strdup(cmdReader);

        printf("LOGGER: args[%d]=%s\n", i, args[i]);

        cmdReader = strtok(NULL, cmdDelims);
        i++;
    }
    return 0;
}

void printToLine(char *args[])
{
    int length;
    length = sizeof(args) / sizeof(char);

    int i = 0;
    while (i < length)
    {
        printf("%s\n", args[i]);
        i++;
    }
}

int main(int argc, char *argv[]) 
{   
    char *in;
    in = malloc(MAXSIZE);

    char *args[15];
    char *cmd = NULL;

    int errorBit = 0;
    int terminationBit = 1;
    char error_message[30] = "An error has occurred\n";

    char inDelims[] = "\n";

    while (terminationBit)
    {
        printf("mysh>");

        // get input from command line
        fgets(in, MAXSIZE, stdin);
        if (ferror != 0)
        {
            perror(error_message);
        }

        // get pointer to command line input w/o the newline
        cmd = strtok(in, inDelims);

        // parse the command into separate arguments
        errorBit = parseCmd(cmd, args);
        if (errorBit)
        {
            perror(error_message);
            exit(1);
        }

        printToLine(args);

        // check if the user wants to exit the shell
        if (strcmp(*args, "exit") == 0)
        {
            terminationBit = 0;
        }
    }
    return 0;
}

Voici quelques sorties :

**[ray@12] (6)$ mysh**
mysh>1 2 3
An error has occurred
: Success
LOGGER: parseCmd(cmd=1 2 3, args=0x7fff4a50b080)
LOGGER: args[0]=1
LOGGER: args[1]=2
LOGGER: args[2]=3
1
2
3
Segmentation fault (core dumped)
**[ray@12] (7)$ mysh**
mysh>1 2 3 4 5 6 7 8 9 10
An error has occurred
: Success
LOGGER: parseCmd(cmd=1 2 3 4 5 6 7 8 9 10, args=0x7fffba053d70)
LOGGER: args[0]=1
LOGGER: args[1]=2
LOGGER: args[2]=3
LOGGER: args[3]=4
LOGGER: args[4]=5
LOGGER: args[5]=6
LOGGER: args[6]=7
LOGGER: args[7]=8
LOGGER: args[8]=9
LOGGER: args[9]=10
1
2
3
4
5
6
7
8
mysh>1 2 3
An error has occurred
: Success
LOGGER: parseCmd(cmd=1 2 3, args=0x7fffba053d70)
LOGGER: args[0]=1
LOGGER: args[1]=2
LOGGER: args[2]=3
1
2
3
4
5
6
7
8
Était-ce utile?

La solution

Pour le ferror erreur, vous devez tester ferror(stdin), pas ferror.Cette dernière est l'adresse de la fonction, qui ne sera jamais nulle :

if (ferror(stdin) != 0)
{
    perror(error_message);
}

Pour au moins certaines erreurs de segmentation, cela ne fait pas ce que vous pensez :

length = sizeof(args) / sizeof(char);

Cela vous dira combien d'octets sont utilisés pour stocker le pointeur, qui vaut 4 ou 8 selon, et pas le nombre d'arguments.

Donc si vous avez quatre (ou huit) arguments, ce sera apparaître travailler.Si vous en avez plus, il semblera ignorer certains arguments.Et si vous en avez moins, il récupérera les arguments manquants à travers le Vide, ce qui entraînera une erreur de segmentation (presque sûre).

Il faut calculer length indépendamment et transmettez-le, ou stockez un terminateur dans args, par exemple en ajoutant un argument NULL après le dernier argument valide que vous trouvez :

        cmdReader = strtok(NULL, cmdDelims);
        i++;
    }
    args[i] = NULL;
    return 0;
}

void printToLine(char *args[])
{
    int i = 0;
    while (args[i])
    {
        printf("%s\n", args[i]);
        i++;
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top