linux c : get curent tty info

前言

在linux shell 中可以用命令来看tty信息
tty 看当前tty名称
who 看所有登陆用户的信息。
结合这2个命令,可以分析出当前tty登陆的信息(tty_name, user_name, long_time, client ip).
将tty和who重定向到文件中,用程序模拟分析,得到了当前tty登陆的信息。

效果

[root@localhost src]# ./test
info->tty_name = pts/3
info->user_name = root
info->login_time = 2018-06-15 20:49
info->ip = 192.168.154.1

测试工程

// @file main.cpp

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <linux/limits.h>

#include <pwd.h>
#include <utmp.h>

#include "my_syslog.h"
#include "time_convert.h"

#ifndef SAFE_DELETE
#define SAFE_DELETE(p) \
    if (NULL != (p)) { \
        delete (p); \
        (p) = NULL; \
    }
#endif // #ifndef SAFE_DELETE

void init(const char* psz_log_owner_name);
void uninit();
void proc_sig_term(int num);
int fn_test();

int main(int argc, char** argv)
{
    char sz_buf[1024] = {'\0'};

#ifdef MAKE_FILE_MACRO__BIN_NAME
    sprintf(sz_buf, "%s", MAKE_FILE_MACRO__BIN_NAME);
    init(sz_buf);
    MYLOG_D("MAKE_FILE_MACRO__BIN_NAME = [%s]", MAKE_FILE_MACRO__BIN_NAME);
#else
    init(NULL);
#endif // #ifdef MAKE_FILE_MACRO__BIN_NAME

    fn_test();
    uninit();

    MYLOG_D("THE END");
    return EXIT_SUCCESS;
}

void init(const char* psz_log_owner_name)
{
    int i = 0;

    // daemon(0, 0);

    ns_syslog::open_syslog((NULL != psz_log_owner_name) ? psz_log_owner_name : "ns_syslog");

    // 设置控制变量中的日志条件, 实际应用中, 是从配置文件读取的控制开关
    ns_syslog::g_log_condition.b_EMERG = false;
    ns_syslog::g_log_condition.b_CRIT = true;
    ns_syslog::g_log_condition.b_ALERT = true;
    ns_syslog::g_log_condition.b_ERR = true;
    ns_syslog::g_log_condition.b_WARNING = true;
    ns_syslog::g_log_condition.b_NOTICE = true;
    ns_syslog::g_log_condition.b_INFO = true;
    ns_syslog::g_log_condition.b_DEBUG = true;

    // 根据控制变量, 设置日志的mask
    // 在实际应用中, 这里可以是动态设置, e.g. 配置文件检测线程发现配置变了, 需要变更某些级别的日志记录结果
    ns_syslog::set_log_level(
        ns_syslog::g_log_condition.b_EMERG, 
        ns_syslog::g_log_condition.b_ALERT,
        ns_syslog::g_log_condition.b_CRIT,
        ns_syslog::g_log_condition.b_ERR,
        ns_syslog::g_log_condition.b_WARNING,
        ns_syslog::g_log_condition.b_NOTICE,
        ns_syslog::g_log_condition.b_INFO,
        ns_syslog::g_log_condition.b_DEBUG);

    // clear screen (print 25 empty line)
    for (i = 0; i < 25; i++) {
        MYLOG_D("");
    }

    signal(SIGTERM, proc_sig_term);
}

void uninit()
{
    ns_syslog::close_syslog();
}

void proc_sig_term(int num)
{
    MYLOG_D("SIGTERM = %d, num = %d", SIGTERM, num);
    MYLOG_D("maybe can do some clean task before quit");
    exit(1);    
}

