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

实现思路是和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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值