|
@@ -12,6 +12,7 @@
|
|
|
*/
|
|
|
|
|
|
#include <linux/ctype.h>
|
|
|
+#include <linux/types.h>
|
|
|
#include <linux/string.h>
|
|
|
#include <linux/kernel.h>
|
|
|
#include <linux/kmsg_dump.h>
|
|
@@ -23,6 +24,7 @@
|
|
|
#include <linux/vmalloc.h>
|
|
|
#include <linux/atomic.h>
|
|
|
#include <linux/module.h>
|
|
|
+#include <linux/moduleparam.h>
|
|
|
#include <linux/mm.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/kallsyms.h>
|
|
@@ -42,6 +44,12 @@
|
|
|
#include <linux/slab.h>
|
|
|
#include "kdb_private.h"
|
|
|
|
|
|
+#undef MODULE_PARAM_PREFIX
|
|
|
+#define MODULE_PARAM_PREFIX "kdb."
|
|
|
+
|
|
|
+static int kdb_cmd_enabled = CONFIG_KDB_DEFAULT_ENABLE;
|
|
|
+module_param_named(cmd_enable, kdb_cmd_enabled, int, 0600);
|
|
|
+
|
|
|
#define GREP_LEN 256
|
|
|
char kdb_grep_string[GREP_LEN];
|
|
|
int kdb_grepping_flag;
|
|
@@ -121,6 +129,7 @@ static kdbmsg_t kdbmsgs[] = {
|
|
|
KDBMSG(BADLENGTH, "Invalid length field"),
|
|
|
KDBMSG(NOBP, "No Breakpoint exists"),
|
|
|
KDBMSG(BADADDR, "Invalid address"),
|
|
|
+ KDBMSG(NOPERM, "Permission denied"),
|
|
|
};
|
|
|
#undef KDBMSG
|
|
|
|
|
@@ -187,6 +196,26 @@ struct task_struct *kdb_curr_task(int cpu)
|
|
|
return p;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Check whether the flags of the current command and the permissions
|
|
|
+ * of the kdb console has allow a command to be run.
|
|
|
+ */
|
|
|
+static inline bool kdb_check_flags(kdb_cmdflags_t flags, int permissions,
|
|
|
+ bool no_args)
|
|
|
+{
|
|
|
+ /* permissions comes from userspace so needs massaging slightly */
|
|
|
+ permissions &= KDB_ENABLE_MASK;
|
|
|
+ permissions |= KDB_ENABLE_ALWAYS_SAFE;
|
|
|
+
|
|
|
+ /* some commands change group when launched with no arguments */
|
|
|
+ if (no_args)
|
|
|
+ permissions |= permissions << KDB_ENABLE_NO_ARGS_SHIFT;
|
|
|
+
|
|
|
+ flags |= KDB_ENABLE_ALL;
|
|
|
+
|
|
|
+ return permissions & flags;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* kdbgetenv - This function will return the character string value of
|
|
|
* an environment variable.
|
|
@@ -475,6 +504,15 @@ int kdbgetaddrarg(int argc, const char **argv, int *nextarg,
|
|
|
char *cp;
|
|
|
kdb_symtab_t symtab;
|
|
|
|
|
|
+ /*
|
|
|
+ * If the enable flags prohibit both arbitrary memory access
|
|
|
+ * and flow control then there are no reasonable grounds to
|
|
|
+ * provide symbol lookup.
|
|
|
+ */
|
|
|
+ if (!kdb_check_flags(KDB_ENABLE_MEM_READ | KDB_ENABLE_FLOW_CTRL,
|
|
|
+ kdb_cmd_enabled, false))
|
|
|
+ return KDB_NOPERM;
|
|
|
+
|
|
|
/*
|
|
|
* Process arguments which follow the following syntax:
|
|
|
*
|
|
@@ -641,8 +679,13 @@ static int kdb_defcmd2(const char *cmdstr, const char *argv0)
|
|
|
if (!s->count)
|
|
|
s->usable = 0;
|
|
|
if (s->usable)
|
|
|
- kdb_register(s->name, kdb_exec_defcmd,
|
|
|
- s->usage, s->help, 0);
|
|
|
+ /* macros are always safe because when executed each
|
|
|
+ * internal command re-enters kdb_parse() and is
|
|
|
+ * safety checked individually.
|
|
|
+ */
|
|
|
+ kdb_register_flags(s->name, kdb_exec_defcmd, s->usage,
|
|
|
+ s->help, 0,
|
|
|
+ KDB_ENABLE_ALWAYS_SAFE);
|
|
|
return 0;
|
|
|
}
|
|
|
if (!s->usable)
|
|
@@ -1003,25 +1046,22 @@ int kdb_parse(const char *cmdstr)
|
|
|
|
|
|
if (i < kdb_max_commands) {
|
|
|
int result;
|
|
|
+
|
|
|
+ if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1))
|
|
|
+ return KDB_NOPERM;
|
|
|
+
|
|
|
KDB_STATE_SET(CMD);
|
|
|
result = (*tp->cmd_func)(argc-1, (const char **)argv);
|
|
|
if (result && ignore_errors && result > KDB_CMD_GO)
|
|
|
result = 0;
|
|
|
KDB_STATE_CLEAR(CMD);
|
|
|
- switch (tp->cmd_repeat) {
|
|
|
- case KDB_REPEAT_NONE:
|
|
|
- argc = 0;
|
|
|
- if (argv[0])
|
|
|
- *(argv[0]) = '\0';
|
|
|
- break;
|
|
|
- case KDB_REPEAT_NO_ARGS:
|
|
|
- argc = 1;
|
|
|
- if (argv[1])
|
|
|
- *(argv[1]) = '\0';
|
|
|
- break;
|
|
|
- case KDB_REPEAT_WITH_ARGS:
|
|
|
- break;
|
|
|
- }
|
|
|
+
|
|
|
+ if (tp->cmd_flags & KDB_REPEAT_WITH_ARGS)
|
|
|
+ return result;
|
|
|
+
|
|
|
+ argc = tp->cmd_flags & KDB_REPEAT_NO_ARGS ? 1 : 0;
|
|
|
+ if (argv[argc])
|
|
|
+ *(argv[argc]) = '\0';
|
|
|
return result;
|
|
|
}
|
|
|
|
|
@@ -1921,10 +1961,14 @@ static int kdb_rm(int argc, const char **argv)
|
|
|
*/
|
|
|
static int kdb_sr(int argc, const char **argv)
|
|
|
{
|
|
|
+ bool check_mask =
|
|
|
+ !kdb_check_flags(KDB_ENABLE_ALL, kdb_cmd_enabled, false);
|
|
|
+
|
|
|
if (argc != 1)
|
|
|
return KDB_ARGCOUNT;
|
|
|
+
|
|
|
kdb_trap_printk++;
|
|
|
- __handle_sysrq(*argv[1], false);
|
|
|
+ __handle_sysrq(*argv[1], check_mask);
|
|
|
kdb_trap_printk--;
|
|
|
|
|
|
return 0;
|
|
@@ -2157,6 +2201,8 @@ static void kdb_cpu_status(void)
|
|
|
for (start_cpu = -1, i = 0; i < NR_CPUS; i++) {
|
|
|
if (!cpu_online(i)) {
|
|
|
state = 'F'; /* cpu is offline */
|
|
|
+ } else if (!kgdb_info[i].enter_kgdb) {
|
|
|
+ state = 'D'; /* cpu is online but unresponsive */
|
|
|
} else {
|
|
|
state = ' '; /* cpu is responding to kdb */
|
|
|
if (kdb_task_state_char(KDB_TSK(i)) == 'I')
|
|
@@ -2210,7 +2256,7 @@ static int kdb_cpu(int argc, const char **argv)
|
|
|
/*
|
|
|
* Validate cpunum
|
|
|
*/
|
|
|
- if ((cpunum > NR_CPUS) || !cpu_online(cpunum))
|
|
|
+ if ((cpunum > NR_CPUS) || !kgdb_info[cpunum].enter_kgdb)
|
|
|
return KDB_BADCPUNUM;
|
|
|
|
|
|
dbg_switch_cpu = cpunum;
|
|
@@ -2375,6 +2421,8 @@ static int kdb_help(int argc, const char **argv)
|
|
|
return 0;
|
|
|
if (!kt->cmd_name)
|
|
|
continue;
|
|
|
+ if (!kdb_check_flags(kt->cmd_flags, kdb_cmd_enabled, true))
|
|
|
+ continue;
|
|
|
if (strlen(kt->cmd_usage) > 20)
|
|
|
space = "\n ";
|
|
|
kdb_printf("%-15.15s %-20s%s%s\n", kt->cmd_name,
|
|
@@ -2629,7 +2677,7 @@ static int kdb_grep_help(int argc, const char **argv)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * kdb_register_repeat - This function is used to register a kernel
|
|
|
+ * kdb_register_flags - This function is used to register a kernel
|
|
|
* debugger command.
|
|
|
* Inputs:
|
|
|
* cmd Command name
|
|
@@ -2641,12 +2689,12 @@ static int kdb_grep_help(int argc, const char **argv)
|
|
|
* zero for success, one if a duplicate command.
|
|
|
*/
|
|
|
#define kdb_command_extend 50 /* arbitrary */
|
|
|
-int kdb_register_repeat(char *cmd,
|
|
|
- kdb_func_t func,
|
|
|
- char *usage,
|
|
|
- char *help,
|
|
|
- short minlen,
|
|
|
- kdb_repeat_t repeat)
|
|
|
+int kdb_register_flags(char *cmd,
|
|
|
+ kdb_func_t func,
|
|
|
+ char *usage,
|
|
|
+ char *help,
|
|
|
+ short minlen,
|
|
|
+ kdb_cmdflags_t flags)
|
|
|
{
|
|
|
int i;
|
|
|
kdbtab_t *kp;
|
|
@@ -2694,19 +2742,18 @@ int kdb_register_repeat(char *cmd,
|
|
|
kp->cmd_func = func;
|
|
|
kp->cmd_usage = usage;
|
|
|
kp->cmd_help = help;
|
|
|
- kp->cmd_flags = 0;
|
|
|
kp->cmd_minlen = minlen;
|
|
|
- kp->cmd_repeat = repeat;
|
|
|
+ kp->cmd_flags = flags;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
-EXPORT_SYMBOL_GPL(kdb_register_repeat);
|
|
|
+EXPORT_SYMBOL_GPL(kdb_register_flags);
|
|
|
|
|
|
|
|
|
/*
|
|
|
* kdb_register - Compatibility register function for commands that do
|
|
|
* not need to specify a repeat state. Equivalent to
|
|
|
- * kdb_register_repeat with KDB_REPEAT_NONE.
|
|
|
+ * kdb_register_flags with flags set to 0.
|
|
|
* Inputs:
|
|
|
* cmd Command name
|
|
|
* func Function to execute the command
|
|
@@ -2721,8 +2768,7 @@ int kdb_register(char *cmd,
|
|
|
char *help,
|
|
|
short minlen)
|
|
|
{
|
|
|
- return kdb_register_repeat(cmd, func, usage, help, minlen,
|
|
|
- KDB_REPEAT_NONE);
|
|
|
+ return kdb_register_flags(cmd, func, usage, help, minlen, 0);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(kdb_register);
|
|
|
|
|
@@ -2764,80 +2810,109 @@ static void __init kdb_inittab(void)
|
|
|
for_each_kdbcmd(kp, i)
|
|
|
kp->cmd_name = NULL;
|
|
|
|
|
|
- kdb_register_repeat("md", kdb_md, "<vaddr>",
|
|
|
+ kdb_register_flags("md", kdb_md, "<vaddr>",
|
|
|
"Display Memory Contents, also mdWcN, e.g. md8c1", 1,
|
|
|
- KDB_REPEAT_NO_ARGS);
|
|
|
- kdb_register_repeat("mdr", kdb_md, "<vaddr> <bytes>",
|
|
|
- "Display Raw Memory", 0, KDB_REPEAT_NO_ARGS);
|
|
|
- kdb_register_repeat("mdp", kdb_md, "<paddr> <bytes>",
|
|
|
- "Display Physical Memory", 0, KDB_REPEAT_NO_ARGS);
|
|
|
- kdb_register_repeat("mds", kdb_md, "<vaddr>",
|
|
|
- "Display Memory Symbolically", 0, KDB_REPEAT_NO_ARGS);
|
|
|
- kdb_register_repeat("mm", kdb_mm, "<vaddr> <contents>",
|
|
|
- "Modify Memory Contents", 0, KDB_REPEAT_NO_ARGS);
|
|
|
- kdb_register_repeat("go", kdb_go, "[<vaddr>]",
|
|
|
- "Continue Execution", 1, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("rd", kdb_rd, "",
|
|
|
- "Display Registers", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("rm", kdb_rm, "<reg> <contents>",
|
|
|
- "Modify Registers", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("ef", kdb_ef, "<vaddr>",
|
|
|
- "Display exception frame", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("bt", kdb_bt, "[<vaddr>]",
|
|
|
- "Stack traceback", 1, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("btp", kdb_bt, "<pid>",
|
|
|
- "Display stack for process <pid>", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]",
|
|
|
- "Backtrace all processes matching state flag", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("btc", kdb_bt, "",
|
|
|
- "Backtrace current process on each cpu", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("btt", kdb_bt, "<vaddr>",
|
|
|
+ KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
|
|
|
+ kdb_register_flags("mdr", kdb_md, "<vaddr> <bytes>",
|
|
|
+ "Display Raw Memory", 0,
|
|
|
+ KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
|
|
|
+ kdb_register_flags("mdp", kdb_md, "<paddr> <bytes>",
|
|
|
+ "Display Physical Memory", 0,
|
|
|
+ KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
|
|
|
+ kdb_register_flags("mds", kdb_md, "<vaddr>",
|
|
|
+ "Display Memory Symbolically", 0,
|
|
|
+ KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
|
|
|
+ kdb_register_flags("mm", kdb_mm, "<vaddr> <contents>",
|
|
|
+ "Modify Memory Contents", 0,
|
|
|
+ KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS);
|
|
|
+ kdb_register_flags("go", kdb_go, "[<vaddr>]",
|
|
|
+ "Continue Execution", 1,
|
|
|
+ KDB_ENABLE_REG_WRITE | KDB_ENABLE_ALWAYS_SAFE_NO_ARGS);
|
|
|
+ kdb_register_flags("rd", kdb_rd, "",
|
|
|
+ "Display Registers", 0,
|
|
|
+ KDB_ENABLE_REG_READ);
|
|
|
+ kdb_register_flags("rm", kdb_rm, "<reg> <contents>",
|
|
|
+ "Modify Registers", 0,
|
|
|
+ KDB_ENABLE_REG_WRITE);
|
|
|
+ kdb_register_flags("ef", kdb_ef, "<vaddr>",
|
|
|
+ "Display exception frame", 0,
|
|
|
+ KDB_ENABLE_MEM_READ);
|
|
|
+ kdb_register_flags("bt", kdb_bt, "[<vaddr>]",
|
|
|
+ "Stack traceback", 1,
|
|
|
+ KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS);
|
|
|
+ kdb_register_flags("btp", kdb_bt, "<pid>",
|
|
|
+ "Display stack for process <pid>", 0,
|
|
|
+ KDB_ENABLE_INSPECT);
|
|
|
+ kdb_register_flags("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]",
|
|
|
+ "Backtrace all processes matching state flag", 0,
|
|
|
+ KDB_ENABLE_INSPECT);
|
|
|
+ kdb_register_flags("btc", kdb_bt, "",
|
|
|
+ "Backtrace current process on each cpu", 0,
|
|
|
+ KDB_ENABLE_INSPECT);
|
|
|
+ kdb_register_flags("btt", kdb_bt, "<vaddr>",
|
|
|
"Backtrace process given its struct task address", 0,
|
|
|
- KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("env", kdb_env, "",
|
|
|
- "Show environment variables", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("set", kdb_set, "",
|
|
|
- "Set environment variables", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("help", kdb_help, "",
|
|
|
- "Display Help Message", 1, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("?", kdb_help, "",
|
|
|
- "Display Help Message", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("cpu", kdb_cpu, "<cpunum>",
|
|
|
- "Switch to new cpu", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("kgdb", kdb_kgdb, "",
|
|
|
- "Enter kgdb mode", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("ps", kdb_ps, "[<flags>|A]",
|
|
|
- "Display active task list", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("pid", kdb_pid, "<pidnum>",
|
|
|
- "Switch to another task", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("reboot", kdb_reboot, "",
|
|
|
- "Reboot the machine immediately", 0, KDB_REPEAT_NONE);
|
|
|
+ KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS);
|
|
|
+ kdb_register_flags("env", kdb_env, "",
|
|
|
+ "Show environment variables", 0,
|
|
|
+ KDB_ENABLE_ALWAYS_SAFE);
|
|
|
+ kdb_register_flags("set", kdb_set, "",
|
|
|
+ "Set environment variables", 0,
|
|
|
+ KDB_ENABLE_ALWAYS_SAFE);
|
|
|
+ kdb_register_flags("help", kdb_help, "",
|
|
|
+ "Display Help Message", 1,
|
|
|
+ KDB_ENABLE_ALWAYS_SAFE);
|
|
|
+ kdb_register_flags("?", kdb_help, "",
|
|
|
+ "Display Help Message", 0,
|
|
|
+ KDB_ENABLE_ALWAYS_SAFE);
|
|
|
+ kdb_register_flags("cpu", kdb_cpu, "<cpunum>",
|
|
|
+ "Switch to new cpu", 0,
|
|
|
+ KDB_ENABLE_ALWAYS_SAFE_NO_ARGS);
|
|
|
+ kdb_register_flags("kgdb", kdb_kgdb, "",
|
|
|
+ "Enter kgdb mode", 0, 0);
|
|
|
+ kdb_register_flags("ps", kdb_ps, "[<flags>|A]",
|
|
|
+ "Display active task list", 0,
|
|
|
+ KDB_ENABLE_INSPECT);
|
|
|
+ kdb_register_flags("pid", kdb_pid, "<pidnum>",
|
|
|
+ "Switch to another task", 0,
|
|
|
+ KDB_ENABLE_INSPECT);
|
|
|
+ kdb_register_flags("reboot", kdb_reboot, "",
|
|
|
+ "Reboot the machine immediately", 0,
|
|
|
+ KDB_ENABLE_REBOOT);
|
|
|
#if defined(CONFIG_MODULES)
|
|
|
- kdb_register_repeat("lsmod", kdb_lsmod, "",
|
|
|
- "List loaded kernel modules", 0, KDB_REPEAT_NONE);
|
|
|
+ kdb_register_flags("lsmod", kdb_lsmod, "",
|
|
|
+ "List loaded kernel modules", 0,
|
|
|
+ KDB_ENABLE_INSPECT);
|
|
|
#endif
|
|
|
#if defined(CONFIG_MAGIC_SYSRQ)
|
|
|
- kdb_register_repeat("sr", kdb_sr, "<key>",
|
|
|
- "Magic SysRq key", 0, KDB_REPEAT_NONE);
|
|
|
+ kdb_register_flags("sr", kdb_sr, "<key>",
|
|
|
+ "Magic SysRq key", 0,
|
|
|
+ KDB_ENABLE_ALWAYS_SAFE);
|
|
|
#endif
|
|
|
#if defined(CONFIG_PRINTK)
|
|
|
- kdb_register_repeat("dmesg", kdb_dmesg, "[lines]",
|
|
|
- "Display syslog buffer", 0, KDB_REPEAT_NONE);
|
|
|
+ kdb_register_flags("dmesg", kdb_dmesg, "[lines]",
|
|
|
+ "Display syslog buffer", 0,
|
|
|
+ KDB_ENABLE_ALWAYS_SAFE);
|
|
|
#endif
|
|
|
if (arch_kgdb_ops.enable_nmi) {
|
|
|
- kdb_register_repeat("disable_nmi", kdb_disable_nmi, "",
|
|
|
- "Disable NMI entry to KDB", 0, KDB_REPEAT_NONE);
|
|
|
- }
|
|
|
- kdb_register_repeat("defcmd", kdb_defcmd, "name \"usage\" \"help\"",
|
|
|
- "Define a set of commands, down to endefcmd", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("kill", kdb_kill, "<-signal> <pid>",
|
|
|
- "Send a signal to a process", 0, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("summary", kdb_summary, "",
|
|
|
- "Summarize the system", 4, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("per_cpu", kdb_per_cpu, "<sym> [<bytes>] [<cpu>]",
|
|
|
- "Display per_cpu variables", 3, KDB_REPEAT_NONE);
|
|
|
- kdb_register_repeat("grephelp", kdb_grep_help, "",
|
|
|
- "Display help on | grep", 0, KDB_REPEAT_NONE);
|
|
|
+ kdb_register_flags("disable_nmi", kdb_disable_nmi, "",
|
|
|
+ "Disable NMI entry to KDB", 0,
|
|
|
+ KDB_ENABLE_ALWAYS_SAFE);
|
|
|
+ }
|
|
|
+ kdb_register_flags("defcmd", kdb_defcmd, "name \"usage\" \"help\"",
|
|
|
+ "Define a set of commands, down to endefcmd", 0,
|
|
|
+ KDB_ENABLE_ALWAYS_SAFE);
|
|
|
+ kdb_register_flags("kill", kdb_kill, "<-signal> <pid>",
|
|
|
+ "Send a signal to a process", 0,
|
|
|
+ KDB_ENABLE_SIGNAL);
|
|
|
+ kdb_register_flags("summary", kdb_summary, "",
|
|
|
+ "Summarize the system", 4,
|
|
|
+ KDB_ENABLE_ALWAYS_SAFE);
|
|
|
+ kdb_register_flags("per_cpu", kdb_per_cpu, "<sym> [<bytes>] [<cpu>]",
|
|
|
+ "Display per_cpu variables", 3,
|
|
|
+ KDB_ENABLE_MEM_READ);
|
|
|
+ kdb_register_flags("grephelp", kdb_grep_help, "",
|
|
|
+ "Display help on | grep", 0,
|
|
|
+ KDB_ENABLE_ALWAYS_SAFE);
|
|
|
}
|
|
|
|
|
|
/* Execute any commands defined in kdb_cmds. */
|