《Linux/Unix系统编程手册》读书笔记5
《Linux/Unix系统编程手册》读书笔记5
《Linux/Unix系统编程手册》读书笔记 目录
第8章
本章讲了用户和组,还有记录用户的密码文件/etc/passwd,shadow密码文件/etc/shadow还有组文件/etc/group。
每个用户都有的用户名和相关的用户标识符(UID)。用户可以属于,每个组都有唯一的组名和相关的组标识符(GID)。
用户和组的用途为:1、可以确定各种系统资源的所有权;2、对赋予进程访问上述资源的权限加以控制。
首先来看一下密码文件/etc/passwd
lancelot@debian:~$ /etc/::root:/root:/bin/::daemon:/usr/sbin:/bin/::bin:/bin:/bin/::sys:/dev:/bin/
:x::::/bin:/bin/::games:/usr/games:/bin/
:x::::/var/cache/:/bin/
:x::::/var/spool/lpd:/bin/::mail:/var/mail:/bin/::news:/var/spool/news:/bin/::uucp:/var/spool/uucp:/bin/::proxy:/bin:/bin/-data:x:::www-data:/var/www:/bin/::backup:/var/backups:/bin/::Mailing List Manager:/var/list:/bin/::ircd:/var/run/ircd:/bin/::Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/::nobody:/nonexistent:/bin/:::/var/lib/libuuid:/bin/:::/var/run/dbus:/bin/::colord colour management daemon,,,:/var/lib/colord:/bin/::usbmux daemon,,,:/home/usbmux:/bin/-exim:x::::/var/spool/exim4:/bin/::Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/::PulseAudio daemon,,,:/var/run/pulse:/bin/-dispatcher:x:::Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/::HPLIP system user,,,:/var/run/hplip:/bin/:::/var/run/sshd:/usr/sbin/::RealtimeKit,,,:/proc:/bin/:::/var/lib/nfs:/bin/:::/home/saned:/bin/-gdm:x:::Gnome Display Manager:/var/lib/gdm3:/bin/::lancelot,,,:/home/lancelot:/bin/::MySQL Server,,,:/nonexistent:/bin/
:x::: daemon,,,:/srv/:/bin/:::/nonexistent:/bin/
第一个字段是登录名;第二个字段是经过加密后的密码(x),实际上经过加密后的密码是存放在shadow密码文件;
第三个字段是用户的ID(UID);第四个字段是组ID(GID);第五个字段是注释;
第六个字段是主目录,是用户登录后的初始路径;第七个字段是登录shell。
接着来看实际存放密码的shadow 密码文件/etc/shadow
格式如下:
lancelot:$$tnTgvJYU$OhoUNZNIeNU7rlZf/f14oD2g.Uz8SbrnWeZbR4yL4XXRvzbCeijsAZE7Y9HlzU4thKVBVcqucwntJBi/4BoY60::::!:::::*::::*:::::::
很明显可以看到第一个字段为用户登录名,第二个字段为见过加密后的密码,后面的字段为与安全性相关的字段。
看完用户,我们来看组文件/etc/group
lancelot@debian:~$ /etc/:x::x::x:-data:x:-cert:x:-exim:x::x:-access:x:-gdm:x::x::
第一个字段是组的名称,第二个字段是经过加密的密码,第三个字段是组ID(GID),第四个字段是用户列表。
对于加密后的密码存放在类似/etc/shadow的文件(/etc/gshadow),格式如下:
cdrom:***:***-data:**********::lancelot
最后一个字段很明显是用户列表。
接着,我们来看如何通过库函数来获取上面提到的信息。
一、从/etc/shadow获取记录:
#include <pwd.h>
passwd *getpwnam( *
passwd *getpwuid(uid_t uid);
getpwnam()是根据提供的登录名返回一个指向对应的密码记录的指针。getpwuid()是根据提供的uid来返回一个指向对应的密码记录的指针。
如果出现错误返回NULL。
PS:
这个应该是练习8-1的答案。
8-1:执行下列代码时,将会发现,尽管这两个用户在密码文件中对应不同的ID,但该程序的输出还是会将同一个数字显示两次。请问为什么?
printf("%ld %ld\n", (long)(getpwnam("avr")->pw_uid), (long)(getpwnam("tsr")->pw_uid));
然后我测试了一下,代码如下:
#include <stdio.h> #include <pwd.h> main( argc, * printf(, ()(getpwnam()->pw_uid), ()(getpwnam()-> } View Code测试结果:
lancelot@debian:~/Code/tlpi$ ./
然后整个人就凌乱了。。。。。。。。。。。。。。
后来,我把程序改成这样:
#include <stdio.h>
#include <pwd.h>
main( argc, * passwd *p1, * p1 = getpwnam( p2 = getpwnam( printf(, p1->pw_uid, p2->
}
才能输出相同的值,因为两个指针变量指向的地址是一样的。但是之前那种是正确的,因为函数的参数是一值传递的方式传递,所以不存在题目说的两个值相同。
后来我查找了作者的网站的磡误:http://www.man7.org/tlpi/errata/index.html
发现这条题的题目修改了!!!!!!
这样传递指针,两个输出的名字就是一样的。。。。。。。。。。。。。。
下面是作者的解释:
好吧,以后还要把书上的错误修改。。。。。。。
PS:再次证明不管例子多简单也要试一试。。。。。
二、从/etc/group获取记录
#include <grp.h>
group *getgrnam( *
group *getgrgid(gid_t gid);
getgrnam根据提供的组名返回指向组的密码记录的指针,getgrigid则根据提供的组号GID返回该指针。失败调用返回NULL
PS:这两个函数也是不可重入的函数。
三、扫描密码文件和组文件
#include <pwd.h>
passwd *getpwent(
setpwent(
endpwent();
getpwent()可以逐条返回记录。setpwent()可以重置为。/etc/passwd文件的起始处。endpwent()可以关闭文件。
四、从/etc/shadow密码文件中获取记录
#include <shadow.h>
spwd *getspnam( *
spwd *getspent(
setspent(
endspent();
getspnam和getspent会返回指向shadow密码记录的指针,失败调用返回NULL。
setspent会重置为文件的起始位置,endspent会关闭文件。
五、密码加密
_XOPEN_SOURCE
#include <unistd.h>
*crypt( *key, key *salt);
#define _XOPEN_SOURCE 是为了获取crypt的声明。
key为输入的密码,salt指向一个两字节的字符串,用来改变DES算法。成功调用返回加密后的密码,失败返回NULL。
---------------------吐槽:好好写博客,写博客的时候思考的感觉真好,要多读书,多code,多思考---------------------------
听同学说有很多厉害的人已经找到实习了,真的后悔大一大二的无作为。正因为后悔,所以要做得更好!!!!
继续努力!!!!!!
---------------------------------------------------------------------------------------------------------------------------------------------------
练习:
8-2: 使用sptwent()、getpwent()和endpwent()来实现getpwnam()。
这题个人觉得很简单,因为getpwent()是逐条查找,查找匹配就输出。输出完应该调用sptwent将文件的偏移量重置为文件的起始位置。结束的时候调用endpwent关闭文件。
#include <pwd.h>
#include <.h>
#include <stdio.h>
#include
passwd * Getpwnam( * passwd * ((pwd = getpwent()) != (strcmp(pwd->pw_name, name) ==
main( argc, * passwd * (argc < || strcmp(argv[], ) == usageErr(, argv[
(i = ; i < argc; ++ p = Getpwnam(( * (p == printf( printf(, argv[i], ()p->pw_uid, ()p->
}
测试结果:
lancelot@debian:~/Code/tlpi$ ./, GID: , GID:
评论暂时关闭