Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1782364
  • 博文数量: 297
  • 博客积分: 285
  • 博客等级: 二等列兵
  • 技术积分: 3006
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-06 22:04
个人简介

Linuxer, ex IBMer. GNU https://hmchzb19.github.io/

文章分类

全部博文(297)

文章存档

2020年(11)

2019年(15)

2018年(43)

2017年(79)

2016年(79)

2015年(58)

2014年(1)

2013年(8)

2012年(3)

分类: C/C++

2015-10-20 10:46:05

例子出自这里:http://www.compsci.hunter.cuny.edu/~sweiss/course_materials/unix_lecture_notes.php
我发现这里的内容很像一本书,Understanding Unix/Linux Programming.
首先是man utmp,真是复杂的结构体啊

点击(此处)折叠或打开

  1. struct utmp {
  2.                short ut_type; /* Type of record */
  3.                pid_t ut_pid; /* PID of login process */
  4.                char ut_line[UT_LINESIZE]; /* Device name of tty - "/dev/" */
  5.                char ut_id[4]; /* Terminal name suffix,
  6.                                                 or inittab(5) ID */
  7.                char ut_user[UT_NAMESIZE]; /* Username */
  8.                char ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or
  9.                                                 kernel version for run-level
  10.                                                 messages */
  11.                struct exit_status ut_exit; /* Exit status of a process
  12.                                                 marked as DEAD_PROCESS; not
  13.                                                 used by Linux init(8) */
  14.                /* The ut_session and ut_tv fields must be the same size when
  15.                   compiled 32- and 64-bit. This allows data files and shared
  16.                   memory to be shared between 32- and 64-bit applications. */
  17.            #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
  18.                int32_t ut_session; /* Session ID (getsid(2)),
  19.                                                 used for windowing */
  20.                struct {
  21.                    int32_t tv_sec; /* Seconds */
  22.                    int32_t tv_usec; /* Microseconds */
  23.                } ut_tv; /* Time entry was made */
  24.            #else
  25.                 long ut_session; /* Session ID */
  26.                 struct timeval ut_tv; /* Time entry was made */
  27.            #endif

  28.                int32_t ut_addr_v6[4]; /* Internet address of remote
  29.                                                 host; IPv4 address uses
  30.                                                 just ut_addr_v6[0] */
  31.                char __unused[20]; /* Reserved for future use */
  32.            }
第一个版本比较原始,read UTMP_FILE,然后打印出结构体里面需要的值。使用ctime转化时间。
点击(此处)折叠或打开
  1. #include <apue.h>
  2. #include <utmp.h>
  3. #include <fcntl.h>
  4. #include <time.h>

  5. void show_info(struct utmp *utbufp);
  6. void show_time(long);

  7. int main(int argc,char *argv[])
  8. {
  9.     int fd;
  10.     struct utmp current_record;
  11.     int reclen=sizeof(struct utmp);

  12.     fd=open(UTMP_FILE,O_RDONLY);
  13.     if(fd==-1){
  14.         perror(UTMP_FILE);
  15.         exit(1);
  16.         }

  17.     while(read(fd,&current_record,reclen)==reclen)
  18.         show_info(&current_record);

  19.     close(fd);
  20.     return 0;
  21.     }


  22. void show_info(struct utmp *utbufp)
  23. {
  24.     if(utbufp->ut_type !=USER_PROCESS)
  25.         return ;

  26.     printf("%-8.8s",utbufp->ut_name); //the logname
  27.     printf(" ");
  28.     printf("%-8.8s",utbufp->ut_line); //the tty
  29.     printf(" ");
  30.     show_time(utbufp->ut_time); //login time
  31.     printf(" ");
  32.     printf("(%s)",utbufp->ut_host); //the host
  33.     printf("\n");
  34. }


  35. void show_time(long timeval)
  36. {
  37.     char* timestr=ctime(&timeval);
  38.     printf("%12.12s",timestr+4);
  39.     }
