use popen replace temp file

前言

linux中,如果用C库函数不容易完成的任务,可以用linux命令组合做,将命令结果重定向到文件中, 分析文件的行内容,得到想要的结果。

但是使用临时文件, 可能面临多线程临时文件名冲突的问题.
也可能面临临时文件落地,引起的安全性问题.

前天看到一段代码, 使用了popen来执行命令,读命令结果的操作,都是针对管道完成。
经过比较 : 使用管道的操作,比使用临时文件简洁多了.

前几天写了一个demo, 取当前tty用户信息, 使用了分析临时结果文件的方法。
改了一版, 用管道操作来完成。改动量小,代码清晰度上升了。

试验

运行效果

[root@localhost src]# ./test 
info->tty_name = pts/0
info->user_name = root
info->login_time = 2018-06-18 04:54
info->ip = 192.168.180.1

demo下载点

src_test_get_curent_tty_info.7z

demo预览

// @file main.cpp
// @note on fedora22 view syslog use 'journalctl -f'
// 'tail -f /var/log/message' is invalid

#include <stdlib.h>
#include <stdio.h>

#include <string.h>
#include <unistd.h>

#include <syslog.h>
#include <signal.h>

// 日志级别 - 调试
#ifndef MYLOG_D

#define MYLOG_D(fmt, ...) \
    do { \
        syslog(LOG_INFO, "[%s : %s.%d : %s()] : " fmt, "LS_LOG", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); \
    } while (0);

#endif // #ifndef MYLOG_D

// info for crrent tty info
typedef struct _tag_who_info {
    char user_name[64];
    char tty_name[64];
    char login_time[64];
    char ip[64];
}TAG_WHO_INFO;

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

bool fn_get_current_tty_info(TAG_WHO_INFO* tty_info);
void fn_show_TAG_WHO_INFO(TAG_WHO_INFO* info);
bool fn_parse_cmd_result_file_who(FILE* fpipe, const char* tty_name, int len_ttyname, TAG_WHO_INFO* /*OUT*/ info);
bool fn_parse_cmd_result_file_tty(FILE* fpipe, char* ttyname, int len_ttyname);

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);
    openlog(((NULL != psz_log_owner_name) ? psz_log_owner_name : "my_syslog"), LOG_NOWAIT | LOG_PID, LOG_LOCAL1);

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

    signal(SIGTERM, proc_sig_term);
}

void uninit()
{
    closelog();
}

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);    
}

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

    memset(&tty_info, 0, sizeof(TAG_WHO_INFO));
    if (fn_get_current_tty_info(&tty_info)) {
        fn_show_TAG_WHO_INFO(&tty_info);
    } else {
        MYLOG_D("can't get current tty info");
    }

    return 0;
}

bool fn_get_current_tty_info(TAG_WHO_INFO* tty_info)
{
    bool rc = false;
    char sz_tty_name[64] = {'\0'};
    char sz_tty_name_for_who[64] = {'\0'};
    char * pfind = NULL;
    FILE* fpipe1 = NULL;
    FILE* fpipe2 = NULL;

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

        // exec 'tty'
        fpipe1 = popen("tty", "r");
        if (NULL == fpipe1) {
            break;
        }

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

        // 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'
        fpipe2 = popen("who", "r");
        if (NULL == fpipe2) {
            break;
        }

        // 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(fpipe2, sz_tty_name_for_who, strlen(sz_tty_name_for_who), tty_info)) {
            break;
        }

        rc = true;
    } while (0);

    if (NULL != fpipe1) {
        pclose(fpipe1);
        fpipe1 = NULL;
    }

    if (NULL != fpipe2) {
        pclose(fpipe2);
        fpipe2 = NULL;
    }

    return rc;
}

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

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

        memset(sz_buf, 0, sizeof(sz_buf));
        if (NULL != fgets(sz_buf, sizeof(sz_buf), fpipe)) {
            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);

    return rc;
}

bool fn_parse_cmd_result_file_who(FILE* fpipe, 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;
    bool first = true;
    bool find_tty_info = false;

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

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

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

        while (NULL != fgets(sz_buf, sizeof(sz_buf), fpipe)) {
            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);

    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);
}

#!/bin/bash
# ==============================================================================
# @file build_all_project.sh
# ==============================================================================

make BIN_NAME="test" rebuild

