دستور lastlog(8) در سیستم‌های شبه یونیکس زمان آخرین لاگین کاربر در سیستم را نشان می‌دهد. این اطلاعات در فایلی به نام lastlog و به صورت struct در آفست خاصی از آن ذخیره شده است. به عنوان مثال اطلاعات کاربری با USERID=1000 در آفست زیر قرار دارد:

off_t offset = 1000 * sizeof(struct lastlog);

حال کافی است فایل را باز کرده، به آفست مورد نظر رفته و اطلاعات فایل را بخوانیم. برای لینک کردن USERID با نام واقعی باید از توابع مربوط به فایل /etc/passwd استفاده کنیم.

کد این برنامه را ملاحظه می‌کنید:

lastlog.c
/*
 * lastlog(8) simulation
 * 
 * Mohsen Safari
 * ----------------------------------
 * 
 * dokaj.ir
 * safari.tafreshi@gmail.com
 */

#include <stdio.h>
#include <stdlib.h>
#include <lastlog.h>
#include <err.h>
#include <pwd.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <paths.h>
#include <time.h>
#include <string.h>

void
usage(const char *program_name)
{
    fprintf(stderr, "usage: %s [-h -u login-name]\n", program_name);
    exit(EXIT_FAILURE);
}

int
main(int argc, char *argv[])
{
    struct passwd *passwd;
    struct lastlog lastlog;
    ssize_t num_read;
    int fd, flag = 0, opt;
    time_t time;
    struct tm *tm;
    char buf[40];
    char *user = NULL;

    while ((opt = getopt(argc, argv, ":hu:")) != -1) {
        switch (opt) {
        case 'u':
            user = optarg;
            break;
        case 'h':
            usage(argv[0]);
            //NOTREACHED
        case '?':
            errx(EXIT_FAILURE, "unknown option -%c", optopt);
        case ':':
            errx(EXIT_FAILURE, "-%c needs argument", optopt);
        }
    }

    fd = open(_PATH_LASTLOG, O_RDONLY);
    if (fd == -1)
        err(EXIT_FAILURE, "open");

    setpwent();

    memset(&lastlog, 0, sizeof(struct lastlog));

    do {
        errno = 0;
        passwd = user ? getpwnam(user) : getpwent();
        if (passwd == NULL) {
            if (errno)
                err(EXIT_FAILURE, "getpw*");

            if (user)
                errx(EXIT_FAILURE, "Unknown user: %s", user);
            // EOF
            break;
        }

        if (lseek(fd, passwd->pw_uid * sizeof(struct lastlog), SEEK_SET) == -1)
            err(EXIT_FAILURE, "lseek");

        if ((num_read = read(fd, &lastlog, sizeof(lastlog))) == -1)
            err(EXIT_FAILURE, "read");

        time = lastlog.ll_time;

        if (time == 0)
            strcpy(buf, "**Never logged in**");
        else {
            tm = localtime(&time);
            strftime(buf, sizeof(buf), "%a %b %d %H:%M:%S %z %Y", tm);
        }

        if (!flag) {
            printf("Username         Port     From             Latest\n");
            flag = 1;
        }

        printf("%-16s %-8s %-16s %-s\n", passwd->pw_name, lastlog.ll_line,
                lastlog.ll_host, buf);

    } while (user == NULL);

    endpwent();
    close(fd);

    exit(EXIT_SUCCESS);
}

کامپایل برنامه و نمونه خروجی آن به صورت زیر است:

SHELL
$ gcc -o lastlog lastlog.c
$ ./lastlog | tail -8
mohsen           tty1                      Wed Dec 23 23:51:44 +0330 2020
systemd-coredump                           **Never logged in**
mysql                                      **Never logged in**
debian-tor                                 **Never logged in**
lightdm                                    **Never logged in**
tcpdump                                    **Never logged in**
fake             tty3                      Wed Dec 23 21:22:59 +0330 2020
sara                                       **Never logged in**

$ ./lastlog -u fake
Username         Port     From             Latest
fake             tty3                      Wed Dec 23 21:22:59 +0330 2020
نوشته شده در: 1402-02-18 (1 سال 6 روز 19 ساعت پیش)

من محسن هستم؛ برنامه‌نویس PHP و Laravel و Zend Framework و پایتون و فلسک، ولی بیشتر تمرکزم روی لاراول است. این سایت را اولین بار با فلسک نوشتم ولی بعد تصمیم گرفتم آن را با لاراول نیز پیاده‌سازی کنم. هم نسخه‌ی فسلک و هم نسخه‌ی لاراول را می‌توانید روی گیت‌هابم پیدا و دانلود کنید.

برای ارتباط با من یا در همین سایت کامنت بگذارید و یا به dokaj.ir(at)gmail.com ایمیل بزنید.

در مورد این مطلب یادداشتی بنویسید.