系統正常運行須要使用大量系統數據文件,其中,全部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