《Unix/Linux编程实践教程》笔记(4)──连接控制stty
Table of Contents
内容
设备和文件有相似之处也有不同之处,文中介绍了磁盘连接和终端连接的属性,磁盘连接具有缓冲,自动添加模式的属性,通过fcntl函数可以通过文件描述符来控制驱动器。自动添加模式,对每个write都自动调用lseek将内容添加到文件的末尾,内核将这两个操作合成一个原子操作。
终端文件的属性可以查看stty的man手册。相关的系统调用如下:
| 控制文件描述符 | fcntl |
| 读取tty驱动程序的属性 | tcgetattr |
| 设置tty驱动程序的属性 | tcsetattr |
| 控制一个设备 | ioctl |
p141 有termios结构每个标志集的独立位的含义
习题
5.22 使write能处理用户不在线和用户登录多个终端的情况
修改了write1,从utmp文件中读取在线用户列表,如果用户不在线,就不发送消息并且提示。如果用户登录多个终端,向每个终端发送消息。代码如下:
#include <stdio.h>
#include <fcntl.h>
#include <utmp.h>
/*
* write2.c
*
* purpose: send messages to another terminal
* method: open the other terminal for output then
* copy from stdin to that terminal
* usage: write1 username
*/
main( int ac, char *av[] )
{
int fd, utfd;
char buf[BUFSIZ];
char *get_tty(), *tty_for_user;
int flag = 0;
/* check args */
if ( ac != 2 ){
fprintf(stderr,"usage: write0 logname\n");
exit(1);
}
if ( (utfd = open( UTMP_FILE, O_RDONLY )) == -1 )
return NULL;
/* find user */
while ((tty_for_user = get_tty( utfd, av[1] )) != NULL )
{
flag ++;
printf ("tty_for_user is %s\n", tty_for_user);
/* open device */
sprintf(buf, "/dev/%s", tty_for_user);
fd = open( buf, O_WRONLY );
if ( fd == -1 ){
perror(buf); exit(1);
}
/* loop until EOF on input */
while( fgets(buf, BUFSIZ, stdin) != NULL )
if ( write(fd, buf, strlen(buf)) == -1 )
break;
close( fd );
}
if ( flag == 0 )
printf ("%s is not on or %s is not existed\n", av[1], av[1]);
close(utfd);
}
char *
get_tty( int utfd, char *logname )
/*
* purpose: find the tty at which 'logname' is logged in
* returns: a string or NULL if not logged in
* errors: does not handle multiple logins
*/
{
static struct utmp utrec;
int namelen = sizeof( utrec.ut_name );
char *retval = NULL ;
/* look for a line where the user is logged in */
while( read( utfd, &utrec, sizeof(utrec)) == sizeof(utrec) )
if ( strncmp(logname, utrec.ut_name, namelen ) == 0 )
{
retval = utrec.ut_line ;
break;
}
/* close file and return result */
return retval;
}
5.23 实现mesg命令
通过使用mesg命令,发现mesg通过接收n,y参数,来置位终端文件的w权限。代码如下:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
int main (int ac, char *av[])
{
struct stat sb;
int nmask = 0777755;
int ymask = 0000020;
char *ttydevice = ttyname(0);
if (ac != 2)
{
printf ("useage: mesg [n|y] \n");
exit(-1);
}
if (stat(ttydevice, &sb))
{
printf ("stat:\n");
exit(-1);
}
if (av[1][0] == 'n')
chmod(ttyname(0), (sb.st_mode & nmask));
else if (av[1][0] == 'y')
chmod(ttyname(0), (sb.st_mode | ymask));
else
printf ("av[1] must be [n|y] \n");
return 0;
}
5.25 通过文件修改时间检查锁是否有效
接收表示秒数的参数,比较当前时间和锁的更新时间,检查锁是否有效,如果无效,删除锁并重新创建
int lock_passwd(int dif)
{
struct stat infobuf;
time_t time1;
int rv = 0;
if ( link("test.txt", "test.txt.LCK") == -1)
rv = (errno == EEXIST?1:2);
if (rv == 1)
{
if (stat("test.txt.LCK", &infobuf) == -1)
perror("test.txt");
time1 = infobuf.st_mtime;
if (( time(NULL) - time1) > dif )
{
printf ("remove the old LCK and create the new LCK\n");
if (remove("test.txt.LCK") == -1)
perror("test.txt.LCK");
if ( link("test.txt", "test.txt.LCK") == -1)
rv = (errno == EEXIST?1:2);
}
}
return rv;
}
5.28 查看olcuc位的状态
不太清楚题目的中的跟踪OLCUC位的状态 是什么意思。下面的程序仅仅是显示当前终端中OLCUC位的状态
struct termios attribs;
tcgetattr (0, &attribs);
if (attribs.c_oflag & OLCUC)
printf ("OLCUC is on\n");
else
printf ("OLCUC is off\n");
项目
结束
这章的重点是终端驱动器的控制,tcgetattr和tcsetattr可以设置相应的位来控制终端。