第二个版本,getutent_r 是可重入函数,线程安全。reentrant
 _PATH_WTMP和_PATH_UTMP 定义在 /usr/include/paths.h
#define _PATH_UTMP  "/var/run/utmp"
#define _PATH_WTMP  "/var/log/wtmp"
/usr/include/utmp.h 其实也就是重新声明而已。
#define UTMP_FILE   _PATH_UTMP
#define WTMP_FILE   _PATH_WTMP

点击(此处)折叠或打开

  1. #include <apue.h>
  2. #define _GNU_SOURCE /* or _SVID_SOURCE or _BSD_SOURCE */
  3. #include <utmp.h>
  4. #include <fcntl.h>
  5. #include <time.h>


  6. void show_info(struct utmp *utbufp);
  7. void show_time(long);

  8. int main(int argc,char *argv[])
  9. {
  10.     struct utmp utbuf,*utbufp;
  11.     int utmpfd;
  12.     
  13.     if((argc>1)&&(strcmp(argv[1],"wtmp")==0))
  14.         utmpname(_PATH_WTMP);
  15.     else
  16.         utmpname(_PATH_UTMP);
  17.     
  18.     setutent();
  19.     while(getutent_r(&utbuf,&utbufp)==0)
  20.         show_info(&utbuf);
  21.     
  22.     endutent();
  23.     return 0;
  24.     }


  25. void show_info(struct utmp *utbufp)
  26. {
  27.     if(utbufp->ut_type !=USER_PROCESS)
  28.         return ;

  29.     printf("%-8.8s",utbufp->ut_name); //the logname
  30.     printf(" ");
  31.     printf("%-8.8s",utbufp->ut_line); //the tty
  32.     printf(" ");
  33.     show_time(utbufp->ut_time); //login time
  34.     printf(" ");
  35.     printf("(%s)",utbufp->ut_host); //the host
  36.     printf("\n");
  37. }


  38. void show_time(long timeval)
  39. {
  40.     char* timestr=ctime(&timeval);
  41.     printf("%12.12s",timestr+4);
  42.     }

点击(此处)折叠或打开

  1. Glibc notes
  2.        The above functions are not thread-safe. Glibc adds reentrant versions

  3.        #define _GNU_SOURCE /* or _SVID_SOURCE or _BSD_SOURCE;
  4.                                  see feature_test_macros(7) */
  5.        #include <utmp.h>

  6.        int getutent_r(struct utmp *ubuf, struct utmp **ubufp);

  7.        int getutid_r(struct utmp *ut,
  8.                      struct utmp *ubuf, struct utmp **ubufp);

  9.        int getutline_r(struct utmp *ut,
  10.                        struct utmp *ubuf, struct utmp **ubufp);

  11.        These functions are GNU extensions, analogs of the functions of the same name without the _r suffix. The ubuf argument gives these functions a place to store
  12.        their result. On success they return 0, and a pointer to the result is written in *ubufp. On error these functions return -1. There are no utmpx equivalents of
  13.        the above functions. (POSIX.1 does not specify such functions.)
最后一个版本,一次读20个struct utmp.然而据说有个缺点:
However, this method has a pitfall: the file may be larger than the available memory for the process. In this case, the
program must be able to identify this and adjust how it reads the file. The GNU implementation
of who does exactly this.

