登录过程作为协同进程

时间:2012-02-24 13:12:35

标签: c linux unix pipe

我尝试将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是终端或串行线。

有没有办法修复我的程序?

2 个答案:

答案 0 :(得分:3)

login期待一个TTY。可能与login进行交互的最简单方法是通过posix_openpt分配伪终端并传递从属的文件描述符而不是管道句柄。 (但我不是这个主题的专家。)

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

答案 1 :(得分:0)

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