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

View File

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

View File

@@ -239,3 +239,39 @@ void cli_cmd_cat(char *args) {
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 <stddef.h>
#define CMD_COLS 70
#define CMD_ROWS 25
#define CMD_COLS 116
#define CMD_ROWS 41
#define LINE_HEIGHT 10
#define CHAR_WIDTH 8
#define PROMPT "> "
@@ -108,6 +108,10 @@ static int pager_top_line = 0;
// Boot time for uptime
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;
// --- Helpers ---
@@ -193,6 +197,12 @@ static void cmd_scroll_up() {
// Public for CLI apps to use
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') {
cursor_col = 0;
cursor_row++;
@@ -225,8 +235,14 @@ void cmd_putchar(char c) {
// Public for CLI apps to use
void cmd_write(const char *str) {
while (*str) {
cmd_putchar(*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) {
cmd_putchar(*str++);
}
}
}
@@ -371,6 +387,8 @@ static const CommandEntry commands[] = {
{"echo", cli_cmd_echo},
{"CAT", cli_cmd_cat},
{"cat", cli_cmd_cat},
{"TOUCH", cli_cmd_touch},
{"touch", cli_cmd_touch},
// Memory Management Commands
{"MEMINFO", cli_cmd_meminfo},
{"meminfo", cli_cmd_meminfo},
@@ -390,7 +408,7 @@ static const CommandEntry commands[] = {
// --- Dispatcher ---
// Buffer for capturing command output
static char pipe_buffer[4096];
static char pipe_buffer[8192];
static int pipe_buffer_pos = 0;
static void pipe_capture_write(const char *str) {
@@ -425,42 +443,73 @@ static void cmd_exec_single(char *cmd) {
cmd_write("\n");
}
// Execute command with pipe support
// Execute command with redirection and pipe support
static void cmd_exec(char *cmd) {
// Check for pipe operator
char *pipe_ptr = NULL;
// Check for redirection operators (> or >>)
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++) {
if (cmd[i] == '|' && (i == 0 || cmd[i-1] != '>' && cmd[i+1] != '>' )) {
pipe_ptr = &cmd[i];
if (cmd[i] == '>' && cmd[i+1] == '>') {
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;
}
}
if (!pipe_ptr) {
// No pipe - execute normally
cmd_exec_single(cmd);
return;
}
// Split into two commands
*pipe_ptr = 0;
char *second_cmd = pipe_ptr + 1;
// Execute first command with output captured
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;
// If redirection found, set it up
if (redirect_ptr) {
// 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;
}
// Open file for redirection
const char *mode = (redirect_op == 'a') ? "a" : "w";
redirect_file = fat32_open(output_file, mode);
if (!redirect_file) {
cmd_write("Error: Cannot open file for redirection\n");
return;
}
redirect_mode = redirect_op;
}
// Execute the command
cmd_exec_single(cmd);
fat32_close(pipe_file);
cmd_exec_single(second_cmd);
// Close redirected file if it was opened
if (redirect_file) {
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)
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;
int name_len = explorer_strlen(items[i].name);
int text_x = item_x + 5;
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
char display_name[24];
int copy_len = name_len > 18 ? 18 : name_len;
for (int j = 0; j < copy_len; j++) {
display_name[j] = items[i].name[j];
// Draw wrapped filename
int line_offset = 0;
char line_buffer[25];
for (int j = 0; j < name_len; 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

View File

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