例子出自这里:
http://www.compsci.hunter.cuny.edu/~sweiss/course_materials/unix_lecture_notes.php
我发现这里的内容很像一本书,Understanding Unix/Linux Programming.
首先是man utmp,真是复杂的结构体啊
-
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 */
-
}
第一个版本比较原始,read
UTMP_FILE,然后打印出结构体里面需要的值。使用ctime转化时间。
点击(此处)折叠或打开
-
#include <apue.h>
-
#include <utmp.h>
-
#include <fcntl.h>
-
#include <time.h>
-
-
void show_info(struct utmp *utbufp);
-
void show_time(long);
-
-
int main(int argc,char *argv[])
-
{
-
int fd;
-
struct utmp current_record;
-
int reclen=sizeof(struct utmp);
-
-
fd=open(UTMP_FILE,O_RDONLY);
-
if(fd==-1){
-
perror(UTMP_FILE);
-
exit(1);
-
}
-
-
while(read(fd,¤t_record,reclen)==reclen)
-
show_info(¤t_record);
-
-
close(fd);
-
return 0;
-
}
-
-
-
void show_info(struct utmp *utbufp)
-
{
-
if(utbufp->ut_type !=USER_PROCESS)
-
return ;
-
-
printf("%-8.8s",utbufp->ut_name); //the logname
-
printf(" ");
-
printf("%-8.8s",utbufp->ut_line); //the tty
-
printf(" ");
-
show_time(utbufp->ut_time); //login time
-
printf(" ");
-
printf("(%s)",utbufp->ut_host); //the host
-
printf("\n");
-
}
-
-
-
void show_time(long timeval)
-
{
-
char* timestr=ctime(&timeval);
-
printf("%12.12s",timestr+4);
-
}
第二个版本,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
-
#include <apue.h>
-
#define _GNU_SOURCE /* or _SVID_SOURCE or _BSD_SOURCE */
-
#include <utmp.h>
-
#include <fcntl.h>
-
#include <time.h>
-
-
-
void show_info(struct utmp *utbufp);
-
void show_time(long);
-
-
int main(int argc,char *argv[])
-
{
-
struct utmp utbuf,*utbufp;
-
int utmpfd;
-
-
if((argc>1)&&(strcmp(argv[1],"wtmp")==0))
-
utmpname(_PATH_WTMP);
-
else
-
utmpname(_PATH_UTMP);
-
-
setutent();
-
while(getutent_r(&utbuf,&utbufp)==0)
-
show_info(&utbuf);
-
-
endutent();
-
return 0;
-
}
-
-
-
void show_info(struct utmp *utbufp)
-
{
-
if(utbufp->ut_type !=USER_PROCESS)
-
return ;
-
-
printf("%-8.8s",utbufp->ut_name); //the logname
-
printf(" ");
-
printf("%-8.8s",utbufp->ut_line); //the tty
-
printf(" ");
-
show_time(utbufp->ut_time); //login time
-
printf(" ");
-
printf("(%s)",utbufp->ut_host); //the host
-
printf("\n");
-
}
-
-
-
void show_time(long timeval)
-
{
-
char* timestr=ctime(&timeval);
-
printf("%12.12s",timestr+4);
-
}
-
Glibc notes
-
The above functions are not thread-safe. Glibc adds reentrant versions
-
-
#define _GNU_SOURCE /* or _SVID_SOURCE or _BSD_SOURCE;
-
see feature_test_macros(7) */
-
#include <utmp.h>
-
-
int getutent_r(struct utmp *ubuf, struct utmp **ubufp);
-
-
int getutid_r(struct utmp *ut,
-
struct utmp *ubuf, struct utmp **ubufp);
-
-
int getutline_r(struct utmp *ut,
-
struct utmp *ubuf, struct utmp **ubufp);
-
-
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
-
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
-
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.
-
#include <apue.h>
-
#include <fcntl.h>
-
#include <utmp.h>
-
#include <sys/types.h>
-
#include <time.h>
-
-
typedef struct utmp utmp_record;
-
#define NUM_RECORDS 20
-
#define NULL_UTMP_RECORD_PTR ((utmp_record *)NULL)
-
#define SIZE_OF_UTMP_RECORD (sizeof(utmp_record))
-
#define BUFSIZE (NUM_RECORDS *SIZE_OF_UTMP_RECORD)
-
-
-
static char utmpbuf[BUFSIZE]; //buffer of records
-
static int number_of_recs_in_buffer; //num records in buffer
-
static int current_record; //next rec to read
-
static int fd_utmp=-1; // file descriptor for utmp file
-
-
void die(char* string1,char* string2);
-
int open_utmp(char *utmp_file);
-
int fill_utmp();
-
utmp_record *next_utmp();
-
void close_utmp();
-
void show_info(struct utmp *utbufp);
-
void show_time(long timeval);
-
-
void die(char* string1,char* string2){
-
fprintf(stderr,"Error: %s ",string1);
-
perror(string2);
-
exit(1);
-
}
-
-
-
int open_utmp(char *utmp_file)
-
{
-
fd_utmp=open(utmp_file,O_RDONLY);
-
current_record=0;
-
number_of_recs_in_buffer=0;
-
return fd_utmp; //either a valid file descriptor or -1
-
}
-
-
-
int fill_utmp()
-
{
-
int bytes_read;
-
-
//read NUM_RECORDS records from the utmp file into buffer
-
//bytes_read is the actual number of bytes read
-
bytes_read=read(fd_utmp,utmpbuf,BUFSIZE);
-
if(bytes_read < 0){
-
die("Failed to read from utmp file", "");
-
}
-
-
//if we reach here, the read was successful
-
//convert the byte count into a number of records
-
number_of_recs_in_buffer=bytes_read/SIZE_OF_UTMP_RECORD;
-
-
//reset current_record to start at the buffer start
-
current_record=0;
-
return number_of_recs_in_buffer;
-
}
-
-
utmp_record * next_utmp()
-
{
-
utmp_record *recordptr;
-
int byte_position;
-
-
if(fd_utmp==-1)
-
//file was not opened correctly
-
return NULL_UTMP_RECORD_PTR;
-
-
if(current_record==number_of_recs_in_buffer)
-
//there are no unread records in the buffer
-
//need to refill the buffer
-
if(fill_utmp()==0)
-
//no utmp records left in the file
-
return NULL_UTMP_RECORD_PTR;
-
-
//there is at lease one record in the buffer,so we can read it
-
byte_position=current_record * SIZE_OF_UTMP_RECORD;
-
recordptr=(utmp_record *)&utmpbuf[byte_position];
-
-
//advance current_record pointer and return record pointer
-
current_record++;
-
-
return recordptr;
-
}
-
-
void close_utmp()
-
{
-
// if file descriptor is a valid one,close the connection
-
if(fd_utmp!=-1)
-
close(fd_utmp);
-
-
}
-
-
void show_info(struct utmp *utbufp)
-
{
-
if(utbufp->ut_type !=USER_PROCESS)
-
return ;
-
-
printf("%-8.8s",utbufp->ut_name); //the logname
-
printf(" ");
-
printf("%-8.8s",utbufp->ut_line); //the tty
-
printf(" ");
-
show_time(utbufp->ut_time); //login time
-
printf(" ");
-
printf("(%s)",utbufp->ut_host); //the host
-
printf("\n");
-
}
-
-
-
void show_time(long timeval)
-
{
-
char* timestr=ctime(&timeval);
-
printf("%12.12s",timestr+4);
-
}
-
-
-
int main(int argc, char *argv[])
-
{
-
utmp_record *utbufp; //pointer to a utmp record
-
if(open_utmp(UTMP_FILE)==-1){
-
perror(UTMP_FILE);
-
exit(1);
-
}
-
-
-
while((utbufp=next_utmp())!=NULL_UTMP_RECORD_PTR)
-
show_info(utbufp);
-
-
close_utmp();
-
return 0;
-
}
阅读(1408) | 评论(0) | 转发(0) |