《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可以设置相应的位来控制终端。