Pergunta

Tenho seguido um tutorial sobre como fazer meu próprio shell, mas estou preso há alguns dias.

Duas coisas:

  1. Quando esse código for compilado e executado, ele terá falhas de segmentação aleatoriamente e não consigo entender o porquê.
  2. A instrução if `if (ferror! = 0)` sempre parece ser verdadeira.o que é estranho porque não entendo por que get() está falhando no principal() função.

Qualquer informação sobre estes tópicos (ou outros tópicos sobre a criação deste shell) seria muito apreciada.

#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;
}

Aqui estão algumas saídas:

**[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
Foi útil?

Solução

Para o ferror erro, você precisa testar ferror(stdin), não ferror.Este último é o endereço da função, que nunca será zero:

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

Para pelo menos alguns dos segfaults, isso não faz o que você pensa:

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

Isso vai te dizer quantos bytes são usados ​​para armazenar o ponteiro, que é 4 ou 8 dependendo, e não o número de argumentos.

Então, se você tiver quatro (ou oito) argumentos, será aparecer trabalhar.Se você tiver mais, parecerá ignorar alguns argumentos.E se você tiver menos, ele irá buscar os argumentos ausentes em todo o Void, resultando em uma falha de segmentação (quase certa).

Você precisa calcular length independentemente e repassá-lo ou armazenar algum terminador em args, por exemplo, adicionando um argumento NULL após o último argumento válido encontrado:

        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++;
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top