Themis Mavridis
Themis Mavridis

Reputation: 166

WAIT does not wait for child

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

char *getdir()  /*find working directory*/
{
  char *buffer;/*buffer is going to be used in getcwd function to get the current directory*/
  char *path_buffer;//path_buffer is going to contain the directory//
  long maxsize = pathconf(".", _PC_PATH_MAX);/* we set maxsize as the maximum pathname length*/
  if((buffer=(char*) malloc((size_t)maxsize))!=NULL)
    {
      path_buffer=getcwd(buffer,maxsize); /*get the current directory*/
      printf("\nMy working directory = %s",path_buffer);
      return path_buffer;
    }
  else{
    exit(-1);
  }
}

char * getcmline() /*get command from stdin by the user*/
{
  int bytes_read;
  int nchars=200;/*max possible number for the input of the user*/
  int nbytes=(sizeof(char))*nchars; /*size of chars in bytes*/
  char *line=(char*) malloc(nbytes+1);
  bytes_read=getline(line,&nbytes,stdin);/*read line from stdin*/
  if(bytes_read == -1){
    printf("Read line error");
    exit(-1);
  } /*error handling for bytes_read*/
  else{
    if(line[strlen(line)-1]=='\n')
      {
        line[strlen(line)-1]='\0'; /*change new line character in the end of the line of stdin*/
      }
  }
  return line;
}

int main(void)
{
  pid_t pid,child_pid;
  int rv=0;
  char* exit_string="exit";
  char *path_buffer=NULL;
  int nchars=200;
  int nbytes=(sizeof(char))*nchars;
  char *line=malloc(nbytes+1);
  char *commands[2];
  while(1){
    switch(pid = fork())
      {
      case -1:
        perror("fork"); /* something went wrong */
        exit(1);
      case 0:
        printf(" CHILD: This is the child process!\n");
        child_pid=getpid();
        printf(" CHILD: My PID is %d\n", child_pid);
        path_buffer=getdir();/*get the directory path*/
        line=getcmline();/*get a command by the user*/
        if(strcmp(line,exit_string)==0)
          {
            rv=3;
            exit(rv);
          }
        commands[0]=line;
        commands[1]=NULL;
        execvp(commands[0],commands);
        perror("Execution error");
        exit(-1);



      default:
        waitpid(-1, &rv, 0);
        if(WIFEXITED(rv)){
          printf("Child exited normally and child's exit status is: %d\n", WEXITSTATUS(rv));
          if((WEXITSTATUS(rv))==3){
            exit(1);
          }
        }
      }
  }
  return 0;
}

I made the changes in getline, rv and I created a proper variable for execvp. But now the error that occurs is that after I type for example "ls". It says:

execution error: no such file or directory.

thanks again for the help and my lack of knowledge.

the error seems to be in the line variable but i cannot understand whats the problem!

Char Array and getline in C

The solution was given here.it should be line[(strlen)-1] and not line[(strlen-1)]

Upvotes: 1

Views: 678

Answers (3)

Useless
Useless

Reputation: 67713

So, for the warnings: you know what lines those numbers refer to, and I'm having to guess: you could make this easier!

int rv=NULL;

initialization makes integer from pointer without a cast [enabled by default] line 42

NULL is a pointer value, rv is an integer. Set it to 0 if that's what you mean.

execvp(line[0],line);

passing argument 1 of ‘execv’ makes pointer from integer without a cast [enabled by default] line 64 passing argument 2 of ‘execv’ from incompatible pointer type [enabled by default] line 64

If you're calling execv, the code you're compiling is not what you posted. However ... line is a char *, so line[0] is a char. The first argument of either execv or execvp is const char *.

What is execv trying to accomplish? It needs a program name to run (first argument, const char *) and an array of arguments (these will form the argv[] array passed to the new program's main function, and the last item in the array must be NULL).

char *line=(char*) malloc(nbytes+1);
bytes_read=getline(&line,&nbytes,stdin);/*read line from stdin*/

passing argument 2 of ‘getline’ from incompatible pointer type [enabled by default] line 29

getline needs the address of a buffer to put characters in ... line is such an address. &line however, is the address of a pointer. Just take out the &.


There are more problems in your code, but these warnings all have some things in common:

  • you don't seem to understand what types a function expects,
  • what types your variables are,
  • what types you're actually passing,
  • or what the compiler means when it complains your types don't match

You need to understand this before you start trying to write multi-process programs. Learn it with something easy, learn to read the documentation, and understand the compiler warnings.

Upvotes: 1

Daniel Fischer
Daniel Fischer

Reputation: 183873

default:
waitpid(child_pid, &status, 0);
//wait(&rv);
printf("PARENT:My child's exit status is: %d\n", WEXITSTATUS(rv));
if((WEXITSTATUS(rv))==3){exit(1);}

You're passing the uninitialised variable child_pid to waitpid, that variable is only set in the child process. You should pass pid. Using the uninitialised variable causes undefined behaviour, so there's no predicting what will happen. Also you call WEXITSTATUS with another uninitialised variable, rv, you should pass status there.

The child doesn't do anything much here because

path_buffer=getcwd(buffer,sizeof(buffer));

the size argument passed to getcwd is the size of a char*, usually four or eight bytes, which is too short for the absolute path of most directories, path_buffer is set toNULLand the child immediately exits. You should pass the size of the buffer,maxsize` there.

Upvotes: 0

BSull
BSull

Reputation: 329

The parent never gets the child's pid therefore waitpid is not waiting on it. waitpid(-1,...) will wait for any child processes to finish before continuing.

I would also suggest indenting cases and ending each case statement with a break;

Upvotes: 4

Related Questions