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_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,9 +235,15 @@ void cmd_putchar(char c) {
// Public for CLI apps to use
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) {
cmd_putchar(*str++);
}
}
}
// Public for CLI apps to use
@ -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);
// 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;
}
// 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");
// 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