[APUE]系統數據文件和信息

  系統正常運行須要使用大量系統數據文件,其中,全部UNIX系統都有的是:口令文件、組文件,大多數系統都提供的是:登陸帳戶記錄、系統標識、時間和日期例程,同時還有其餘一些經常使用系統數據文件如:BSD網絡軟件有一個記錄各網絡服務器所提供服務的數據文件(/etc/services)、記錄協議住處的數據文件(etc/protocols)等。html

  一、口令文件node

  口令文件包括瞭如下字段,這些字段包含在<pwd.h>中定義的passwd結構中:shell

struct passwd數組

服務器

  char*  pw_name;          //用戶名網絡

  char*  pw_passwd;    //加密口令函數

  uid_t  pw_uid;              //數值用戶IDui

  gid_t  pw_gid;              //數值組IDthis

  char*  pw_gecos;          //註釋字段加密

  char*  pw_dir;               //初始工做目錄

  char*  pw_shell;            //初始shell(用戶程序)

  char*  pw_class;            //用戶訪問類

  time_t  pw_change;        //下次更改口令時間

  time_t  pw_expire;          //帳戶有效期時間

};

(1)POSIX.1只定義了兩個獲取口令文件相的函數。在給出用戶登陸名或者數值用戶ID,這兩個函數容許咱們經過查找相關項

#include <pwd.h>

struct passwd *getpwuid(uid_t uid); struct passwd *getpwnam(const char *name); //二者成功都返回指針,失敗返回NULL

getpwuid函數被ls程序使用,它將i節點中的數值用戶ID數值映射到一個用戶登陸名,在鍵入登陸名時候,getpwnam函數被login(1)函數使用。

(2)如下三個函數能夠用於程序查看整個口令文件

複製代碼
#include <pwd.h>

struct passwd *getpwent(void); //成功返回指針,失敗或文件結尾返回NULL。 void setpwent(void); void endpwent(void);
複製代碼

調用getpwent時,它返回口令文件中下一個記錄項,函數setpwent反繞它所使用的文件,endpwent則關閉這些文件,在使用getpwent查看完口令文件後,必定要調用endpwent關閉這些文件。

  二、陰影口令

  爲了更難獲取原始資料(加密口令),某些系統把加密密碼存在另外一個一般被稱爲影子密碼的文件中,該文件最少必須包含用戶名和加密密碼。其它密碼相關的信息一樣也存在該文件,看下錶:

文件/etc/shadow的域
描述 結構體spwd成員
用戶登陸名 char *sp_namp
加密密碼 char *sp_pwdp
最後修改密碼的自Epoch的天數 int sp_lstchg
直到改變容許的天數 int sp_min
須要改變以前的天數 int sp_max
警告密碼到期的天數 int sp_warn
賬號失效前的天數 int sp_inact
賬號過時的自Epoch距今的天數 int sp_expire
保留 unsigned int sp_flag

與訪問口令文件的一組函數相似,有另外一組函數可用於訪問陰影口令文件

與訪問口令文件的一組函數相似,有另外一組函數可用於訪問陰影口令文件

複製代碼
#include <shadow.h>

struct spwd *getspnam(const char *name); struct spwd *getspent(void); //二者成功時都返回指針,不然返回NULL。 void setspent(void); void endspent(void);
複製代碼

 

3.組文件

1).能夠用下面由POSIX.1定義的兩個函數查看組名或組ID

#include <grp.h>

struct group *getgrgid(gid_t gid); struct group *getgrnam(const char *name); //二者成功都返回指針,不然返回NULL。

和口令文件函數同樣,這兩個函數一般都返回一個靜態變量的指針,每次調用時都被重寫該靜態變量。

2).若是須要查找整個組文件,則須要使用另外幾個函數,如下三個函數相似於針對口令文件的三個函數:

複製代碼
#include <grp.h>

struct group *getgrent(void); //成功返回指針,失敗或文件尾返回NULL。 void setgrent(void); void endgrent(void);
複製代碼

 

4.附加組ID

 使用附加組ID的好處是咱們再也不須要顯式地改變組

複製代碼
#include <unistd.h>

int getgroups(int gidsetsize, gid_t grouplist[]); //成功返回補充組ID的數量,錯誤返回-1。  #inlcude <grp.h> /* on Linux */ #inlcude <unistd.h> /* on FreeBSD, Mac OS X, and Solaris */ int setgroups(int ngroups, const gid_t grouplist[]); #inlcude <grp.h> /* on Linux and Solaris */ #inlcude <unistd.h> /* on FreeBSD and Mac OS X */ int initgroups(const char *username, gid_t basegid); //二者成功都返回0,不然返回-1。
複製代碼

 

5.其餘數據文件

對於每一個數據文件有至少三個函數

1).get函數,讀取下一個記錄,必要時打開這個文件。這些函數一般返回一個結構體的指針。當到達文件尾時一個空指針被返回。多數get函數返回一個靜態結構體的指針,因此咱們若是想保存它則老是須要拷貝它。

2).set函數,若是文件沒打開的話打開這個文件,並回退這個文件。這個函數在咱們知道咱們想從文件開頭從新開始時被使用。

