前言
在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;
}