《UNIX环境高级编程》笔记22--口令文件,阴影文件,组文件,附加组ID,其他数据文件

1.口令文件

UNIX系统的口令文件(/etc/passwd)包含如下个字段,这些字段包含在<pwd.h>中定义的passwd文件中。
《UNIX环境高级编程》笔记22--口令文件,阴影文件,组文件,附加组ID,其他数据文件

POSIX只定义了两个获取口令文件项的函数,在给出用户登录名或者数值用户ID后,这两个函数就能查询相关项。
[cpp] view plain copy
  1. #include <pwd.h>  
  2. struct passwd *getpwuid(uid_t uid);  
  3. struct passwd *getpwnam(const char *name);  
两个函数返回值,如果成功返回指针,出错则返回NULL。

实践:
[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <pwd.h>  
  3.   
  4.   
  5. int main(void){  
  6.         struct passwd* pwd;  
  7.         if((pwd = getpwuid(1)) == NULL){  
  8.                 perror("getpwuid");  
  9.                 return -1;  
  10.         }  
  11.         printf("%s,%s,%ld,%ld,%s,%s,%s\n",pwd->pw_name,pwd->pw_passwd,pwd->pw_uid,pwd->pw_gid,pwd->pw_gecos,pwd->pw_dir,pwd->pw_shell);  
  12.   
  13.   
  14.         if((pwd = getpwnam("daemon")) == NULL){  
  15.                 perror("getpwnam");  
  16.                 return -1;  
  17.         }  
  18.         printf("%s,%s,%ld,%ld,%s,%s,%s\n",pwd->pw_name,pwd->pw_passwd,pwd->pw_uid,pwd->pw_gid,pwd->pw_gecos,pwd->pw_dir,pwd->pw_shell);  
  19.         return 0;  
  20. }  
运行结果:
daemon,x,1,1,daemon,/usr/sbin,/bin/sh
daemon,x,1,1,daemon,/usr/sbin,/bin/sh

如果要查看整个口令文件,可使用以下三个函数。
[cpp] view plain copy
  1. #include <pwd.h>  
  2. struct passwd* getpwent(void); //如果成功返回指针,出错或者达到文件末尾则返回NULL。  
  3. void setpwent(void); //反绕所使用的文件,使指针指向文件的第一行  
  4. void endpwent(void); //关闭文件。  

实践:
[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <pwd.h>  
  3.   
  4. int main(void){  
  5.         struct passwd* pwd;  
  6.         if((pwd = getpwent()) == NULL){  
  7.                 perror("getpwent");  
  8.                 return -1;  
  9.         }  
  10.         printf("%s,%s,%ld,%ld,%s,%s,%s\n",pwd->pw_name,pwd->pw_passwd,pwd->pw_uid,pwd->pw_gid,pwd->pw_gecos,pwd->pw_dir,pwd->pw_shell);  
  11.   
  12.         setpwent();  
  13.   
  14.         while((pwd = getpwent()) != NULL){  
  15.                 printf("%s,%s,%ld,%ld,%s,%s,%s\n",pwd->pw_name,pwd->pw_passwd,pwd->pw_uid,pwd->pw_gid,pwd->pw_gecos,pwd->pw_dir,pwd->pw_shell);  
  16.         }  
  17.         endpwent();  
  18.         return 0;  
  19. }  

运行结果:
root,x,0,0,root,/root,/bin/bash
root,x,0,0,root,/root,/bin/bash
daemon,x,1,1,daemon,/usr/sbin,/bin/sh
bin,x,2,2,bin,/bin,/bin/sh
.......此处省略多行
hplip,x,112,7,HPLIP system user,,,,/var/run/hplip,/bin/false
pulse,x,113,121,PulseAudio daemon,,,,/var/run/pulse,/bin/false
saned,x,114,123,,/home/saned,/bin/false
yan,x,1000,1000,yanwenjie,,,,/home/yan,/bin/bash
sshd,x,115,65534,,/var/run/sshd,/usr/sbin/nologin

2.阴影文件

因为/etc/passwd文件对普通用户来说是可见的,所以现在的系统都将加密的密码存放在一个阴影文件(shadow password)中,
该文件至少包含用户名和密码。阴影文件(/etc/shadow)各字段说明如下:
《UNIX环境高级编程》笔记22--口令文件,阴影文件,组文件,附加组ID,其他数据文件

与口令文件一组函数类似,有另一组函数可以访问阴影文件。(只有root用户才能权限调用该组函数)
[cpp] view plain copy
  1. #include <pwd.h>  
  2. struct spwd *getspnam(const char *name); //如果成功返回指针, 如果出错则返回NULL。  
  3.   
  4. struct spwd *getspent(void);  //如果成功返回指针, 如果出错则返回NULL。  
  5. void setspent(void);  //反绕阴影文件,将指针指向文件的第一行。  
  6. void entspent(void);  //关闭文件。  

实践:
[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <shadow.h>  
  3.   
  4. int main(void){  
  5.         struct spwd* spwd;  
  6.         if((spwd = getspnam("yan")) == NULL){  
  7.                 perror("getspnam");  
  8.                 return -1;  
  9.         }  
  10.         printf("%s,%s,%ld,%ld,%ld,%ld,%ld,%ld,%lu\n",spwd->sp_namp,spwd->sp_pwdp,spwd->sp_lstchg,spwd->sp_min,spwd->sp_max,spwd->sp_warn,spwd->sp_inact,spwd->sp_expire,spwd->sp_flag);  
  11.   
  12.         if((spwd = getspent()) == NULL){  
  13.                 perror("getspent");  
  14.                 return -1;  
  15.         }  
  16.   
  17.         setspent();  
  18.   
  19.         while((spwd = getspent()) != NULL){  
  20.                 printf("%s,%s,%ld,%ld,%ld,%ld,%ld,%ld,%lu\n",spwd->sp_namp,spwd->sp_pwdp,spwd->sp_lstchg,spwd->sp_min,spwd->sp_max,spwd->sp_warn,spwd->sp_inact,spwd->sp_expire,spwd->sp_flag);  
  21.         }  
  22.         endspent();  
  23.         return 0;  
  24. }  
运行结果:
yan,$6$OGnTte0B$fAq8CO01RIyf2mkaBUaY2LZjYyZDyLrQVbv94im4tpMgs1SdTjHIC9ls1p9MDI4TP5meeI8HWxgrkKWqJII.D.,15807,0,99999,7,-1,-1,4294967295
root,$6$sr2Imb6g$hbPz1T3OJTszUFgQXR36oW1l4qnzEA8cZR1qgqCMq3jIpv4Ev4Kyt3Nbfv/2PcOLYKoLk9sA.aGtV.srKGZM8.,15807,0,99999,7,-1,-1,4294967295
daemon,*,15630,0,99999,7,-1,-1,4294967295
bin,*,15630,0,99999,7,-1,-1,4294967295
.......此处省略多行
saned,*,15630,0,99999,7,-1,-1,4294967295
yan,$6$OGnTte0B$fAq8CO01RIyf2mkaBUaY2LZjYyZDyLrQVbv94im4tpMgs1SdTjHIC9ls1p9MDI4TP5meeI8HWxgrkKWqJII.D.,15807,0,99999,7,-1,-1,4294967295
sshd,*,15807,0,99999,7,-1,-1,4294967295

3.组文件

UNIX组文件包含了下表所示的字段,这些字段包含在<grp.h>所定义的group结构中。
《UNIX环境高级编程》笔记22--口令文件,阴影文件,组文件,附加组ID,其他数据文件
字段gr_mem是一个指针数组,其中每个指针各指向一个属于该组的用户名,该数组以空指针结尾。

对组文件的访问函数如下,形式基本与口令文件和阴影文件相同。
[cpp] view plain copy
  1. #include <grp.h>  
  2. struct group *getgrgid(gid_t gid);  
  3. struct group *getgrnam(const char *name);  
  4. //两个函数返回值:如果成功返回指针,出错则返回NULL。  
  5.   
  6. struct group *getgrent(void);  //如果成功返回指针,出错或者到达文件结尾则返回NULL  
  7. void setgrent(void);  
  8. void endgrent(void);  

4.附加组

我们不仅可以属于口令文件记录项中组ID所对应的组,也可以属于多达16个另外的组。为了获取和设置附加组ID,提供以
下函数。
#include <unistd.h>
int getgroup(int gidsetsize, gid_t grouplist[]);  //如果成功返回附加组ID,出错则返回-1.
//函数将个附加组ID填写到数组grouplist中,数组中存放的元素最多为gidsetsize个。

#include <grp.h>  //on linux
#include <unistd.h>  //on FreeBSD and Mac OS X and Solaris
int setgroups(int ngroups, const gid_t grouplist[]);  //如果成功返回0,出错则返回-1.
//由root调用,为进程设置附加组ID表,grouplist是组ID数组,ngroups指定了数组中的元素个数。

#include <grp.h>  //on linux and Solaris
#include <unistd.h>  //on FreeBSD and Mac OS X 
int initgroups(const char* username, gid_t basegid); //如果成功返回0,出错则返回-1.
//initgroups()用来从组文件(/etc/group)读取整个组文件,然后对username确定其组的成员关系,然后调用setgroups,
为该用户初始化附加组ID表。除了在组文件中找到username是成员的所有组,initgroups也在附加组ID表中包括了
basegid,basegid是username在口令文件中的组ID。

5.其他数据文件

至此讨论了口令文件,阴影文件和组文件,在日常操作中,UNIX还使用其他文件。一般情况下,对于每个数据文件至少
有三个函数:get函数,set函数,end函数。下面列出了UNIX常用的文件对应的函数。
《UNIX环境高级编程》笔记22--口令文件,阴影文件,组文件,附加组ID,其他数据文件