3).end項,關閉數據文件。正如咱們早先提到的,咱們老是須要在完成工做時調用它,來關閉全部的文件。

下面表裏有全部數據文件的get、set和end函數:

訪問系統數據文件的相似函數
描述 數據文件 頭文件 結構體 補充的關鍵字查找函數
密碼 /etc/passwd <pwd.h> passwd getpwnam, getpwuid
/etc/group <grp.h> group getgrnam, getgrgid
影子 /etc/shadow <shadow.h> spwd getspanam
主機 /etc/hosts/ <netdb.h> hostent gethostbyname, gethostbyaddr
網絡 /etc/networks <netdb.h> netent getnetbyname, getnetbyaddr
協議 /etc/protocols <netdb.h> protoent getprotobyname, getprotobynumber
服務 /etc/services <netdb.h> servent getservbyname, getservbyport

 

6.登錄帳戶記錄

大多數UNIX系統提供的兩個數據文件是:utmp文件,它記錄當前登陸系統的各個用戶;wtmp文件,它記錄全部的登錄與註銷事件。在V7,一個記錄類型被這兩個文件寫,一個與下面結構體一致的二進制記錄

struct utmp { char ut_line[8]; /* tty line: "tyh0", "ttyd0", "ttyp0", ... */ char ut_name[8]; /* login name */ long ut_time; /* seconds since Epoch */ }; 

 

7.系統標識

1).POSIX.1定義了uname函數,它返回當前主機和操做系統的有關信息 

#include <sys/utsname.h>

int uname(struct utsname *name); //成功返回非負值,失敗返回-1。

一個utsname結構體:

複製代碼
struct utsname { char sysname[]; /* name of the operating system */ char nodename[]; /* name of hits node */ char release[]; /* current release of operating system */ char version[]; /* current version of this release */ char machine[]; /* name of hardware type */ }; 
複製代碼

 

2).基於BSD的系統提供了gethostname函數來只返回主機的名字。這個名字一般是在TCP/IP網絡上的主機名。

#include <unistd.h>

int gethostname(char *name, int namelen); //成功返回0,失敗返回-1。

namelen參數指定了name緩衝的長度。如提供了足夠的空間,返回的字符串以null結尾。若是沒有提供足夠的空間,沒有指定這個字符串是否以null結尾。

 

8.時間和日期例程

1).time函數返回當前的時間和日期。

#include <time.h>

time_t time(time_t *calptr); //成功返回時間值,錯誤返回-1。

 

2).gettimeofday函數提供了比time函數更好的精度(精確到微秒)

#include <sys/time.h>

int gettimeofday(struct timeval *restrict tp, void *restrict tzp); //返回值:老是返回0。

 timeval結構體

struct timeval { time_t tv_sec; /* seconds */ long tv_usec; /* microseconds */ };

 

3).localtime和gmtime

#include <time.h>

struct tm *gmtime(const time_t *calptr); struct tm *localtime(const time_t *calptr); //二者都返回分解時間的指針。

localtime和gmtime這兩個函數把日曆時間轉換了一個被稱爲分解時間(broken-down time)的一個結構體tm:

複製代碼
struct tm {  /* a broken-down time */ int tm_sec; /* seconds after the minute: [0 - 60] */ int tm_min; /* minutes after the hour: [0-59] */ int tm_hour; /* hours after midnight:[0-23] */ int tm_mday; /* day of the month: [1-31] */ int tm_mon; /* months since January: [0-11] */ int tm_year; /* years since 1900 */ int tm_wday; /* days since sunday: [0-6] */ int tm_yday; /* days since January 1: [0-365] */ int tm_isdst; /* daylight saving time flag: <0, 0, >0 */ }; 
複製代碼

localtime和gmtime的區別在於第一個把日曆時間轉換爲本地時間,根據時區和夏令時標誌,然後者把日曆時間轉換成一個表示爲UTC的分解時間

 

4).函數mktime接受一個表示爲本地時間的分解時間,並把它轉換成一個time_t值

#include <time.h>

time_t mktime(struct tm *tmptr); //成功返回日曆時間,錯誤返回-1

 

5).asctime和ctime函數生產熟悉的26字節字符串

#include <time.h>

char *asctime(const struct tm *tmptr); char *ctime(const time_t *calptr); //二者都返回以null結尾的字符串。

 

6).strftime,是最複雜的。它是一個對於時間值相似於printf的函數

#include <time.h>

size_t strftime(char *restrict buf, size_t maxsize, const char *restrict format, const struct tm *restrict tmptr); //若是空間足夠返回存儲在數組裏的字符數,不然返回0。

最後的參數是格式所需的時間值,由一個分解時間值的指針指定。格式化的結構存儲在尺寸爲maxsize的buf數組裏。若是包括終止null的結果的尺寸,能夠放入這個緩衝,那麼函數返回在buf裏存儲的字符數,不包括終止null。不然,該函數返回0。

 

轉自:http://www.cnblogs.com/biyeymyhjob/archive/2012/08/03/2621445.html

相關文章
相關標籤/搜索