1. 程式人生 > >Linux下編寫Who命令

Linux下編寫Who命令

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);
}