1. gzyueqian
      13352868059
      首頁 > 新聞中心 > > 正文

      編寫who命令--從Linux中學習Linux

      更新時間: 2012-03-09 09:08:47來源: 粵嵌教育瀏覽量:2450

          執行who命令查看已登錄的用戶信息

      $ who
      orisun tty7 2011-12-19 14:12 (:0)
      orisun pts/0 2011-12-19 14:12 (:0.0)

          顯示出了:用戶名、終端名、登錄時間、登錄地址

          現在我們要自己寫一個程序來實現who。是不是要用到一些特殊的系統調用,或者需要root權限呢?實際上都不用,我們要學會使用Linux的聯機幫助文檔,從Linux中學習Linux。

          要學習linux系統給我們提供的編程接口,很多時間查看相應的頭文件就可以了。

      $ man who

      WHO(1) User Commands WHO(1)

      NAME
      who - show who is logged on

      SYNOPSIS
      who [OPTION]... [ FILE | ARG1 ARG2 ]

      DESCRIPTION
      Print information about users who are currently logged in.

      -a, --all
      same as -b -d --login -p -r -t -T -u

      -b, --boot
      time of last system boot

      -d, --dead

      ……

          注意我紅色標出的那個1是小節編號。使用who命令時可以指定FILE,在who的DESCRIPTION中有這么幾行字:If FILE is not specified, use /var/run/utmp. /var/log/wtmp as FILE iscommon.實際上who是通過讀取/var/run/utmp文件來獲取已登錄的用戶信息的。

          帶有選項-k的man命令可以根據關鍵字來搜索聯機幫助。

      $ man -k utmp
      endutent (3) - access utmp file entries
      endutxent (3) - access utmp file entries
      getutent (3) - access utmp file entries
      getutent_r (3) - access utmp file entries
      getutid (3) - access utmp file entries
      getutid_r (3) - access utmp file entries
      getutline (3) - access utmp file entries
      getutline_r (3) - access utmp file entries
      getutmp (3) - copy utmp structure to utmpx, and vice versa
      getutmpx (3) - copy utmp structure to utmpx, and vice versa
      getutxent (3) - access utmp file entries
      getutxid (3) - access utmp file entries
      getutxline (3) - access utmp file entries
      login (3) - write utmp and wtmp entries
      logout (3) - write utmp and wtmp entries
      pututline (3) - access utmp file entries
      pututxline (3) - access utmp file entries
      sessreg (1) - manage utmp/wtmp entries for non-init clients
      setutent (3) - access utmp file entries
      setutxent (3) - access utmp file entries
      utmp (5) - login records
      utmpname (3) - access utmp file entries
      utmpx (5) - login records
      utmpxname (3) - access utmp file entries

          這里的“5”是小節編號。

      $ man 5 utmp  UTMP(5) Linux Programmer's Manual UTMP(5)  

      NAME

      utmp, wtmp - login records

      SYNOPSIS
      #include <utmp.h>

      DESCRIPTION
      The utmp file allows one to discover information about who is currently using the system. There may be more users currently using the system, because not all programs use utmp logging.

      ……

      /* Values for ut_type field, below */

      #define EMPTY 0 /* Record does not contain valid info (formerly known as UT_UNKNOWN on Linux) */
      #define RUN_LVL 1 /* Change in system run-level (see init(8)) */
      #define BOOT_TIME 2 /* Time of system boot (in ut_tv) */
      #define NEW_TIME 3 /* Time after system clock change (in ut_tv) */
      #define OLD_TIME 4 /* Time before system clock change (in ut_tv) */
      #define INIT_PROCESS 5 /* Process spawned by init(8) */
      #define LOGIN_PROCESS 6 /* Session leader process for user login */
      #define USER_PROCESS 7 /* Normal process */
      #define DEAD_PROCESS 8 /* Terminated process */
      #define ACCOUNTING 9 /* Not implemented */

      #define UT_LINESIZE 32
      #define UT_NAMESIZE 32
      #define UT_HOSTSIZE 256

      struct exit_status { /* Type for ut_exit, below */
      short int e_termination; /* Process termination status */
      short int e_exit; /* Process exit status */
      };

      struct utmp {
      short ut_type; /* Type of record */
      pid_t ut_pid; /* PID of login process */
      char ut_line[UT_LINESIZE]; /* Device name of tty - "/dev/" */
      char ut_id[4]; /* Terminal name suffix, or inittab(5) ID */
      char ut_user[UT_NAMESIZE]; /* Username */
      char ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or kernel version for run-level messages */
      struct exit_status ut_exit; /* Exit status of a process marked as DEAD_PROCESS; not used by Linux init(8) */
      /* The ut_session and ut_tv fields must be the same size when compiled 32- and 64-bit. This allows data files and shared memory to be shared between 32- and 64-bit applications. */
      #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
      int32_t ut_session; /* Session ID (getsid(2)), used for windowing */

      struct {
      int32_t tv_sec; /* Seconds */
      int32_t tv_usec; /* Microseconds */
      } ut_tv; /* Time entry was made */
      #else
      long ut_session; /* Session ID */
      struct timeval ut_tv; /* Time entry was made */
      #endif

      int32_t ut_addr_v6[4]; /* Internet address of remote host; IPv4 address uses just ut_addr_v6[0] */
      char __unused[20]; /* Reserved for future use */
      };

      /* Backwards compatibility hacks */
      #define ut_name ut_user
      #ifndef _NO_UT_TIME
      #define ut_time ut_tv.tv_sec
      #endif
      #define ut_xtime ut_tv.tv_sec
      #define ut_addr ut_addr_v6[0]

      ……

      #include<stdio.h>#include<utmp.h>#include<string.h>#include<stdlib.h>#define SHOWHOSTvoid show_info(struct utmp*);int main(){    struct utmp record;    FILE *fp;    int strulen=sizeof(record);    if((fp=fopen("/var/run/utmp","r"))==0){     //打開文件        perror("fopen");        exit(0);    }    memset(&record,0x00,strulen);    while(fread(&record,strulen,1,fp)){      //循環讀取記錄(結構體)        show_info(&record);    }    fclose(fp);     //關閉文件    return 0;}void show_info(struct utmp *buf){    printf("%-8s  ",buf->ut_name);      //輸出用戶名    printf("%-8s  ",buf->ut_line);      //終端設備名    printf("%10ld  ",buf->ut_time);      //登錄時間#ifdef SHOWHOST    printf("(%s)",buf->ut_host);#endif    printf("\n");}
      運行結果:
      $ ./who1
      reboot ~ 1324275122 (2.6.38-13-generic)
      runlevel ~ 1324275122 (2.6.38-13-generic)
      LOGIN tty4 1324275122 ()
      LOGIN tty5 1324275122 ()
      LOGIN tty2 1324275122 ()
      LOGIN tty3 1324275122 ()
      LOGIN tty6 1324275122 ()
      LOGIN tty1 1324275128 ()
      orisun tty7 1324275138 (:0)
      orisun pts/0 1324275175 (:0.0)
      orisun pts/1 1324285820 (:0.0)

          上面的程序有兩個問題:

          時間顯示的是time_t類型的,不便于閱讀

          utmp文件不僅包含活動用戶的信息,連那些尚未用到的終端信息也保存在utmp文件。

          解決問題1。讓我們找一下和時間格式轉換相關的函數。

      $ man -k time | grep -i transform
      asctime (3) - transform date and time to broken-down time or ASCII
      asctime_r (3) - transform date and time to broken-down time or ASCII
      ctime (3) - transform date and time to broken-down time or ASCII
      ctime_r (3) - transform date and time to broken-down time or ASCII
      gmtime (3) - transform date and time to broken-down time or ASCII
      gmtime_r (3) - transform date and time to broken-down time or ASCII
      localtime (3) - transform date and time to broken-down time or ASCII
      localtime_r (3) - transform date and time to broken-down time or ASCII
      mktime (3) - transform date and time to broken-down time or ASCII

          好,我們仔細閱讀一下localtime

      $ man localtime

      CTIME(3) Linux Programmer's Manual CTIME(3)

      NAME
      asctime, ctime, gmtime, localtime, mktime, asctime_r, ctime_r, gmtime_r, localtime_r - transform date and time to
      broken-down time or ASCII

      SYNOPSIS
      #include <time.h>

      char *asctime(const struct tm *tm);
      char *asctime_r(const struct tm *tm, char *buf);

      char *ctime(const time_t *timep);
      char *ctime_r(const time_t *timep, char *buf);

      struct tm *gmtime(const time_t *timep);
      struct tm *gmtime_r(const time_t *timep, struct tm *result);

      struct tm *localtime(const time_t *timep);
      struct tm *localtime_r(const time_t *timep, struct tm *result);

      time_t mktime(struct tm *tm);

      Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

      asctime_r(), ctime_r(), gmtime_r(), localtime_r():
      _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || _POSIX_SOURCE

      DESCRIPTION
      The ctime(), gmtime() and localtime() functions all take an argument of data type time_t which represents calendar
      time. When interpreted as an absolute time value, it represents the number of seconds elapsed since the Epoch,
      1970-01-01 00:00:00 +0000 (UTC).

      The asctime() and mktime() functions both take an argument representing broken-down time which is a representation
      separated into year, month, day, etc.

      Broken-down time is stored in the structure tm which is defined in <time.h> as follows:

      struct tm {
      int tm_sec; /* seconds */
      int tm_min; /* minutes */
      int tm_hour; /* hours */
      int tm_mday; /* day of the month */
      int tm_mon; /* month */
      int tm_year; /* year */
      int tm_wday; /* day of the week */
      int tm_yday; /* day in the year */

          解決問題2。通過閱讀utmp.h我們發現,utmp結構中有一個成員ut_type,當它的值為7(USER_PROCESS)時,表示這個用戶已經登錄。

          綜上所述,我們給出改進后的代碼。

      #include<stdio.h>

      #include<utmp.h>

      #include<string.h>

      #include<stdlib.h>

      #include<time.h>

       

      #define SHOWHOST

       

      void show_info(struct utmp*);

       

      int main(){

      struct utmp record;

      FILE *fp;

      int strulen=sizeof(record);

      if((fp=fopen("/var/run/utmp","r"))==0){ //打開文件

      perror("fopen");

      exit(0);

      }

      memset(&record,0x00,strulen);

      while(fread(&record,strulen,1,fp)){ //循環讀取記錄(結構體)

      show_info(&record);

      }

      fclose(fp); //關閉文件

      return 0;

      }

      void show_info(struct utmp *buf){

      if(buf->ut_type!=USER_PROCESS) //非登錄用戶

      return;

      printf("%-8s ",buf->ut_name); //輸出用戶名

      printf("%-12s ",buf->ut_line); //終端設備名

      time_t timelong=buf->ut_time;

      struct tm *localnow=localtime(&timelong);

      printf("%d-%d-%d %d:%d ",localnow->tm_year+1990,localnow->tm_mon+1,localnow->tm_mday,localnow->tm_hour,localnow->tm_min); //登錄時間

      #ifdef SHOWHOST

      printf("(%s)",buf->ut_host);

      #endif

      printf("\n");

      }

      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 尤物国产区精品视频 | 欲求不满放荡的女老板bd中文 | 视色日韩AV一区二区三区 | 欧美日韩精品久久久久免费看 | 欧美三级欧美一级在线视频 | 午夜成午夜成年片在线观看bd |