unix/linux who命令的实现
2017-03-07 14:35
489 查看
Understanding Unix/Linux Programming(Unix/Linux编程实践教程)
学习模式:
(1)它能做什么?
(2)它是如何实现的?
(3)能不能自己编写一个?
(实验环境:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) )
who命令的学习
(1) who命令能做什么?
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/965bd752d8bef805e0e321d90f5b40bb)
(2)如何实现的?
联机帮助告诉我们,who命令通过读取utmp这个文件以实现对应的功能。utmp这个结构包含了我们需要的who所需要的全部信息,除此之外还提供了其他信息。
命令输入: man 5 utmp
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/cfaac491767d10b7ac16d50891c6c828)
输入命令:cat /usr/include/utmp.h
可知道_UTMP_FILE保存了用户登录的信息。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/0c5e880b7f6128df7ed0cdebaae094f6)
(3)编码实现
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/0b75facb1eed0b8fc22a9a0c32c28bcf)
完善:
(1) 清除空白记录(通过判断用户是否在线即可)
同样可通过命令:man 5 utmp
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/c4486fa5dee3c85e7f591bfc223dd7b4)
(2)时间格式化打印(使用系统调用将long int转为ASCII 打印输出)
通过联机查询步骤:
1.man -k time | grep transform
2.man 3 ctime
代码完善实现如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/a240ec6587a956dbfcc9144a07708210)
还记得前面那三个问题吗?这里增加一个问题,如何使程序的运行更加高效呢?
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/22f54e4f9e797dac3a2554225fa35269)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/417f5193de14e80937744c45e8e32fb1)
代码实现:
utmplib.h
who3.c
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/ddecb75a18b4987420546867411d1fec)
(1)who am i 能做什么?
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/9f9eb6ae46b5ae594e165e80489aee49)
用户当前使用的相关终端设备。
(2)如何实现?
我们可以在who2的基础上进行筛选出用户名相关终端设备的信息。
问题在于如何获取用户名相关的当前终端设备??
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/07709e19348c4f5d12572d1bee0edb41)
(3)代码实现
#include<stdio.h>
#include<unistd.h>
#include<utmp.h>
#include<fcntl.h>
#include<time.h>
#include<stdlib.h>
#include<string.h>
void showtime(long);
void show_info(struct utmp*);
char* whats_my_line(int);
int main(int argc,char* argv[])
{
if(argc!=3)
{
printf("argument need : who am i");
exit(1);
}
struct utmp utbuf; //read info into here
int utmpfd; // read from this descriptor
char* myline = NULL;
myline = whats_my_line(0);// get the device name of tty
if((utmpfd = open(UTMP_FILE,O_RDONLY)) == -1)
{
perror(UTMP_FILE);
exit(1);
}
while(read(utmpfd,&utbuf,sizeof(utbuf)) == sizeof(utbuf))
{
if(myline == NULL || strcmp(utbuf.ut_line,myline) == 0)
show_info(&utbuf);
}
close(utmpfd);
return 0;
}
char* whats_my_line(int fd)
{
char *rv;
rv = ttyname(fd);
//puts(rv); //debug print: dev/pts/6
if(rv)
if(strncmp(rv,"/dev/",5) == 0)
return rv+5;
return rv;
// return pts/6
}
void showtime(long timeval)
{
char* cp;
cp = ctime(&timeval);
printf("%12.12s",cp + 4);
}
void show_info(struct utmp* utbufp)
{
if(utbufp->ut_type != USER_PROCESS) //online
return ;
printf("%-8.8s ",utbufp->ut_name);
printf("%-8.8s ",utbufp->ut_line);
showtime(utbufp->ut_time);
#ifdef SHOWHOST
if(utbufp->host[0] != '\0')
printf(" (%s) ",utbuf->ut_host);
#endif
printf("\n");
}
(1)whoami能做什么?
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/707c11378f1c8e72dbe3817b5c2e765f)
可知打印当前用户名。
(2)如何实现的??
通过联机帮助:man 2 geteuid, 可以通过获取当前用户id,通过使用getpwuid函数对应id找到用户所对应的信息,这些信息包括用户名。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/58a760b2d0bc1e1df528a9549d6fd254)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/76b6b8225f1aefd5f1d2357f181c563d)
cat /usr/include/pwd.h
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/10/c9e9adadeff4ac7887b4a9b634432fc8)
(3)代码实现#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pwd.h>
#include<sys/types.h>
int main()
{
uid_t id; //effective user id of process
struct passwd* p; // will hold pwd data for user
id = geteuid(); //manpage says geteuid always succeeds
p = getpwuid(id);
if(p == NULL)
printf("I don't know thow you are \n");
else
printf("%s\n",p->pw_name);
return 0;
}
学习模式:
(1)它能做什么?
(2)它是如何实现的?
(3)能不能自己编写一个?
(实验环境:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) )
who命令的学习
(1) who命令能做什么?
(2)如何实现的?
联机帮助告诉我们,who命令通过读取utmp这个文件以实现对应的功能。utmp这个结构包含了我们需要的who所需要的全部信息,除此之外还提供了其他信息。
命令输入: man 5 utmp
输入命令:cat /usr/include/utmp.h
可知道_UTMP_FILE保存了用户登录的信息。
(3)编码实现
#include<stdio.h> #include<stdlib.h> #include<utmp.h> #include<fcntl.h> #include<unistd.h> #define SHOWHOST /*include remote machine on output*/ void show_info(struct utmp* utbufp) { printf("%-8.8s ",utbufp->ut_name); /*thie logname */ printf("%-8.8s ",utbufp->ut_line); /*the logtty*/ printf("%10ld ",utbufp->ut_time); /*the logtime*/ #ifdef SHOWHOST printf("s",utbufp->ut_host); /*the host*/ #endif printf("\n"); } int main() { struct utmp current_record; /*read info into here*/ int utmpfd; /*read from the descriptor*/ int reclen = sizeof(current_record); //if((utmpfd = open("UTMP_FILE",O_RDONLY)) == -1) if((utmpfd = open(UTMP_FILE,O_RDONLY)) == -1) { perror(UTMP_FILE); /* UTMP_FILE is in utmp.h , #define UTMP_FILE _PATH_UTMP /*#define _PATH_UTMP "/var/run/utmp"*/ exit(1); } while(read(utmpfd,¤t_record,reclen) == reclen) show_info(¤t_record); close(utmpfd); return 0; }运行结果:可知跟我们shell提供的命令打印不太一样。
完善:
(1) 清除空白记录(通过判断用户是否在线即可)
同样可通过命令:man 5 utmp
(2)时间格式化打印(使用系统调用将long int转为ASCII 打印输出)
通过联机查询步骤:
1.man -k time | grep transform
2.man 3 ctime
代码完善实现如下:
#include<stdio.h> #include<stdlib.h> #include<utmp.h> #include<fcntl.h> #include<unistd.h> #include<time.h> #define SHOWHOST /*include remote machine on output*/ void showtime(long timeval) { char* cp; cp = ctime(&timeval); printf("%12.12s",cp+4); } void show_info(struct utmp* utbufp) { /*USER_PROCESS indicate the user is active or not*/ if(utbufp->ut_type!= USER_PROCESS) return ; printf("%-8.8s ",utbufp->ut_name); /*thie logname */ printf("%-8.8s ",utbufp->ut_line); /*the logtty*/ showtime(utbufp->ut_time); #ifdef SHOWHOST if(utbufp->ut_host[0] != '\0') printf("s",utbufp->ut_host); /*the host*/ #endif printf("\n"); } int main() { struct utmp current_record; /*read info into here*/ int utmpfd; /*read from the descriptor*/ int reclen = sizeof(current_record); //if((utmpfd = open("UTMP_FILE",O_RDONLY)) == -1) if((utmpfd = open(UTMP_FILE,O_RDONLY)) == -1) { perror(UTMP_FILE); /* UTMP_FILE is in utmp.h , #define UTMP_FILE _PATH_UTMP /*#define _PATH_UTMP "/var/run/utmp"*/ exit(1); } while(read(utmpfd,¤t_record,reclen) == reclen) show_info(¤t_record); close(utmpfd); return 0; }
还记得前面那三个问题吗?这里增加一个问题,如何使程序的运行更加高效呢?
代码实现:
utmplib.h
#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<utmp.h> #define NRECS 16 #define NULLUT ((struct utmp*) NULL) #define UTSIZE (sizeof(struct utmp)) static char utmpbuf[NRECS* UTSIZE]; /*storage*/ static int num_recs; /*num stored*/ static int cur_rec; /*next to go */ static int fd_utmp = -1; /*read from*/ int utmp_open(char* filename) { fd_utmp = open(filename,O_RDONLY); cur_rec = num_recs = 0; return fd_utmp; } int utmp_reload() /*read next bunch of records into buffer*/ { int amt_read; amt_read = read(fd_utmp,utmpbuf,NRECS*UTSIZE); num_recs = amt_read/UTSIZE; cur_rec = 0; return num_recs; } struct utmp* utmp_next() { struct utmp* recp; if(fd_utmp == -1) return NULLUT; if(cur_rec == num_recs && utmp_reload() == 0) return NULLUT; recp = (struct utmp* )&utmpbuf[cur_rec * UTSIZE]; cur_rec ++; return recp; } void utmp_close() { if(fd_utmp!=-1) close(fd_utmp); }
who3.c
#include<stdio.h> #include<stdlib.h> #include<utmp.h> #include<fcntl.h> #include<unistd.h> #include<time.h> #include"utmplib.h" #define SHOWHOST /*include remote machine on output*/ void showtime(long timeval) { char* cp; cp = ctime(&timeval); printf("%12.12s",cp+4); } void show_info(struct utmp* utbufp) { /*USER_PROCESS indicate the user is active or not*/ if(utbufp->ut_type!= USER_PROCESS) return ; printf("%-8.8s ",utbufp->ut_name); /*this logname */ printf("%-8.8s ",utbufp->ut_line); /*the logtty*/ showtime(utbufp->ut_time); #ifdef SHOWHOST if(utbufp->ut_host[0] != '\0') printf("s",utbufp->ut_host); /*the host*/ #endif printf("\n"); } int main() { struct utmp *utbufp; /*read info into here*/ int utmpfd; /*read from the descriptor*/ if(utmp_open(UTMP_FILE) == -1) { perror(UTMP_FILE); exit(1); } while((utbufp =utmp_next()) != ((struct utmp*)NULL)) { show_info(utbufp); } utmp_close(); return 0; }
(1)who am i 能做什么?
用户当前使用的相关终端设备。
(2)如何实现?
我们可以在who2的基础上进行筛选出用户名相关终端设备的信息。
问题在于如何获取用户名相关的当前终端设备??
(3)代码实现
#include<stdio.h>
#include<unistd.h>
#include<utmp.h>
#include<fcntl.h>
#include<time.h>
#include<stdlib.h>
#include<string.h>
void showtime(long);
void show_info(struct utmp*);
char* whats_my_line(int);
int main(int argc,char* argv[])
{
if(argc!=3)
{
printf("argument need : who am i");
exit(1);
}
struct utmp utbuf; //read info into here
int utmpfd; // read from this descriptor
char* myline = NULL;
myline = whats_my_line(0);// get the device name of tty
if((utmpfd = open(UTMP_FILE,O_RDONLY)) == -1)
{
perror(UTMP_FILE);
exit(1);
}
while(read(utmpfd,&utbuf,sizeof(utbuf)) == sizeof(utbuf))
{
if(myline == NULL || strcmp(utbuf.ut_line,myline) == 0)
show_info(&utbuf);
}
close(utmpfd);
return 0;
}
char* whats_my_line(int fd)
{
char *rv;
rv = ttyname(fd);
//puts(rv); //debug print: dev/pts/6
if(rv)
if(strncmp(rv,"/dev/",5) == 0)
return rv+5;
return rv;
// return pts/6
}
void showtime(long timeval)
{
char* cp;
cp = ctime(&timeval);
printf("%12.12s",cp + 4);
}
void show_info(struct utmp* utbufp)
{
if(utbufp->ut_type != USER_PROCESS) //online
return ;
printf("%-8.8s ",utbufp->ut_name);
printf("%-8.8s ",utbufp->ut_line);
showtime(utbufp->ut_time);
#ifdef SHOWHOST
if(utbufp->host[0] != '\0')
printf(" (%s) ",utbuf->ut_host);
#endif
printf("\n");
}
(1)whoami能做什么?
可知打印当前用户名。
(2)如何实现的??
通过联机帮助:man 2 geteuid, 可以通过获取当前用户id,通过使用getpwuid函数对应id找到用户所对应的信息,这些信息包括用户名。
cat /usr/include/pwd.h
(3)代码实现#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pwd.h>
#include<sys/types.h>
int main()
{
uid_t id; //effective user id of process
struct passwd* p; // will hold pwd data for user
id = geteuid(); //manpage says geteuid always succeeds
p = getpwuid(id);
if(p == NULL)
printf("I don't know thow you are \n");
else
printf("%s\n",p->pw_name);
return 0;
}
相关文章推荐
- Linux下who命令的实现
- 【C语言】实现Linux下的who命令
- linux命令实现:whoami
- linux编程实践3(实现who命令)
- unix/linux more命令的实现
- linux whoami cp mv mesg 命令 c语言实现(部分功能)
- Linux下who命令之C语言实现
- C语言编程实现Linux命令——who
- 实现Linux的whoami命令
- 【Unix/Linux编程实践】从零做起:编写who命令
- unix/linux ls命令的实现
- Linux命令简单实现 -- whoami
- Linux 和unix下SAR命令的用法
- linux//unix实用基本命令小全
- Linux/Unix环境下的make命令详解
- linux下用mdadm命令实现软raid(zt)
- Linux/Unix环境下的make命令详解
- Linux/UNIX命令dd简介
- linux和unix下SAR命令的用法,对机器性能检测很有帮助
- 深入浅出Shell 编程:Unix/Linux 命令