Advanced Programming in UNIX Environment Episode 26

口令文件
UNIX系统口令文件(POSIX.1则将其称为用户数据库)包含了下列表格所示的各字段,这些字段包含在<pwd.h>中定义的passwd结构中。

注意,POSIX.1只指定passwd结构包含的10个字段中的5个。大多数平台至少支持其中7各字段。BSD派生的平台支持全部10个字段。

说明 struct passwd成员 POSIX.1 FreeBSD Linux 3.2.0 Mac OS X 10.6.8 Solaris 10
用户名 char *pw_name · · · · ·
加密口令 char *pw_passwd · · · ·
数值用户ID uid_t pw_uid · · · · ·
数值组ID gid_t pw_gid · · · · ·
注释字段 char *pw_gecos · · · ·
初始工作目录 char *pw_dir · · · · ·
初始shell(用户程序) char *pw_shell · · · · ·
用户访问类 char *pw_class · ·
下次更改口令时间 time_t pw_change · ·
账户有效期间 time_t pw_expire · ·

POSIX.1定义了两个获取口令文件项的函数。

#include <pwd.h>

struct passwd *getpwid(uid_t uid);
struct passwd *getpwnam(const char *name);

如果要查看的只是登录名或用户ID,那么这两个POSIX.1函数能满足要求,但是也有些程序要查看整个口令文件。

#include <pwd.h>

struct passwd *getpwent(void);

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

基本POSIX.1标准没有定义这三个函数。在Single UNIX Specification中,他们被定义为XSI扩展。

#include <pwd.h>
#include <stddef.h>
#include <string.h>

struct passwd * getpwnam(const char *name)
{
    struct passwd *ptr;

    setpwent();
    while((ptr=getpwent())!=NULL)
    {
        break;
    }
    endpwent();
    return ptr;
}

getpwnam函数

为使企图这样做的人难以获得原始资料(加密口令),现在,某些系统将加密口令存放在另一个通常称为阴影口令(shadow password)的文件中。该文件至少要包括用户名和加密口令。

加密口令char *sp_pwdp上次更改口令以来经过的时间int sp_lstchg经多少天后允许更改int *sp_min要求更改尚余天数int sp_max超期警告天数int sp_warn账户不活动之前尚余天数int sp_inact账户超期天数int sp_expire保留unsigned int sp_flag
说明 struct spwd成员
用户登录名 char *sp_namp

阴影口令文件不应是一般用户可以读取的。仅用少数几个程序需要访问加密口令,如login和passwd,这些程序常常是设置用户ID为root的程序。

#include <shadow.h>

struct spwd *getspnam(const char *name);
struct spwd *getspent(void);

void setspend(void);
void endspent(void);

组文件

UNIX组文件(POSIX.1称其为组数据库)包含了所示字段。

说明 struct group成员 POSIX.1 FreeBSD Linux 3.2.0 Mac OS X 10.6.8 Solaris 10
组名 char *gr_name · · · · ·
加密口令 char *gr_passwd · · · ·
数值组ID int gr_uid · · · · ·
数值组ID gid_t pw_gid · · · · ·
指向个用户名指针的数组/th> char **gr_mem · · · · ·

查看组名或数值组ID。

#include <grp.h>

struct group *getgrgid(gid_t gid);
struct group *getgrnam(const char *name);

需要搜索整个组文件,则需要使用另外几个函数。类似于针对口令文件的3个函数。

#include <grp.h>

struct group *getgrent(void);

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

这3个函数不是基本POSIX.1标准的组成部分。Single UNIX Specification的XSI扩展定义了这些函数。所有UNIX系统都提供这3个函数。

附属组ID

附属组ID是POSIX.1要求的特性。常量NGROUPS_MAX规定了附属组ID的数量,其常用值为16。

为了获取和设置附属组ID,提供了下列3个函数。

#include <unistd.h>
int getgroups(int gidsetsize,gid_t grouplist[]);

#include <grp.h> /* on Linux */
#include <unistd.h> /* on FreeBSD,Mac OS X,and Solaris */
int setgroups(int ngroups,const gid_t grouplist[]);

#include <grp.h> /* on Linux and Solaris */
#include <unistd.h> /*on FreeBSD and Mac OS X */
int initgroups(const char *username,gid_t basegid);

在这3个函数中,POSIX.1只说明了getgroups。因为setgroups和initgroups是特权操作,所以它们并非POSIX.1的组成部分。但是,本书说明的4中平台多支持这3个函数。

Implementation Differences

Figure summarized how the four platforms covered in this book store user and group information.

information FreeBSD 8.0 Linux 3.2.0 Mac OS X 10.6.8 Solaris 10
account information /etc/passwd /etc/passwd Directory Services /etc/passwd
encrypted passwords /etc/master.passwd /etc/shadow Directory Services /etc/shadow
hashed password files yes no no no

On many systems,the user and group databases are implemented using the Network Information Service (NIS). This allows administrators to edit a master copy of the databases and distribute them automatically to all servers in an organization. Client systems contact servers to look up information about users and groups. NIS+ and the Lightweight Directory Access Protocol (LDAP) provide similar functionality. Many systems control the method used to administer each type of information through the /etc/nsswitch.conf configuration file.

Other Data Files

The general principle is that every data file has at least three functions:

1.A get function that reads the next record,opening the file if necessary. These functions normally return a pointer to a structure. A null pointer is returned when the end of file is reached. Most of the get functions return a pointer to a static structure,so we always have to copy the structure if we want to save it.

2.A set function that opens the file,if not already open,and rewinds the file. We use this function when we know we want to start again at the beginning of the file.

3.An end entry that closes the data file. As we mentioned earlier,we always have to call this function when we’re done,to close all the files.

Login Accounting

Two data files provided with most UNIX systems are the utmp file,which keeps track of all the users currently logged in,and the wtmp file,which keeps track of all logins and logouts.

struct utmp
{
    char ut_line[8];
    char ut_name[8];
    long ut_time;
};

Most versions of the UNIX System still provide the utmp and wtmp files,but as expected,the amount of information in these files has grown. The 20-byte structure that was written by Version 7 grew to 36 bytes with SVR2,and the extended utmp structure with SVR4 takes more than 350 bytes!

System Identification

POSIX.1 defines the uname function to return information on the current host and operating system.

#include <sys/utsname.h>

int uname(struct utsname *name);

We pass the address of a utsname structure to this function,and the function then fills it in. POSIX.1 defines only the minimum fields in the structure,which are all character arrays,and it’s up to each implementation to set the size of each array.

struct utsname
{
    char sysname[];
    char nodename[];
    char release[];
    char version[];
    char machine[];
};
Interface Maximum name length
FreeBSD 8.0 Linux 3.2.0 Mac OS X 10.6.8 Solaris 10
uname 256 65 256 257
gethostname 256 64 256 256

Historically,BSD-derived systems provided the gethostname function to return only the name of the host. This name is usually the name of the host on a TCP/IP network.

#include <unistd.h>
int gethostname(char *name,int namelen);

Time and Date Routines

The basic time service provided by the UNIX kernel counts the number of seconds that have passed since the Epoch: 00:00:00 January 1,1970,Coordinated Universal Time (UTC).

The UNIX System has always differed from other operating systems in (a) keeping time in UTC instead of the local time,(b) automatically handling conversions,such as daylight saving time,and (c) keeping the time and date as a single quantity.
The time function returns the current time and date.

#include <time.h>
time_t time(time_t *calptr);

The time value is always returned as the value of the function. If the argument is non-null,the time value is also stored at the location pointed to by calptr.

The real-time extensions to POSIX.1 added support for multiple system clocks. In Version 4 of the Single UNIX Specification,the interfaces used to control these clocks were moved from an option group to the base.

#include <sys/time.h>
int clock_gettime(clockid_t clock_id,struct timespec *tsp);

When the clock ID is set to CLOCK_REALTIME,the clock_gettime function provides similar functionality to the time function,except with clock_gettime,we might be able to get a higher-resolution time value if the system supports it.

We can use the clock_getres function to determine the resolution of a given system clock.

#include <sys/time.h>
int clock_getres(clockid_t clock_id,struct timespec *tsp);

The clock_getres function initializes the timespec structure pointed to by the tsp argument to the resolution of the clock corresponding to the clock_id argument.

#inlcude <sys//time.h>
int clock_settime(clockid_t clock_id,const struct timespec *tsp);

We can use the clock_getres function to determine the resolution of a given system clock.

#include <sys/time.h>
int clock_getres(clockid_t clock_id,struct timespec *tsp);

To set the time for a particular clock,we can call the clock_settime function

#include <sys/time.h>
int clock_settime(clockid_t clock_id,const struct timespec *tsp);

Historically,on implementations derived from System V,the stime(2) function was called to set the system time,whereas BSD-derived systems used settimeofday(2).

Version 4 of the Single UNIX Specification specifies that the gettimeofday function is now obsolescent. However,a lot of programs still use it,because it provides greater resolution (up to a microsecond) than the time function.

#include <sys/time.h>
int gettimeofday(struct timeval *restrict tp,void *restrict tzp);

The only legal value for tzp is NULL; other values result in unspecified behavior. Some platforms support the specification of a time zone through the use of tzp,but this is implementation specific and not defined by the Single UNIX Specification.

The gettimeofday function stores the current time as measured from the Epoch in the memory pointed to by tp. This time is represented as a timeval structure,which stores seconds and microseconds.

A tm structure:

struct tm
{
    int tm_sec;
    int tm_min;
    int tm_hour;
    int tm_mday;
    int tm_mon;
    int tm_year;
    int tm_wday;
    int tm_yday;
    int tm_isdst;
}

The formal definition of UTC doesn’t allow for double leap seconds,so the valid range for seconds is now 0–60.

#include <time.h>

struct tm *gmtime(const time_t *calptr);
struct tm *localtime(const time_t *calptr);

The difference between localtime and gmtime is that the first converts the calendar time to the local time,taking into account the local time zone and daylight saving time flag,whereas the latter converts the calendar time into a broken-down time expressed as UTC.

相关文章

用的openwrt路由器,家里宽带申请了动态公网ip,为了方便把2...
#!/bin/bashcommand1&command2&wait从Shell脚本并行...
1.先查出MAMP下面集成的PHP版本cd/Applications/MAMP/bin/ph...
1、先输入locale-a,查看一下现在已安装的语言2、若不存在如...
BashPerlTclsyntaxdiff1.进制数表示Languagebinaryoctalhexa...
正常安装了k8s后,使用kubect工具后接的命令不能直接tab补全...