Linux下編寫Who命令
阿新 • • 發佈:2018-11-03
Who命令可以顯示登入系統的使用者資訊。
1、檢視who命令相關內容
通過聯機手冊,可以查詢到who命令的詳解。在終端輸入man who,在Ubuntu 14.04 系統上,在DESCRIPTION可以看到如下所示的內容。
即登入的資訊是放在/var/run/utmp 、/var/log/wtmp中,執行who命令後,從utmp檔案中讀取資訊。因此,我們繼續檢視utmp檔案是什麼。
2、檢視utmp
運用man命令的關鍵詞搜尋功能,在終端輸入man -k utmp, 可以看到以下內容。
我們可以看到utmp(5) 這一行與登入資訊有關,接下來檢視該部分。在終端輸入man 5 utmp,在description處可以看到utmp的具體介紹。utmp中存放了一系列的結構體,並且宣告在<utmp.h>標頭檔案中。utmp中的資料結構如下圖所示。
結構體中存放了使用者名稱、tty、時間等資訊。其中值得注意的是時間資訊。為了將32位作業系統與64位作業系統保持一致,在這裡通過一個巨集定義來進行兩種設定。我的作業系統是64位的,所以看64位處,即定義了一個ut_tv的結構體,裡面包含了兩個32位數,一個表示秒數,一個表示微妙數。unix中的時間表示是從1970年1月1日0時開始到所求時間所經過的秒數。所以我們還需要將秒數換算成時間,經過搜尋,發現使用linux中的ctime()函式就可以實現。
3、函式一覽表
函式名 | open |
目標 | 開啟一個檔案 |
標頭檔案 | #include< fcntl.h > |
函式原型 | int fd = open( char* name, int how ) |
引數 | name 檔名 how O_REONLY, O_WRONLY, O_RDWR |
返回值 | -1 錯誤 int 成功返回檔案描述符 |
函式名 | read |
目標 | 從檔案把資料讀取到緩衝區 |
標頭檔案 | #include< unistd.h > |
函式原型 | ssize_t numread = read( int fd, void* buf, size_t qty ) |
引數 | fd 檔案描述符 buf 目的緩衝區 要讀取的位元組數 |
返回值 | -1 錯誤 numread 讀取的位元組數 |
函式名 | close |
目標 | 關閉檔案 |
標頭檔案 | #include <unistd.h> |
函式原型 | int res = close( int fd ) |
引數 | fd 檔案描述符 |
返回值 | -1 遇到錯誤 0 成功關閉 |
函式名 | ctime() |
目標 | 將秒數轉換為時間 |
標頭檔案 | #include <time.h> |
函式原型 | char* res = ctime( const time_t *timep) |
引數 | time_t (實際上是long int) |
返回值 | char * |
4、程式碼
#include <utmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
int show_info(struct utmp* utbuf);
void show_time(time_t);
int main(){
int fd = open(UTMP_FILE, O_RDONLY);
if( fd == -1){
perror( UTMP_FILE );
exit( 1 );
}
struct utmp cur_record;
int len = sizeof(cur_record);
while( read(fd, &cur_record, len) == len ){
show_info( &cur_record);
}
close(fd);
return 0;
}
int show_info(struct utmp* utbuf){
printf(" %-8.8s ", utbuf->ut_user); //登入名
printf(" ");
printf(" %-8.8s ", utbuf->ut_line);//tty
printf(" ");
//char* cp = ctime(&((utbuf->ut_tv).tv_sec));
time_t time = (utbuf->ut_tv).tv_sec;
show_time(time);
printf("\n");
return 0;
}
void show_time(time_t tm){
char* cp;
cp = ctime(&tm);
printf(" %20.20s", cp);
}