作为协同处理的登录过程
问题描述:
我尝试运行login(1)
过程作为我的程序的协处理。 程序应该接收登录提示并写入登录名。作为协同处理的登录过程
login
过程很好地作为协处理启动。 但是在写入登录提示之前它立即退出。
程序的简化版本(写的东西等去掉):
int main(int argc, char** argv)
{
int fd1[2];
int fd2[2];
if((pipe(fd1) != -1) && (pipe(fd2) != -1))
{
const pid_t child_pid = fork();
if(child_pid == 0)
{
dup2(fd2[0], STDIN_FILENO);
dup2(fd1[1], STDOUT_FILENO);
close(fd1[0]);
close(fd1[1]);
close(fd2[0]);
close(fd2[1]);
execl("/bin/login", "login", (char*)NULL);
fprintf(stderr, "execl failed\n");
}
else if(child_pid)
{
char buffer[1000];
ssize_t len;
close(fd1[1]);
close(fd2[0]);
len = read(fd1[0], buffer, sizeof(buffer) - 1);
if(len > 0)
fprintf(stderr, "%zd bytes received\n", len);
else if(len == 0)
fprintf(stderr, "read return zero \n");
else
fprintf(stderr, "read failed: %V \n", errno);
}
else
{
fprintf(stderr, "Fork failed: %V", errno);
}
}
else
{
fprintf(stderr, "Can not open pipes: %V", errno);
}
return 0;
}
当我运行程序,结果是:
~ # my_program
read return zero
~ #
如果我用strace的运行它,我得到了以下结果(很多不相关的行被删除)
~ # strace -f my_program
[pid 4028] read(3, <unfinished ...>
[pid 4030] execve("/bin/login", ["login"], [/* 12 vars */]) = 0
[pid 4030] ioctl(0, TCGETS or SNDCTL_TMR_TIMEBASE, 0x7bc28aec) = -1 EINVAL (Invalid argument)
[pid 4030] exit_group(1) = ?
Process 4030 detached
[pid 4028] <... read resumed> ""..., 999) = 0
[pid 4028] --- SIGCHLD (Child exited) @ 0 (0) ---
[pid 4028] write(2, "read return zero \n"..., 18) = 18
login
进程使得出口af ter失败ioctl(STDIN_FILENO, TCGETS,)
致电。 login
似乎预计输入fd是终端或串行线路。
有什么方法可以修复我的程序吗?
答
login
预计TTY。可能最容易与login
交互的方法是通过posix_openpt分配伪终端,并传递从属文件描述符而不是管道句柄。 (但我不是这方面的专家。)
你想做什么?也许更好的方法是通过PAM进行身份验证,具体取决于您的使用情况。
答
如果你想以这种方式运行程序,我建议尝试系统(3),popen(3)等,而不是滚动自己的例程来做同样的事情。
+0
我没有找到合适的功能。系统和popen调用不能使用,因为需要读写。 – SKi 2012-02-27 07:41:12
最初的问题是'mount.ecryptfs'。 'login'和'mount.ecryptfs'的失败方式类似。所以我选择登录的问题,因为它是众所周知的程序。但是,我会尝试伪终端.... – SKi 2012-02-24 13:39:43