zoukankan      html  css  js  c++  java
  • 伪终端和交互式应用程序通信

    【自动修改 Linux 用户密码】今天学习了一下如何使用伪终端和交互式应用程序通信
    其实主要就是 openpty/forkpty/login_tty 三个函数。

    以下内容为程序代码:
    flw@debian:~/study$ ./tpasswd chinaunix perlchina
    pty name: /dev/pts/1
    Changing password for flw.
    (当前)UNIX 口令:chinaunix
    输入新的 UNIX 口令:perlchina
    重新输入新的 UNIX 口令:perlchina
    passwd:已成功更新密码
    flw@debian:~/study$ ./tpasswd perlchina abcdef
    pty name: /dev/pts/1
    Changing password for flw.
    (当前)UNIX 口令:perlchina
    输入新的 UNIX 口令:abcdef
    重新输入新的 UNIX 口令:abcdef
    Bad: new password is too simple
    输入新的 UNIX 口令:abcdef
    重新输入新的 UNIX 口令:abcdef
    Bad: new password is too simple
    输入新的 UNIX 口令:abcdef
    重新输入新的 UNIX 口令:abcdef
    Bad: new password is too simple
    passwd:鉴定令牌操作错误
    passwd: password unchanged

    [code]flw@debian:~/study$ cat tpasswd.c
    # include <stdio.h>
    # include <stdlib.h>
    # include <string.h>
    # include <unistd.h>
    # include <sys/types.h>
    # include <linux/limits.h>
    # include <pty.h>
    void do_passwd( int pty, const char *old_passwd, const char *new_passwd );
    int main( int argc, char *argv[] )
    {
    int pty, slave;
    char pty_name[PATH_MAX];
    int ret;
    pid_t child;
    if ( argc < 3 ){
    fprintf( stderr, "Usage: %s <old password> <new password>\n", argv[0] );
    exit( EXIT_FAILURE );
    }
    ret = openpty( &pty, &slave, pty_name, NULL, NULL );
    if ( ret == -1 ){
    perror( "openpty" );
    exit( EXIT_FAILURE );
    }
    child = fork();
    if ( child == -1 ){
    perror( "fork" );
    exit( EXIT_FAILURE );
    }
    else if ( child == 0 ){
    close( pty );
    login_tty( slave );
    execl( "/usr/bin/passwd", "passwd", NULL );
    }
    close( slave );
    printf( "pty name: %s\n", pty_name );
    do_passwd( pty, argv[1], argv[2] );
    exit( EXIT_SUCCESS );
    }
    void do_passwd( int pty, const char *old_passwd, const char *new_passwd )
    {
    char buffer[80];
    int ret;
    fd_set reads;
    int input_old_passwd = 0;
    while(1){
    FD_ZERO( &reads );
    FD_SET( pty, &reads );
    ret = select( pty+1, &reads, NULL, NULL, NULL );
    if ( ret == -1 ){
    perror( "select" );
    break;
    }
    ret = read( pty, buffer, sizeof(buffer) );
    if ( ret <= 0 ){
    break;
    }
    write( fileno(stdout), buffer, ret );
    fflush( stdout );
    if ( buffer[ret-1] == '\n' ){
    continue;
    }
    if ( !input_old_passwd ){
    write( pty, old_passwd, strlen(old_passwd) );
    write( pty, "\n", 1 );
    write( fileno(stdout), old_passwd, strlen(old_passwd) );
    input_old_passwd = 1;
    }
    else{
    write( pty, new_passwd, strlen(new_passwd) );
    write( pty, "\n", 1 );
    write( fileno(stdout), new_passwd, strlen(new_passwd) );
    }
    }
    return;
    }
    flw@debian:~/study$[/code]

    2008-4-14 18:55LinuxKen

    学习,代码写得好漂亮.:)

    2008-4-14 18:58flw

    因为 forkpty 实际上是 openpty/fork/login_tty 三个函数的组合,因此主函数也可以简写成这样:
    [code]int main( int argc, char *argv[] )
    {
    int pty, slave;
    char pty_name[PATH_MAX];
    int ret;
    pid_t child;
    if ( argc < 3 ){
    fprintf( stderr, "Usage: %s <old password> <new password>\n", argv[0] );
    exit( EXIT_FAILURE );
    }
    child = forkpty( &pty, pty_name, NULL, NULL );
    if ( child == -1 ){
    perror( "fork" );
    exit( EXIT_FAILURE );
    }
    else if ( child == 0 ){
    execl( "/usr/bin/passwd", "passwd", NULL );
    }
    printf( "pty name: %s\n", pty_name );
    do_passwd( pty, argv[1], argv[2] );
    exit( EXIT_SUCCESS );
    }[/code]

    2008-4-14 19:03flw

    如同标题所说,本程序旨在演示如何操纵伪终端和交互式应用程序通信,
    因此对于 passwd 实用工具的输出解析并不多,只是做了一些简单的判断。
    事实上,根据输入内容的不同,passwd 实用工具的输出信息多达十多种,PAM 的到来使得 passwd 的输出更加复杂,
    因此如果希望能够自动控制 passwd,那么还是用 expect/perl 等工具较为方便。
    另外需要说明的一点是,自动控制交互式应用程序运行时,尽量运行其英文版本,这样信息会规范一些从而有利于捕获并匹配。
    中文或者其它语种的信息不仅要考虑到编码的问题,而且信息用语经常会有变化。
    通过设定环境变量 LANG=C,可以使 passwd 实用工具的输出变成英文。
    [ 本帖最后由 flw 于 2008-4-14 19:06 编辑 ]

    2008-4-15 11:26Sorehead

    很少用到这方面的东西,学习。

    2008-4-15 11:28system888net

    顶...

    本篇文章来自于:百家学院 (http://www.9php.com),转载请保留此行

  • 相关阅读:
    数组中的每一个对象执行一次方法:makeObjectsPerformSelector
    $.each() each
    JQ js选择节点操作
    Sublime Text 3 快捷键
    TotoiseSVN的基本使用方法
    Hbuilder快捷键
    获取网页内容区域各种高/宽汇总
    TP操作
    xhr接收php://output的二进制文件,并转换成excel表格
    Go语言的%d,%p,%v等占位符的使用
  • 原文地址:https://www.cnblogs.com/cute/p/1984922.html
Copyright © 2011-2022 走看看