1. 程式人生 > >who命令的編寫——登入與登出__who, whoami, who am i

who命令的編寫——登入與登出__who, whoami, who am i

摘要:who是一個linux下重要的系統內建指令,編寫who命令,需要了解相關的資料結構struct utmp。同時進一步熟悉結構化資料的讀取和訪問方法。另外總結了系統呼叫相關的知識。

1.who程式的編寫

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<fcntl.h>
#include<utmp.h>
#include<time.h>

#define SHOWHOST
int show_info(struct utmp *utbufp);
void showtime(long);

int main(int arv, char *arg[])
{
  struct utmp current_record;
  int utmpfd;
  int reclen=sizeof(struct utmp);

  if((utmpfd = open(UTMP_FILE,O_RDONLY))==-1)
  {
    perror(UTMP_FILE);
    exit(1);
  }
  
  while(read(utmpfd,¤t_record,reclen)==reclen)
  {
    show_info(¤t_record);
    
  }
  close(utmpfd);
  return 0;

}

int show_info(struct utmp *utbufp)
{
  if(utbufp->ut_type!=USER_PROCESS)
    return;
  printf("%-8.8s",utbufp->ut_name);
  printf(" ");
  printf("%-8.8s",utbufp->ut_line);
  printf(" ");
  showtime(utbufp->ut_time);
  printf(" ");
#ifdef SHOWHOST
    printf("%-8.8s",utbufp->ut_host);
#endif
  printf("\n");
}


void showtime(long timeeval)
{
  char *p;
  p=ctime(&timeeval );
  printf("%12.12s",p+4);
}

1)從who命令的man文件可以檢視到它與utmp這個檔案有關,進而man utmp這個檔案,可以找到這個標頭檔案和utmp這個結構體的一些資訊。

2)open,write,close,seek,creat是與檔案讀寫有關的系統呼叫,我們在下一篇部落格裡總結它們。

3)與時間有關的函式ctime,我們將用一篇文章總結它們。

4)同樣,知道了登入資訊是存在UTMPFILE,那麼我們可以進一步編寫登出資訊,實際上就是將改寫該檔案中的資料而已。下面是登出的程式碼:

2.登出程式的編寫

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<utmp.h>
#include<fcntl.h>
#include<sys/types.h>
#include<string.h>
#include<time.h>


int main(int argc, char *argv[])
{
  char *termname=argv[1];
  logout(termname);
  return 0;
}


int logout(const char *ttyname)
{
  int fd; 
  struct utmp utmpunit;
  int utmpunitlen=sizeof(struct utmp);

  if ((fd=open(UTMP_FILE,O_RDWR))==-1)
  {
    perror("can not open file:");
    return -1; 

  }
  
  while(read(fd,&utmpunit,utmpunitlen )==utmpunitlen)
  {
    printf("%s      %s\n",ttyname,utmpunit.ut_line );
    if(strstr(ttyname,utmpunit.ut_line)!=NULL)
    {   
      printf("find the login account\n");
      utmpunit.ut_type=DEAD_PROCESS;
      utmpunit.ut_time=time(NULL);
      if(lseek(fd,-utmpunitlen,SEEK_CUR)!=-1)
      {   
        if(write(fd,&utmpunit,utmpunitlen)==utmpunitlen)
          ;   
      }
      break;
    }
  }
  if(close(fd)==-1)
  {
    perror("can not close file:");
    return -1;
  }
注意,登出的是當前終端,當前終端的名稱可以用tty獲得,作為命令列引數

3.析who,whoami,who am i

先看看這三個命令的輸出資訊: [[email protected] ~]$ whoami rocrocket [[email protected] ~]$ who am i rocrocket pts/3        2008-12-30 13:17 (:0.0) [[email protected] ~]$ who rocrocket :0           2008-12-30 09:54 rocrocket pts/0        2008-12-30 09:55 (:0.0) rocrocket pts/1        2008-12-30 09:57 (:0.0) rocrocket pts/3        2008-12-30 13:17 (:0.0) 當我用sudo su(或者sudo su -)更換到root使用者之後,你再看看:   www.2cto.com   [
[email protected]
~]$ sudo su [[email protected] rocrocket]# whoami root [[email protected] rocrocket]# who am i rocrocket pts/3        2008-12-30 13:17 (:0.0) [[email protected] rocrocket]# who rocrocket :0           2008-12-30 09:54 rocrocket pts/0        2008-12-30 09:55 (:0.0) rocrocket pts/1        2008-12-30 09:57 (:0.0) rocrocket pts/3        2008-12-30 13:17 (:0.0) 看出區別來了吧,whoami顯示的是當前“操作使用者”的使用者名稱,而who am i顯示的是“登入使用者”的使用者名稱。

4.結構化提取utmp資料:

4.1.getutent函式 標頭檔案:#include <utmp.h>
定義函式:struct utmp *getutent(void);
函式說明:getutent()用來從utmp 檔案(/var/run/utmp)中讀取一項登入資料, 該資料以utmp 結構返回. 第一次呼叫時會取得第一位使用者資料, 之後每呼叫一次就會返回下一項資料, 直到已無任何資料時返回NULL。
4.2.getutmp函式 #define _GNU_SOURCE             /* See feature_test_macros(7) */        #include <utmpx.h>


        void getutmp(const struct utmpx *ux, struct utmp *u);
        void getutmpx(const struct utmp *u, struct utmpx *ux);


DESCRIPTION
       The getutmp() function copies the fields of the utmpx structure pointed
       to by ux to the corresponding fields of the utmp structure  pointed  to
       by u.  The getutmpx() function performs the converse operation.

5.另外一個命令w:

顯示當前使用者和他們正在進行的操作

$ w
 14:57:22 up 3 days, 18:35,  6 users,  load average: 0.38, 0.25, 0.22
USER     TTY      FROM              [email protected]   IDLE   JCPU   PCPU WHAT
hyk      tty7                      Sun20    3days  1:18m  2.17s gnome-session -
hyk      pts/1    :0.0             Mon18   17:33m  5.06s  4.77s vncviewer 10.10
hyk      pts/2    :0.0             Mon10   16:57m  0.48s  0.01s ssh [email protected]
hyk      pts/3    :0.0             10:43    3:44m  0.83s  2:01  gnome-terminal
hyk      pts/4    :0.0             10:45    2.00s  0.91s  0.01s w

6.斷電處理

如果系統忽然掉電,此時utmp檔案裡面的內容還沒有來得及更改,所以下次重啟的時候,init程序將會清除utmp的所有記錄為空(設定為DEADPROCESS),大致如下:

init——login——getty——utmp