bool fn_get_tmp_flie_path_name(char* buf, int buf_len) {
    bool rc = false;
    char sz_tmp_file_name[PATH_MAX] = {'\0'};
    char* psz_tmp_file_name = NULL;
    int len_tmp_file_name = 0;

    do {
        if ((NULL == buf) || (buf_len <= 0)) {
            break;
        }

        memset(buf, 0, buf_len);

        strcpy(sz_tmp_file_name, "/tmp/my_tmp_XXXXXX"); // the post fix "XX" must 6X, e.g. "XXXXXX"
        psz_tmp_file_name = mktemp(sz_tmp_file_name);
        if (NULL == psz_tmp_file_name) {
            break;
        }

        len_tmp_file_name = strlen(sz_tmp_file_name);
        if (len_tmp_file_name > (buf_len - 1)) {
            break;
        }

        strcpy(buf, sz_tmp_file_name);
        rc = true;
    } while (0);

    return rc;
}

bool fn_parse_cmd_result_file_tty(const char* cmd_result_name, char* ttyname, int len_ttyname)
{
    bool rc = false;
    char sz_buf[4096] = {'\0'};
    int len_read_back = 0;
    FILE* fp = NULL;

    do {
        if (NULL == ttyname) {
            break;
        }

        // get result from temp file
        fp = fopen(cmd_result_name, "r");
        if (NULL == fp) {
            break;
        }

        memset(sz_buf, 0, sizeof(sz_buf));
        if (NULL != fgets(sz_buf, sizeof(sz_buf), fp)) {
            len_read_back = strlen(sz_buf);
            if (len_read_back <= 0) {
                break;
            }

            if (('\r' == sz_buf[len_read_back - 1])
                || ('\n' == sz_buf[len_read_back - 1]))
            {
                sz_buf[len_read_back - 1] = '\0';
            }
        }

        if ((len_ttyname - 1) < len_read_back) {
            break;
        }

        strcpy(ttyname, sz_buf);

        rc = true;
    } while (0);

    if (NULL != fp) {
        fclose(fp);
        fp = NULL;
    }

    return rc;
}

typedef struct _tag_who_info {
    char user_name[64];
    char tty_name[64];
    char login_time[64];
    char ip[64];
}TAG_WHO_INFO;

bool fn_parse_cmd_result_file_who(const char* cmd_result_name, const char* tty_name, int len_ttyname, TAG_WHO_INFO* /*OUT*/ info)
{
    bool rc = false;
    char sz_buf[4096] = {'\0'};
    int len_read_back = 0;

    char* p = NULL;
    char* buffer = NULL;
    const char* delims = " ";
    int pos = 0;
    int len = 0;
    FILE* fp = NULL;
    bool first = true;
    bool find_tty_info = false;

    do {
        if ((NULL == cmd_result_name) || (NULL == tty_name) || (NULL == info)) {
            break;
        }

        memset(info, 0, sizeof(TAG_WHO_INFO));

        // get result from temp file
        fp = fopen(cmd_result_name, "r");
        if (NULL == fp) {
            break;
        }

        memset(sz_buf, 0, sizeof(sz_buf));

        while (NULL != fgets(sz_buf, sizeof(sz_buf), fp)) {
            len_read_back = strlen(sz_buf);
            if (len_read_back <= 0) {
                continue;
            }

            if (('\r' == sz_buf[len_read_back - 1])
                || ('\n' == sz_buf[len_read_back - 1]))
            {
                sz_buf[len_read_back - 1] = '\0';
            }

            /*
            [root@localhost src]# who               
            root     tty1         2018-06-15 20:06
            root     pts/0        2018-06-15 20:09 (192.168.154.1)
            root     pts/1        2018-06-15 20:35 (192.168.154.1)
            root     pts/2        2018-06-15 20:40 (192.168.154.1)
            root     pts/3        2018-06-15 20:49 (192.168.154.1)
            root     pts/4        2018-06-15 21:13 (192.168.154.1)
            */

            first = true;
            pos = 0;
            buffer = strdup(sz_buf);
            if (NULL != buffer) {
                do {
                    if (first) {
                        p = strtok(buffer, delims);
                        first = false;
                    } else {
                        p = strtok(NULL, delims);
                    }

                    if (NULL == p) {
                        break;
                    }

                    switch (pos) {
                        case 0:
                            strcpy(info->user_name, p);
                            break;

                        case 1:
                            strcpy(info->tty_name, p);
                            break;

                        case 2:
                            strcpy(info->login_time, p);
                            strcat(info->login_time, " ");

                            break;

                        case 3:
                            strcat(info->login_time, p);

                            break;

                        case 4:
                            len = strlen(p);
                            if (len > 0) {
                                if (p[0] == '(') {
                                    len = strlen(p);
                                    strncpy(info->ip, p + 1, len - 2);
                                } else {
                                    strcpy(info->ip, p);
                                }
                            } else {
                                strcpy(info->ip, "127.0.0.1");
                            }

                            break;
                        default:
                            break;
                    }

                    pos++;

                    if (pos > 4) {
                        break;
                    }
                } while (1);

                free(buffer);
                buffer = NULL;
            }

            if (0 == strcmp(info->tty_name, tty_name)) {
                find_tty_info = true;
                break; // find tty_name info
            } else {
                memset(info, 0, sizeof(TAG_WHO_INFO));
            }
        }

        rc = find_tty_info;
    } while (0);

    if (NULL != fp) {
        fclose(fp);
        fp = NULL;
    }

    return rc;
}

