Piping of commands into text files

usage: xxx(command) > xxxx.xxx (file)
This commit is contained in:
Chris 2026-02-04 21:37:51 +01:00
parent 5e3dc237cc
commit e7752b7253
13 changed files with 134 additions and 41 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -27,6 +27,7 @@ void cli_cmd_mkdir(char *args);
void cli_cmd_rm(char *args); void cli_cmd_rm(char *args);
void cli_cmd_echo(char *args); void cli_cmd_echo(char *args);
void cli_cmd_cat(char *args); void cli_cmd_cat(char *args);
void cli_cmd_touch(char *args);
// Memory management commands // Memory management commands
void cli_cmd_meminfo(char *args); void cli_cmd_meminfo(char *args);

View file

@ -239,3 +239,39 @@ void cli_cmd_cat(char *args) {
fat32_close(fh); fat32_close(fh);
} }
void cli_cmd_touch(char *args) {
if (!args || args[0] == 0) {
cli_write("Usage: touch <filename>\n");
return;
}
char filename[256];
int i = 0;
while (args[i] && args[i] != ' ' && args[i] != '\t') {
filename[i] = args[i];
i++;
}
filename[i] = 0;
// Check if file already exists
if (fat32_exists(filename)) {
cli_write("File already exists: ");
cli_write(filename);
cli_write("\n");
return;
}
// Open file in write mode to create it
FAT32_FileHandle *fh = fat32_open(filename, "w");
if (!fh) {
cli_write("Error: Cannot create file\n");
return;
}
fat32_close(fh);
cli_write("Created: ");
cli_write(filename);
cli_write("\n");
}

View file

