Unix环境高级编程 读书笔记 第六章 系统数据文件和信息

口令文件

UNIX系统的口令文件是/etc/passwd,包含了多个字段,字段之间使用冒号分隔。这些字段包含在pwd.h中定义的passwd结构中。对于Linux系统,其结构定义为:

/* The passwd structure.  */
struct passwd
{
	char *pw_name;        /* Username.  */
	char *pw_passwd;      /* Password.  */
	__uid_t pw_uid;       /* User ID.  */
	__gid_t pw_gid;       /* Group ID.  */
	char *pw_gecos;       /* Real name.  */
	char *pw_dir;         /* Home directory.  */
	char *pw_shell;       /* Shell program.  */
};

在Linux系统中,/etc/passwd的部分内容如下:

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
jamza:x:1011:1012::/home/jamza:/bin/bash

若想阻止任何人以某个用户名登录到系统,则将该用户名对应的shell字段设置为/dev/null即可。而使用/bin/nologin命令,打印可定制的出错信息,然后以非0状态阻止登录到系统。

标准提供了2个获取口令文件项的函数:

#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
struct passwd *getpwnam(const char *name);
/*若成功,返回指针,若出错,返回NULL*/

如果要查看整个的口令文件,可调用一下的函数:

#include <pwd.h>
struct passwd *getpwent(void);
/*若成功,返回指针,若出错或者到达文件尾端,返回NULL*/

void setpwent(void);
void endpwent(void);

每次调用getpwent函数,则返回口令文件中的下一个记录项。
函数setpwent反绕它所使用的口令文件,即将getpwent的读写地址指回口令文件的起始位置,endpwent关闭使用的口令文件。
在使用getpwent函数查看完口令文件后,一定要使用endpwent关闭口令文件。

阴影口令

为了保证系统的安全性,将加密口令存放在另一个被称为阴影口令的文件中,改文件至少包含用户名与加密口令,以及其他与口令相关的信息字段。
在Linux系统中的阴影口令文件为/etc/shadow,其字段对应的数据结构为spwd结构,在shadow.h中定义:

/* Structure of the password file.  */
struct spwd
{
   char *sp_namp;              /* Login name.  */
   char *sp_pwdp;              /* Encrypted password.  */
   long int sp_lstchg;         /* Date of last change.  */
   long int sp_min;            /* Minimum number of days between changes.  */
   long int sp_max;            /* Maximum number of days between changes.  */
   long int sp_warn;           /* Number of days to warn user to change the password.  */
   long int sp_inact;          /* Number of days the account may be inactive.  */
   long int sp_expire;         /* Number of days since 1970-01-01 until account expires.  */
   unsigned long int sp_flag;  /* Reserved.  */
};

访问阴影口令文件的相关函数为:

#include <shadow.h>
struct spwd *getspent(uid_t uid);
struct spwd *getspnam(const char *name);
/*若成功,返回指针,若出错,返回NULL*/

void setspwent(void);
void endspwent(void);

组文件

组文件在Linux系统中为/etc/group,文件中的相关字段对应grp.h文件中定义的group结构:

/* The group structure.  */
struct group
{
	char *gr_name;              /* Group name.  */
	char *gr_passwd;            /* Password.    */
    __gid_t gr_gid;             /* Group ID.    */
	char **gr_mem;              /* Member list. */
};

字段gr_mem是一个指针数组,每个指针指向属于该组的用户名。数组以null结尾。
使用以下的函数来查看组名和组ID值:

#include <grp.h>
struct group *getgrgid(gid_t gid);
struct group *getgrnam(const char *name);
/*若成功,返回指针,若出错,返回NULL*/

若是搜索整个组文件,使用以下3个函数,这些函数类似针对口令文件的3个函数:

#include <grp.h>
struct group *getgrent(void);
/*若成功,返回指针,若出错或者到达文件尾端,返回NULL*/

void setgrent(void);
void endgrent(void);

附属组

每个用户账户不仅可以属于口令文件记录项中组ID所对应的组,也可以属于多至16个另外的组。
当有附属组的概念后,文件访问权限检查相应的修改为:不仅将进程的有效组ID与文件的组ID比较,还将所有附属组ID与文件的组ID进行比较。

为了获取与设置附属组ID,使用以下函数:

