Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problems with fork() and execvp()

Status
Not open for further replies.

Rhoon

Programmer
Mar 23, 2001
55
US

I'm trying to get this to emulate as a shell (this program) sitting on a shell (the actual one which came with the OS).

If I type just ls, all that returns is the environmental variables (BLOCKSIZE=, PWD=, TERM, USER, VENDOR, etc.. ) returned as : No such file or directory.

If I type ls -la : the fork'd process returns back to the main program and I get no such file (coded by myself (the error message))

If anyone has any ideas, thanks in advance.

the code in its entirety is below...



#include "prompt.h"
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;

prompt::prompt(void)
{
compName = &quot;Andrew$&quot;;
dir = &quot;&quot;;
}

prompt::~prompt(void)
{
}

void prompt::parse_args(char *args)
{
int i = 0;
pid_t pidValue;
char *command;
char *partmp[20];
char *tok;
tok = &quot; &quot;;
command = strtok(args, &quot; &quot;);
tok = strtok(NULL,&quot; &quot;);
if (command == '\0')
{
return;
}
// Breaks the string up into each individual parameters
while (tok != NULL)
{
partmp = tok;
tok = strtok(NULL,&quot; &quot;);
i++;
}
int j =0;
char *params;
// Copies the number of parameters into a dynamically allocated array
while ( j <= i )
{
params[j] = partmp[j];
j++;
}
// looking for the cd command to change the directory name
if ( strcmp(command, &quot;cd&quot; ) == 0)
{
dir = params[0];
}
// a way to exit the shell since it is set into an infinite loop
else if ( strcmp(command, &quot;exit&quot; ) == 0)
{
exit(0);
}
// When all else fails its time to test the unix environment to see if they own the command
else
{
pidValue = fork();
// pidValue is Zero for the child process
if (pidValue == 0)
{
printf(&quot;Child program entering Execution...\n&quot;);
if ( i == 0)
{
// If no parameters are typed into the shell, we don't want to send garbage data to be misinterpretted
printf(&quot;My command is: %s\n&quot;, command);
execvp(command, NULL);
}
else
{
// if i is something other than Zero
// chances are that there are parameters to be passed and we do just that
printf(&quot;My command is: %s\n&quot;, command);
printf(&quot;My parameters are: %s\n&quot;, params[0]);
execlp(command, params);
}
printf(&quot;Invalid File or Command\n&quot;); // should not reach this line of code
}

else
{
// the wait command holds the parent process until the before called child process terminates
wait(0);
}
}
}

// This Method's Purpose was to update and redraw
// the directory and machine name everytime.
void prompt::draw_path()
{
printf(&quot;%s %s>&quot;, compName, dir);
}

void prompt::get_command()
{

cin.getline(cmd, 200, '\n');

parse_args(cmd);
}

// Alot of this program was broken up into alot of little pieces
// in an attempt to make it more readable and more modular

void main()
{
// Wouldn't be an Object Oriented Program without an Object. Allows for more diverse use in the future.
prompt p;

while (1)
{
p.draw_path();
p.get_command();
}
}
 
Post your code again, but this time enclose your code in
Code:
delimiters or uncheck Emoticons/Smileys and Process TGML.

People probably aren't going to take the time to reconstruct your code as it is.
 
dont even see any smiles in any of the code, weird... thanks for the heads up on that, let me know if this is any better.

Code:
#include &quot;prompt.h&quot;
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;

prompt::prompt(void)
{
    compName = &quot;Andrew$&quot;;
    dir = &quot;&quot;;
}

prompt::~prompt(void)
{
}

void prompt::parse_args(char *args)
{
    int i = 0;
    pid_t pidValue;
    char *command;
    char *partmp[20];
    char *tok;
    tok = &quot; &quot;;
    command = strtok(args, &quot; &quot;);
    tok = strtok(NULL,&quot; &quot;);
    if (command == '\0')
    {
        return;
    }
    // Breaks the string up into each individual parameters
    while (tok != NULL)
    {
        partmp = tok;
        tok = strtok(NULL,&quot; &quot;);
        i++;
    }
    int j =0;
    char *params;
    // Copies the number of parameters into a dynamically allocated array
    while ( j <= i )
    {
        params[j] = partmp[j];
        j++;
    }
    // looking for the cd command to change the directory name
    if ( strcmp(command, &quot;cd&quot; ) == 0)
    {
        dir = params[0];
    }
    // a way to exit the shell since it is set into an infinite loop
    else if ( strcmp(command, &quot;exit&quot; ) == 0)
    {
        exit(0);
    }
    // When all else fails its time to test the unix environment to see if they own the command
    else 
    {
        pidValue = fork();
        // pidValue is Zero for the child process
        if (pidValue == 0)
        {
            printf(&quot;Child program entering Execution...\n&quot;);
            if ( i == 0)
            {
                // If no parameters are typed into the shell, we don't want to send garbage data to be misinterpretted
                printf(&quot;My command is: %s\n&quot;, command);
                execvp(command, NULL);
            }
            else
            {
                // if i is something other than Zero
                // chances are that there are parameters to be passed and we do just that
                printf(&quot;My command is: %s\n&quot;, command);
                printf(&quot;My parameters are: %s\n&quot;, params[0]);
                execlp(command, params);
            }
            printf(&quot;Invalid File or Command\n&quot;); // should not reach this line of code
        }
   
        else 
        {
            // the wait command holds the parent process until the before called child process terminates
            wait(0);
        }
    }   
}

