</pre>一.注销过程</h1><h2 style="margin:0px; padding:0px; color:rgb(51,51,51); font-family:Arial; line-height:26px"><a target=_blank target="_blank" name="t1" style="color:rgb(51,102,153)"></a><span style="font-size:14px">1.基本步骤:</span></h2><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(有关 utmp 的内容参见 :<a target=_blank target="_blank" href="http://blog.csdn.net/xiaofan086/article/details/8489822" style="color:rgb(51,102,153); text-decoration:none">who命令的编写</a>)</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">注销过程中,系统改变了文件utmp中相应的登录记录,注销过程如下:</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(1).打开文件utmp;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(2).从utmp中找到包含你所在终端的登录记录;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(3).对当前记录做修改;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(4).关闭文件;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">其中要注意的是第3步:对当前记录做修改。</p><h2 style="margin:0px; padding:0px; color:rgb(51,51,51); font-family:Arial; line-height:26px"><a target=_blank target="_blank" name="t2" style="color:rgb(51,102,153)"></a><span style="font-size:14px">2.对当前记录做修改:</span></h2><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(1)把ut_type的值从USER_PROCESS DEAD_PROCESS;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(2)把ut_time字段的值改为注销时间,即当前时间;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(3)有些版本会把用户名和远程主机字段的内容清空;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"> 除以上步骤外:最棘手的是如何把修改过阿记录写回文件?不能用write,write只会更新下一条记录,而不是当前那条要修改的记录。因为系统每次打开一个文件都会保存一个指向文件当前位置的指针,当读写完成时,指针都会移向下一个记录位置,这个指针与文件描述符相关联。如何操作呢?可以使用系统调用 lseek 。</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"> 指针是与文件描述符相关联的,而不是与文件关联 ,所以如果两个程序同时打开一个文件,这时会有两个指针,两个程序对文件的读操作不会互相干扰。lseek改变文件描述符所关联的指针位置。</p><h2 style="margin:0px; padding:0px; color:rgb(51,51,51); font-family:Arial; line-height:26px"><a target=_blank target="_blank" name="t3" style="color:rgb(51,102,153)"></a><span style="font-size:14px">3.lseek函数</span></h2><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">目标 使指针指向文件中的指针位置</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">头文件 #include<sys/type.h></p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"> #include<unistd.h> </p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">函数原型 off_t currpos = lseek( int fd , off_t dist , int base );</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">参数 fd:文件描述符 ; dist:移动的距离 (可以为负);</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"> base :SEEK_SET 文件的开始 ; SEEK_CUR 文件当前; SEEK_END 文件结尾 ;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">返回值 -1 遇到错误 ; </p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"></p><h1 style="margin:0px; padding:0px; color:rgb(51,51,51); font-family:Arial; line-height:26px"><a target=_blank target="_blank" name="t4" style="color:rgb(51,102,153)"></a><span style="font-size:14px">二.代码实例</span></h1><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">程序需要在终端下以root身份运行,如 #: ./a.out pts/1</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">( pts/1 为一个打开的终端用户 )</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"></p><h1 style="margin:0px; padding:0px; color:rgb(51,51,51); font-family:Arial; line-height:26px"><span style="font-size:14px"></span><pre code_snippet_id="396034" snippet_file_name="blog_20140617_2_5042944" name="code" class="cpp"><pre name="code" class="cpp">#include <stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include<utmp.h>
#include<fcntl.h>
#include<string.h>
#include<time.h>
int logout_tty(char *line);
int main(int ac,char * av[])
{
if(ac != 2)
{
puts("参数个数不正确\n");
exit(1);
}
char line[32];
strcpy(line,av[1]);
logout_tty(line);
return EXIT_SUCCESS;
}
int logout_tty(char *line)
{
int fd;
struct utmp rec;
int len = sizeof(struct utmp);
int retval = -1;
// 此处 O_RDWR 需要root用户运行
if((fd = open(UTMP_FILE , O_RDWR)) == -1)
{
perror(UTMP_FILE);
return -1;
}
off_t pos;
while(read(fd,&rec,len) == len)
{
if(strncmp(rec.ut_line,line,sizeof(rec.ut_line)) == 0)
{
rec.ut_type = DEAD_PROCESS;
if(time(&rec.ut_time) != -1)
if( (pos=lseek(fd,-len,SEEK_CUR) )!= -1)
if(write(fd,&rec,len) == len)
retval = 0;
break;
}
}
if(close(fd) == -1)
retval = -1;
return retval;
}
鸣谢:http://blog.csdn.net/xiaofan086/article/details/8497848
</pre>一.注销过程</h1><h2 style="margin:0px; padding:0px; color:rgb(51,51,51); font-family:Arial; line-height:26px"><a target=_blank target="_blank" name="t1" style="color:rgb(51,102,153)"></a><span style="font-size:14px">1.基本步骤:</span></h2><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(有关 utmp 的内容参见 :<a target=_blank target="_blank" href="http://blog.csdn.net/xiaofan086/article/details/8489822" style="color:rgb(51,102,153); text-decoration:none">who命令的编写</a>)</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">注销过程中,系统改变了文件utmp中相应的登录记录,注销过程如下:</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(1).打开文件utmp;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(2).从utmp中找到包含你所在终端的登录记录;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(3).对当前记录做修改;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(4).关闭文件;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">其中要注意的是第3步:对当前记录做修改。</p><h2 style="margin:0px; padding:0px; color:rgb(51,51,51); font-family:Arial; line-height:26px"><a target=_blank target="_blank" name="t2" style="color:rgb(51,102,153)"></a><span style="font-size:14px">2.对当前记录做修改:</span></h2><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(1)把ut_type的值从USER_PROCESS DEAD_PROCESS;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(2)把ut_time字段的值改为注销时间,即当前时间;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">(3)有些版本会把用户名和远程主机字段的内容清空;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"> 除以上步骤外:最棘手的是如何把修改过阿记录写回文件?不能用write,write只会更新下一条记录,而不是当前那条要修改的记录。因为系统每次打开一个文件都会保存一个指向文件当前位置的指针,当读写完成时,指针都会移向下一个记录位置,这个指针与文件描述符相关联。如何操作呢?可以使用系统调用 lseek 。</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"> 指针是与文件描述符相关联的,而不是与文件关联 ,所以如果两个程序同时打开一个文件,这时会有两个指针,两个程序对文件的读操作不会互相干扰。lseek改变文件描述符所关联的指针位置。</p><h2 style="margin:0px; padding:0px; color:rgb(51,51,51); font-family:Arial; line-height:26px"><a target=_blank target="_blank" name="t3" style="color:rgb(51,102,153)"></a><span style="font-size:14px">3.lseek函数</span></h2><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">目标 使指针指向文件中的指针位置</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">头文件 #include<sys/type.h></p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"> #include<unistd.h> </p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">函数原型 off_t currpos = lseek( int fd , off_t dist , int base );</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">参数 fd:文件描述符 ; dist:移动的距离 (可以为负);</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"> base :SEEK_SET 文件的开始 ; SEEK_CUR 文件当前; SEEK_END 文件结尾 ;</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">返回值 -1 遇到错误 ; </p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"></p><h1 style="margin:0px; padding:0px; color:rgb(51,51,51); font-family:Arial; line-height:26px"><a target=_blank target="_blank" name="t4" style="color:rgb(51,102,153)"></a><span style="font-size:14px">二.代码实例</span></h1><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">程序需要在终端下以root身份运行,如 #: ./a.out pts/1</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">( pts/1 为一个打开的终端用户 )</p><p style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"></p><h1 style="margin:0px; padding:0px; color:rgb(51,51,51); font-family:Arial; line-height:26px"><span style="font-size:14px"></span><pre code_snippet_id="396034" snippet_file_name="blog_20140617_2_5042944" name="code" class="cpp"><pre name="code" class="cpp">#include <stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include<utmp.h>
#include<fcntl.h>
#include<string.h>
#include<time.h>
int logout_tty(char *line);
int main(int ac,char * av[])
{
if(ac != 2)
{
puts("参数个数不正确\n");
exit(1);
}
char line[32];
strcpy(line,av[1]);
logout_tty(line);
return EXIT_SUCCESS;
}
int logout_tty(char *line)
{
int fd;
struct utmp rec;
int len = sizeof(struct utmp);
int retval = -1;
// 此处 O_RDWR 需要root用户运行
if((fd = open(UTMP_FILE , O_RDWR)) == -1)
{
perror(UTMP_FILE);
return -1;
}
off_t pos;
while(read(fd,&rec,len) == len)
{
if(strncmp(rec.ut_line,line,sizeof(rec.ut_line)) == 0)
{
rec.ut_type = DEAD_PROCESS;
if(time(&rec.ut_time) != -1)
if( (pos=lseek(fd,-len,SEEK_CUR) )!= -1)
if(write(fd,&rec,len) == len)
retval = 0;
break;
}
}
if(close(fd) == -1)
retval = -1;
return retval;
}