@ -14,8 +14,8 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#define CMD_COLS 70 #define CMD_COLS 116
#define CMD_ROWS 25 #define CMD_ROWS 41
#define LINE_HEIGHT 10 #define LINE_HEIGHT 10
#define CHAR_WIDTH 8 #define CHAR_WIDTH 8
#define PROMPT "> " #define PROMPT "> "
@ -108,6 +108,10 @@ static int pager_top_line = 0;
// Boot time for uptime // Boot time for uptime
int boot_time_init = 0; int boot_time_init = 0;
// Output redirection state
static FAT32_FileHandle *redirect_file = NULL;
static char redirect_mode = 0; // '>' for write, 'a' for append, 0 for normal output
int boot_year, boot_month, boot_day, boot_hour, boot_min, boot_sec; int boot_year, boot_month, boot_day, boot_hour, boot_min, boot_sec;
// --- Helpers --- // --- Helpers ---
@ -193,6 +197,12 @@ static void cmd_scroll_up() {
// Public for CLI apps to use // Public for CLI apps to use
void cmd_putchar(char c) { void cmd_putchar(char c) {
// If output is being redirected to a file, write there instead
if (redirect_file && redirect_mode) {
fat32_write(redirect_file, &c, 1);
return;
}
if (c == '\n') { if (c == '\n') {
cursor_col = 0; cursor_col = 0;
cursor_row++; cursor_row++;
@ -225,9 +235,15 @@ void cmd_putchar(char c) {
// Public for CLI apps to use // Public for CLI apps to use
void cmd_write(const char *str) { void cmd_write(const char *str) {
// If output is being redirected to a file, write there instead
if (redirect_file && redirect_mode) {
fat32_write(redirect_file, (void *)str, cmd_strlen(str));
} else {
// Normal output to screen
while (*str) { while (*str) {
cmd_putchar(*str++); cmd_putchar(*str++);
} }
}
} }
// Public for CLI apps to use // Public for CLI apps to use
@ -371,6 +387,8 @@ static const CommandEntry commands[] = {
{"echo", cli_cmd_echo}, {"echo", cli_cmd_echo},
{"CAT", cli_cmd_cat}, {"CAT", cli_cmd_cat},
{"cat", cli_cmd_cat}, {"cat", cli_cmd_cat},
{"TOUCH", cli_cmd_touch},
{"touch", cli_cmd_touch},
// Memory Management Commands // Memory Management Commands
{"MEMINFO", cli_cmd_meminfo}, {"MEMINFO", cli_cmd_meminfo},
{"meminfo", cli_cmd_meminfo}, {"meminfo", cli_cmd_meminfo},
@ -390,7 +408,7 @@ static const CommandEntry commands[] = {
// --- Dispatcher --- // --- Dispatcher ---
// Buffer for capturing command output // Buffer for capturing command output
static char pipe_buffer[4096]; static char pipe_buffer[8192];
static int pipe_buffer_pos = 0; static int pipe_buffer_pos = 0;
static void pipe_capture_write(const char *str) { static void pipe_capture_write(const char *str) {
@ -425,42 +443,73 @@ static void cmd_exec_single(char *cmd) {
cmd_write("\n"); cmd_write("\n");
} }
// Execute command with pipe support // Execute command with redirection and pipe support
static void cmd_exec(char *cmd) { static void cmd_exec(char *cmd) {
// Check for pipe operator // Check for redirection operators (> or >>)
char *pipe_ptr = NULL; char *redirect_ptr = NULL;
char redirect_op = 0; // '>' or 'a' for append
char output_file[256] = {0};
int cmd_len = 0;
for (int i = 0; cmd[i]; i++) { for (int i = 0; cmd[i]; i++) {
if (cmd[i] == '|' && (i == 0 || cmd[i-1] != '>' && cmd[i+1] != '>' )) { if (cmd[i] == '>' && cmd[i+1] == '>') {
pipe_ptr = &cmd[i]; redirect_ptr = cmd + i + 2;
redirect_op = 'a'; // append
cmd_len = i;
break;
} else if (cmd[i] == '>') {
redirect_ptr = cmd + i + 1;
redirect_op = '>'; // write
cmd_len = i;
break; break;
} }
} }
if (!pipe_ptr) { // If redirection found, set it up
// No pipe - execute normally if (redirect_ptr) {
cmd_exec_single(cmd); // Null terminate command
cmd[cmd_len] = 0;
// Parse output filename
int i = 0;
while (redirect_ptr[i] && (redirect_ptr[i] == ' ' || redirect_ptr[i] == '\t')) {
i++;
}
int j = 0;
while (redirect_ptr[i] && redirect_ptr[i] != ' ' && redirect_ptr[i] != '\t') {
output_file[j++] = redirect_ptr[i++];
}
output_file[j] = 0;
if (!output_file[0]) {
cmd_write("Error: No output file specified\n");
return; return;
} }
// Split into two commands // Open file for redirection
*pipe_ptr = 0; const char *mode = (redirect_op == 'a') ? "a" : "w";
char *second_cmd = pipe_ptr + 1; redirect_file = fat32_open(output_file, mode);
if (!redirect_file) {
// Execute first command with output captured cmd_write("Error: Cannot open file for redirection\n");
pipe_buffer_pos = 0;
cmd_memset(pipe_buffer, 0, sizeof(pipe_buffer));
FAT32_FileHandle *pipe_file = fat32_open("_pipe_temp.tmp", "w");
if (!pipe_file) {
cmd_write("Error: Cannot create pipe\n");
return; return;
} }
redirect_mode = redirect_op;
}
// Execute the command
cmd_exec_single(cmd); cmd_exec_single(cmd);
fat32_close(pipe_file); // Close redirected file if it was opened
if (redirect_file) {
cmd_exec_single(second_cmd); fat32_close(redirect_file);
redirect_file = NULL;
redirect_mode = 0;
cmd_write("Output redirected to: ");
cmd_write(output_file);
cmd_write("\n");
}
} }

View file

@ -335,21 +335,28 @@ static void explorer_paint(Window *win) {
// Draw icon (larger area) // Draw icon (larger area)
explorer_draw_file_icon(item_x + 5, item_y + 5, items[i].is_directory); explorer_draw_file_icon(item_x + 5, item_y + 5, items[i].is_directory);
// Draw name below icon // Draw name below icon with text wrapping
uint32_t text_color = (i == selected_item) ? COLOR_WHITE : COLOR_BLACK; uint32_t text_color = (i == selected_item) ? COLOR_WHITE : COLOR_BLACK;
int name_len = explorer_strlen(items[i].name); int name_len = explorer_strlen(items[i].name);
int text_x = item_x + 5; int text_x = item_x + 5;
int text_y = item_y + 50; int text_y = item_y + 50;
int max_name_width = EXPLORER_ITEM_WIDTH - 10; // 110 pixels available for text
int chars_per_line = max_name_width / 8; // 8 pixels per character
// Truncate name if too long // Draw wrapped filename
char display_name[24]; int line_offset = 0;
int copy_len = name_len > 18 ? 18 : name_len; char line_buffer[25];
for (int j = 0; j < copy_len; j++) { for (int j = 0; j < name_len; j++) {
display_name[j] = items[i].name[j]; int pos_in_line = j % chars_per_line;
line_buffer[pos_in_line] = items[i].name[j];
line_buffer[pos_in_line + 1] = 0;
// Draw line when we reach end of line or end of name
if (pos_in_line == chars_per_line - 1 || j == name_len - 1) {
draw_string(text_x, text_y + (line_offset * 10), line_buffer, text_color);
line_offset++;
}
} }
display_name[copy_len] = 0;
draw_string(text_x, text_y, display_name, text_color);
} }
// Draw dialogs // Draw dialogs

View file

@ -160,7 +160,7 @@ static void minesweeper_paint(Window *win) {
} else if (game_won) { } else if (game_won) {
draw_string(win->x + 10, win->y + 30, "You Won!", COLOR_BLUE); draw_string(win->x + 10, win->y + 30, "You Won!", COLOR_BLUE);
} else { } else {
draw_string(win->x + 10, win->y + 30, "Minesweeper", COLOR_BLACK); draw_string(win->x + 10, win->y + 30, "", COLOR_BLACK);
} }
// Draw grid // Draw grid