我无法理解什么是错的......它不会给我在父进程中执行程序返回的任何消息。有人可以解释并帮助出错吗?谢谢。任何帮助将不胜感激。
基本上,我的程序应该读取用户ID和密码,创建一个新进程来运行VALIDATE程序(在文件validate.c中),向VALIDATE程序发送用户ID和密码,并打印消息&# 34;密码已验证"如果用户ID和密码匹配或者“#34;密码无效"或"没有这样的用户"取决于验证程序的返回值。)0 - 一切正常,2和3 smth出错了。
#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;
}
答案 0 :(得分:1)
您似乎使用pipe
制作了管道,但未使用dup2
使stdin
或stdout
使用这些文件描述符。那么你execl
的程序如何知道要读取哪个fd?
来自pipe
的手册页:
pipe()
创建一个管道,一个可用于进程间通信的单向数据通道。数组pipefd
用于返回引用管道末端的两个文件描述符。pipefd[0]
指的是管道的读取端。pipefd[1]
指的是管道的写端。写入管道写端的数据由内核缓冲,直到从管道的读端读取。有关详细信息,请参阅pipe(7).
在你的程序中,父程序要写入管道,并且(我假设)孩子(execl
)是从管道中读取的。
所以父母应该这样做:
close (fd[0]); /* close read end of pipe - NB you have close(fd[1]) currently */
write (fd[1], ...);
并且孩子应该做类似的事情:
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 ...)
我认为你只是依赖于validate命令的退出状态?如果没有,并且您需要捕获写入STDOUT
的内容,那么您需要另一个管道。
在您的下方,我会找到一个固定版本的代码,只要我没有您的密码验证程序就可以获得它:
#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;
}