?
6?1〓引言?
有很多操作需要使用一些與系統有關的數據文件,例如,口令字文件/etc/passwc
l和組文件
/etc/group就是經常由多種程序使用的兩個文件。用戶每次登錄入Unix系統時,以
及每次執
行ls-l命令時都要使用口令字文件。?
由于歷史原因,這些數據文件都是ASCII文本文件,并且使用標準I/O庫讀這些文件
。但是,
對于較大的系統,順序掃描口令字文件變得很花費時間,我們想以非ASCII文本格
式存放這
些文件,但仍向應用程序提供一個可以處理任何一種文件格式的界面。對于這些數
據文件的
可移植界面是本章的主題。本章也包括了系統標識函數、時間和日期函數。?
6?2〓口令字文件?
Unix口令字文件(POSIX?1則將其稱為用戶數據庫)包含了圖6?1中所示的各字段,
這些字段
包含在<pwd?h>中定義的passwd結構中。?
注意,POSIX?1只指定passwd結構中7個字段中的5個。另外2個元素由SVR4和4?3
+BSD支持
。???P146?
圖6?1〓/etc/passwd文件中的字段?
由于歷史原因,口令字文件是/etc/passwd,而且是一個文本文件。每一行包含圖
6?1中所
示的7個字段,字段之間用冒號相分隔。例如,該文件中可能有下列三行:?
root:jheVopR58x9Fx:0:1:The superuser:/:/bin/sh?
nobody:*:65534:65534::/:?
stevens:3hKVD8R58r9Fx:224:20:Richard Stevens:/home/stevens:/bin/ksh?
關于這些記錄項請注意下列各點:?
·通常有一個記錄項,其用戶名為root。此記錄項的用戶ID是O(超級用戶)。?
·密碼口令字字段包含了經單向密碼單法處理過的用戶口令字副本。因為此算法是
單問的,
所以我們不能從密碼口令字猜測到原來的口令字。當前使用的算法(見Morris和Th
ompson〔
1979〕)總是產生13個可打印字符(在64字符集〔a-zA-Z0-9?1〕中)。因為對
用戶名no
b
ody的記錄的密碼口令字段只包含一個字符(*),所以密碼口令字決不會與此值相匹
配。此用
戶名可用于網絡服務器,這些服務器允許我們登錄到一個系統,但其用戶ID和組I
D(65534)
,并不提供優先權。以此用戶ID和組ID我們可存取的文件只是大家都可讀、寫的文
件。(這
假定用戶ID65534和組ID65534并不擁有任何文件。)在本節稍后部分我們將討論對
口令字文
件最近所作的更改(陰影口令字)。?
·在口令字文件記錄中的某些字段可能是空。如果密碼口令字段為空,這通常就意
味著該用
戶沒有口令字。(不希望這樣做。)nobody記錄有兩個空白字段:注釋字段和初始s
hell字段
??瞻鬃⑨屪侄尾划a生任何影響??瞻譻hell字段則表示取系統默認值,這通常是
/bin/sh。
?
·支持finger(1)命令的某些Unix系統支持在注釋字段中的附加信息。其中,各部
分之間都
用逗號分隔:用戶姓名,辦公室地點,辦公室電話號碼,家庭電話號碼。另外,如
果在注釋
字段中的用戶姓名是一個&,則它被代換為登錄名。例如,可以有下列記錄:??
stevens:3hKVD8R58r9Fx:224:20:Richard &,B232,555-1111,555-2222:/home/ste
vens:/bin
/ksh?
即使你所使用的系統并不支持finger命令,這些信息仍可存放在注釋字段中,因為
該字段只
是一個注釋,并不由系統公用程序解釋。?
POXIX?1只定義了兩個存取口令字文件中信息的函數。在給出用戶登錄名或數值用
戶ID后,
這兩個函數就能查看相關記錄。?
#include <sys/types?h>?
include <pwd?h>?
struct passwd *getpwuid(uid 跡茫模*常病絫 ?uid?);?
struct passwd *getpwnaw(const char *?name?);?
Both return:pointer if OK,NULL on error?
兩個函數反回:看成功為指針,出錯為NULL?
getpwuid由ls(1)程序使用,以便將包含在一個i-node中的數值用戶ID映照為用戶
登錄名。g
etpwnaw在我們鍵入登錄名時由login(1)程序使用。?
這兩個函數都返回一個指向passwd結構的指針,該結構已由這兩個函數在執行時填
入了所需
的信息。此結構通常是在相關函數內的靜態變量,只要調用相關函數,其內容就會
被重寫。
?
如果我們要查看的只是一個登錄名或一個用戶ID,那么這兩個POSIX?1函數是能滿
足要求的
,但是也有些程序要查看整個口令字文件。下列三個函數則可用于此種目的。?
#include <sys/types?h>?
#include <pwd?h>?
struct passwd *getpwent(void);?
Returns:pointer if OK,NULL on error or end of file?
返回:看成功為指針,出錯或文件尾為NULL??
void setpwent(void);?
void endpwent(void);?
POXIX?1沒有定義這三個函數,但它們受到SVR4和4?3+BSD的支持。?
調用getpwent時,它返回口令字文件中的下一個記錄。如同上面所述的兩個POSIX
?1函數一
樣,它返回一個由它填寫好的passwd結構的指針。每次調用此函數時都重寫該結構
。在第一
次調用該函數時,它打開它所使用的各個文件。在使用本函數時,對口令字文件中
各個記錄
安排的順序并無要求。?
函數setpwent反繞它所使用的文件,endpwent則關閉這些文件。在使用getpwent查
看完了口
令字文件后,一定要調用endpwent關閉這些文件。getpwent知道什么時間它應當打
開它所使
用的文件(第一次被調用時),但是它并不能知道何時關閉這些文件。?
實例?
程序6?1示出了函數getpwnam的一個實現。?
程序6?1〓getpwent函數?
P148?
在程序開始處調用setpwent是保護性的措施,以便在調用者在此之前已經調用過g
etpwent的
情況下,反繞有關文件使它們定位到文件開始處。getpwnaw和getpwuid完成后不應
使有關文
件仍處于打開狀態,所以應調用endpwent關閉它們。?
6?3〓陰影口令字(Shadow Passwords)?
在上面一節我們曾提及,對Unix口令字通常使用的密碼算法是單向算法。給出一個
密碼口令
字,我們找不到一種算法可以將其反變換到普通文本口令字。(普通文本口令字是
在Passwor
d:提示后鍵入的口令字。)但是我們可以對口令字進行猜測,將猜測的口令字經單
向算法變
換成密碼形成,然后將其與用戶的密碼口令字相比較。如果用戶口令字是隨機選擇
的,那么
這種方法并不是很有用的。但是用戶往往以非隨機方式選擇口令字(對偶的姓名、
街名、寵
物名等)。一個經常重復的試驗是先得到一份口令字文件,然后用試探方法猜測口
令字。(Ga
rfinkel和Spaftord〔1991〕的第二章對Unix口令字及口令字密碼處理方案的
歷史情況
及細節進行了說明。)?
為使企圖這樣做的人難以獲得原始資料(密碼口令字),某些系統將密碼口令字存放
在另一個
通常稱為陰影口令字文件中。該文件至少要包含用戶名和密碼口令字。與該口令字
相關的其
它信息也可存放在該文件中。例如,具有陰影口令字的系統經常要求用戶在一定時
間間隔后
選擇一個新口令字。這被稱之為口令字時效,要選擇新口令字的時間間隔長度經常
也存放在
陰影口令字文件中。?
在SVR4中,陰影口令文件是/etc/shadow。在4?3+BSD中,密碼口令字存放在/etc
/master?
passwd中。?
陰影口令字文件不應是一般用戶可以讀取的。僅有少數幾個程序需要存取密碼口令
字文件,
例如login(1)和passwd(1),這些程序常常是設置-用戶-ID為root。有了陰影口令
字后,普
通口令字文件/etc/passwd可由各用戶自由讀取。?
6?4〓組文件?
Unix組文件(POSIX?1稱其為組數據庫)包含了圖6?2中所示字段。這些字段包含在
<grp?h>
中所定義的group結構中。??
P149???
圖6?2〓/etc/group文件中的字段?
POSIX?1只定義了其中3個字段。另一個字段gr 跡茫模*常病絧asswd則由SVR4和
4?3+BSD
支持。?
字段gr-mem是一個指針數組,其中的指針各指向一個屬于該組的用戶名。該數組以
空指針(n
ull)結尾。?
我們可以用下列兩個由posix?1定義的函數來查看組名或數值組I。?
#include <sys/types?h>?
#include <grp?h>?
struct group *getgrgid(gid 跡茫模*常病絫 ?gid?);?
struct group *getgrnam(const char *?name?);?
Both return:pointer if OK,NULL on error兩個函數返回:若成功為指針,出錯
為NULL?
如同對口令字文件進行操作的函數一樣,這兩個函數通常也返回指向一個靜態變量
的指針,
在每次調用時都重寫該靜態變量。?
如果需要搜索整個組文件,則須使用另外幾個函數。下列三個函數類似于針對口令
字文件的
三個函數。?
#include <sys/types?h>?
#include <grp?h>?
struct group *getgrent(void);?
Returns:Pointer if OK,NULL on error or end of file?
返回:若成功為指針,出錯或文件尾為NULL?
void setgrent(void);?
void endgrent(void);?
這三個函數由SVR4和4?3+BSD提供POSIX?1并末定義這些函數。?
setgrent打開組文件(如若它尚末被打開)并反繞它。getgrent從組文件中讀下一個
記錄,如
若該文件尚末打開則先打開它。endgrent關閉組文件。?
6?5〓添加組ID?
在Unix中,組的使用已經作了些更改。在Version7中,每個用戶任何時候都只屬于
一個組。
當用戶登錄時,系統就按口令字文件中與其相關記錄中的數字組ID,賦給他實際組
ID。我們
可以在任何時候執行newgrp(1)以更改組ID。如果newgrp命令執行成功(關于許可權
規則,請
參閱手冊頁。),則我們的實際組ID就更改為新的組ID,它將被用于后續的文件存
取許可權
檢查。執行不帶任何參數的newgrp,則可返回到原來的組。?
這種組的成員關系一直維持到1983年左右。此時,4?2BSD引入了添加組ID的概念
。我們不
僅屬于我們的口令字記錄中組ID所對應的組,也可屬于多至16個另外的一些組。文
件存取權
檢查相應修改為:不僅將進程的有效組ID與文件的組ID相比較,而且也將所有添加
組ID與文
件的組ID進行比較。?
添加組ID是POSIX?1的可選特性。常數NGROUPS 跡茫模*常病組AX(圖2?7)規定了
添加組ID
的數量,其常用值是16。如果不支持添加組ID,則此常數值為O。?
SVR4和4?3+BSD都支持添加組ID。?
FIPS 151-1要求支持添加組ID,并要求NGROUP 跡茫模*常病組AX至少是8。?
使用添加組ID的優點是我們不必再顯式地經常更改組。一個用戶常常會參加多個項
目組,因
此也就要同時屬于多個組。?
為了存取和設置添加組ID提供了下列三個函數:?
POSIX?1只說明了getgroups。因為setgroups和initgroups是特權操作,所以Pos
ix?1沒有
說明它們。但是,SVR4和4?3+BSD支持所有這三個函數。?
getgroups將進程所屬用戶的各添加組ID填寫到數組bgrouplist中,填寫入該數組
的添加組I
D數最多為gidsetsize個。實際填寫到數組中的添加組ID數由函數返回。如果系統
常數NGROU
P 跡茫模*常病組AX為0,則返回0,這并不表示出錯。?
#include <sys/types?h>?
#include <unistd?h>?
int getgroups(int ?gidsetsize?,gid 跡茫模*常病絫 ?grouplist?[]);
?
Returns:number of supplementary group IDs if OK,-1 on error?
int setgroups(int? ngroups,?const gid 跡茫模*常病絫 ?grouplist?[]
);?
int initgroups(const char *?username,?gid 跡茫模*常病絫? basegid);?
?
兩個函數返回:若成功為0,出錯為-1?
Both return:0 if OK,-1 on error?
作為一種特殊情況,如若giclsetsize為0,則函數只返回添加組ID數,而對數組g
rouplist
則不作修改。(這使調用者可以確定grouplist數組的長度,以便進行分配。)?
setgroups可由超級用戶調用以便為調用進程設置添加組ID表。grouplist,是組I
D數組,而
ngroups說明了數組中的元素數。?
通常,只有initgroups函數調用setgroups,initgroups讀整個組文件(用函數getg
rent,setg
rent和endgrent),然后對username確定其組的成員關系。然后,它調用setgroup
s,以便為
該用戶初始化添加組ID表。因為initgroups調用setgroups,所以只有超級用戶才能
調用init
groups。除了在組文件中找到username是成員的組,initgroups也在添加組ID表中
包括了ba
segid。basegid是username在口令字文件中的組ID。?
initgroups只有少數幾個程序調用,例如login(1)程序在用戶登錄時調用該函數。
?
6?6〓其它數據文件?
至此我們討論了兩個系統數據文件-口令字文件和組文件。在日常事務操作中,Un
ix系統還
使用很多其它文件。例如,BSD網絡軟件有一個記錄各網絡服務器所提供的服務的
數據文件(
/etc/services),有一個記錄協議信息是數據文件(/etc/protocols),還有一個則
是記錄網
絡信息的數據文件(/etc.networks)。幸運的是,對于這些數據文件的界面都與上
述對口令
字文件和組文件的相似。?
一般原理是,每個數據文件至少有三個函數:?
1? get函數;讀下一個記錄,如果需要還打開該文件。此種函數通常返回指向一
個結構的
指針。當已達到文件尾端時返回空指針。大多數get函數返回指向一個靜態存儲類
結構的指
針,如果要保存其內容,則需復制它。?
2? set函數:打開相應數據文件(如果尚末打開),然后反繞該文件。如果希望在
相應文件
起始處開始處理,則調用此函數。?
3? end函數:關閉相應數據文件。正如前述,在結束了對相應數據文件的讀、寫
操作后,
總應調用此函數以關閉所有相關文件。?
另外,如果數據文件支持某種形式的關鍵字搜尋,則也提供搜尋具有指定關鍵字的
記錄的例
程。例如,對于口令字文件提供了兩個按關鍵字進行搜尋的程序:getpwnam尋找具
有指定用
戶名的記錄;getpwuid尋找具有指定用戶ID的記錄。?
圖6?3中列出了一些這樣的例程,這些都是SVR4和4?3+BSD支持的。在圖中列出了
針對口令
字文件和組文件的函數,這些已在上面說明過。圖中也列出了一些與網絡有關的函
數。對圖
中列出的所有數據文件都有get、set和end函數。?
在SVR4中,圖6?3中最后四個數據文件都是符號連接,連接到目錄/e6tc/inet下的
同名文件
上。?
SVR4和4?3+BSD都有類似于圖中所列的附加函數,但是這些附加函數都處理系統管
理文件,
專用于各個實現。?
P153???
圖6?3〓存取系統數據文件的一些例程?
6?7〓登錄會計?
大多數Unix系統都提供下列兩個數據文件:utmp文件,它記錄當前登錄進系統的各
個用戶;
wtmp文件,它跟蹤各個登錄和注銷事件。?
在Version7中,一個包含下列結構的二進制記錄寫入這兩個文件中:?
struct utmp {?
char ut 跡茫模*常病絣ine[8]; /* tty 行:"ttyh0","ttyd0","ttyp0",… *
/?
char ut 跡茫模*常病絥ame[8]; /*登錄名 */?
long ut 跡茫模*常病絫ime; /*公元秒數 */?
};?
在登錄時,login程序填寫這樣的一個結構,然后將其寫入到utmp文件中,同時也
將其添寫
到wtmp文件中。在注銷時,init進程在utmp文件中的相應記錄擦除(每個字節都填
以0),并
將一個新記錄添寫到wtmp文件中。讀wtmp文件中的該注銷記錄,其ut 跡茫模*常?nbsp;
〗name字
段清除為0。在
系統再啟動時,以及更改系統時間和日期的前后,都在wtmp文件中添寫特殊的記錄
項。who(
1)程序讀utmp文件,并以可讀格式打印其內容。后來的Unix版本提供last(1)命令
,它讀wtm
p文件并打印所選擇的記錄。?
大多數Unix版本仍提供utmp和wtmp文件,但在這些文件中的信息量卻增加了。ver
sion 7中2
0字節的結構在SVR2中已擴充為36字節,而在SVR4中,utmp結構已擴充為350字節。
?
SVR4中,這些記錄的詳細格式請參見手冊頁utmp(4)和utmpx(4)。在SVR4中,這兩
個文件都
在目錄/var/adm中。SVR4提供了很多函數(見getut(3)和getutx(3))讀、寫這兩個
文件。?
4?3+BSD中,登錄記錄的格式請參見手冊頁utmp(5)。這兩個文件的路徑名是/var
/run/utmp
和/var/log/wtmp。?
6?8〓系統標識?
POSIX?1定義了uname函數,它返回與宿主機和操作系統有關的信息。?
#include <sys/utsname?h>?
int uname(struct utsname *?name?;?
Returns:nonnegative value if OK,-1 on error 返回:若成功為非負值,出錯為
-1?
通過該函數的參數向其傳遞一個utsname結構的地址,然后該函數填寫此結構。PO
SIX?1只
定義了該結構中最少需要的字段(它們都是字符數組),而每個數組的長度則由實現
確定。某
些實現在該結構中提供了另外一些字段。在歷史上,系統V為每個數組分配9個字節
,其中有
1個字節用于字符串結束符(null字符)。?
struct utsname {?
char sysname[9]; /*name of the operating system */操作系統名?
char nodename[9]; /* name of this node */ 此節點名?
char release[9]; /*current release of operating system */操作系統當前
發行版?
char version[9]; /*current version of this release */此發行版的當前版
?
char machine[9]; /*name of hardware type */硬件類型名?
};?
在utsname結構中的信息通??捎胾name(1)命令打印。?
POSIX?1警告:nodename元素可能并不適用于在一通信網絡上引用宿主機。此函數
來自于系
統V,在較早時期,nodename元素適用于在UUCP網絡上引用主機。?
也應理解在此結構中并沒有給出有關POSIX?1版本的信息。這應當使用2?5?2節
中所說明
的 跡茫模*常病絇OSIX 跡茫模*常病絍ERSION以獲得該信息。最后,此函數給出
了一種存
取該結構中信息的方法,至于
如何初始化這些信息,POSIX?1沒有作任何說明。大多數系統V版本在構造系統核
時通過編
譯將這些信息存放在系統核中。?
貝克萊類的版本提供gethostname函數,它只返回宿主機名。這通常就是在TCP/IP
網上該宿
主機的名字。??
#include <unistd?h>?
int gethostname(char *?name,?int ?namelen);??
Returns:0 if OK,-1 on error返回:若成功為0,出錯為-1?
通過name返回的字符串以null符結尾(除非沒有提供足夠的空間)。<sys/param?h
>中的常數
MAXHOSTNAMELEN規定了此名字的最大長度(通常是64字節)。如果該宿主機聯到TCP
/IP網,則
此宿主機名通常是該宿主機的完整的域名。?
hostname(1)命令可用來存取和設置宿主機名。(超級用戶用一個類似的函數setho
stname來
設置宿主機名。)宿主機名通常在系統自舉時設置,它由/etc/rc取自一個啟動文件
。?
雖然此函數是貝克萊所特有的,但是,SVR4作為BSD兼容性軟件包的一部分提供ge
tbostname
和setbostname函數,以及hostname命令。SVR4也將MAXHOSTNAMELEN擴充為256字節
。?
6?9〓時間和日期例程?
由Unix系統核提供的基本時間服務是國際標準時公元1970?1?1 00:00:00以來
經過的秒
數。在1?10節中曾提及這種秒數是以數據類型time-t表示的。我們稱它們為日歷
時間。日
歷時間包括時間和日期。Unix在這方面與其它操作系統的區別是(a)以國際標準時
而非本地
時間計時,(b)可自動進行轉換,例如變換到夏日制,(c)將時間和日期作為一個量
值保存。
time函數返回當前時間和日期。?
#include <time?h>?
time 跡茫模*常病絫 time(time 跡茫模*常病絫 *?calptr);??
Returns:value of time if OK,-1 on error 返回:若成功為時間值,出錯為-1?
時間值作為函數值返回。如果參數是非null,則時間值也存放在由calptr指向的單
元內。?
在很多貝克萊類的系統中,time(3)只是一個函數,它調用gettime of day(2)系統
調用。?
在SVR4中調用stime(2)函數,在貝克萊類的系統中調用settime of day(2)對系統
核中的當
前時間設置初始值。?
與time和stime函數相比,BSD的gettime of day和settime of day提供了更高的分
辨率(微
秒級)。這對某些應用是很重要的。?
一旦取得這種以秒計的很大的時間值后,通常要調用另一個時間函數將其變換為人
們可讀的
時間和日期。圖6?4說明了各種時間函數之間的關系。(圖中以虛線表示的四個函
數localti
me、mktime、ctime和strftime都受到環境變量TZ的影響。我們將在本節的最后部
分對其進
行說明。)?
P156???
圖6?4〓各個時間函數之間的關系?
兩個函數localtime和gmtime將日歷時間變換成以年、月、日、時、分、秒、周日
表示的時
間,將這些存放在一個tm結構中。?
struct tm { /* a broken-down time */ 以年、月、日、時、分、秒表示的時間
?
int tm 跡茫模*常病絪ec; /* seconds after the minute:[0,61] */秒[0
,61]
?int tm 跡茫模*常病絤in; /* minutes after the hour:[0,59] */分[0
,59]
?int tm 跡茫模*常病絟our; /* hours after midnight:[0,23] */時[0,
23]?
int tm 跡茫模*常病絤day; /* day of the month:[1,31] */日[1,31]
?
int tm 跡茫模*常病絤on; /* month of the year:[0,11] */月[0,11]
?
int tm 跡茫模*常病統ear; /* years since 1900 */ 1900后的年?
int tm 跡茫模*常病絯day; /* days since Sunday:[0,6] */①星期幾[0,
6]?
int tm 跡茫模*常病統day; /* days since January 1:[0,365] */②自1月1日
經過的天
數[0,365]?
int tm 跡茫模*常病絠sdst; /* daylight saving time flag:<0,0,>0 */③夏日
制時間標
志:<0,0,>0?
};?
秒可以超過59的理由是可以表示潤秒。注意,除了月日字段,其它字段的值都以0
開始。如
果夏日制生效,則夏日制標志值為正,如果已非夏日制時間則為零,如果此信息不
可用,則
為負。?
#include <time?h>?
struct tm *gmtime(const time 跡茫模*常病健t—?calptr);??
struct tm *localtime(const time 跡茫模*常病絫 ?*calptr);??
Both return:pointer to broken-down time?
兩個函數返回:指向tm結構的指針?
localtime和gmtime之間的區別是:localtime將日歷時間變換成本地時間(考慮到本
地時區和
夏日制標志),而gmtime則將日歷時間變換成國際標準時的年、月、日、時、分、
秒、周日
。?
函數mktime以本地時間的年、月、日等作為參數,將其變換成time-t值。?
#include <time?h>?
time 跡茫模*常病絫 mktime(struct tm *?tmptr);? 返回:若成功為日歷時間
,出錯為
-1?
asctime和ctime函數產生下列形式的26字節字符串,這與date(1)命令的系統默認
輸出形式
類似:??
Tue Jan 14 17:49:03 1992\n\0?
#include <time?h>?
char *asctime(const struct tm *?tmptr);??
char *ctime(const time 跡茫模*常病絫 *?calptr);??
兩個函數返回:指向null結尾的字符串?
asctime的參數是指向年、月、日等字符串的指針,而ctime的參數則是指向日歷時
間的指針
。?
最后一個時間函數是strftime,它是非常復雜的printf類的時間值函數。?
#include <time?h>?
size 跡茫模*常病絫 strftime(char *?buf,?size 跡茫模*常病絫 maxsize,
const cha
r *?format,??
const struct tm *?tmptr);? 返回:若有空間為存入數組的字符數,否則為0?
最后一個參數是要格式化的時間值,說明為指向一個年、月、日、時、分、秒、周
日時間值
的指針。格式化結果存放在一個長度為maxsize個字符的buf數組中,如果buf長度
是以存放
格式化結果及一個null絡止符,則該函數返回在buf中存放的字符數(不包括null終
止符)。
否則該函數返回0。?
format參數控制時間值的格式。如同printf函數一樣,變換說明的形式是百分號之
后跟一個
特定字符。在format中的其它字符則按原擇輸出。兩個連續的百分號在輸出中產生
一個百分
號。與printf函數的不同之處是,每個變換說明產生一個定長輸出字符串,在for
mat字符串
中沒有字段磯刃奘畏?M??5中列出了21種ANSIC規定的變換說明。?
P158???
圖6?5〓strftime?
圖中第三列的數據來自于在SVR4上,對應于下列時間和日期,執行strftime函數所
得的結果
。?
Tue〓Jan〓14〓19:40〓MST〓1992?
圖6?5中的大多數格式說明的意義是很明顯的。需要略作解釋的是%U和%W。%U是相
應日期在
該年中所屬因數,包含該年中第一個星期日的周是第一周。%W也是相應日期在該年
中所屬的
周數,不同的是包含第一個星期一的周為第一周。?
SVR4和4?3+BSD都對strftime的格式字符串提供另一些擴充支持。?
我們曾在前面提及,圖6?4中以虛線表示的四個函數受到環境變量TZ的影響。這四
個函數是
:localtime,mktime,ctime和strftime。如果定義了TZ,則這些函數將使用其值以
代替系統
默認時區。如果TZ定義為空串(亦即TZ=),則使用國際標準時。TZ的值常常類似于
TZ=EST5ED
T,但是POSIX?1允許更詳細的說明。有關TZ的詳細情況請參閱POSIX?1標準[IE
EE 1990]
的8?1?1節,SVR4 environ(5)手冊頁[A T&T 1990e],或4?3+BSD ctime(3)手
冊頁。?
本節所述的所有時間和日期函數都是由ANSIC標準定義的。在此基礎上,POSIX?1
只增加了
環境變量TZ。?
圖6?4中七個函數中的五個可以回溯到Version7(或更早),它們是:time、local
time、gmt
ime、asctime和ctime。在Unix時間功能方面近期所作的增加大多是處理非US時區
以及夏日
制的更改規則。?
6?10〓摘要?
在所有Unix系統上都使用口令字文件和組文件。我們說明了各種讀這些文件的函數
。我們也
介紹了陰影口令字,它可以增加系統的安全性。添加組ID正在得到更多應用,它提
供了一個
用戶同時可以參辦多個組的方法。我們也介紹了大多數系統所提供的存取其它與系
統有關的
數據文件的類似的函數。最后,我們說明了ANSIC和POSIX?1提供的與時間和日期
有關的一些函數?!迹蹋汀?/TD>