我尝试将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
进程在ioctl(STDIN_FILENO, TCGETS,)
调用失败后退出。
login
似乎期望输入fd是终端或串行线。
有没有办法修复我的程序?
答案 0 :(得分:3)
login
期待一个TTY。可能与login
进行交互的最简单方法是通过posix_openpt分配伪终端并传递从属的文件描述符而不是管道句柄。 (但我不是这个主题的专家。)
你想做什么?也许更好的方法是通过PAM进行身份验证,具体取决于您的使用情况。
答案 1 :(得分:0)
如果你想以这种方式运行程序,我建议尝试使用system(3),popen(3)等,而不是滚动你自己的例程来做同样的事情。