Linux下who命令的實現

2021-10-02 19:06:31 字數 4420 閱讀 6069

linux系統的正常運作需要使用大量與系統有關的資料檔案,例如,口令檔案/etc/passwd和組檔案/etc/group就是經常被多個程式頻繁使用的兩個檔案。使用者每次登陸 linux系統,以及每次執行ls -l命令時都要使用口令檔案。本實驗中的程式就是這樣乙個需要呼叫系統資料檔案的程式,只不過呼叫的是/var/run/utmp(記錄機器的啟動時間以及當前登陸使用者)和/var/log/wtmp檔案。由於歷史原因,這些資料檔案都是 ascii 文字檔案,並且使用標準 i/o 庫讀這些檔案。但是,對於較大的系統,順序掃瞄口令檔案很花費時間,我們需要能夠以非 ascii 文字格式存放這些檔案,但仍向使用其他文字格式的應用程式提供介面。對於這些資料檔案的可移植性介面的使用是本次實驗的主題。

2.1 who命令介紹

who命令的作用是顯示目前登入系統的使用者資訊。執行who命令可得知目前有那些使用者登入系統,單獨執行who命令會列出登入帳號、使用的終端機、登入時間以及從何處登入或正在使用哪個顯示器。

2.2 引數說明

who-h或–heading:顯示各字段的標題資訊列;

who-q–count:只顯示登入系統的帳號名稱和總人數。

2.3 utmp 和 wtmp 檔案概述

linux 系統維護著兩個包含與使用者登入和登出系統有關的資訊的資料檔案。

2.4 實現原理

讀取utmp檔案的內容,然後顯示記錄,最後關閉utmp。實際上就是乙個「開啟檔案——儲存檔案id——根據檔案id讀取使用者登陸資訊——顯示在終端 」的過程。

3.1 main函式

main 函式的主要作用是接收命令列傳過來的引數,然後根據不同的引數標記不同的變數,以便 mywho()函式能夠根據這些標記的變數分類處理。

main函式裡主要涉及到 getopt()這個函式。該函式的定義如下(摘錄自《linux/unix系統程式設計手冊》一書》):

getopt()是乙個標準庫函式,我們可以通過連續呼叫getopt()來解析命令列。每次呼叫都會返回下乙個未處理選項的資訊。如果找到了選項,那麼代表該選項的字元就作為函式結果返回。如果到達了選項列表的結尾,getopt()就返回−1。每次呼叫 getopt()時,全域性變數optind都會得到更新,其中包含著引數列表ar**中未處理的下乙個元素的索引。在首次呼叫 getopt()之前,變數 optind 會自動設為 1(因為ar**[0]表示的是程式名,所以argc起始的值為1,且命令列選項是從ar**[1]開始算起的)。若檢索完所有選項後 argc 不等於 optind,說明存在錯誤的選項。

main函式**如下:

int

main

(int argc,

char

*ar**)

}//命令列檢錯

if(argc != optind)

printf

("fault commend rose!\n");

//呼叫mywho程式,並檢查是否正常執行

run =

mywho()

;if(!run)

exit

(exit_success)

;else

exit(1);}

3.2 設計mywho函式

3.2.1 -q引數解析

-q引數的原理為:先讀取 utmp 檔案的資料, 過濾出utmpx結構ut_type欄位為user_process的記錄,然後計數。

while

((ut =

getutxent()

)printf

("\n# users=%d\n"

, users)

;

3.2.2 -h 引數解析

-h選項用於列印輸出的各列的含義:

if

(opt_h)

printf

("%-12s%-12s%-20.20s %s\n"

,"name"

,"line"

,"time"

,"comment"

);

3.2.3 不帶任何選項解析

不帶任何選項用於分別讀取 utmp 檔案關於使用者登陸的資訊。這裡重點介紹一下timeval結構體和strftime()函式。

maxsize引數指定 outstr 的最大長度。

如果轉化成功,strftime()返回 outstr 所指緩衝區的位元組長度,且不包括終止空位元組。如果結果字串的總長度(含終止空位元組)超過了 maxsize 引數,那麼 strftime()會返回 0 以示出錯,且此時無法確定 outstr 的內容。

這部分的**如下:

while

((ut =

getutxent()

))endutxent()

;exit

(exit_success)

;

3.2.4 mywho()函式彙總

mywho()函式整合了上面幾段**。首先呼叫系統資料檔案的介面函式,然後逐條將其資料儲存下來,再根據選項的標記輸出不同的資訊,最後關閉系統資料檔案。**如下:

static

intmywho()

printf

("\n# users=%d\n"

, users)

;// 關閉檔案

endutxent()

;exit

(exit_success);}

//列印各欄標題頭部

if(is_h)

printf

("%-12s%-12s%-20.20s %s\n"

,"name"

,"line"

,"time"

,"comment");

//不帶選項的設計

while

((ut =

getutxent()

))endutxent()

;exit

(exit_success)

;}

將上述所有**塊彙總成who.c檔案。完整**如下:

#include

#include

#include

#include

#include

#include

#include

//設定標誌位,標識命令列引數,預設不使用,設為false

bool is_h = false;

bool is_q = false;

static

intmywho()

printf

("\n# users=%d\n"

, users)

;// 關閉檔案

endutxent()

;exit

(exit_success);}

//列印各欄標題頭部

if(is_h)

printf

("%-12s%-12s%-20.20s %s\n"

,"name"

,"line"

,"time"

,"comment");

//不帶選項的設計

while

((ut =

getutxent()

))endutxent()

;exit

(exit_success);}

intmain

(int argc,

char

*ar**)

}//命令列檢錯

if(argc != optind)

printf

("fault command!\n");

//呼叫mywho程式,並檢查是否正常執行

Linux命令實現(1) who

想學linux c程式設計 借來的書都千篇一律 都是從讀寫檔案到程序通訊和socket 感覺沒有vc的書豐富 學起來也很枯燥 終於借到一本帶例項的書 understanding unix linux programming a guide to theroy and practice 一本在例項裡教...

Linux基礎命令 who

常用工具命令 who命令是顯示目前登入系統的使用者資訊。執行who命令可得知目前有那些使用者登入系統,單獨執行who命令會列出登入帳號,使用的終端機,登入時間以及從何處登入或正在使用哪個x顯示器。who 選項 引數 選項 h或 heading 顯示各字段的標題資訊列 i或 u或 idle 顯示閒置時...

Linux下 使用C語言編寫who命令

在linux 下 who命令是查詢當前登入的每個使用者。who的預設輸出包括使用者名稱 終端型別 登入日期及遠端主機。如圖 我們man一下who,在聯機幫助裡可以看到,who命令是讀取 var run utmp檔案來得到以上資訊的。我們在man一下utmp,知道utmp這個檔案,是二進位制檔案,裡面...