void fn_show_TAG_WHO_INFO(TAG_WHO_INFO* info)
{
    do {
        if (NULL == info) {
            break;
        }

        printf("info->tty_name = %s\n", info->tty_name);
        printf("info->user_name = %s\n", info->user_name);
        printf("info->login_time = %s\n", info->login_time);
        printf("info->ip = %s\n", info->ip);
    } while (0);
}

void fn_get_current_tty_info() {
    char sz_buf[1024];
    char sz_tmp_file_name[PATH_MAX];
    char sz_tty_name[64];
    char sz_tty_name_for_who[64];
    char * pfind = NULL;
    TAG_WHO_INFO cur_tty_info;

    do {
        memset(sz_buf, 0, sizeof(sz_buf));
        memset(sz_tmp_file_name, 0, sizeof(sz_tmp_file_name));

        // get temp file name
        if (!fn_get_tmp_flie_path_name(sz_tmp_file_name, (int)sizeof(sz_tmp_file_name))) {
            break;
        }

        // exec 'tty' to temp file
        sprintf(sz_buf, "tty > %s%c", sz_tmp_file_name, '\0');
        system(sz_buf);

        if (!fn_parse_cmd_result_file_tty(sz_tmp_file_name, sz_tty_name, sizeof(sz_tty_name))) {
            break;
        }

        // delete temp file
        sprintf(sz_buf, "rm -f %s%c", sz_tmp_file_name, '\0');
        system(sz_buf);

        // printf("current tty name is [%s]\n", sz_tty_name); // current tty name is [/dev/pts/1]
        // printf( "Controlling terminal is %s\n", ctermid( NULL ) ); // Controlling terminal is /dev/tty

        // get tty name for cmd 'who'
        pfind = strstr(sz_tty_name, "/dev/");
        if (NULL == pfind) {
            strcpy(sz_tty_name_for_who, sz_tty_name);
        } else {
            strcpy(sz_tty_name_for_who, sz_tty_name + strlen("/dev/"));
        }

        // exec 'who' to temp file
        sprintf(sz_buf, "who > %s%c", sz_tmp_file_name, '\0');
        system(sz_buf);

        // sz_tty_name_for_who is [pts/1]
        // printf("sz_tty_name_for_who is [%s]\n", sz_tty_name_for_who);

        if (!fn_parse_cmd_result_file_who(sz_tmp_file_name, sz_tty_name_for_who, strlen(sz_tty_name_for_who), &cur_tty_info)) {
            break;
        }

        fn_show_TAG_WHO_INFO(&cur_tty_info);

    } while (0);
}

int fn_test()
{
    MYLOG_D(">> fn_test()");

    fn_get_current_tty_info();

    return 0;
}

猜你喜欢

转载自blog.csdn.net/lostspeed/article/details/80713398
tty