0

I'm trying to write a code about a process that executes programs from $PATH using the execlp() command.(it doesn't need to be the execlp command but I've found it useful for this one) I've achieved my expected output, but I need to run more than one commands. More specifically I want the child process to run the exec command, then the parent process to print a text indicating that it's ready to accept another command. Then the child process will run the new exec command. My code is this:

int main ( int argc, char *argp[]) { 
pid_t progpid = fork(); // the fork command for the creation of the child process
int status = 0;
char com[256];

if (progpid < 0)  // the check in case of failure
   {
    printf("PROGRAM ABORTED!");
    return 0;
   }
do
   {
    if (progpid == 0)  // the child process
      {
       scanf( "%s", com);
         if (com == "exit")
          {
            exit(0);
          }
        else
            {
               execlp(com, com, NULL);
            }
      }
else //the parent process
    {
      wait(&status);
      printf("$");
    }
}while (com != "exit");
return 0;
}

The expected output is :

<program which I input from keyboard> ( for example  : ls )
<output of the program>
$<next program>
<output of the next program>
.
.
.
$exit

In short I want to keep running programs till I enter exit where it ends without doing anything else. However the output I get is this:

<program>
<output of program>
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

It keeps printing $ until I shut it down. I'm new to processes so please don't be too harsh about my code so far. Thank you in advance!

Dimitris Delis
  • 55
  • 1
  • 10
  • 1
    The logic of your loop is flawed. You only create *one* child process, at the beginning of the program. You need to create one child process *per command entered*. – Some programmer dude Nov 01 '16 at 15:32

1 Answers1

2

This

if (com == "exit")

should be

if (strcmp(com, "exit") == 0)

Similarly change the while condition as well.

In C, string comparisons are done using strcmp(). == in your case, simply compares the address of com and the address of the string literal "exit". (In expressions, an array gets converted into a pointer to its first element. Hence, "address" comparison. Also see: What is array decaying?).

Note that your execlp() call has an issue. NULL may be defined as 0, in which case execlp(), being a variadic function, may be able to recognize it as the last argument. I'd suggest to change it to:

execlp(com, com, (char*)0);

You'd also want to check if wait() failed or not by checking its return code.


Here's a simple example based on yours with improved error checking.

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

int main ( int argc, char *argp[]) {

for(;;) {
    char com[1024];
    printf("$ ");
    fgets(com, sizeof com, stdin);
    com[strcspn(com, "\n")] = 0; /* Remove if there's a newline at the end */

    if (strcmp(com, "exit") == 0) {
       exit(0);
    }

    pid_t pid = fork();
    if (pid < 0) {
        perror("fork");
        exit(1);
    }

    if (pid == 0) { /* child process */
       execlp(com, com, (char*)0);
    }

    int status;
    int rc = wait(&status);
    /* You can inspect 'status' for further info. */
    if (rc == -1) {
        perror("wait");
        exit(1);
    }
}

return 0;
}

Note that if you want your to execute commands with arguments then you need to do argument processing.

Community
  • 1
  • 1
P.P
  • 106,931
  • 18
  • 154
  • 210
  • wait did not fail. I have tested it without the do while loop and it works. – Dimitris Delis Nov 01 '16 at 15:35
  • I am just saying it'd be a good practice to check the return code. If there's any problem with the execution `com` then you'd want to know about it. – P.P Nov 01 '16 at 15:40