#whoami
-->root
要实现的就是这个命令,很简单,稍微分析一下:
1.通过系统调用getuid取得执行该程序的UID
2.检索/etc/passwd文件,通过UID寻找到对应的USER_NAME.(/etc/passwd格式 "USER_NAME:x:UID:GID:DESCRIPTION:HOME_DIR:SHELL ")
3.打印USER_NAME
整个过程没什么复杂的,也就检索/etc/passwd,通过UID查找USER_NAME的时候花费了一些时间去想。这算得上我第一次在linux下编程,代码写的有点乱,还有各种不优化的地方,欢迎各位指点。
附上代码:
//2015.5.6
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<sys/types.h>
#define PASSWD "/etc/passwd"
#define MAXLEN 1000
char swp[MAXLEN];
int find(int,char *);
void int_to_char(int ,char*);
int main(int ac,char *av[])
{
int w_uid,flag;//UID number;
char name_id[30];
w_uid = geteuid();
if(find(w_uid,name_id) != 1){
perror("find error:");
return -1;
}
printf("%s\n",name_id);
return 1;
}
int find(int w_uid,char *name_id)
{
char usr[10],swp_name[30];
int fd,lslp,i,j;
off_t k;
ssize_t rd;
int_to_char(w_uid,usr);
fd = open(PASSWD,O_RDONLY);
if(fd == -1 ){
perror("file open error:");
return -1;
}
while((rd=read(fd,swp,MAXLEN))!=0)
{
if(rd == -1 ){
perror("read error:");
return -2;
}
lslp=0;
j=0;
k=0;
for(i=0;i<rd;i++)
{
k++;
if(swp[i] == ':') lslp++;
else if(swp[i] == '\n') {lslp=0;j=0;k=0;}
else if(lslp == 0) {
swp_name[j++]=swp[i];
swp_name[j]=0;
}
else if(lslp == 2){
if(strncmp(swp+i,usr,strlen(usr)) == 0) {
strcpy(name_id,swp_name);
return 1;
}
}
}
int mov;
if((mov=lseek(fd,-k,SEEK_CUR))==-1){
perror("lseek error");
return -3;
}
// printf("mov----->%d\n",mov);
}
printf("no find that\n");
return 0;
}
void int_to_char(int x,char *b)
{
char a[10];
int i,len=0;
for(i=0;x;x/=10,i++)
{
a[i]=x%10+48;
}
a[i]=0;
while(i--)
b[len++]=a[i];
b[len]='\0';
return ;
}
后面发现,查找/etc/passwd文件太繁琐了,原来有专门记录uid与username的函数,struct passwd *getpwuid(uid_t uid)
可以直接在shell下执行
$ man getpwuid
查看这个函数及其相关用法,很详细
修改过的代码:
/*2015.5.11
*whoami02.c
*
*/
#include<stdio.h>
#include<sys/types.h>
#include<pwd.h>
int main(int ac,char *av[])
{
struct passwd *pw=NULL;
pw=getpwuid(getuid());
if(pw == NULL){
perror(*av);
return -1;
}
printf("%s\n",pw->pw_name);
}