busybox源码剖析(1)
来源:互联网 发布:四川省广电网络 编辑:程序博客网 时间:2024/05/16 08:36
想找个简单的代码来看,学习代码的架构设计,就找到了busybox。先从最早的版本开始看。
whoami命令是获取当前终端的用户名。/etc/passwd文件存储了所有用户名的清单。要注意的是/etc存储的配置文件大多是系统级的配置文件。而whoami想要达到目的,就需要与/etc/passwd文件打交道。
首先来看whoami.c的主体程序:
1 extern int whoami_main(int argc, char **argv) 2 { 3 char user[9]; 4 uid_t uid = geteuid(); 5 6 if (argc > 1) 7 show_usage(); 8 9 my_getpwuid(user, uid);10 if (*user) {11 puts(user);12 return EXIT_SUCCESS;13 }14 error_msg_and_die("cannot find username for UID %u", (unsigned) uid);15 }
首先通过geteuid()系统调用获得uid,然后,通过my_getpwuid(user,uid)获得username。
再看my_getpwuid函数。
1 void my_getpwuid(char *name, long uid) 2 { 3 struct passwd *myuser; 4 5 myuser = getpwuid(uid); 6 if (myuser==NULL) 7 sprintf(name, "%-8ld ", (long)uid); 8 else 9 strcpy(name, myuser->pw_name);10 }
/etc/passwd中的每条记录都有相同的格式:
name:password:uid:gid:comment:home:shell
每项的具体内容可以查看这里。
struct passwd 结构就对应了这个记录:
1 struct passwd 2 { 3 char *pw_name; /* Username. */ 4 char *pw_passwd; /* Password. */ 5 uid_t pw_uid; /* User ID. */ 6 gid_t pw_gid; /* Group ID. */ 7 char *pw_gecos; /* Real name. */ 8 char *pw_dir; /* Home directory. */ 9 char *pw_shell; /* Shell program. */10 };
我们无法单独得到username,所有,我们必须先得到struct passwd结构。my_getpwuid函数中的getpwuid函数就实现这个功能。
1 struct passwd *getpwuid(uid_t uid) 2 { 3 int passwd_fd; 4 struct passwd *passwd; 5 6 if ((passwd_fd = open("/etc/passwd", O_RDONLY)) < 0) 7 return NULL; 8 9 while ((passwd = __getpwent(passwd_fd)) != NULL)10 if (passwd->pw_uid == uid) {11 close(passwd_fd);12 return passwd;13 }14 15 close(passwd_fd);16 return NULL;17 }
第9行while不断读取/etc/passwd中的条目,找到目标就return。进入到__getpwent中。
1 if ((line_len = read(pwd_fd, line_buff, PWD_BUFFER_SIZE)) <= 0) // 2 return NULL; //当read之后,pwd_fd所指向的文件的offet到了line_buff的末尾。这对后面的处理很重要。 3 field_begin = strchr(line_buff, '\n'); 4 if (field_begin != NULL) 5 lseek(pwd_fd, (long) (1 + field_begin - (line_buff + line_len)), 6 SEEK_CUR); //找到一个'\n'后,就需要进行parse。然后就要将offset调到当前'\n'的后一位,就是这个语句的作用了。 7 else { 8 9 do {10 if ((line_len = read(pwd_fd, line_buff, PWD_BUFFER_SIZE)) <= 0)11 return NULL;12 } while (!(field_begin = strchr(line_buff, '\n')));13 lseek(pwd_fd, (long) (field_begin - line_buff) - line_len + 1,14 SEEK_CUR); 15 goto restart;16 }
得到一个条目的首地址line_buff后,就可以parse了。过程很简单。
1 for (i = 0; i < 7; i++) { 2 switch (i) { 3 case 0: 4 passwd.pw_name = field_begin; 5 break; 6 case 1: 7 passwd.pw_passwd = field_begin; 8 break; 9 case 2:10 uid_ptr = field_begin;11 break;12 case 3:13 gid_ptr = field_begin;14 break;15 case 4:16 passwd.pw_gecos = field_begin;17 break;18 case 5:19 passwd.pw_dir = field_begin;20 break;21 case 6:22 passwd.pw_shell = field_begin;23 break;24 }25 if (i < 6) {26 field_begin = strchr(field_begin, ':');27 if (field_begin == NULL)28 goto restart;29 *field_begin++ = '\0';30 }
找到符合uid的条目后,my_getpwuid函数得到username,输出就可以了。
<script type="text/javascript"><!--google_ad_client = "ca-pub-1944176156128447";/* cnblogs 首页横幅 */google_ad_slot = "5419468456";google_ad_width = 728;google_ad_height = 90;//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
- busybox源码剖析(1)
- busybox源码剖析(1)---whoami.c
- busybox源码剖析(3)
- busybox源码剖析(2)
- busybox源码剖析(2)---pwd.c
- busybox源码剖析(3)---cat.c
- Busybox源码
- STL源码剖析(1)
- CLucene源码剖析(1)
- Scintilla源码剖析1
- Ogre源码剖析1
- STL源码剖析1
- Flask0.1源码剖析
- busybox源码解析
- BusyBox源码结构简介
- 基于real6410和android2.1源码的busybox移植
- STL源码剖析笔记(1)
- nginx源码剖析(1)----概要
- 整数的所有不同分割数目
- 毕业求职
- 世纪末的星期
- java 线程同步
- HDU-2046骨牌铺方格
- busybox源码剖析(1)
- 【JAX-WS入门系列】第08章_与Spring集成以及获取ServletAPI
- c++ 学习之2
- 状态压缩dp学习小记part1
- vc exec
- 红黑树C++源码, 有详细注释
- S5PV210的BL1应用
- IIS 7+用URLRewrite设置伪静态的方法
- 如果是初学C语言请看完一些成功人士的心得