mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
Piping of commands into text files
usage: xxx(command) > xxxx.xxx (file)
This commit is contained in:
parent
5e3dc237cc
commit
e7752b7253
13 changed files with 134 additions and 41 deletions
BIN
brewos.iso
BIN
brewos.iso
Binary file not shown.
BIN
build/brewos.elf
BIN
build/brewos.elf
Binary file not shown.
Binary file not shown.
BIN
build/cmd.o
BIN
build/cmd.o
Binary file not shown.
BIN
build/explorer.o
BIN
build/explorer.o
Binary file not shown.
Binary file not shown.
BIN
build/notepad.o
BIN
build/notepad.o
Binary file not shown.
Binary file not shown.
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
111
src/kernel/cmd.c
111
src/kernel/cmd.c
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue