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.登出程式的編寫
注意,登出的是當前終端,當前終端的名稱可以用tty獲得,作為命令列引數#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; }
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 [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