LinuxLinux学习之路

APUE读书笔记-18终端输入输出(11)

2020-09-04  本文已影响0人  QuietHeart

10、canonical模式

Canonical模式非常简单:我们调用一个read,然后终端驱动程序会在输入完一行之后返回。导致read返回的有以下几种情况。

getpass函数的例子

我们现在看看getpass函数。这个函数会从用户终端读取某种密码,login和crypt程序就会调用这个函数。为了读取密码,函数必须关闭字符的显示,但是它也必须让终端处于canonical模式,把我们输入的组成一行的密码读取。

getpass函数的实现

下面代码就列举了unix系统上面一个典型的这个函数的实现。

#include <signal.h>
#include <stdio.h>
#include <termios.h>

#define MAX_PASS_LEN    8      /* max #chars for user to enter */

char * getpass(const char *prompt)
{
    static char     buf[MAX_PASS_LEN + 1]; /* null byte at end */
    char            *ptr;
    sigset_t        sig, osig;
    struct termios  ts, ots;
    FILE            *fp;
    int             c;

    if ((fp = fopen(ctermid(NULL), "r+")) == NULL)
        return(NULL);
    setbuf(fp, NULL);

    sigemptyset(&sig);
    sigaddset(&sig, SIGINT);        /* block SIGINT */
    sigaddset(&sig, SIGTSTP);       /* block SIGTSTP */
    sigprocmask(SIG_BLOCK, &sig, &osig);    /* and save mask */

    tcgetattr(fileno(fp), &ts);     /* save tty state */
    ots = ts;                       /* structure copy */
    ts.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
    tcsetattr(fileno(fp), TCSAFLUSH, &ts);
    fputs(prompt, fp);

    ptr = buf;
    while ((c = getc(fp)) != EOF && c != '\n')
        if (ptr < &buf[MAX_PASS_LEN])
            *ptr++ = c;
    *ptr = 0;                  /* null terminate */
    putc('\n', fp);            /* we echo a newline */

    tcsetattr(fileno(fp), TCSAFLUSH, &ots); /* restore TTY state */
    sigprocmask(SIG_SETMASK, &osig, NULL);  /* restore mask */
    fclose(fp);         /* done with /dev/tty */
    return(buf);
}

这个例子中有几个需要注意的地方。

上一篇 下一篇

猜你喜欢

热点阅读