'How can I get my C Shell to recognize that this is a command?

I am very new at C but am currently working on creating a C program to serve as a shell interface. It is supposed to accept commands and then execute each command in a separate process. I am currently stuck trying to get C to recognize that it is a command. I am unsure how to do this, and can't seem to find any useful examples.

Here is my code, it is saying that everything is not a valid command ("no cmd"). Does anyone have any idea why this would be occurring? Is C not able to recognize it is a command in the execvp() function or do I need to implement something for that specific purpose?

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

#define MAX_LINE 80
/* 80 chars per line per command */

int main(void) {
  //char *args[MAX_LINE/2 + 1];
    char *args = calloc(MAX_LINE, (MAX_LINE/2 +1));
    const size_t sz = MAX_LINE;
    pid_t pid;
  /* command line (of 80) has max of 40 arguments*/
  int should_run = 1;

  while (should_run) {
    printf("osh>"); //beginning of command line
        fgets(args, sz, stdin); //gets the stdin

        char *token = strtok(args, " \n"); //supposed to break str if it has a space or line and recognize there are 2 commands
        printf("%s\n", token);
        
        token = strtok(NULL," \n");
        printf("%s\n", token);
            pid_t parent = getpid();
      pid = fork(); //forking child
            if(pid == 0){ //if forking occurred
                int status = execvp(&args[0], &args); //status of input, is it a command?
                printf("%d", status);
                printf("forked!");
                if(status == -1) { //if cmd err, print
                    printf("no cmd");
                    return 1;
                } else {
                    printf("line will be printed");
                }
                return 0;
            }
        fflush(stdout); //flush
        /*

   
    * After reading user input, the steps are :
    * 1: fork a child process
    * 2: the child process will invoke execvp()
    * 3: parent process waits for the child to exit before       
    continuing
    */
  }

  exit(0);
  /**
  return to the operating system:
    -exit this process
    -flush all
  */

  
}


Solution 1:[1]

If you look at the documentation for the exec family of functions, you'll note that the functions only return if the exec failed. That's because exec, when successful, completely replaces the calling process with the invoked program.

What you need to do is, from the parent process (i.e., the one that got a positive value returned from fork), wait on the child process via waitpid.

pid_t pid;

pid = fork();
if ( pid < 0 ) {
    // Handle the error.
}
else if ( pid == 0 ) {
    execvp(&args[0], &args);
    // The fact that we've reached this line means that execvp failed.
    exit(1);
}
else {
    int status;

    while ( waitpid(pid, &status, 0) != pid ) {} // We need this loop in case waitpid gets interrupted by a signal.

    // status doesn't equal the return value of the child process.  We need to extract that with macros.
    if ( WIFEXITED(status) ) {
        printf("Child process exited with code %i\n", WEXITSTATUS(status));
    }
    else {
        printf("Child process was terminated by signal number %i\n", WTERMSIG(status));
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Daniel Walker