【C语言】实现Linux下的last命令的基本功能

来源:互联网 发布:买了域名之后怎么备案 编辑:程序博客网 时间:2024/05/22 06:12

实现思路是和who命令差不多,通过读取WTMP_FILE来获取相应的属性,下面的做法不支持传递参数,只做了基本的功能。

代码实现

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <utmp.h>#include <fcntl.h>#include <time.h>#define NRECS 16#define NULLUT ((struct utmp *)NULL)#define UTSIZE (sizeof(struct utmp))static char utmpbuf[NRECS*UTSIZE];static int num_recs;static int cur_rec;static int fdWtmp = -1;struct utmp_list{    struct utmp value;    struct utmp_list * next;};int wtmp_open(char * filename){    fdWtmp = open(filename, O_RDONLY);    cur_rec = num_recs = 0;    return fdWtmp;}int wtmp_reload(void){    int amt_read;    amt_read = read(fdWtmp, utmpbuf, NRECS * UTSIZE);    num_recs = amt_read/UTSIZE;    cur_rec = 0;    return num_recs;}struct utmp * wtmp_next(void){    struct utmp * recp;    if(fdWtmp == -1)        return NULLUT;    if(cur_rec == num_recs && wtmp_reload() == 0)        return NULLUT;    recp = (struct utmp *)&utmpbuf[cur_rec * UTSIZE];    cur_rec++;    return recp;}void wtmp_close(void){    if(fdWtmp != -1)        close(fdWtmp);}struct utmp_list * st_list_init(void){    struct utmp_list * list = (struct utmp_list *)malloc(sizeof(struct utmp_list));    if(!list)    {        printf("struct utmp_list malloc failed\n");        return NULL;    }    memset(list, 0 , sizeof(struct utmp_list));    return list;}struct utmp * st_utmp_init(void){    struct utmp * stUTMP = (struct utmp *)malloc(sizeof(struct utmp));    if(!stUTMP)    {        printf("struct utmp malloc failed\n");        return NULL;    }    memset(stUTMP, 0 , sizeof(struct utmp));    return stUTMP;}void list_insert(struct utmp_list * list, struct utmp * value){    if(!list)        return;    struct utmp_list *pList = list;    while(pList->next)        pList = pList->next;    struct utmp_list * node = (struct utmp_list *)malloc(sizeof(struct utmp_list));    if(!node)    {        printf("malloc struct utmp_list failed\n");        return;    }    if(value)        memcpy(&node->value, value, sizeof(struct utmp));    node->next = NULL;    pList->next = node;}int list_get_ele_and_del(struct utmp_list * list, char * value, struct utmp * retUtmp){    if(!list)    {        printf("List is empty, insert error\n");        return -1;    }    struct utmp_list * pList = list;    struct utmp_list * beforeNode = list;    while(pList)    {        if(0 == strcmp(value, pList->value.ut_line))        {            beforeNode->next = pList->next;            if(retUtmp)                memcpy(retUtmp, &pList->value, sizeof(struct utmp));            free(pList);            return 0;        }        else        {            beforeNode = pList;            pList = pList->next;        }    }        return -1;}void show_end_time(long timeval){    struct tm *t;    char tt[12] = {0};    t = localtime(&timeval);    strftime(tt, 100, "%R", t);    printf("%s", tt);}void show_start_time(long timeval){    struct tm *t;    char tt[32] = {0};    t = localtime(&timeval);    strftime(tt, 100, "%a %b %e %R", t);    printf("%s", tt);    printf(" - ");}void show_base_info(struct utmp * uBuf){    printf("%-9.8s", uBuf->ut_name);    if(uBuf->ut_type == BOOT_TIME)        printf("%-13s", "system boot");    else        printf("%-13.8s", uBuf->ut_line);    printf("%-17.16s", uBuf->ut_host);}int main(void){    int ret = -2;    struct utmp *utbufp, *wtmp_next();    if(wtmp_open(WTMP_FILE) == -1)    {        printf("open WTMP_FILE file error\n");        exit(1);    }    struct utmp_list * normalList = st_list_init();    struct utmp_list * deadList = st_list_init();    struct utmp * nodeUTMP = st_utmp_init();    while((utbufp = wtmp_next()) != ((struct utmp *)NULL))    {        if(utbufp->ut_type == USER_PROCESS || utbufp->ut_type == BOOT_TIME)            list_insert(normalList, utbufp);        else if(utbufp->ut_type == DEAD_PROCESS)            list_insert(deadList, utbufp);         }    normalList = normalList->next;    while(normalList)    {         memset(nodeUTMP, 0, sizeof(struct utmp));         ret = list_get_ele_and_del(deadList, normalList->value.ut_line, nodeUTMP);        show_base_info(&normalList->value);        show_start_time(normalList->value.ut_time);        if(deadList != NULL && ret != -1)            show_end_time(nodeUTMP->ut_time);        else if(ret == -1 && normalList->value.ut_type == USER_PROCESS)            printf("still logged in");        else if(ret == -1 && normalList->value.ut_type == BOOT_TIME)            printf("system boot");        normalList = normalList->next;        printf("\n");    }    wtmp_close();    return 0;}
0 0