vfs: check userland buffers before reading them.
[haiku.git] / src / system / kernel / debug / debug_builtin_commands.cpp
blob59e5e01cd2fbe9600d1778cfa39f8c0a895a9fe4
1 /*
2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de
3 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de
4 * Distributed under the terms of the MIT License.
6 * Copyright 2001, Travis Geiselbrecht. All rights reserved.
7 * Distributed under the terms of the NewOS License.
8 */
10 #include "debug_builtin_commands.h"
12 #include <ctype.h>
13 #include <string.h>
14 #include <strings.h>
16 #include <debug.h>
17 #include <kernel.h>
19 #include "debug_commands.h"
20 #include "gdb.h"
23 static int
24 cmd_reboot(int argc, char **argv)
26 arch_cpu_shutdown(true);
27 return 0;
28 // I'll be really suprised if this line ever runs! ;-)
32 static int
33 cmd_shutdown(int argc, char **argv)
35 arch_cpu_shutdown(false);
36 return 0;
40 static int
41 cmd_help(int argc, char **argv)
43 debugger_command *command, *specified = NULL;
44 const char *start = NULL;
45 int32 startLength = 0;
46 bool ambiguous;
48 if (argc > 1) {
49 specified = find_debugger_command(argv[1], false, ambiguous);
50 if (specified == NULL) {
51 start = argv[1];
52 startLength = strlen(start);
56 if (specified != NULL) {
57 // only print out the help of the specified command (and all of its aliases)
58 kprintf("debugger command for \"%s\" and aliases:\n", specified->name);
59 } else if (start != NULL)
60 kprintf("debugger commands starting with \"%s\":\n", start);
61 else
62 kprintf("debugger commands:\n");
64 for (command = get_debugger_commands(); command != NULL;
65 command = command->next) {
66 if (specified && command->func != specified->func)
67 continue;
68 if (start != NULL && strncmp(start, command->name, startLength))
69 continue;
71 kprintf(" %-20s\t\t%s\n", command->name, command->description ? command->description : "-");
74 return 0;
78 static int
79 cmd_continue(int argc, char **argv)
81 return B_KDEBUG_QUIT;
85 static int
86 cmd_expr(int argc, char **argv)
88 if (argc != 2) {
89 print_debugger_command_usage(argv[0]);
90 return 0;
93 uint64 result;
94 if (evaluate_debug_expression(argv[1], &result, false)) {
95 kprintf("%" B_PRIu64 " (0x%" B_PRIx64 ")\n", result, result);
96 set_debug_variable("_", result);
99 return 0;
103 static int
104 cmd_error(int argc, char **argv)
106 if (argc != 2) {
107 print_debugger_command_usage(argv[0]);
108 return 0;
111 int32 error = parse_expression(argv[1]);
112 kprintf("error 0x%" B_PRIx32 ": %s\n", error, strerror(error));
114 return 0;
118 static int
119 cmd_head(int argc, char** argv)
121 debugger_command_pipe_segment* segment
122 = get_current_debugger_command_pipe_segment();
123 if (segment == NULL) {
124 kprintf_unfiltered("%s can only be run as part of a pipe!\n", argv[0]);
125 return B_KDEBUG_ERROR;
128 struct user_data {
129 uint64 max_lines;
130 uint64 lines;
132 user_data* userData = (user_data*)segment->user_data;
134 if (segment->invocations == 0) {
135 if (argc != 3) {
136 print_debugger_command_usage(argv[0]);
137 return B_KDEBUG_ERROR;
140 if (!evaluate_debug_expression(argv[1], &userData->max_lines, false))
141 return B_KDEBUG_ERROR;
142 userData->lines = 0;
145 if (++userData->lines <= userData->max_lines) {
146 kputs(argv[2]);
147 kputs("\n");
150 return 0;
154 static int
155 cmd_tail(int argc, char** argv)
157 debugger_command_pipe_segment* segment
158 = get_current_debugger_command_pipe_segment();
159 if (segment == NULL) {
160 kprintf_unfiltered("%s can only be run as part of a pipe!\n", argv[0]);
161 return B_KDEBUG_ERROR;
164 struct user_data {
165 uint64 max_lines;
166 int64 line_count;
167 bool restarted;
169 user_data* userData = (user_data*)segment->user_data;
171 if (segment->invocations == 0) {
172 if (argc > 3) {
173 print_debugger_command_usage(argv[0]);
174 return B_KDEBUG_ERROR;
177 userData->max_lines = 10;
178 if (argc > 2 && !evaluate_debug_expression(argv[1],
179 &userData->max_lines, false)) {
180 return B_KDEBUG_ERROR;
183 userData->line_count = 1;
184 userData->restarted = false;
185 } else if (!userData->restarted) {
186 if (argv[argc - 1] == NULL) {
187 userData->restarted = true;
188 userData->line_count -= userData->max_lines;
189 return B_KDEBUG_RESTART_PIPE;
192 ++userData->line_count;
193 } else {
194 if (argv[argc - 1] == NULL)
195 return 0;
197 if (--userData->line_count < 0) {
198 kputs(argv[argc - 1]);
199 kputs("\n");
203 return 0;
207 static int
208 cmd_grep(int argc, char** argv)
210 bool caseSensitive = true;
211 bool inverseMatch = false;
213 int argi = 1;
214 for (; argi < argc; argi++) {
215 const char* arg = argv[argi];
216 if (arg[0] != '-')
217 break;
219 for (int32 i = 1; arg[i] != '\0'; i++) {
220 if (arg[i] == 'i') {
221 caseSensitive = false;
222 } else if (arg[i] == 'v') {
223 inverseMatch = true;
224 } else {
225 print_debugger_command_usage(argv[0]);
226 return B_KDEBUG_ERROR;
231 if (argc - argi != 2) {
232 print_debugger_command_usage(argv[0]);
233 return B_KDEBUG_ERROR;
236 const char* pattern = argv[argi++];
237 const char* line = argv[argi++];
239 bool match;
240 if (caseSensitive) {
241 match = strstr(line, pattern) != NULL;
242 } else {
243 match = false;
244 int32 lineLen = strlen(line);
245 int32 patternLen = strlen(pattern);
246 for (int32 i = 0; i <= lineLen - patternLen; i++) {
247 // This is rather slow, but should be OK for our purposes.
248 if (strncasecmp(line + i, pattern, patternLen) == 0) {
249 match = true;
250 break;
255 if (match != inverseMatch) {
256 kputs(line);
257 kputs("\n");
260 return 0;
264 static int
265 cmd_wc(int argc, char** argv)
267 debugger_command_pipe_segment* segment
268 = get_current_debugger_command_pipe_segment();
269 if (segment == NULL) {
270 kprintf_unfiltered("%s can only be run as part of a pipe!\n", argv[0]);
271 return B_KDEBUG_ERROR;
274 struct user_data {
275 uint64 lines;
276 uint64 words;
277 uint64 chars;
279 user_data* userData = (user_data*)segment->user_data;
281 if (segment->invocations == 0) {
282 if (argc != 2) {
283 print_debugger_command_usage(argv[0]);
284 return B_KDEBUG_ERROR;
287 userData->lines = 0;
288 userData->words = 0;
289 userData->chars = 0;
292 const char* line = argv[1];
293 if (line == NULL) {
294 // last run -- print results
295 kprintf("%10" B_PRIu64 " %10" B_PRIu64 " %10" B_PRIu64 "\n",
296 userData->lines, userData->words, userData->chars);
297 return 0;
300 userData->lines++;
301 userData->chars++;
302 // newline
304 // count words and chars in this line
305 bool inWord = false;
306 for (; *line != '\0'; line++) {
307 userData->chars++;
308 if ((isspace(*line) != 0) == inWord) {
309 inWord = !inWord;
310 if (inWord)
311 userData->words++;
315 return 0;
319 static int
320 cmd_faults(int argc, char** argv)
322 if (argc > 2) {
323 print_debugger_command_usage(argv[0]);
324 return B_KDEBUG_ERROR;
327 if (argc == 2)
328 gInvokeCommandDirectly = parse_expression(argv[1]) == 0;
330 kprintf("Fault handling is %s%s.\n", argc == 2 ? "now " : "",
331 gInvokeCommandDirectly ? "off" : "on");
332 return 0;
336 // #pragma mark -
339 void
340 debug_builtin_commands_init()
342 add_debugger_command_etc("help", &cmd_help, "List all debugger commands",
343 "[name]\n"
344 "Lists all debugger commands or those starting with \"name\".\n", 0);
345 add_debugger_command_etc("reboot", &cmd_reboot, "Reboot the system",
346 "\n"
347 "Reboots the system.\n", 0);
348 add_debugger_command_etc("shutdown", &cmd_shutdown, "Shut down the system",
349 "\n"
350 "Shuts down the system.\n", 0);
351 add_debugger_command_etc("gdb", &cmd_gdb, "Connect to remote gdb",
352 "\n"
353 "Connects to a remote gdb connected to the serial port.\n", 0);
354 add_debugger_command_etc("continue", &cmd_continue, "Leave kernel debugger",
355 "\n"
356 "Leaves kernel debugger.\n", 0);
357 add_debugger_command_alias("exit", "continue", "Same as \"continue\"");
358 add_debugger_command_alias("es", "continue", "Same as \"continue\"");
359 add_debugger_command_etc("expr", &cmd_expr,
360 "Evaluates the given expression and prints the result",
361 "<expression>\n"
362 "Evaluates the given expression and prints the result.\n",
363 B_KDEBUG_DONT_PARSE_ARGUMENTS);
364 add_debugger_command_etc("error", &cmd_error,
365 "Prints a human-readable description for an error code",
366 "<error>\n"
367 "Prints a human-readable description for the given numeric error\n"
368 "code.\n"
369 " <error> - The numeric error code.\n", 0);
370 add_debugger_command_etc("faults", &cmd_faults, "Toggles fault handling "
371 "for debugger commands",
372 "[0|1]\n"
373 "Toggles fault handling on (1) or off (0).\n", 0);
374 add_debugger_command_etc("head", &cmd_head,
375 "Prints only the first lines of output from another command",
376 "<maxLines>\n"
377 "Should be used in a command pipe. It prints only the first\n"
378 "<maxLines> lines of output from the previous command in the pipe and\n"
379 "silently discards the rest of the output.\n", 0);
380 add_debugger_command_etc("tail", &cmd_tail,
381 "Prints only the last lines of output from another command",
382 "[ <maxLines> ]\n"
383 "Should be used in a command pipe. It prints only the last\n"
384 "<maxLines> (default 10) lines of output from the previous command in\n"
385 "the pipe and silently discards the rest of the output.\n",
386 B_KDEBUG_PIPE_FINAL_RERUN);
387 add_debugger_command_etc("grep", &cmd_grep,
388 "Filters output from another command",
389 "[ -i ] [ -v ] <pattern>\n"
390 "Should be used in a command pipe. It filters all output from the\n"
391 "previous command in the pipe according to the given pattern.\n"
392 "When \"-v\" is specified, only those lines are printed that don't\n"
393 "match the given pattern, otherwise only those that do match. When\n"
394 "\"-i\" is specified, the pattern is matched case insensitive,\n"
395 "otherwise case sensitive.\n", 0);
396 add_debugger_command_etc("wc", &cmd_wc,
397 "Counts the lines, words, and characters of another command's output",
398 "<maxLines>\n"
399 "Should be used in a command pipe. It prints how many lines, words,\n"
400 "and characters the output of the previous command consists of.\n",
401 B_KDEBUG_PIPE_FINAL_RERUN);