ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
io.c
Go to the documentation of this file.
1
5
6#include <ascii-chat/log/io.h>
8#include <libplatform/compiler.h>
9#include <libplatform/system.h>
10#include <libplatform/terminal.h>
11#include <string.h>
12
13#define LOG_IO_BUFFER_SIZE 8192
14
16 log_io_t capture = {.saved_stdout_fd = -1, .saved_stderr_fd = -1, .output = NULL};
17
18 // A pipe cannot be drained until the wrapped call returns. A temporary file
19 // lets backend worker threads finish even when diagnostics exceed pipe capacity.
20 capture.output = platform_tmpfile();
21 if (!capture.output)
22 return capture;
23
24 fflush(stdout);
25 fflush(stderr);
26 capture.saved_stdout_fd = platform_dup(STDOUT_FILENO);
27 capture.saved_stderr_fd = platform_dup(STDERR_FILENO);
28 if (capture.saved_stdout_fd < 0 || capture.saved_stderr_fd < 0)
29 goto fail;
30
31 int output_fd = platform_fileno(capture.output);
32 if (platform_dup2(output_fd, STDOUT_FILENO) != ASCIICHAT_OK)
33 goto fail;
34 if (platform_dup2(output_fd, STDERR_FILENO) != ASCIICHAT_OK) {
35 // Restore stdout if only the first redirection succeeded.
36 platform_dup2(capture.saved_stdout_fd, STDOUT_FILENO);
37 goto fail;
38 }
39 return capture;
40
41fail:
42 if (capture.saved_stdout_fd >= 0)
43 platform_close(capture.saved_stdout_fd);
44 if (capture.saved_stderr_fd >= 0)
45 platform_close(capture.saved_stderr_fd);
46 fclose(capture.output);
47 return (log_io_t){.saved_stdout_fd = -1, .saved_stderr_fd = -1, .output = NULL};
48}
49
50void log_io_stop(log_io_t capture, const char *prefix) {
51 if (capture.saved_stdout_fd < 0 || capture.saved_stderr_fd < 0) {
52 return; // Capture was not started successfully
53 }
54
55 // Flush before restoring so buffered backend output is captured.
56 fflush(stdout);
57 fflush(stderr);
58
59 // Restore stdout and stderr
60 platform_dup2(capture.saved_stdout_fd, STDOUT_FILENO);
61 platform_dup2(capture.saved_stderr_fd, STDERR_FILENO);
62 platform_close(capture.saved_stdout_fd);
63 platform_close(capture.saved_stderr_fd);
64
65 // Read and log the captured output
66 if (capture.output) {
67 char buffer[LOG_IO_BUFFER_SIZE];
68 size_t bytes_read;
69
70 // Replay only after restoring the descriptors, so logger output cannot feed
71 // back into this capture. fseek synchronizes the stream with descriptor writes.
72 if (fseek(capture.output, 0, SEEK_SET) != 0) {
73 fclose(capture.output);
74 return;
75 }
76 while ((bytes_read = fread(buffer, 1, sizeof(buffer) - 1, capture.output)) > 0) {
77 buffer[bytes_read] = '\0';
78
79 // Split by lines and log each line
80 char *line_start = buffer;
81 char *line_end;
82
83 while ((line_end = strchr(line_start, '\n')) != NULL) {
84 // Null-terminate the line (overwriting the newline)
85 *line_end = '\0';
86
87 // Log the line if it's not empty
88 if (line_start[0] != '\0') {
89 if (prefix) {
90 log_debug("[%s] %s", prefix, line_start);
91 } else {
92 log_debug("%s", line_start);
93 }
94 }
95
96 // Move to the next line
97 line_start = line_end + 1;
98 }
99
100 // Log any remaining partial line
101 if (line_start[0] != '\0') {
102 if (prefix) {
103 log_debug("[%s] %s", prefix, line_start);
104 } else {
105 log_debug("%s", line_start);
106 }
107 }
108 }
109
110 fclose(capture.output);
111 }
112}
@ ASCIICHAT_OK
Definition error_codes.h:46
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:595
asciichat_error_t platform_dup2(int source_fd, int target_fd)
int platform_fileno(FILE *stream)
int platform_dup(int fd)
log_io_t log_io_start(void)
Start capturing stdout and stderr.
Definition io.c:15
void log_io_stop(log_io_t capture, const char *prefix)
Stop capturing and log the accumulated output.
Definition io.c:50
#define LOG_IO_BUFFER_SIZE
Definition io.c:13
Capture stdout/stderr and redirect to logging system.
📝 Logging API with multiple log levels and terminal output control
🔤 String Manipulation and Shell Escaping Utilities
Saved descriptors and temporary file used during stdout/stderr capture.
Definition io.h:37
FILE * output
Temporary capture file, deleted on close.
Definition io.h:40
int saved_stdout_fd
Saved stdout file descriptor.
Definition io.h:38
int saved_stderr_fd
Saved stderr file descriptor.
Definition io.h:39