0

I've been tasked with creating a nested Unix shell that executes commands using the fork/exec/wait model. One of the instructions states that if the command doesn't exist (like "cd", then I need to print the attempted command. E.G. (If input is cd, output is "cd: command not found.")

But I cannot for the life of me figure out how to print the command that was input.

I declared an array, tried using scanf, tried converting from char ** to char *, or to int; none of my attempts to brute force it are working.

Here's the code:


int main() {
        char **command;
        char *input;
        pid_t child_pid;
        int stat_loc;
        char arg[20];

        while (1)
        {
                input = readline("minor2> ");
                command = get_input(input);

                if(!command[0])
                {
                        free(input);
                        free(command);
                        continue;
                }
                else if(command[0]=="quit")
                {
                        exit(1);
                }

                child_pid = fork();
                if (child_pid == 0)
                {
                        /*Never returns if call is a success*/
                        execvp(command[0], command);
                        printf("%s", arg);
                        printf(": command not found.\n");
                }
                else
                {
                        waitpid(child_pid, &stat_loc, WUNTRACED);
                }

                free(input);
                free(command);
        }

char **get_input(char *input) {
    char **command = malloc(8 * sizeof(char *));
    char *separator = " ";
    char *parsed;
    int index = 0;

    parsed = strtok(input, separator);
    while (parsed != NULL) {
        command[index] = parsed;
        index++;

        parsed = strtok(NULL, separator);
    }

    command[index] = NULL;
    return command;
}

Some of the errors I've receieved: "assignment makes integer from pointer without a cast -wint-conversion"

"Cast to pointer of integer with different size"

"1value required as left operand of assignment"

I'm just confused. I'm sure there's an elegant solution, I just am not experienced enough to figure it out.

  • 1
    What is `get_input`? What does it do? Where (if anywhere) do you define it? Where (if anywhere) do you declare it? Please take some time to refresh [how to ask good questions](http://stackoverflow.com/help/how-to-ask), as well as [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). Lastly please don't forget how to create a [mcve] to show us. – Some programmer dude Oct 07 '19 at 19:46
  • Edited for clarity – Rocko Bishop Oct 07 '19 at 19:48
  • This line makes no sense: `(char *) arg[20] = command` arg[20] is past the end of the `arg` array and its type is `char`. Casting it to `char *` leads to undefined behavior. – pcarter Oct 07 '19 at 19:49
  • That gore was my last attempt to try and get a printable statement. It definitely did not work. – Rocko Bishop Oct 07 '19 at 19:52
  • 1
    I think you need to take a couple of steps back, and restart with basic C knowledge as it seems you miss some. – Some programmer dude Oct 07 '19 at 19:52
  • I wonder why you need such conversion in the first place. You have your command returned from `getline` in a perfectly usable condition. Anyway, if you don"t know how to print a `char**` you are passing to an exec-style function, you need better C learning material. – n. m. could be an AI Oct 07 '19 at 19:54
  • Thanks everyone, I took a few steps back, and I figured it out. – Rocko Bishop Oct 07 '19 at 20:02
  • Possible duplicate of [How do I properly compare strings?](https://stackoverflow.com/questions/8004237/how-do-i-properly-compare-strings) – S.S. Anne Oct 07 '19 at 23:02

1 Answers1

3

First of all, you are trying to print arg as the command name, but I really cannot see where you assign anything to arg, so that print may break anytime due to invalid memory access (unless you hit a 0 interpreted as NULL-terminator somewhere close on the stack). You can simply replace

printf("%s", arg);

with

printf("%s", command[0]);

and it should do it.

Otherwise you should take care of filling the arg char array to hold the command name.

I'll edit my answer as I could see another problem as well:

In C, a char * is a pointer to a memory location, so it is technically just an integer. If you try to compare like this:

if (command[0]=="quit")

the check will almost always fail (in your code flow it will always fail). This is because you compare 2 memory addresses which are different whereas you should compare the contents of the memory locations. The proper way to compare 2 strings in C is to compare character by character until you hit the NULL-terminator. There is a function which does that:

strcmp(command[0], "quit");

It will return 0 if the strings are equal, or something different than 0 otherwise.

Vlad Rusu
  • 1,414
  • 12
  • 17