summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2012-05-01 21:41:59 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2012-05-01 21:41:59 +0200
commite4e3fbd22bca38f10f1cd7a3f5eb75e0b265dcaa (patch)
treefc713ed2e9b4ed774bc4dda9521dcb7ff867e2dd
parent8ca42643d4a3a15d4802f93d1433e640b846df04 (diff)
parent9492976bc88a9fe4633202681fcdc24ce1dab636 (diff)
downloadbarebox-e4e3fbd22bca38f10f1cd7a3f5eb75e0b265dcaa.tar.gz
barebox-e4e3fbd22bca38f10f1cd7a3f5eb75e0b265dcaa.tar.xz
Merge tag 'complete_update_support' of git://git.jcrosoft.org/barebox into next
improve complete support The following patch serie improve the complete support by adding a complete framework to allow commands complete support. The add also car complete support for eval and setting and executable file support This also include an update of the stringlist API to support asprintf API
-rw-r--r--arch/arm/cpu/cpuinfo.c2
-rw-r--r--arch/arm/mach-imx/speed.c2
-rw-r--r--arch/arm/mach-mxs/imx.c2
-rw-r--r--commands/clear.c2
-rw-r--r--commands/false.c2
-rw-r--r--commands/go.c2
-rw-r--r--commands/help.c2
-rw-r--r--commands/login.c2
-rw-r--r--commands/lsmod.c2
-rw-r--r--commands/meminfo.c2
-rw-r--r--commands/net.c2
-rw-r--r--commands/partition.c2
-rw-r--r--commands/passwd.c2
-rw-r--r--commands/pwd.c2
-rw-r--r--commands/reginfo.c2
-rw-r--r--commands/reset.c2
-rw-r--r--commands/sleep.c2
-rw-r--r--commands/true.c2
-rw-r--r--commands/usb.c2
-rw-r--r--commands/version.c2
-rw-r--r--common/complete.c201
-rw-r--r--drivers/base/driver.c2
-rw-r--r--drivers/usb/gadget/u_serial.c2
-rw-r--r--fs/devfs-core.c19
-rw-r--r--include/command.h8
-rw-r--r--include/complete.h12
-rw-r--r--include/stringlist.h7
-rw-r--r--lib/stringlist.c32
-rw-r--r--net/dhcp.c2
-rw-r--r--net/eth.c21
30 files changed, 312 insertions, 34 deletions
diff --git a/arch/arm/cpu/cpuinfo.c b/arch/arm/cpu/cpuinfo.c
index 09acb5f4de..ca986f8013 100644
--- a/arch/arm/cpu/cpuinfo.c
+++ b/arch/arm/cpu/cpuinfo.c
@@ -22,6 +22,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
#define CPU_ARCH_UNKNOWN 0
#define CPU_ARCH_ARMv3 1
@@ -181,5 +182,6 @@ static int do_cpuinfo(int argc, char *argv[])
BAREBOX_CMD_START(cpuinfo)
.cmd = do_cpuinfo,
.usage = "Show info about CPU",
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/arch/arm/mach-imx/speed.c b/arch/arm/mach-imx/speed.c
index 63e24b494f..6f8d20b741 100644
--- a/arch/arm/mach-imx/speed.c
+++ b/arch/arm/mach-imx/speed.c
@@ -24,6 +24,7 @@
#include <asm-generic/div64.h>
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <mach/clock.h>
/*
@@ -80,5 +81,6 @@ static int do_clocks(int argc, char *argv[])
BAREBOX_CMD_START(dump_clocks)
.cmd = do_clocks,
.usage = "show clock frequencies",
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/arch/arm/mach-mxs/imx.c b/arch/arm/mach-mxs/imx.c
index a4dae205ca..c64f23ceb5 100644
--- a/arch/arm/mach-mxs/imx.c
+++ b/arch/arm/mach-mxs/imx.c
@@ -19,6 +19,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
extern void imx_dump_clocks(void);
@@ -32,4 +33,5 @@ static int do_clocks(int argc, char *argv[])
BAREBOX_CMD_START(dump_clocks)
.cmd = do_clocks,
.usage = "show clock frequencies",
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/clear.c b/commands/clear.c
index 9e5da10d4f..28b4da9661 100644
--- a/commands/clear.c
+++ b/commands/clear.c
@@ -22,6 +22,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <readkey.h>
static int do_clear(int argc, char *argv[])
@@ -39,4 +40,5 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(clear)
.cmd = do_clear,
.usage = "clear screen",
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/false.c b/commands/false.c
index 6ba3823229..1642f8de15 100644
--- a/commands/false.c
+++ b/commands/false.c
@@ -23,6 +23,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
static int do_false(int argc, char *argv[])
{
@@ -32,5 +33,6 @@ static int do_false(int argc, char *argv[])
BAREBOX_CMD_START(false)
.cmd = do_false,
.usage = "do nothing, unsuccessfully",
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/go.c b/commands/go.c
index c821207a6f..e9e9d40dbe 100644
--- a/commands/go.c
+++ b/commands/go.c
@@ -25,6 +25,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <fs.h>
#include <fcntl.h>
#include <linux/ctype.h>
@@ -91,4 +92,5 @@ BAREBOX_CMD_START(go)
.cmd = do_go,
.usage = "start application at address or file",
BAREBOX_CMD_HELP(cmd_go_help)
+ BAREBOX_CMD_COMPLETE(cammand_var_complete)
BAREBOX_CMD_END
diff --git a/commands/help.c b/commands/help.c
index 706b9057e9..d7d9ba25af 100644
--- a/commands/help.c
+++ b/commands/help.c
@@ -23,6 +23,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
/*
* Use puts() instead of printf() to avoid printf buffer overflow
@@ -68,5 +69,6 @@ BAREBOX_CMD_START(help)
.aliases = help_aliases,
.usage = "print online help",
BAREBOX_CMD_HELP(cmd_help_help)
+ BAREBOX_CMD_COMPLETE(command_complete)
BAREBOX_CMD_END
diff --git a/commands/login.c b/commands/login.c
index 2f3d7668d5..0b5f3cbb4a 100644
--- a/commands/login.c
+++ b/commands/login.c
@@ -20,6 +20,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <password.h>
#include <getopt.h>
@@ -80,4 +81,5 @@ BAREBOX_CMD_START(login)
.cmd = do_login,
.usage = "login",
BAREBOX_CMD_HELP(cmd_login_help)
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/lsmod.c b/commands/lsmod.c
index f7da1d01ef..e54eadc2ff 100644
--- a/commands/lsmod.c
+++ b/commands/lsmod.c
@@ -1,5 +1,6 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <module.h>
static int do_lsmod(int argc, char *argv[])
@@ -15,4 +16,5 @@ static int do_lsmod(int argc, char *argv[])
BAREBOX_CMD_START(lsmod)
.cmd = do_lsmod,
.usage = "list modules",
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/meminfo.c b/commands/meminfo.c
index b41274439d..1d24cfdb3c 100644
--- a/commands/meminfo.c
+++ b/commands/meminfo.c
@@ -21,6 +21,7 @@
*/
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <malloc.h>
static int do_meminfo(int argc, char *argv[])
@@ -33,4 +34,5 @@ static int do_meminfo(int argc, char *argv[])
BAREBOX_CMD_START(meminfo)
.cmd = do_meminfo,
.usage = "print info about memory usage",
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/net.c b/commands/net.c
index c5c6373dd3..a453f4ed33 100644
--- a/commands/net.c
+++ b/commands/net.c
@@ -28,6 +28,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <environment.h>
#include <driver.h>
#include <net.h>
@@ -96,5 +97,6 @@ BAREBOX_CMD_START(ethact)
.cmd = do_ethact,
.usage = "set current ethernet device",
BAREBOX_CMD_HELP(cmd_ethact_help)
+ BAREBOX_CMD_COMPLETE(eth_complete)
BAREBOX_CMD_END
diff --git a/commands/partition.c b/commands/partition.c
index 4892261885..6cce0423d3 100644
--- a/commands/partition.c
+++ b/commands/partition.c
@@ -32,6 +32,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <driver.h>
#include <malloc.h>
#include <partition.h>
@@ -225,5 +226,6 @@ BAREBOX_CMD_START(delpart)
.cmd = do_delpart,
.usage = "delete partition(s)",
BAREBOX_CMD_HELP(cmd_delpart_help)
+ BAREBOX_CMD_COMPLETE(devfs_partition_complete)
BAREBOX_CMD_END
diff --git a/commands/passwd.c b/commands/passwd.c
index cdbcdf540f..7f704ad454 100644
--- a/commands/passwd.c
+++ b/commands/passwd.c
@@ -20,6 +20,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <password.h>
#include <errno.h>
@@ -95,4 +96,5 @@ BAREBOX_CMD_START(passwd)
.cmd = do_passwd,
.usage = "passwd",
BAREBOX_CMD_HELP(cmd_passwd_help)
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/pwd.c b/commands/pwd.c
index 4afe2d4a49..d68a509f78 100644
--- a/commands/pwd.c
+++ b/commands/pwd.c
@@ -21,6 +21,7 @@
*/
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <fs.h>
static int do_pwd(int argc, char *argv[])
@@ -32,4 +33,5 @@ static int do_pwd(int argc, char *argv[])
BAREBOX_CMD_START(pwd)
.cmd = do_pwd,
.usage = "print working directory",
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/reginfo.c b/commands/reginfo.c
index 009a065a2d..a31013a664 100644
--- a/commands/reginfo.c
+++ b/commands/reginfo.c
@@ -22,6 +22,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
static int do_reginfo(int argc, char *argv[])
{
@@ -32,4 +33,5 @@ static int do_reginfo(int argc, char *argv[])
BAREBOX_CMD_START(reginfo)
.cmd = do_reginfo,
.usage = "print register information",
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/reset.c b/commands/reset.c
index 9f242d12c1..97d04eed13 100644
--- a/commands/reset.c
+++ b/commands/reset.c
@@ -22,6 +22,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
static int cmd_reset(int argc, char *argv[])
{
@@ -34,4 +35,5 @@ static int cmd_reset(int argc, char *argv[])
BAREBOX_CMD_START(reset)
.cmd = cmd_reset,
.usage = "Perform RESET of the CPU",
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/sleep.c b/commands/sleep.c
index f772e87a0d..c5f7867400 100644
--- a/commands/sleep.c
+++ b/commands/sleep.c
@@ -22,6 +22,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <clock.h>
static int do_sleep(int argc, char *argv[])
@@ -46,4 +47,5 @@ static int do_sleep(int argc, char *argv[])
BAREBOX_CMD_START(sleep)
.cmd = do_sleep,
.usage = "delay execution for n seconds",
+ BAREBOX_CMD_COMPLETE(cammand_var_complete)
BAREBOX_CMD_END
diff --git a/commands/true.c b/commands/true.c
index 773ddef8a7..e50152ff57 100644
--- a/commands/true.c
+++ b/commands/true.c
@@ -23,6 +23,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
static int do_true(int argc, char *argv[])
{
@@ -32,5 +33,6 @@ static int do_true(int argc, char *argv[])
BAREBOX_CMD_START(true)
.cmd = do_true,
.usage = "do nothing, successfully",
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/usb.c b/commands/usb.c
index e28afd051b..d02ea4b0f7 100644
--- a/commands/usb.c
+++ b/commands/usb.c
@@ -21,6 +21,7 @@
*/
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <usb/usb.h>
#include <getopt.h>
@@ -56,4 +57,5 @@ BAREBOX_CMD_START(usb)
.cmd = do_usb,
.usage = "(re-)detect USB devices",
BAREBOX_CMD_HELP(cmd_usb_help)
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/version.c b/commands/version.c
index 8901faea68..6dbda7aade 100644
--- a/commands/version.c
+++ b/commands/version.c
@@ -23,6 +23,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
static int do_version(int argc, char *argv[])
{
@@ -33,5 +34,6 @@ static int do_version(int argc, char *argv[])
BAREBOX_CMD_START(version)
.cmd = do_version,
.usage = "print monitor version",
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/common/complete.c b/common/complete.c
index 6d5349b509..0b03d7ce9a 100644
--- a/common/complete.c
+++ b/common/complete.c
@@ -20,16 +20,13 @@
#include <common.h>
#include <complete.h>
#include <xfuncs.h>
-#include <linux/list.h>
-#include <malloc.h>
#include <fs.h>
#include <linux/stat.h>
#include <libgen.h>
#include <command.h>
-#include <stringlist.h>
#include <environment.h>
-static int file_complete(struct string_list *sl, char *instr)
+static int file_complete(struct string_list *sl, char *instr, int exec)
{
char *path = strdup(instr);
struct stat s;
@@ -49,15 +46,20 @@ static int file_complete(struct string_list *sl, char *instr)
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
- if (!strncmp(base, d->d_name, strlen(base))) {
- strcpy(tmp, instr);
- strcat(tmp, d->d_name + strlen(base));
- if (!stat(tmp, &s) && S_ISDIR(s.st_mode))
- strcat(tmp, "/");
- else
- strcat(tmp, " ");
- string_list_add_sorted(sl, tmp);
+ if (strncmp(base, d->d_name, strlen(base)))
+ continue;
+
+ strcpy(tmp, instr);
+ strcat(tmp, d->d_name + strlen(base));
+ if (!stat(tmp, &s) && S_ISDIR(s.st_mode)) {
+ strcat(tmp, "/");
+ } else {
+ if (exec && !S_ISREG(s.st_mode))
+ continue;
+ strcat(tmp, " ");
}
+
+ string_list_add_sorted(sl, tmp);
}
closedir(dir);
@@ -131,17 +133,128 @@ static int path_command_complete(struct string_list *sl, char *instr)
return 0;
}
-static int command_complete(struct string_list *sl, char *instr)
+int command_complete(struct string_list *sl, char *instr)
{
struct command *cmdtp;
- char cmd[128];
+
+ if (!instr)
+ instr = "";
for_each_command(cmdtp) {
- if (!strncmp(instr, cmdtp->name, strlen(instr))) {
- strcpy(cmd, cmdtp->name);
- cmd[strlen(cmdtp->name)] = ' ';
- cmd[strlen(cmdtp->name) + 1] = 0;
- string_list_add(sl, cmd);
+ if (strncmp(instr, cmdtp->name, strlen(instr)))
+ continue;
+
+ string_list_add_asprintf(sl, "%s ", cmdtp->name);
+ }
+
+ return 0;
+}
+
+int device_complete(struct string_list *sl, char *instr)
+{
+ struct device_d *dev;
+ int len;
+
+ if (!instr)
+ instr = "";
+
+ len = strlen(instr);
+
+ for_each_device(dev) {
+ if (strncmp(instr, dev_name(dev), len))
+ continue;
+
+ string_list_add_asprintf(sl, "%s ", dev_name(dev));
+ }
+
+ return COMPLETE_CONTINUE;
+}
+
+static int device_param_complete(char *begin, struct device_d *dev,
+ struct string_list *sl, char *instr)
+{
+ struct param_d *param;
+ int len;
+
+ if (!instr)
+ instr = "";
+
+ len = strlen(instr);
+
+ list_for_each_entry(param, &dev->parameters, list) {
+ if (strncmp(instr, param->name, len))
+ continue;
+
+ string_list_add_asprintf(sl, "%s%s.%s%c",
+ begin ? begin : "", dev_name(dev), param->name,
+ begin ? ' ' : '=');
+ }
+
+ return 0;
+}
+
+int empty_complete(struct string_list *sl, char *instr)
+{
+ return COMPLETE_END;
+}
+
+int cammand_var_complete(struct string_list *sl, char *instr)
+{
+ return COMPLETE_CONTINUE;
+}
+
+static int env_param_complete(struct string_list *sl, char *instr, int eval)
+{
+ struct device_d *dev;
+ struct variable_d *var;
+ struct env_context *c, *current_c;
+ char *instr_param;
+ int len;
+ char end = '=';
+ char *begin = "";
+
+ if (!instr)
+ instr = "";
+
+ if (eval) {
+ begin = "$";
+ end = ' ';
+ }
+
+ instr_param = strrchr(instr, '.');
+ len = strlen(instr);
+
+ current_c = get_current_context();
+ for(var = current_c->local->next; var; var = var->next) {
+ if (strncmp(instr, var_name(var), len))
+ continue;
+ string_list_add_asprintf(sl, "%s%s%c",
+ begin, var_name(var), end);
+ }
+
+ for (c = get_current_context(); c; c = c->parent) {
+ for (var = c->global->next; var; var = var->next) {
+ if (strncmp(instr, var_name(var), len))
+ continue;
+ string_list_add_asprintf(sl, "%s%s%c",
+ begin, var_name(var), end);
+ }
+ }
+
+ if (instr_param) {
+ len = (instr_param - instr);
+ instr_param++;
+ } else {
+ len = strlen(instr);
+ instr_param = "";
+ }
+
+ for_each_device(dev) {
+ if (!strncmp(instr, dev_name(dev), len)) {
+ if (eval)
+ device_param_complete("$", dev, sl, instr_param);
+ else
+ device_param_complete(NULL, dev, sl, instr_param);
}
}
@@ -155,6 +268,32 @@ void complete_reset(void)
tab_pressed = 0;
}
+static char* cmd_complete_lookup(struct string_list *sl, char *instr)
+{
+ struct command *cmdtp;
+ int len;
+ int ret = 1;
+ char *res = NULL;
+
+ for_each_command(cmdtp) {
+ len = strlen(cmdtp->name);
+ if (!strncmp(instr, cmdtp->name, len) && instr[len] == ' ') {
+ instr += len + 1;
+ if (cmdtp->complete) {
+ ret = cmdtp->complete(sl, instr);
+ res = instr;
+ }
+ goto end;
+ }
+ }
+
+end:
+ if (ret == COMPLETE_CONTINUE && *instr == '$')
+ env_param_complete(sl, instr + 1, 1);
+
+ return res;
+}
+
int complete(char *instr, char **outstr)
{
struct string_list sl, *entry, *first_entry;
@@ -178,16 +317,24 @@ int complete(char *instr, char **outstr)
while (*t == ' ')
t++;
- instr = t;
-
/* get the completion possibilities */
- if ((t = strrchr(t, ' '))) {
- t++;
- file_complete(&sl, t);
+ instr = cmd_complete_lookup(&sl, t);
+ if (!instr) {
instr = t;
- } else {
- command_complete(&sl, instr);
- path_command_complete(&sl, instr);
+ if (t && (t[0] == '/' || !strncmp(t, "./", 2))) {
+ file_complete(&sl, t, 1);
+ instr = t;
+ } else if ((t = strrchr(t, ' '))) {
+ t++;
+ file_complete(&sl, t, 0);
+ instr = t;
+ } else {
+ command_complete(&sl, instr);
+ path_command_complete(&sl, instr);
+ env_param_complete(&sl, instr, 0);
+ }
+ if (*instr == '$')
+ env_param_complete(&sl, instr + 1, 1);
}
pos = strlen(instr);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 9924fee8ac..547d6843a6 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -33,6 +33,7 @@
#include <errno.h>
#include <fs.h>
#include <linux/list.h>
+#include <complete.h>
LIST_HEAD(device_list);
EXPORT_SYMBOL(device_list);
@@ -443,6 +444,7 @@ BAREBOX_CMD_START(devinfo)
.cmd = do_devinfo,
.usage = "Show information about devices and drivers.",
BAREBOX_CMD_HELP(cmd_devinfo_help)
+ BAREBOX_CMD_COMPLETE(device_complete)
BAREBOX_CMD_END
#endif
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index c5e7387d54..946b4f2d4c 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -18,6 +18,7 @@
/* #define VERBOSE_DEBUG */
#include <common.h>
+#include <complete.h>
#include <usb/cdc.h>
#include <kfifo.h>
#include <clock.h>
@@ -502,6 +503,7 @@ static int do_mycdev(int argc, char *argv[])
BAREBOX_CMD_START(mycdev)
.cmd = do_mycdev,
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
/**
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index 3014d0ebff..ff6a97627a 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -20,6 +20,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <common.h>
+#include <complete.h>
#include <driver.h>
#include <errno.h>
#include <malloc.h>
@@ -29,6 +30,24 @@
LIST_HEAD(cdev_list);
+#ifdef CONFIG_AUTO_COMPLETE
+int devfs_partition_complete(struct string_list *sl, char *instr)
+{
+ struct cdev *cdev;
+ int len;
+
+ len = strlen(instr);
+
+ list_for_each_entry(cdev, &cdev_list, list) {
+ if (cdev->flags & DEVFS_IS_PARTITION &&
+ !strncmp(instr, cdev->name, len)) {
+ string_list_add_asprintf(sl, "%s ", cdev->name);
+ }
+ }
+ return COMPLETE_CONTINUE;
+}
+#endif
+
struct cdev *cdev_by_name(const char *filename)
{
struct cdev *cdev;
diff --git a/include/command.h b/include/command.h
index b2e84496c8..80cbf5603f 100644
--- a/include/command.h
+++ b/include/command.h
@@ -40,6 +40,8 @@ extern struct list_head command_list;
#define for_each_command(cmd) list_for_each_entry(cmd, &command_list, list)
+struct string_list;
+
/*
* Monitor Command Table
*/
@@ -48,6 +50,7 @@ struct command {
const char **aliases;
/* Implementation function */
int (*cmd)(int, char *[]);
+ int (*complete)(struct string_list *sl, char *instr);
const char *usage; /* Usage message (short) */
struct list_head list; /* List of commands */
@@ -88,6 +91,11 @@ const struct command __barebox_cmd_##_name \
#define BAREBOX_CMD_END \
};
+#ifdef CONFIG_AUTO_COMPLETE
+#define BAREBOX_CMD_COMPLETE(_cpt) .complete = _cpt,
+#else
+#define BAREBOX_CMD_COMPLETE(_cpt)
+#endif
#define BAREBOX_CMD_HELP_START(_name) \
static const __maybe_unused char cmd_##_name##_help[] =
diff --git a/include/complete.h b/include/complete.h
index cc0e88de0f..8248c64d0c 100644
--- a/include/complete.h
+++ b/include/complete.h
@@ -2,9 +2,21 @@
#define __COMPLETE_
#include <linux/list.h>
+#include <malloc.h>
+#include <stringlist.h>
+
+#define COMPLETE_END 0
+#define COMPLETE_CONTINUE 1
int complete(char *instr, char **outstr);
void complete_reset(void);
+int command_complete(struct string_list *sl, char *instr);
+int device_complete(struct string_list *sl, char *instr);
+int empty_complete(struct string_list *sl, char *instr);
+int eth_complete(struct string_list *sl, char *instr);
+int cammand_var_complete(struct string_list *sl, char *instr);
+int devfs_partition_complete(struct string_list *sl, char *instr);
+
#endif /* __COMPLETE_ */
diff --git a/include/stringlist.h b/include/stringlist.h
index c92354281e..dd3f623618 100644
--- a/include/stringlist.h
+++ b/include/stringlist.h
@@ -5,10 +5,11 @@
struct string_list {
struct list_head list;
- char str[0];
+ char *str;
};
int string_list_add(struct string_list *sl, char *str);
+int string_list_add_asprintf(struct string_list *sl, const char *fmt, ...);
int string_list_add_sorted(struct string_list *sl, char *str);
int string_list_contains(struct string_list *sl, char *str);
void string_list_print_by_column(struct string_list *sl);
@@ -22,8 +23,10 @@ static inline void string_list_free(struct string_list *sl)
{
struct string_list *entry, *safe;
- list_for_each_entry_safe(entry, safe, &sl->list, list)
+ list_for_each_entry_safe(entry, safe, &sl->list, list) {
+ free(entry->str);
free(entry);
+ }
}
#endif /* __STRING_H */
diff --git a/lib/stringlist.c b/lib/stringlist.c
index a8ff97964f..b965aa058c 100644
--- a/lib/stringlist.c
+++ b/lib/stringlist.c
@@ -1,6 +1,7 @@
#include <common.h>
#include <xfuncs.h>
#include <malloc.h>
+#include <errno.h>
#include <stringlist.h>
static int string_list_compare(struct list_head *a, struct list_head *b)
@@ -16,9 +17,31 @@ int string_list_add(struct string_list *sl, char *str)
{
struct string_list *new;
- new = xmalloc(sizeof(struct string_list) + strlen(str) + 1);
+ new = xmalloc(sizeof(*new));
+ new->str = xstrdup(str);
- strcpy(new->str, str);
+ list_add_tail(&new->list, &sl->list);
+
+ return 0;
+}
+
+int string_list_add_asprintf(struct string_list *sl, const char *fmt, ...)
+{
+ struct string_list *new;
+ va_list args;
+
+ new = xmalloc(sizeof(*new));
+
+ va_start(args, fmt);
+
+ new->str = vasprintf(fmt, args);
+
+ va_end(args);
+
+ if (!new->str) {
+ free(new);
+ return -ENOMEM;
+ }
list_add_tail(&new->list, &sl->list);
@@ -29,9 +52,8 @@ int string_list_add_sorted(struct string_list *sl, char *str)
{
struct string_list *new;
- new = xmalloc(sizeof(struct string_list) + strlen(str) + 1);
-
- strcpy(new->str, str);
+ new = xmalloc(sizeof(*new));
+ new->str = xstrdup(str);
list_add_sort(&new->list, &sl->list, string_list_compare);
diff --git a/net/dhcp.c b/net/dhcp.c
index bd3ac1a297..79efa3e30e 100644
--- a/net/dhcp.c
+++ b/net/dhcp.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <environment.h>
#include <clock.h>
#include <net.h>
@@ -705,6 +706,7 @@ BAREBOX_CMD_START(dhcp)
.cmd = do_dhcp,
.usage = "invoke dhcp client to obtain ip/boot params",
BAREBOX_CMD_HELP(cmd_dhcp_help)
+ BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
BAREBOX_MAGICVAR(bootfile, "bootfile returned from DHCP request");
diff --git a/net/eth.c b/net/eth.c
index 130805b7aa..4ea9fb0f4e 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -23,6 +23,7 @@
#include <common.h>
#include <command.h>
+#include <complete.h>
#include <driver.h>
#include <init.h>
#include <net.h>
@@ -109,6 +110,26 @@ struct eth_device *eth_get_byname(char *ethname)
return NULL;
}
+#ifdef CONFIG_AUTO_COMPLETE
+int eth_complete(struct string_list *sl, char *instr)
+{
+ struct eth_device *edev;
+ const char *devname;
+ int len;
+
+ len = strlen(instr);
+
+ list_for_each_entry(edev, &netdev_list, list) {
+ devname = dev_name(&edev->dev);
+ if (strncmp(instr, devname, len))
+ continue;
+
+ string_list_add_asprintf(sl, "%s ", devname);
+ }
+ return COMPLETE_CONTNINUE;
+}
+#endif
+
int eth_send(void *packet, int length)
{
int ret;