# ==============================================================================
# @file makefile
# ==============================================================================
# @note 
# howto build project
#       make BIN_NAME="bin_name_by_you_want" rebuild

MY_MAKE_FILE_PATH_NAME = $(MAKEFILE_LIST)

# macro from Makefile command line
# BIN_NAME

# macro to C project
MAKE_FILE_MACRO__BIN_NAME="make_file_macro__bin_name"

# var define on Makefile
BIN = output_not_give_bin_name
IS_BUILD_TYPE_VALID = 0

ifdef BIN_NAME
    IS_BUILD_TYPE_VALID = 1
    BIN = $(BIN_NAME)
    MAKE_FILE_MACRO__BIN_NAME=$(BIN_NAME)
else
    IS_BUILD_TYPE_VALID = 0
endif

LINE80 = --------------------------------------------------------------------------------
CC = g++ -std=c++98

# -Werror is "warning as error"
CFLAGS = -Wall -Werror -g

INC = -I.
LIBPATH = -L/usr/lib/ -L/usr/local/lib/

ifeq (1, $(IS_BUILD_TYPE_VALID))
    LIBS = 
else
    LIBS = 
endif

DEPEND_CODE_DIR = ./empty_dir \

DEPEND_CODE_SRC = $(shell find $(DEPEND_CODE_DIR) -name '*.cpp')
DEPEND_CODE_OBJ = $(DEPEND_CODE_SRC:.cpp=.o)

ROOT_CODE_SRC = $(shell find ./ -name '*.cpp')
ROOT_CODE_OBJ = $(ROOT_CODE_SRC:.cpp=.o)

SUB_CODE_DIR = ./socket_easy
SUB_CODE_SRC = $(shell find $(SUB_CODE_DIR) -name '*.cpp')
SUB_CODE_OBJ = $(SUB_CODE_SRC:.cpp=.o)

.PHONY: help
help:
    clear
    @echo "usage:"
    @echo
    @echo "build project by given bin name"
    @echo "make BIN_NAME=\"bin_name_by_you_want\" rebuild"
    @echo

.PHONY: clean
clean:
    clear

    @echo
    @echo
    @echo
    @echo
    @echo
    @echo
    @echo
    @echo
    @echo
    @echo

    @echo
    @echo
    @echo
    @echo
    @echo
    @echo
    @echo
    @echo
    @echo
    @echo

    @echo
    @echo
    @echo
    @echo
    @echo

    @echo "make clean begin"
    @echo $(LINE80)

    @echo "@file $(MY_MAKE_FILE_PATH_NAME)"
    @echo "IS_BUILD_TYPE_VALID = $(IS_BUILD_TYPE_VALID)"
    @echo "BIN = $(BIN)"

    @echo $(LINE80)

    rm -f $(ROOT_CODE_OBJ) $(DEPEND_CODE_OBJ) $(SUB_CODE_OBJ)

ifeq (1, $(IS_BUILD_TYPE_VALID))
    rm -f ./$(BIN)
endif

    @echo "make clean over"

.PHONY: all
all:$(BIN)
    @echo $(LINE80)
    @echo make all
    chmod 777 ./$(BIN)
    find . -name "$(BIN)"

$(BIN) : $(ROOT_CODE_OBJ) $(DEPEND_CODE_OBJ) $(SUB_CODE_OBJ)
    $(CC) $(CFLAGS) -o $@ $^ $(SHLIBS) $(INC) $(LIBPATH) $(LIBS)

.cpp.o:
    $(CC) -c $(CFLAGS) -DMAKE_FILE_MACRO__BIN_NAME="\"$(MAKE_FILE_MACRO__BIN_NAME)\"" $^ -o $@ $(INC) $(LIBPATH) $(LIBS)

.PHONY: rebuild
rebuild:
    make -f $(MY_MAKE_FILE_PATH_NAME) clean

ifeq (1, $(IS_BUILD_TYPE_VALID))
    @echo $(LINE80)
    make -f $(MY_MAKE_FILE_PATH_NAME) all
    chmod 775 ./$(BIN)
    ldd ./$(BIN)
else
    @echo $(LINE80)
    @echo "error : Makefile command line input error, please see help"  
    @echo "please run => make help" 
    @echo $(LINE80)
endif


猜你喜欢

转载自blog.csdn.net/lostspeed/article/details/80726437
今日推荐