// This Method's Purpose was to update and redraw
// the directory and machine name everytime.
void prompt::draw_path()
{
    printf(&quot;%s %s>&quot;, compName, dir);
}

void prompt::get_command()
{
    
    cin.getline(cmd, 200, '\n');

    parse_args(cmd);
}

// Alot of this program was broken up into alot of little pieces
// in an attempt to make it more readable and more modular

void main()
{
    // Wouldn't be an Object Oriented Program without an Object. Allows for more diverse use in the future.
    prompt p;

    while (1)
    {
        p.draw_path();
        p.get_command();
    }
}
 
>void prompt::parse_args(char *args)
>{
> int i = 0;
> pid_t pidValue;
> char *command;
> char *partmp[20];
> char *tok;
> tok = &quot; &quot;;
> command = strtok(args, &quot; &quot;);
> tok = strtok(NULL,&quot; &quot;);
> if (command == '\0')

You should be comparing this to NULL, not '\0'.

> {
> return;
> }
> // Breaks the string up into each individual parameters
> while (tok != NULL)
> {
> partmp = tok;

This is an incompatible assignment. partmp is an array of 20 pointers to char and tok is a pointer to char.

> tok = strtok(NULL,&quot; &quot;);
> i++;
> }
> int j =0;
> char *params;
> // Copies the number of parameters into a dynamically allocated array
> while ( j <= i )
> {
> params[j] = partmp[j];
> j++;
> }

Since you didn't assign things properly above, partmp won't contain the program arguments.

Try this to tokenize the entered string:

#define MAX_PARAMS 20

char *param;
char *command;
int i = 0;
char *params[MAX_PARAMS];

command = strtok(args, &quot; &quot;);
params[0] = NULL;
if (command != NULL) {
while ((param = strtok(NULL, &quot; &quot;)) != NULL && i < (MAX_PARAMS - 1)) {
params[i++] = param;
}
params = NULL; /* execvp requires last element to be NULL */
}

> // looking for the cd command to change the directory name
> if ( strcmp(command, &quot;cd&quot; ) == 0)
> {
> dir = params[0];

Hmmmm...not sure why you're isolating cd and then not executing it.

> }
> // a way to exit the shell since it is set into an infinite loop
> else if ( strcmp(command, &quot;exit&quot; ) == 0)
> {
> exit(0);
> }
> // When all else fails its time to test the unix environment to see if they own the command
> else
> {
> pidValue = fork();
> // pidValue is Zero for the child process
> if (pidValue == 0)
> {
> printf(&quot;Child program entering Execution...\n&quot;);
> if ( i == 0)
> {
> // If no parameters are typed into the shell, we don't want to send garbage data to be misinterpretted
> printf(&quot;My command is: %s\n&quot;, command);
> execvp(command, NULL);
> }
> else
> {
> // if i is something other than Zero
> // chances are that there are parameters to be passed and we do just that
> printf(&quot;My command is: %s\n&quot;, command);
> printf(&quot;My parameters are: %s\n&quot;, params[0]);
> execlp(command, params);
> }
> printf(&quot;Invalid File or Command\n&quot;); // should not reach this line of code
> }
>
> else
> {
> // the wait command holds the parent process until the before called child process terminates
> wait(0);
> }

You'll want to test if fork() returned -1, indicating an error. As it is, you call wait() if it returned 1 or -1.

You want execvp instead of execlp since you're passing it an array of pointers to char for the arguments. If you parse the arguments per my example above, you also don't need to test whether any params are present. Try something like this.

if ((pidValue = fork()) == 0) {
/* Child */
if (execvp(command, params) < 0) {
/* Report execvp error */
}
} else if (pidValue == -1) {
/* Report fork() error */
} else {
wait(0);
}

> }
>}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top