linux系統編程:自己動手寫一個who命令,linuxwho

來源:互聯網
上載者:User

linux系統編程:自己動手寫一個who命令,linuxwho

who命令的作用用於顯示當前有哪些使用者登入到系統。

這個命令執行的原理是讀取了系統上utmp檔案中記錄的所有登入資訊,直接顯示出來的

utmp檔案在哪裡呢?

man who的時候,在手冊下面有這麼一段說明:意思就是不指定檔案參數,那麼讀取的就是/var/run/utmp,到底是不是,驗證下

If FILE is not specified, use /var/run/utmp.  /var/log/wtmp as FILE  is       common.   If  ARG1  ARG2  given, -m presumed: 'am i' or 'mom likes' are       usual.

當我指定file參數為/var/run/utmp或者省略這個參數的時候,結果都是一樣, 當我用一個錯誤的檔案時,沒有任何結果,從這裡可以推斷,who命令確實從/var/run/utmp中讀取使用者登入的資訊

ghostwu@ubuntu:~$ whoghostwu  tty7         2018-01-08 09:09 (:0)ghostwu  pts/18       2018-01-08 12:59 (:0)ghostwu  pts/19       2018-01-08 13:00 (:0)ghostwu  pts/20       2018-01-08 13:03 (:0)ghostwu@ubuntu:~$ who -b         system boot  2018-01-08 09:08ghostwu@ubuntu:~$ who -b /var/run/utmp          system boot  2018-01-08 09:08ghostwu@ubuntu:~$ who -b /var/run/utmp2ghostwu@ubuntu:~$ who -b /var/run/utmp3

那麼utmp到底在哪裡?

利用man -k utmp 尋找所有的可能:    推斷--->  utmp (5) - login records  這裡的可能性比較大,描述說,這裡是記錄登入資訊的

ghostwu@ubuntu:~$ man -k utmpendutent (3)         - access utmp file entriesendutxent (3)        - access utmp file entriesgetutent (3)         - access utmp file entriesgetutent_r (3)       - access utmp file entriesgetutid (3)          - access utmp file entriesgetutid_r (3)        - access utmp file entriesgetutline (3)        - access utmp file entriesgetutline_r (3)      - access utmp file entriesgetutmp (3)          - copy utmp structure to utmpx, and vice versagetutmpx (3)         - copy utmp structure to utmpx, and vice versagetutxent (3)        - access utmp file entriesgetutxid (3)         - access utmp file entriesgetutxline (3)       - access utmp file entrieslogin (3)            - write utmp and wtmp entrieslogout (3)           - write utmp and wtmp entriespututline (3)        - access utmp file entriespututxline (3)       - access utmp file entriessessreg (1)          - manage utmpx/wtmpx entries for non-init clientssetutent (3)         - access utmp file entriessetutxent (3)        - access utmp file entriessystemd-update-utmp (8) - Write audit and utmp updates at bootup, runlevel ch...systemd-update-utmp-runlevel.service (8) - Write audit and utmp updates at bo...systemd-update-utmp.service (8) - Write audit and utmp updates at bootup, run...utmp (5)             - login recordsutmpdump (1)         - dump UTMP and WTMP files in raw formatutmpname (3)         - access utmp file entriesutmpx (5)            - login recordsutmpxname (3)        - access utmp file entries

接下來,我們去 man 5 utmp 看下,會發現有這麼一段提示:

The file is a sequence of utmp structures, declared as follows in <utmp.h> (note that this       is only one of several definitions around; details depend on the version of libc):

意思是utmp檔案的資訊是一系列utmp結構體資料, 這個結構體定義在utmp.h檔案中,  每個linux發行版可能不一樣.

接下來,我用強大的find命令尋找到了2個目標:

ghostwu@ubuntu:~$ find /usr/include -name "utmp.h"/usr/include/x86_64-linux-gnu/bits/utmp.h/usr/include/utmp.h

結構體的定義就在這個檔案中( /usr/include/x86_64-linux-gnu/bits/utmp.h  )

這裡有兩個宏要注意下( ut_time和UTMP_FILE ), 下面的程式會用到

#ifndef _NO_UT_TIME/* We have a problem here: `ut_time' is also used otherwise.  Define   _NO_UT_TIME if the compiler complains.  */# define ut_time    ut_tv.tv_sec#endif
ghostwu@ubuntu:~$ grep "UTMP_FILE" /usr/include/utmp.h #define UTMP_FILE    _PATH_UTMP#define UTMP_FILENAME    _PATH_UTMPghostwu@ubuntu:~$ grep "_PATH_UTMP" /usr/include/utmp.h#define UTMP_FILE    _PATH_UTMP#define UTMP_FILENAME    _PATH_UTMPghostwu@ubuntu:~$ grep "_PATH_UTMP" /usr/include/x86_64-linux-gnu/bits/utmp.h ghostwu@ubuntu:~$ grep "_PATH_UTMP" /usr/include/*.h/usr/include/paths.h:#define    _PATH_UTMP    "/var/run/utmp"/usr/include/utmp.h:#define UTMP_FILE    _PATH_UTMP/usr/include/utmp.h:#define UTMP_FILENAME    _PATH_UTMP/usr/include/utmpx.h:# define UTMPX_FILE    _PATH_UTMPX/usr/include/utmpx.h:# define UTMPX_FILENAME    _PATH_UTMPXghostwu@ubuntu:~$