点击(此处)折叠或打开

  1. #include <apue.h>
  2. #include <fcntl.h>
  3. #include <utmp.h>
  4. #include <sys/types.h>
  5. #include <time.h>

  6. typedef struct utmp utmp_record;
  7. #define NUM_RECORDS 20
  8. #define NULL_UTMP_RECORD_PTR ((utmp_record *)NULL)
  9. #define SIZE_OF_UTMP_RECORD (sizeof(utmp_record))
  10. #define BUFSIZE (NUM_RECORDS *SIZE_OF_UTMP_RECORD)


  11. static char utmpbuf[BUFSIZE]; //buffer of records
  12. static int number_of_recs_in_buffer; //num records in buffer
  13. static int current_record; //next rec to read
  14. static int fd_utmp=-1; // file descriptor for utmp file

  15. void die(char* string1,char* string2);
  16. int open_utmp(char *utmp_file);
  17. int fill_utmp();
  18. utmp_record *next_utmp();
  19. void close_utmp();
  20. void show_info(struct utmp *utbufp);
  21. void show_time(long timeval);

  22. void die(char* string1,char* string2){
  23.     fprintf(stderr,"Error: %s ",string1);
  24.     perror(string2);
  25.     exit(1);
  26. }


  27. int open_utmp(char *utmp_file)
  28. {
  29.     fd_utmp=open(utmp_file,O_RDONLY);
  30.     current_record=0;
  31.     number_of_recs_in_buffer=0;
  32.     return fd_utmp; //either a valid file descriptor or -1
  33. }


  34. int fill_utmp()
  35. {
  36.     int bytes_read;

  37.     //read NUM_RECORDS records from the utmp file into buffer
  38.     //bytes_read is the actual number of bytes read
  39.     bytes_read=read(fd_utmp,utmpbuf,BUFSIZE);
  40.     if(bytes_read < 0){
  41.         die("Failed to read from utmp file", "");
  42.     }

  43.     //if we reach here, the read was successful
  44.     //convert the byte count into a number of records
  45.     number_of_recs_in_buffer=bytes_read/SIZE_OF_UTMP_RECORD;

  46.     //reset current_record to start at the buffer start
  47.     current_record=0;
  48.     return number_of_recs_in_buffer;
  49. }

  50. utmp_record * next_utmp()
  51. {
  52.     utmp_record *recordptr;
  53.     int byte_position;

  54.     if(fd_utmp==-1)
  55.         //file was not opened correctly
  56.         return NULL_UTMP_RECORD_PTR;

  57.     if(current_record==number_of_recs_in_buffer)
  58.         //there are no unread records in the buffer
  59.         //need to refill the buffer
  60.         if(fill_utmp()==0)
  61.             //no utmp records left in the file
  62.             return NULL_UTMP_RECORD_PTR;

  63.     //there is at lease one record in the buffer,so we can read it
  64.     byte_position=current_record * SIZE_OF_UTMP_RECORD;
  65.     recordptr=(utmp_record *)&utmpbuf[byte_position];

  66.     //advance current_record pointer and return record pointer
  67.     current_record++;

  68.     return recordptr;
  69. }

  70. void close_utmp()
  71. {
  72.     // if file descriptor is a valid one,close the connection
  73.     if(fd_utmp!=-1)
  74.         close(fd_utmp);

  75. }

  76. void show_info(struct utmp *utbufp)
  77. {
  78.     if(utbufp->ut_type !=USER_PROCESS)
  79.         return ;

  80.     printf("%-8.8s",utbufp->ut_name); //the logname
  81.     printf(" ");
  82.     printf("%-8.8s",utbufp->ut_line); //the tty
  83.     printf(" ");
  84.     show_time(utbufp->ut_time); //login time
  85.     printf(" ");
  86.     printf("(%s)",utbufp->ut_host); //the host
  87.     printf("\n");
  88. }


  89. void show_time(long timeval)
  90. {
  91.     char* timestr=ctime(&timeval);
  92.     printf("%12.12s",timestr+4);
  93. }


  94. int main(int argc, char *argv[])
  95. {
  96.     utmp_record *utbufp; //pointer to a utmp record
  97.     if(open_utmp(UTMP_FILE)==-1){
  98.         perror(UTMP_FILE);
  99.         exit(1);
  100.         }


  101.     while((utbufp=next_utmp())!=NULL_UTMP_RECORD_PTR)
  102.         show_info(utbufp);
  103.     
  104.     close_utmp();
  105.     return 0;
  106.     }



阅读(1408) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~