返回:见下
如若ptr是非null,则他被认为是个指针,指向长度至少为L-ctermid字节的数组
,进程的
控制终端名存放在该数组中。常数L-ctermid定义在<stdio.h>中。若ptr是个空
指针,则
该函数为数组(通常作为静态变量)分配空间。同样,进程的控制终端名存放在该数
组中。
在这两种情况中,该数组的起始地址作为函数值返回。因为大多数Unix系统都使用
/dev/tty
作为控制终端名,所以此函数的主要作用是帮助提高向其他操作系统的可移植性。
实例〖CD2〗ctermid函数
程式113是POSIX1 ctermid函数的一个实现。
P346
程式113〓POSIX1 ctermid函数的实现
另外两个和终端标识有关的函数是isatty和ttyname。假如文档描述符引用一个终
端设备,
则isatty返回真,而ttyname则返回在该文档描述符上打开的终端设备的路径名。
#include<inistd.h>
int isatty(int filedes);
Returns:1(true)if terminal device,0(false)otherwise
返回:若为终端设备为1(真),否则为0(假)
char * ttyname(int filedes);
Returns:pointer to pathname of terminal,NULL on error
返回:指向终端路径名的指针,出错为NULL
实例〖CD2〗isatty函数
如程式114所示,isatty函数是很容易实现的。其中只使用了一个终端专用的函
数tcgetat
tr,并取其返回值。
P346
程式114〓POSIX1 isatty函数的实现
P347
程式115〓测试isatty函数
我们用程式115测试isatty函数,得到:
$ a.out
fd 0:tty
fd 1:tty
fd 2:tty
$ a.out </etc/passwd 2>/dev/null
fd 0:not a tty
fd 1:tty
fd 2:not a tty
实例〖CD2〗ttyname函数
ttyname函数(程式116)稍长一点,因为他要搜索任何设备表项,寻找正配项。其
方法是读
/dev目录,寻找具备相同设备号和i-node编号的表项。回忆423节,每个文档系
统有一个
唯一的设备号(stat结构中的st-dev字段,见42节),文档系统中的每个目录项有
一个唯一
的i-node号(stat结构中的st-ino字段)。在此函数中我们假定当找到一个匹配的设
备号和匹
配的i-node号时,就找到了所希望的目录项。我们也可验证这二个表项和st-rdev
字段(终端
设备的主、次设备号)相匹配,连同该目录项是个字符特别文档。但是,因为我
们已验
证了文档描述符参数是个终端设备连同一个字符特别设备,而且在Unix系统中,
匹配的设
备号和i-node号是唯一的,所以不再需要作另外的比较。
用程式117测试这一实现。运行程式117得到:
$ a.out </dev/console 2>/dev/null
fd 0/dev/console
fd 1:/dev/ttyp3
fd 2:not a tty
P348
程式116〓POSIX1 ttyname函数的实现
P349
程式117〓测试Hyname函数
1110〓规范方式
规范方式是简单的〖CD2〗我们发一个读请求,当一行已输入后,终端驱动程式
即返回。
许多条件造成读返回。
· 所需要的字节数已读到时读即返回。我们无需读一个完整的行。假如读了部分
行,那么
也不会丢失任何信息〖CD2〗下一次读从前一次读的停止处开始。
· 当读到一个行定界符时,读返回。回忆113节,在规范方式中,下列字符被解
释为"行
结束":NL、EOL、EOL2和EOF。另外,在115节中也曾说明,如若已配置ICRNL,
但未配置
IGNCR,则CR字符的作用和NL字符相同,所以他也终止一行。
在这五个行定界符中,其中只有一个EOF符在终端驱动程式对其进行处理即被删除
。其他四
个字符则作为该行的最后一个字符返回调行者。
· 假如捕获到信号而且该函数并不自动再起动(105节),则读也返回。
实例〖CD2〗getpass函数
下面说明一个函数getpass,他读入一个用户在终端上键入的口令字。此函数由Un
ix login(
1)和crypt(1)程式调用。为了读口令字,该函数必须禁止回送,但仍可使终端以规
范方式进
行工作,因为用户在键入口令字后,一定要按回车键,这样也就构成了一个完整行
。程式11
8是个典型的Unix实现。
P350
程式118〓getpass函数的实现
在此例中,有很多点应当考虑。
· 调用函数ctermid打开控制终端,而不是直接将/dev/tty写在程式中。
· 我们只是读、写控制终端,假如不能以读、写方式打开此设备则出错返回。在
有些系统
中也使用一些其他约定。在43 BSD中,假如不能以读、写方式打开控制终端,则
getpass
从标准输入读,写到标准出错文档中。SVR4则总是写到标准出错文档中,但只从控
制终端读
。
· 我们阻塞两个信号SIGINT和SIGTSTP。假如不这样做,则在输入INTR字符时就会
使程式终
止,并使终端仍处于禁止回送状态。和此相类似,输入SUSP字符时将使程式暂停,
并且在禁
止回送状态下返回到shell。在禁止回送时,我们选择了阻塞这两个信号。在读口
令字期间
假如发生了这两个信号,则他们被保持,直到getpass返回前才解除对他们的阻塞
。也有其
他方法来处理这些信号。某些getpass版本忽略SIGINT(保存他以前的动作),在返
回前则将
其动作恢复为以前的值。这就意味着在该信号被忽略期间所发生的这种信号都丢失
。其他版
本捕获SGINT(保存他以前的动作),假如捕获到此信号,则在复置终端状态和信号
动作后,
用kill函数发送此信号。没有一个getpass版本捕获、忽略或阻塞SIGQUIT,所以键
入QUIT字
符就会使程式夭折,并且极可能终端仍处于禁止回送状态。
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!



