views:

130

answers:

3

I am reading GNU/Linux application programming the 2nd edition,you can reach what am reading from here.After I write the code similar to his,but it work strangely:

$ ./shell
./shell>>quit
$ ./shell
./shell>>date
Sun Aug  8 21:19:37 CST 2010
./shell>>quit
$ ./shell
./shell>>abc
execlp failed: No such file or directory
./shell>>quit
./shell>>quit
$./shell 
./shell>>abcd execlp
execlp failed: No such file or directory
./shell>>quit 
./shell>>quit

The first and second cases are ok,but the third and forth ones somewhat need two quit to quit.This is not what i am expecting.I guess something is wrong with fork(),or the waitpid(),but this still got unsolved after asking a few people around me.Now is summer time, i.e. summer holiday,I got no more mates to go for.Thanks always.

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

#define LINE_LEN 80

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

 pid_t pid;
 char cmd[LINE_LEN+1]={'\0'};

 while(1)
 {
  printf("%s>>",argv[0]);
  if(fgets(cmd,sizeof(cmd),stdin)==NULL)
  {
   perror("fgets failed");
   break;
  }
  cmd[strlen(cmd)-1]='\0';
  if(strncmp(cmd,"quit",4)==0)
  {
   break;
  }
  if((pid=fork())==-1)
  {
   perror("fork failed");
   break;
  }else if(pid==0)
  {
   //TODO no option can be specified for cmd
   execlp(cmd,cmd,NULL);
   perror("execlp failed");
  }else
  {
   waitpid(pid,NULL,0);
  }
 }
 return 0;
}
+3  A: 

Normally, if execlp succeeds, your child process becomes the new process, and thus execution of your code effectively stops at that point.

Now the execlp failed, you print out the error, and continue the child process as if nothing happened! You should exit(0) the child, if the execlp failed.

mvds
Thanks.I see what you mean.The code in the book does not do any error check about execlp,So this fix may go to the errata?
schemacs
definitely! If your book doesn't say so, remember this: *always check return values*
mvds
(although, for the `exec` class of functions, the fact that your code is still alive is an indication of failure, so checking a return value is strictly not needed to know things went wrong...)
mvds
Thanks again.You answered this question so quick.I love stackoverflow.com.So professional,but I am just a newbie.
schemacs
A: 

execlp will fail if cmd does not exist.

As mvds rightly said, when execlp fails, you should exit the child process. But I recommend not forking when cmd does not exist.

You could use something like access (see access(2)) before using fork to make sure cmd exists (within your PATH), and is an executable.

Bertrand Marron
Yes,I should call access before pass cmd to execlp.Thanks a lot.
schemacs
UPDATE:access(with X_OK) only check pathname,not filename(i.e. I have to figure out it with path.)
schemacs
A: 

Just post the debug version to make it clear:strncmp is called in which process,and when child or parent exit

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

#define LINE_LEN 80

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

    pid_t pid;
    char cmd[LINE_LEN+1]={'\0'};

    while(1)
    {
        printf("%s>>",argv[0]);
        if(fgets(cmd,sizeof(cmd),stdin)==NULL)
        {
            perror("fgets failed");
            break;
        }
        cmd[strlen(cmd)-1]='\0';
        if(strncmp(cmd,"quit",4)==0)
        {
            printf("process :%d in strncmp equal\n",getpid());
            break;
        }
        if((pid=fork())==-1)
        {
            perror("fork failed");
            break;
        }else if(pid==0)
        {
            printf("new child:%d\n",getpid());
            //TODO no option can be specified for cmd
            execlp(cmd,cmd,NULL);
            perror("execlp failed");
            //This is critical
            //exit(0);
        }else
        {
            printf("parent:%d(his child is %d)\n",getpid(),pid);
            waitpid(pid,NULL,0);
        }
    }
    printf("process :%d exit...\n",getpid());
    return 0;
}

just see one case:

./shell
./shell>>abc
parent:8356(his child is 8357)
new child:8357
execlp failed: No such file or directory
./shell>>quit
process :8357 in strncmp equal
process :8357 exit...
./shell>>quit
process :8356 in strncmp equal
process :8356 exit...
schemacs