UTMP_FILE的尋找思路: 首先grep兩個目錄下面的檔案utmp.h,在/usr/include/utmp.h找到一個宏定義 _PATH_UTMP,下一步就是確定 _PATH_UTMP到底是什麼,利用grep "_PATH_UTMP" /usr/include/*.h

最終在paths.h標頭檔中,發現了他的真面目

who命令書寫思路:

1)從/var/run/utmp讀取檔案,每次讀取一個struct utmp結構體這麼大,如果長度每次都有這麼大,繼續讀取

2)格式化4個資訊:使用者名稱,主機,地址,時間

3)只列印當前活動的使用者(當前登入的使用者)

4)格式化時間( 小時,分鐘,秒, >10的補0, <10的原樣返回 )

原始碼

1 /*================================================================ 2 * Copyright (C) 2018 . All rights reserved. 3 * 4 * 檔案名稱:mywho.c 5 * 創 建 者:ghostwu(吳華) 6 * 建立日期:2018年01月08日 7 * 描 述: 8 * 9 ================================================================*/ 10 11 #include <stdio.h> 12 #include <utmp.h> 13 #include <sys/types.h> 14 #include <sys/stat.h> 15 #include <fcntl.h> 16 #include <stdlib.h> 17 #include <unistd.h> 18 #include <time.h> 19 #include <string.h> 20 21 #ifndef UTMP_FILE 22 #define UTMP_FILE "/var/run/utmp" 23 #endif 24 25 int count = 0; 26 27 //格式化時間, <10 就補0, >10 原樣返回 28 char* format_time( char* s, const char *time ) { 29 if( strlen( time ) < 2 ) { 30 return strcat( s, time ); 31 } 32 return strcpy( s, time ); 33 } 34 35 void show_info( struct utmp* t_utmp ) { 36 if ( t_utmp->ut_type != USER_PROCESS ) //不顯示 非活躍的使用者資訊 37 return; 38 39 printf( "%-8.8s", t_utmp->ut_user ); 40 printf( " " ); 41 printf( "%-8.8s", t_utmp->ut_line ); 42 printf( " " ); 43 44 //printf( " " ); 45 //printf( "%12.12s", ctime( (time_t*)&(t_utmp->ut_time) ) + 4 ); //+4--->去除天(day)和後面的空格 46 47 /*測試localtime用法 48 //目前時間 49 time_t now; 50 struct tm* pNow; 51 time( &now ); 52 pNow = localtime( &now ); 53 printf( "%d-%d-%d %d:%d", pNow->tm_year + 1900, pNow->tm_mon + 1, pNow->tm_mday, pNow->tm_hour, pNow->tm_min ); 54 */ 55 56 struct tm* ptm; 57 time_t u_time = t_utmp->ut_time; 58 ptm = localtime( &u_time ); 59 int ihour = ptm->tm_hour; 60 int imin = ptm->tm_min; 61 62 char hour[3] = "0"; 63 char hour2[3] = "0"; 64 sprintf( hour2, "%d", ihour ); 65 format_time( hour, hour2 ); 66 67 char min[3] = "0"; 68 char min2[3] = "0"; 69 sprintf( min2, "%d", imin ); 70 format_time( min, min2 ); 71 72 //printf( "%d-%d-%d %d:%d", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ihour, imin ); 73 printf( "%d-%d-%d %s:%s", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, hour, min ); 74 75 printf( " " ); 76 printf( "%-8.8s", t_utmp->ut_host ); 77 78 printf( "\n" ); 79 } 80 81 int main(int argc, char *argv[]) 82 { 83 struct utmp myutmp; 84 int fd = -1; 85 int reclen = sizeof( myutmp ); 86 87 fd = open( UTMP_FILE, O_RDONLY ); 88 89 if( -1 == fd ) { 90 perror( "open utmp" ); 91 exit( -1 ); 92 } 93 94 //printf( "fd = %d\n", fd ); 95 96 while( read( fd, &myutmp, reclen ) == reclen ) { 97 count++; 98 show_info( &myutmp ); 99 }100 printf( "檔案讀取的次數:%d\n", count );101 close( fd );102 103 104 return 0;105 }View Code

 

總結:

 一個非常小的功能,囊括以下知識點:

1)檔案讀取

2)man手冊與系統命令提示

3)指標用法

4)字串函數用法

5)時間函數用法

6)宏與typedef的用法

   

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.