login过程作为协处理

我尝试运行login(1)过程作为我的程序的协处理。 程序应该接收login提示并写入login名。

login过程作为一个协处理器很好地启动。 但是在写入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过程在失败的ioctl(STDIN_FILENO, TCGETS,)调用后退出。 login似乎预计inputfd是一个terminal或串行线。

有什么办法来解决我的程序?

login期望一个TTY。 可能最简单的方法就是通过posix_openpt分配一个伪终端,并传递从属文件描述符而不是管道句柄。 (但我不是这方面的专家。)

你想做什么? 也许更好的方法是通过PAM进行身份验证,具体取决于您的使用情况。

如果你想以这种方式运行一个程序,我建议尝试系统(3),popen(3)等,而不是滚动自己的例程来做同样的事情。