Dimitris Delis Dimitris Delis - 1 month ago 24
C Question

process loop in C

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!

Answer

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.

Comments