Linux下who命令之C语言实现
2016-11-13 23:37
387 查看
Linux下who命令之C语言实现
Step1:前期准备
首先要有一个清楚的认识:linux中一切皆文件实现who命令,who命令也是Linux中的一个文件,那我们怎么找到它呢?我们可以“找男人”(man),终端下执行命令:
man who
此处我装了汉译版的man手册,查看到这样一段提示如下:
![](https://images2015.cnblogs.com/blog/877163/201611/877163-20161113231839749-1744908423.jpg)
所以退出man手册,执行命令:
info who
找到如下图相关信息:
![](https://images2015.cnblogs.com/blog/877163/201611/877163-20161113231847670-1988921075.jpg)
也可以找到下面这样的一段话,也就是说:who命令可以这样实现,读取utmp里边的内容,然后显示记录,最后关闭utmp,who命令就是一个很简单的体现吧,打开文件,保存文件id,根据文件id读取用户的登陆信息,显示在终端。
![](https://images2015.cnblogs.com/blog/877163/201611/877163-20161113231902311-879884197.jpg)
我们尝试地打开一下
/var/run/utmp这个文件得到如下画面,发现是一串乱码,但还是能看出相关who的信息的
![](https://images2015.cnblogs.com/blog/877163/201611/877163-20161115192845295-1980606960.jpg)
既然不清楚
utmp是干嘛的,我们可以使用
man -k来检索一下相关信息,得到信息如下
![](https://images2015.cnblogs.com/blog/877163/201611/877163-20161115192857545-991688277.jpg)
经过筛选,发现只有
utmpx(5)是符合我们要求的,其中后面显示的是
login records,而who命令不就是用来输出登录信息的;
man的第五个类型表示的是文件格式和规范,说明此处可能存储了登录记录的数据结构
使用指令:
man 5 utmpx,可以得到如下有用信息:
![](https://images2015.cnblogs.com/blog/877163/201611/877163-20161115192905279-582156817.jpg)
也可以使用输出重定向指令
man 5 utmpx > utmp.txt,得到文本格式的
utmp数据结构体如下:
struct utmp { 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, or inittab(5) ID */ char ut_user[UT_NAMESIZE]; /* Username */ char ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or kernel version for run-level messages */ struct exit_status ut_exit; /* Exit status of a process marked as DEAD_PROCESS; not used by Linux init (1 */ /* The ut_session and ut_tv fields must be the same size when compiled 32- and 64-bit. This allows data files and shared memory to be shared between 32- and 64-bit applications. */ #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32 int32_t ut_session; /* Session ID (getsid(2)), used for windowing */ struct { int32_t tv_sec; /* Seconds */ int32_t tv_usec; /* Microseconds */ } ut_tv; /* Time entry was made */ #else long ut_session; /* Session ID */ struct timeval ut_tv; /* Time entry was made */ #endif int32_t ut_addr_v6[4]; /* Internet address of remote host; IPv4 address uses just ut_addr_v6[0] */ char __unused[20]; /* Reserved for future use */ };
此时万里长征已走一半,对比系统who命令,发现该结构体中并没有直接给出用户登录时间的成员变量,而是内嵌了一个
ut_tv的时间结构体,其中成员变量
tv_sec才是我们需要的。
如果耐心地看完该帮助文档,可以在下面一段代码中有新的发现:
![](https://images2015.cnblogs.com/blog/877163/201611/877163-20161115194641685-372829307.jpg)
此处定义了一个ut_time的宏,指向的就是
ut_tv.ut_sec,而我们需要用到的不是这样一个以秒为单位的格林威治标准时间,所以才后面需用到
ctime()函数。
在这儿用的就是刚刚说的linux的一个思想,一切事物都是文件。
Step2:其余头文件的准备
time.h:将格林威治标准时间(GMT)长整形的数时间转化为我们所熟悉的时间表示,运用
ctime()函数
string.h:调整输出格式,后面调试时会提到用处。
其余头文件:因为要打开文件嘛,所以有些头文件必不可少,这个在我本周博客中有详细介绍:博客地址
Step3:编程思想
查看UTMP_FILE宏:grep -nr UTMP_FILE /usr/include
![](https://images2015.cnblogs.com/blog/877163/201611/877163-20161113231924499-905799599.jpg)
读取其结构体,将需要的变量提取出来并按照一定的格式输出
其中,时间输出本来是一串格林威治标准时间(GMT)长整形的数,可以用ctime()将把日期和时间转换为字符串
Step4:代码实现
who代码其中等下需要修改的代码贴在此处:
void showtime(long timeval) { char* cp; cp = ctime(&timeval); printf("%s",cp+4); //+4是因为*cp所指的一串字符前4个字符表示为“星期”,可以忽略此信息 }
Step5:编译执行
执行结果如下:![](https://images2015.cnblogs.com/blog/877163/201611/877163-20161113231934717-2104815555.jpg)
发现“(:0)”被换行了,但是程序中并没有输出换行字符。经过一番思索后,猜想ctime()函数的返回值
*cp可能自动在最后补了一个字符
\n。
Step6:调试代码
那只要能回退一个字符就好了,比如输出一个\b(退格字符)
编译再运行,发现输出格式仍是原样,最后经过了解
\b确实是可以回退一个字符,但是并不能实现退到上行,也就是不能消除
\n带来的影响
百度之后,说可以通过输出
\r\b来实现“退行”,但实践后发现也不可取
最后考虑到直接修改
*cp字符串中最后一个字符为
\0,使输出达到与系统
who命令一样的效果
在输出语句前添加如下代码(需用到
string.h):
cp[strlen(cp)-1] = '\0'
最后编译执行效果,可以看出与who命令基本一致:
![](https://images2015.cnblogs.com/blog/877163/201611/877163-20161113231944858-421111906.jpg)
相关文章推荐
- linux whoami cp mv mesg 命令 c语言实现(部分功能)
- 【C语言】实现Linux下的who命令
- 在linux中用C语言实现ping命令
- linux 命令c语言代码实现
- 【C语言】实现Linux下的cp命令的基本功能
- 【C语言】实现Linux下的last命令的基本功能
- linux命令实现:whoami
- 课后练习:C语言实现Linux命令——od
- C语言实现Linux命令——od
- C语言实现Linux命令——od
- C语言实现linux中cat命令
- 加分项——C语言实现Linux的pwd命令
- 20155308 加分项——C语言实现Linux的pwd命令
- 20155212 C语言实现linux下pwd命令的两种方法
- C语言——Linux项目:文件复制命令的实现
- 用Linux_C语言模拟CP命令,实现文件和文件夹的拷贝
- Linux中tree命令的C语言实现
- C语言实现Linux系统下ls命令的过滤文件功能
- C语言编程实现Linux命令——who
- 实现Linux的whoami命令