简体   繁体   中英

Something is wrong with process and status of child process

I cannot understand whats wrong…. It does not give me any messages returning from executing program in parent process. Can somebody explain and help what is wrong???? thank you. Any help will be appreciated.

Basically, my program should read a user id and password, creates a new process to run the VALIDATE program (which is in file validate.c), sends to VALIDATE program the user id and password, and prints a message "Password verified" if the user id and password matched or either "Invalid password" or "No such user" depending on the return value of the validate program.) 0 - everything is ok, 2 and 3 smth went wrong.

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

#define MAXLINE 256
#define MAXPASSWD 10

void
strip (char *str, int capacity)
{
  char *ptr;
  if ((ptr = strchr (str, '\n')) == NULL)
    {
      str[capacity - 1] = '\0';
    }
  else
    {
      *ptr = '\0';
    }
}


int
main (void)
{
  char userid[MAXLINE];
  char password[MAXLINE];
  pid_t pid;
  int fd[2];
  /* Read a user id and password from stdin */
  printf ("User id:\n");
  if ((fgets (userid, MAXLINE, stdin)) == NULL)
    {
      fprintf (stderr, "Could not read from stdin\n");
      exit (1);
    }
  strip (userid, MAXPASSWD);
  printf ("Password:\n");
  if ((fgets (password, MAXLINE, stdin)) == NULL)
    {
      fprintf (stderr, "Could not read from stdin\n");
      exit (1);
    }
  strip (password, MAXPASSWD);
  pipe (fd);
  pid = fork ();
  if (pid == -1)
    {
      printf ("Error making process\n");
      return (-1);
    }
  if (pid == 0)
    {
      close (fd[0]);
      printf ("Hey I am the child with pid: %d\n", getpid ());
      dup2 (fd[0], 0);
      execl ("/h/u15/c2/00/validate.c", "validate.c", NULL);

    }
  int status;

  if (pid > 0)
    {

      write (fd[1], password, (strlen (password) - 1));
      write (fd[1], userid, (strlen (userid) - 1));
      printf ("status %d\n", WEXITSTATUS (status));
      if (waitpid (pid, &status, 0) == 0)
        {
          printf ("status %d\n", WEXITSTATUS (status));
          if (WIFEXITED (status) && WEXITSTATUS (status))
            {
              if (WEXITSTATUS (status) == 3)
                {
                  printf (" No such a user\n");
                }
              else if (WEXITSTATUS (status) == 2)
                {
                  printf ("Invalid password");
                }
              else
                printf ("Password verified\n");
            }
        }    
    }
  return 0;
}

You appear to have made a pipe using pipe , but have not used dup2 to make stdin or stdout use those file descriptors. So how is the program you execl meant to know which fd to read from?

From the man page for pipe :

pipe() creates a pipe, a unidirectional data channel that can be used for interprocess communication. The array pipefd is used to return two file descriptors referring to the ends of the pipe. pipefd[0] refers to the read end of the pipe. pipefd[1] refers to the write end of the pipe. Data written to the write end of the pipe is buffered by the kernel until it is read from the read end of the pipe. For further details, see pipe(7).

In your program the parent is meant to be writing to the pipe, and (I assume) the child (which does the execl ) is meant to be reading from the pipe.

So the parent should be doing something like:

close (fd[0]); /* close read end of pipe - NB you have close(fd[1]) currently */
write (fd[1], ...);

and the child should be doing something like:

close (fd[1]); /* close write end of pipe */
dup2 (fd[0], STDIN_FILENO); /* STDIN_FILENO is 0 */
close (fd[0]); /* now we have this on FD we don't need it any more *.
execl ( ... something that works with STDIN ...)

I presume you are just relying on the exit status from validate command? If not, and you need to capture what is written to STDOUT , you'll need another pipe for that.

Below you'll find a fixed up version of your code that gets as far as I can get it without your password verifier:

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

#define MAXLINE 256
#define MAXPASSWD 10

void
strip (char *str, int capacity)
{
  char *ptr;
  if ((ptr = strchr (str, '\n')) == NULL)
    {
      str[capacity - 1] = '\0';
    }
  else
    {
      *ptr = '\0';
    }
}


int
main (void)
{
  char userid[MAXLINE];
  char password[MAXLINE];
  pid_t pid;
  int fd[2];
  /* Read a user id and password from stdin */
  printf ("User id:\n");
  if ((fgets (userid, MAXLINE, stdin)) == NULL)
    {
      fprintf (stderr, "Could not read from stdin\n");
      exit (1);
    }
  strip (userid, MAXPASSWD);
  printf ("Password:\n");
  if ((fgets (password, MAXLINE, stdin)) == NULL)
    {
      fprintf (stderr, "Could not read from stdin\n");
      exit (1);
    }
  strip (password, MAXPASSWD);
  pipe (fd);
  pid = fork ();
  if (pid == -1)
    {
      printf ("Error making process\n");
      return (-1);
    }
  if (pid == 0)
    {
      close (fd[0]);
      fprintf (stderr, "Hey I am the child with pid: %d\n", getpid ());
      dup2 (fd[0], 0);
      execl ("/h/u15/c2/00/validate.c", "validate.c", NULL);
      exit (1);
    }
  int status;

  if (pid > 0)
    {
      write (fd[1], password, (strlen (password) - 1));
      write (fd[1], userid, (strlen (userid) - 1));
      if (waitpid (pid, &status, 0) != -1)
        {
          printf ("status %d\n", WEXITSTATUS (status));
          if (WIFEXITED (status) && WEXITSTATUS (status))
            {
              if (WEXITSTATUS (status) == 3)
                {
                  printf (" No such a user\n");
                }
              else if (WEXITSTATUS (status) == 2)
                {
                  printf ("Invalid password");
                }
              else
                printf ("Password verified\n");
            }
        }
    }
  return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM