2021/03/17

C 將 stdout 轉給 console

daemon 的除錯訊息被殼層吃掉的時候, 將訊息丟到 console 可以方便除錯, 如果是每次呼叫 debug 時都 openfile 和 closefile 會有點浪費資源, 所以直接將 stdout 轉給 console, 就能繼續用 printf 來送出除錯訊息了.

做法就是開個 file handler 給 console, 然後重新將 stdout 設定給 console 的 file handler. 範例程式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <stdio.h>
int main()
{
	FILE *stdout_bk;
	FILE *fpout = fopen("/dev/console" ,"w" );
	stdout_bk = stdout;
	printf("printf not to console\n");
	stdout = fpout;
	printf("printf to console\n");
	stdout = stdout_bk;
	return 0;
}


做成 MACRO

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#ifdef AIMDBG
#undef AIMDBG
#endif
#define AIMDBG(fmt,...) \
do { \
    FILE *console = fopen("/dev/console" ,"w" ); \
    if (console) { \
        fprintf(console, fmt, __VA_ARGS__); \
        fflush(console); \
        fclose(console); \
    } \
} while(0)


追加 Hexdump

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
static void hexdump (uint8_t* ptr, int len) {
    int i;
    for (i=0; i<len; i++) {
        if (15 == (i % 16)) {
            AIMDBG("%02X\n", ptr[i]);
        }
        else if (7 == (i % 8)) {
            AIMDBG("%02X   ", ptr[i]);
        }
        else {
            AIMDBG("%02X ", ptr[i]);
        }
    }
    AIMDBG("%s", "\n");
}


類似 printf 的用法直接輸出到 console
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
void console_debug(const char *fmt, ...)
{
    static FILE *console_fp = NULL;
    static int tried_open = 0;

    if (!tried_open) {
        console_fp = fopen("/dev/console", "w");
        if (console_fp == NULL) {
            perror("Warning: Cannot open /dev/console, fallback to stderr");
            console_fp = stderr;
        }
        tried_open = 1;
    }
    char log_buf[1024];
    va_list args;
    va_start(args, fmt);
    vsnprintf(log_buf, sizeof(log_buf), fmt, args);
    va_end(args);
    fprintf(console_fp, "[SYSLOGD] %s", log_buf);
    fflush(console_fp);
}

沒有留言: