linux检测有回显执行命令,通过dup2实现linux命令回显的捕获

前言

在bash代码中,看到关闭了一个fd后,屏幕上才出现linux命令执行后的回显内容.

做了一个试验,实现了回显数据的捕获。

实现思路:

dup2重定向stdin到自己建立的管道

select管道,如果有数据就读取管道中的数据,并转发. 如果超时,就跳出.

做了好久的试验,终于达到预期的效果了:)

demo

// @file main.cpp

// @note on fedora22 view syslog use 'journalctl -f'

// 'tail -f /var/log/message' is invalid

#include

#include

#include

#include

#include

#include

#include

#include

#include

// 日志级别 - 调试

#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

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

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()

{

int fd_stdin_org = -1;

int fd_stdout_org = -1;

int fd_stderr_org = -1;

char sz_buf[1024] = {'\0'};

// char* p_rd = NULL;

int n = 0;

int my_pipe[2] = {0};

int fd0 = -1;

int fd1 = -1;

FILE* fp = NULL;

const char* msg = NULL;

fd_set rfds;

struct timeval tv;

int retval;

MYLOG_D(">> fn_test()");

//printf("STDIN_FILENO = %d\n", STDIN_FILENO);

//printf("STDOUT_FILENO = %d\n", STDOUT_FILENO);

//printf("STDERR_FILENO = %d\n", STDERR_FILENO);

/*

STDIN_FILENO = 0

STDOUT_FILENO = 1

STDERR_FILENO = 2

*/

do {

// backup original STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO

fd_stdin_org = dup(STDIN_FILENO);

if (fd_stdin_org < 0) {

break;

}

fd_stdout_org = dup(STDOUT_FILENO);

if (fd_stdout_org < 0) {

break;

}

fd_stderr_org = dup(STDERR_FILENO);

if (fd_stderr_org < 0) {

break;

}

// if want view a file will be create later, can use 'tail -F obj_file_path_name'

msg = "1. write to stdout";

printf("%s\n", msg); // write to stdout

if(pipe(my_pipe) == -1)

{

break;

}

fd0 = dup2(my_pipe[0], STDIN_FILENO);

if (fd0 != STDIN_FILENO) {

break;

}

fd1 = dup2(my_pipe[1], STDOUT_FILENO);

if (fd1 != STDOUT_FILENO) {

break;

}

msg = "2. write to my_pipe[0]";

printf("%s\n", msg); // write to my_pipe

msg = "3. write to my_pipe[0]";

printf("%s\n", msg); // write to my_pipe

fp = fdopen(fd0, "r");

if (NULL != fp) {

FD_ZERO(&rfds);

FD_SET(fd0, &rfds);

tv.tv_sec = 5;

tv.tv_usec = 0;

do {

retval = select(1, &rfds, NULL, NULL, &tv);

if (retval < 0) {

// error happen

break;

} else if (retval > 0) {

// now, data is available

if (FD_ISSET(fd0, &rfds)) {

// method 1

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

// read 可以将用户多次输入的数据都读全

n = read(fd0, sz_buf, sizeof(sz_buf));

if(n < 0) {

break;

}

// MYLOG_D("read from pipe : %s", buf);

// method 2

// get user input

/*

// 输入多句,fgets只能读第一句, 再select时,就超时了, 第2句没读到

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

// 因为上面就写了1句,fgets执行一次就没数据了

// 为了防止阻塞, 不能直接调用fgets, 必须用select的超时机制来防止阻塞

p_rd = fgets(sz_buf, sizeof(sz_buf) - 1, fp); // if user not input and fp is valid, will block here

if (NULL == p_rd) {

break;

}

*/

} else {

// fd is invalid, break

break;

}

}

else {

// time out

break;

}

// trans user input to real stdout

// can trans user input to other from this point

write(fd_stdout_org, sz_buf, sizeof(sz_buf));

// read user input continue

} while (1);

fclose(fp);

fp = NULL;

}

close(my_pipe[0]);

my_pipe[0] = -1;

close(my_pipe[1]);

my_pipe[1] = -1;

} while (0);

if (fd0 >= 0) {

close(fd0);

fd0 = -1;

}

if (fd1 >= 0) {

close(fd1);

fd1 = -1;

}

if (fd_stdin_org >= 0) {

close(STDIN_FILENO);

dup2(fd_stdin_org, STDIN_FILENO); // restore original stdin

close(fd_stdin_org);

fd_stdin_org = -1;

}

if (fd_stdout_org >= 0) {

close(STDOUT_FILENO);

dup2(fd_stdout_org, STDOUT_FILENO); // restore original stdout

close(fd_stdout_org);

fd_stdout_org = -1;

}

if (fd_stderr_org >= 0) {

close(STDERR_FILENO);

dup2(fd_stdout_org, STDERR_FILENO); // restore original stderr

close(fd_stderr_org);

fd_stderr_org = -1;

}

return 0;

}

标签:FILENO,回显,dup2,int,sz,fd,linux,org,buf

来源: https://blog.csdn.net/LostSpeed/article/details/80727983

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值