linux中who的实现

编写who命令

通过解答一下3个问题来解决

1who 命令能做什么?

2who 命令是如何工作的?

3如何编写who?


1who命令能做些什么?


只要输入who命令,输出如下

fantasy@fantasy-HP-ProBook-4436s:~$who

fantasy tty2 2014-07-15 16:38

fantasy tty1 2014-07-15 16:37

fantasy :0 2014-07-15 16:26 (:0)

fantasy pts/12 2014-07-15 16:27 (:0)

每一行代表一个已登录的用户,第一列代表用户名,第二列代表终端名,第三列代表用户的登陆时间,第四列代表登陆地址(默认状态不显示)


也就是说who命令能够显示用户名,用户登陆时间,用户登陆的终端名,所以要实现who,就是要求编写程序实现以上功能


2who 是如何工作的呢?


学会从unix中学习unix

阅读联机帮助

搜索联机帮助

阅读.h文件

从参阅部分(SEEALSO)得到启示


通过查找在utmp.h中保存有相应的登陆结构

structutmp {

short ut_type; /* Type of record */

pid_t ut_pid; /* PID of login process */

char ut_line[UT_LINESIZE]; /* Device name of tty - "/dev/" */

char ut_id[4]; /* Terminal name suffix,

orinittab(5) ID */

char ut_user[UT_NAMESIZE]; /* Username */

char ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or

kernelversion for run-level

messages*/

struct exit_status ut_exit; /* Exit status of a process


3如何编写who

我们知道可以从utmp中读取结构信息,可以用fgets读字符字符串,但是这样读取效率很低,那么如何读取一个结构呢?

使用系统自带的openclose read函数

open

目标 打开一个文件

头文件 #include<fcntl.h>

函数原型 intfd = open(char *name,int how)

参数 name文件名 howO_RDONLY(只读)O_WRONLY(只写)or O_RDWR(又读又写)

返回值 -1遇到错误int成功返回


如果成功读取就会返回一个正整数的值,这个值就叫做文件描述符。在unix系统中文件是可以被不同进程打开多次。每次打开文件描述符都是不同的,这样就可以知道是不同进程打开的。


read 目标 把数据读到缓冲区

头文件 #include<unistd.h>

函数原型 ssize_tnumread = read(int fd,void * buf,size_t qty)

参数 fd文件描述符buf用来存放数据的目的缓冲区 qty 要读取的字节数

返回值 -1遇到错误numread 成功读取

read这个系统调用从fd所指定的文件中读取qty个字节,存放到buf所指定内存空间的,内核如果成功地读取了数据,就返回所读取的字节数目,否则返回-1当读到文件末尾时要再读的话,numread会为0


close 目标 关闭一个文件

头文件 #include<unistd.h>

函数原型 intresult = close(int fd)

参数 fd文件描述符

返回值 遇到错误 -1 成功关闭 0

close会关闭进程和文件fd之间的连接


知道了who的工作原理,只需要打开文件,读取数据,关闭文件

第一个测试代码!!


/*who01.c -a first version of the who program

*open, read UTMP file ,and show results

*/

#include<stdio.h>

#include<fcntl.h>

#include<unistd.h>

#include<stdlib.h>

#include<utmp.h>


#defineSHOWHOST //include matchine on output

/*show_info

*display contents of utmp struct in human readable form

**note these sizes should not be hardwired

*/

voidshow_info(struct utmp *utbufp){

printf("%-8.8s",utbufp->ut_name);//登录名

printf("");

printf("%-8.8s",utbufp->ut_line);//控制台

printf("");

// printf("%10ld",utbufp->ut_time); // 登录时间目前还不知道ut_time应该用什么类型time_t

printf("");

#ifdefSHOWHOST

printf("(%s)",utbufp->ut_host);//远程主机名

#endif

printf("\n");

}


intmain()

{

structutmp current_record ; //read info from here

intutmpfd; //read from this descriptor

intreclen = sizeof(current_record);

if((utmpfd = open(UTMP_FILE,O_RDONLY))== -1){


perror(UTMP_FILE);//UTMP_FILE is in utmp.h

exit(1);

}

while(read(utmpfd,&current_record,reclen)== reclen)

show_info(&current_record);

close(utmpfd);

return0;

}


这个who能正确显示主机名,终端名,远程主机名

需要改进的地方

1消除空白记录


系统所带的who会列出已登录的用户信息,而我们编写的who1还会显示出其他信息,这些信息都来源于utmp文件,所以要想办法出去未登录的那些终端用户


解决办法:过滤掉那些用户名为空的记录

LOGIN的那一行对应的是控制台,ut_type当值为7USER_PROCESS,时就对应已经登陆的用户

utmp

#defineINIT_PROCESS 5 /* Process spawned by init(8) */

#defineLOGIN_PROCESS 6 /* Session leader process for user login */

#defineUSER_PROCESS 7 /* Normal process */


voidshow_info(struct utmp *utbufp){ //users only

if(utbufp->ut_type!= USER_PROCESS) //the users name

return;

}


2正确显示登录时间

time_tlongint 类型

完整的who程序

/*who03.c - read /etc/utmp and list info therein

*supperess empty records

*formats time nicely

*/

#include<stdio.h>

#include<fcntl.h>

#include<unistd.h>

#include<stdlib.h>

#include<utmp.h>

#include<time.h>

/*displaytime in a format fit for human consuption

*usesctime to build a string then picks parts out of it

*Note:%12.12s prints a string 12 chars wide and LIMITS it to 12 chars

*/

voidshowtime(long timeval){

char*cp;

cp= ctime(&timeval);

printf("%12.12s",cp+4);//picks 12 chars from pos 4


}

/*show_info

*display contents of utmp struct in human readable form

**note these sizes should not be hardwired

*/

voidshow_info(struct utmp *utbufp){

if(utbufp->ut_type!= USER_PROCESS) 判断一哈是不是正在登陆的用户

return;

printf("%-8.8s",utbufp->ut_name);//the logname

printf("");

printf("%-8.8s",utbufp->ut_line);//the tty

printf("");

showtime(utbufp->ut_time);

// printf("%10ld",utbufp->ut_time); //login time

printf("");

#ifdefSHOWHOST

printf("(%s)",utbufp->ut_host);//the host

#endif

printf("\n");

}


intmain()

{

structutmp current_record ; //read info from here

intutmpfd; //read from this descriptor

intreclen = sizeof(current_record);

if((utmpfd = open(UTMP_FILE,O_RDONLY)) == -1){


perror(UTMP_FILE);//UTMP_FILE is in utmp.h

exit(1);

}

while(read(utmpfd,&current_record,reclen)== reclen)

show_info(&current_record);

close(utmpfd);

return0;

}

代码最终实现

——————————————————————————————————————————————————————————



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值