#include <unistd.h>
int getgroups(int gidsetsize, gid_t grouplist[]);
/*若成功,返回附属组ID数量,若出错,返回-1*/

#include <grp.h> /* on Linux */
int setgroups(int ngroups, const gid_t grouplist[]);
int initgroups(const char *username, gid_t basegid);

函数getgroups将进程所属用户的各个附属组ID写到数组grouplist中,填到该数组的ID数量最多为gidsetsize,函数返回实际填写到数组中的ID数量。

若gidsetsize为0,则函数只返回附属组ID的数量,对数组grouplist不作修改。

其他数据文件

访问系统数据的相关例程与函数如下:
在这里插入图片描述

系统标识

系统定义了uname函数,返回与主机与操作系统相关的信息。

#include <sys/utsname.h>
int uname(struct utsname *name);
/*若成功,返回非负值,若出错,返回-1*/

在Linux系统中,结构体utsname定义在/usr/include/sys/utsname.h。具体定义如下:

/* Structure describing the system and machine.  */
struct utsname
  {
    /* Name of the implementation of the operating system.  */
    char sysname[_UTSNAME_SYSNAME_LENGTH];

    /* Name of this node on the network.  */
    char nodename[_UTSNAME_NODENAME_LENGTH];

    /* Current release level of this implementation.  */
    char release[_UTSNAME_RELEASE_LENGTH];
    /* Current version level of this release.  */
    char version[_UTSNAME_VERSION_LENGTH];

    /* Name of the hardware type the system is running on.  */
    char machine[_UTSNAME_MACHINE_LENGTH];

#if _UTSNAME_DOMAIN_LENGTH - 0
    /* Name of the domain of this node on the network.  */
# ifdef __USE_GNU
    char domainname[_UTSNAME_DOMAIN_LENGTH];
# else
    char __domainname[_UTSNAME_DOMAIN_LENGTH];
# endif
#endif
  };

时间和日期

在UNIX系统中,计算从公元1970年1月1日 00:00:00(协调世界时,UTC)这一特定时间以来所经历的秒数,这种秒数是以数据类型time_t来表示。称为日历时间。日历时间包括时间和日期。
函数time返回日历时间:

#include <time.h>
time_t time(time_t *calptr);
/*若成功,返回时间值,若出错,返回-1*/

函数clock_gettime可用于获取指定时钟的时间,函数原型为:

#include <sys/time.h>
int clock_gettime(clockid_t clock_id, struct timespec *tsp);
/*若成功,返回0,若出错,返回-1*/

其中时钟通过类型为clockid_t来标识,可取的值保护:

#  ifdef __USE_POSIX199309
/* Identifier for system-wide realtime clock.  */
#   define CLOCK_REALTIME               0
/* Monotonic system-wide clock.  */
#   define CLOCK_MONOTONIC              1
/* High-resolution timer from the CPU.  */
#   define CLOCK_PROCESS_CPUTIME_ID     2
/* Thread-specific CPU-time clock.  */
#   define CLOCK_THREAD_CPUTIME_ID      3
/* Monotonic system-wide clock, not adjusted for frequency scaling.  */
#   define CLOCK_MONOTONIC_RAW          4
/* Identifier for system-wide realtime clock, updated only on ticks.  */
#   define CLOCK_REALTIME_COARSE        5
/* Monotonic system-wide clock, updated only on ticks.  */
#   define CLOCK_MONOTONIC_COARSE       6
/* Monotonic system-wide clock that includes time spent in suspension.  */
#   define CLOCK_BOOTTIME               7
/* Like CLOCK_REALTIME but also wakes suspended system.  */
#   define CLOCK_REALTIME_ALARM         8
/* Like CLOCK_BOOTTIME but also wakes suspended system.  */
#   define CLOCK_BOOTTIME_ALARM         9

/* Flag to indicate time is absolute.  */
#   define TIMER_ABSTIME                1
#  endif

另外Linux系统中常用的关于时间的数据结构为struct timespec 和struct timeval。两者的区别是timespec的第二个参数是纳秒数,而timeval的第二个参数是毫秒数。

struct timespec
{
    __time_t tv_sec;        /* Seconds. */
    long   tv_nsec;       /* Nanoseconds. */
};

struct timeval {
  time_t tv_sec;  
  suseconds_t tv_usec;
}; 

猜你喜欢

转载自blog.csdn.net/jiangzhangha/article/details/85711080