|
| 1 | +#define _POSIX_C_SOURCE 199309L |
| 2 | + |
| 3 | +#include <stdio.h> |
| 4 | +#include <stdlib.h> |
| 5 | +#include <string.h> |
| 6 | +#include <unistd.h> |
| 7 | +#include <sys/types.h> |
| 8 | + |
| 9 | +#include "builtin_commands.h" |
| 10 | + |
| 11 | +// Built-in command implementations |
| 12 | + |
| 13 | +// Echo command - prints its arguments |
| 14 | +int cmd_echo(terminal_t* term, int argc, char* argv[]) { |
| 15 | + if (!term) { |
| 16 | + return -1; |
| 17 | + } |
| 18 | + |
| 19 | + // Print all arguments separated by spaces |
| 20 | + for (int i = 1; i < argc; i++) { |
| 21 | + if (i > 1) { |
| 22 | + terminal_write_string(term, " "); |
| 23 | + } |
| 24 | + terminal_write_string(term, argv[i]); |
| 25 | + } |
| 26 | + |
| 27 | + // Add newline at the end |
| 28 | + terminal_write_string(term, "\r\n"); |
| 29 | + |
| 30 | + return 0; |
| 31 | +} |
| 32 | + |
| 33 | +// Clear command - clears the terminal screen |
| 34 | +int cmd_clear(terminal_t* term, int argc, char* argv[]) { |
| 35 | + (void)argc; // Unused parameter |
| 36 | + (void)argv; // Unused parameter |
| 37 | + |
| 38 | + if (!term) { |
| 39 | + return -1; |
| 40 | + } |
| 41 | + |
| 42 | + terminal_clear_screen(term); |
| 43 | + return 0; |
| 44 | +} |
| 45 | + |
| 46 | +// Getpid command - prints the current process ID |
| 47 | +int cmd_getpid(terminal_t* term, int argc, char* argv[]) { |
| 48 | + (void)argc; // Unused parameter |
| 49 | + (void)argv; // Unused parameter |
| 50 | + |
| 51 | + if (!term) { |
| 52 | + return -1; |
| 53 | + } |
| 54 | + |
| 55 | + pid_t pid = getpid(); |
| 56 | + char pid_str[32]; |
| 57 | + snprintf(pid_str, sizeof(pid_str), "%d\r\n", (int)pid); |
| 58 | + terminal_write_string(term, pid_str); |
| 59 | + |
| 60 | + return 0; |
| 61 | +} |
| 62 | + |
| 63 | +// Help command - shows available built-in commands |
| 64 | +int cmd_help(terminal_t* term, int argc, char* argv[]) { |
| 65 | + (void)argc; // Unused parameter |
| 66 | + (void)argv; // Unused parameter |
| 67 | + |
| 68 | + if (!term) { |
| 69 | + return -1; |
| 70 | + } |
| 71 | + |
| 72 | + terminal_write_string(term, "Available built-in commands:\r\n"); |
| 73 | + terminal_write_string(term, "============================\r\n"); |
| 74 | + |
| 75 | + for (int i = 0; i < builtin_command_count; i++) { |
| 76 | + char help_line[256]; |
| 77 | + snprintf(help_line, sizeof(help_line), " %-10s - %s\r\n", |
| 78 | + builtin_commands[i].name, builtin_commands[i].description); |
| 79 | + terminal_write_string(term, help_line); |
| 80 | + } |
| 81 | + |
| 82 | + terminal_write_string(term, "\r\n"); |
| 83 | + return 0; |
| 84 | +} |
| 85 | + |
| 86 | +// Command processing functions |
| 87 | + |
| 88 | +// Split a command line into arguments |
| 89 | +void split_command_line(const char* line, char* argv[], int max_args, int* argc) { |
| 90 | + if (!line || !argv || !argc || max_args <= 0) { |
| 91 | + if (argc) *argc = 0; |
| 92 | + return; |
| 93 | + } |
| 94 | + |
| 95 | + *argc = 0; |
| 96 | + |
| 97 | + // Make a copy of the line since we need to modify it |
| 98 | + char* line_copy = malloc(strlen(line) + 1); |
| 99 | + if (!line_copy) { |
| 100 | + if (argc) *argc = 0; |
| 101 | + return; |
| 102 | + } |
| 103 | + strcpy(line_copy, line); |
| 104 | + |
| 105 | + char* p = line_copy; |
| 106 | + |
| 107 | + // Skip leading whitespace |
| 108 | + while (*p && (*p == ' ' || *p == '\t')) { |
| 109 | + p++; |
| 110 | + } |
| 111 | + |
| 112 | + while (*p && *argc < max_args - 1) { |
| 113 | + argv[*argc] = p; |
| 114 | + (*argc)++; |
| 115 | + |
| 116 | + // Find end of argument |
| 117 | + while (*p && *p != ' ' && *p != '\t') { |
| 118 | + p++; |
| 119 | + } |
| 120 | + |
| 121 | + // Null-terminate the argument |
| 122 | + if (*p) { |
| 123 | + *p = '\0'; |
| 124 | + p++; |
| 125 | + } |
| 126 | + |
| 127 | + // Skip whitespace |
| 128 | + while (*p && (*p == ' ' || *p == '\t')) { |
| 129 | + p++; |
| 130 | + } |
| 131 | + } |
| 132 | + |
| 133 | + argv[*argc] = NULL; // Null-terminate the argument list |
| 134 | +} |
| 135 | + |
| 136 | +// Execute a built-in command |
| 137 | +int execute_builtin_command(terminal_t* term, const char* command, int argc, char* argv[]) { |
| 138 | + if (!term || !command) { |
| 139 | + return -1; |
| 140 | + } |
| 141 | + |
| 142 | + // Find the command |
| 143 | + for (int i = 0; i < builtin_command_count; i++) { |
| 144 | + if (strcmp(command, builtin_commands[i].name) == 0) { |
| 145 | + return builtin_commands[i].func(term, argc, argv); |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | + // Command not found |
| 150 | + char error_msg[256]; |
| 151 | + snprintf(error_msg, sizeof(error_msg), "Command not found: %s\r\n", command); |
| 152 | + terminal_write_string(term, error_msg); |
| 153 | + return -1; |
| 154 | +} |
| 155 | + |
| 156 | +// Process a complete command line |
| 157 | +void process_command(terminal_t* term, const char* command_line) { |
| 158 | + if (!term || !command_line) { |
| 159 | + return; |
| 160 | + } |
| 161 | + |
| 162 | + // Skip empty lines |
| 163 | + if (strlen(command_line) == 0) { |
| 164 | + return; |
| 165 | + } |
| 166 | + |
| 167 | + char* argv[32]; |
| 168 | + int argc = 0; |
| 169 | + |
| 170 | + // Split the command line into arguments |
| 171 | + split_command_line(command_line, argv, 32, &argc); |
| 172 | + |
| 173 | + if (argc > 0) { |
| 174 | + // Execute the command |
| 175 | + execute_builtin_command(term, argv[0], argc, argv); |
| 176 | + |
| 177 | + // Free the allocated memory |
| 178 | + if (argv[0]) { |
| 179 | + free(argv[0]); |
| 180 | + } |
| 181 | + } |
| 182 | +} |
| 183 | + |
| 184 | +// Built-in commands table |
| 185 | +const builtin_command_t builtin_commands[] = { |
| 186 | + {"echo", "Print arguments to the terminal", cmd_echo}, |
| 187 | + {"clear", "Clear the terminal screen", cmd_clear}, |
| 188 | + {"getpid", "Print the current process ID", cmd_getpid}, |
| 189 | + {"help", "Show available built-in commands", cmd_help} |
| 190 | +}; |
| 191 | + |
| 192 | +const int builtin_command_count = sizeof(builtin_commands) / sizeof(builtin_commands[0]); |
0 commit comments