Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 107 additions & 21 deletions cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,11 @@ static void uci_usage(void)
"\tchanges [<config>]\n"
"\tcommit [<config>]\n"
"\tadd <config> <section-type>\n"
"\tadd_list <config>.<section>.<option>=<string>\n"
"\tadd_list <config>.<section>.<option>=<string> [<comment>]\n"
"\tdel_list <config>.<section>.<option>=<string>\n"
"\tshow [<config>[.<section>[.<option>]]]\n"
"\tget <config>.<section>[.<option>]\n"
"\tset <config>.<section>[.<option>]=<value>\n"
"\tget <config>.<section>[.<option>] [#]\n"
"\tset <config>.<section>[.<option>]=<value> [<comment>]\n"
"\tdelete <config>[.<section>[[.<option>][=<id>]]]\n"
"\trename <config>.<section>[.<option>]=<name>\n"
"\trevert <config>[.<section>[.<option>]]\n"
Expand All @@ -162,6 +162,7 @@ static void uci_usage(void)
"\t-c <path> set the search path for config files (default: "UCI_CONFDIR")\n"
"\t-C <path> set the search path for config override files (default: "UCI_CONF2DIR")\n"
"\t-d <str> set the delimiter for list values in uci show\n"
"\t-D don't load, store in memory, or save comments\n"
"\t-f <file> use <file> as input instead of stdin\n"
"\t-m when importing, merge data into an existing package\n"
"\t-n name unnamed sections on export (default)\n"
Expand Down Expand Up @@ -212,7 +213,42 @@ static void uci_print_value(FILE *f, const char *v)
fprintf(f, "'");
}

static void uci_show_value(struct uci_option *o, bool quote)
static void uci_print_changes_comment(FILE *f, const char *comment)
{
if (!comment || !comment[0])
return;

fputc('#', f);
for (const char *readptr = comment; *readptr; readptr++) {
if (*readptr == '\\') {
fputc('\\', f);
fputc('\\', f);
} else if (*readptr == '\n') {
fputc('\\', f);
fputc('n', f);
} else
fputc(*readptr, f);
}
}

static void uci_print_comment(FILE *f, const char *comment)
{
fputc('\'', f);
if (comment) {
for (const char *readptr = comment; *readptr; readptr++) {
if (*readptr != '\'')
fputc(*readptr, f);
else {
fputc('\'', f); /* end single-quoted string */
fputc('\\', f); fputc('\'', f); /* escaped single quote */
fputc('\'', f); /* start single-quoted string */
}
}
}
fputc('\'', f);
}

static void uci_show_option_value(struct uci_option *o, bool quote)
{
struct uci_element *e;
bool sep = false;
Expand All @@ -224,7 +260,6 @@ static void uci_show_value(struct uci_option *o, bool quote)
uci_print_value(stdout, o->v.string);
else
printf("%s", o->v.string);
printf("\n");
break;
case UCI_TYPE_LIST:
uci_foreach_element(&o->v.list, e) {
Expand All @@ -236,10 +271,31 @@ static void uci_show_value(struct uci_option *o, bool quote)
uci_print_value(stdout, e->name);
sep = true;
}
printf("\n");
break;
default:
printf("<unknown>\n");
printf("<unknown>");
break;
}
}

static void uci_show_option_comment(struct uci_option *o)
{
struct uci_element *e;
bool sep = false;

switch(o->type) {
case UCI_TYPE_STRING:
uci_print_comment(stdout, o->e.comment);
break;
case UCI_TYPE_LIST:
uci_foreach_element(&o->v.list, e) {
printf("%s", (sep ? delimiter : ""));
uci_print_comment(stdout, e->comment);
sep = true;
}
break;
default:
printf("<unknown>");
break;
}
}
Expand All @@ -250,7 +306,8 @@ static void uci_show_option(struct uci_option *o, bool quote)
o->section->package->e.name,
(cur_section_ref ? cur_section_ref : o->section->e.name),
o->e.name);
uci_show_value(o, quote);
uci_show_option_value(o, quote);
printf("\n");
}

static void uci_show_section(struct uci_section *s)
Expand All @@ -261,7 +318,8 @@ static void uci_show_section(struct uci_section *s)

cname = s->package->e.name;
sname = (cur_section_ref ? cur_section_ref : s->e.name);
printf("%s.%s=%s\n", cname, sname, s->type);
printf("%s.%s=%s", cname, sname, s->type);
printf("\n");
uci_foreach_element(&s->options, e) {
uci_show_option(uci_to_option(e), true);
}
Expand Down Expand Up @@ -309,6 +367,8 @@ static void uci_show_changes(struct uci_package *p)
printf("%s", op);
uci_print_value(stdout, h->value);
}
if (!(ctx->flags & UCI_FLAG_NO_COMMENTS))
uci_print_changes_comment(stdout, e->comment);
printf("\n");
}
}
Expand Down Expand Up @@ -472,7 +532,8 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv)
int ret = UCI_OK;
int dummy;

if (argc != 2)
if (!((argc == 2) ||
((argc == 3) && ((cmd == CMD_GET) || (cmd == CMD_SET) || (cmd == CMD_ADD_LIST)))))
return 255;

if (uci_lookup_ptr(ctx, &ptr, argv[1], true) != UCI_OK) {
Expand All @@ -483,11 +544,20 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv)
return 1;
}

if (argc == 3) {
ptr.comment = argv[2];
if ((cmd == CMD_GET) && strcmp(ptr.comment, "#"))
return 1;
else if (!uci_validate_comment(ptr.comment))
return 1;
}

if (ptr.value && (cmd != CMD_SET) && (cmd != CMD_DEL) &&
(cmd != CMD_ADD_LIST) && (cmd != CMD_DEL_LIST) &&
(cmd != CMD_RENAME) && (cmd != CMD_REORDER))
return 1;


switch(cmd) {
case CMD_GET:
if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) {
Expand All @@ -498,10 +568,20 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv)
cli_perror();
return 1;
}
if (ptr.o)
uci_show_value(ptr.o, false);
else if (ptr.s)
printf("%s\n", ptr.s->type);
if (ptr.o) {
if (!ptr.comment)
uci_show_option_value(ptr.o, false);
else
uci_show_option_comment(ptr.o);
printf("\n");
}
else if (ptr.s) {
if (!ptr.comment)
printf("%s", ptr.s->type);
else
uci_print_comment(stdout, ptr.s->e.comment);
printf("\n");
}
break;
case CMD_RENAME:
ret = uci_rename(ctx, &ptr);
Expand Down Expand Up @@ -685,7 +765,7 @@ static int uci_cmd(int argc, char **argv)

int main(int argc, char **argv)
{
int ret;
int ret = 1;
int c;

flags = CLI_FLAG_SHOW_EXT;
Expand All @@ -694,10 +774,10 @@ int main(int argc, char **argv)
ctx = uci_alloc_context();
if (!ctx) {
cli_error("Out of memory\n");
return 1;
goto cleanup;
}

while((c = getopt(argc, argv, "c:C:d:f:LmnNp:P:qsSt:X")) != -1) {
while((c = getopt(argc, argv, "c:C:d:Df:LmnNp:P:qsSt:X")) != -1) {
switch(c) {
case 'c':
uci_set_confdir(ctx, optarg);
Expand All @@ -712,15 +792,18 @@ int main(int argc, char **argv)
if (input != stdin) {
fclose(input);
cli_error("Too many input files.\n");
return 1;
goto cleanup;
}

input = fopen(optarg, "r");
if (!input) {
cli_error("uci: %s", strerror(errno));
return 1;
goto cleanup;
}
break;
case 'D':
ctx->flags |= UCI_FLAG_NO_COMMENTS;
break;
case 'm':
flags |= CLI_FLAG_MERGE;
break;
Expand Down Expand Up @@ -755,7 +838,8 @@ int main(int argc, char **argv)
break;
default:
uci_usage();
return 0;
ret = 0;
goto cleanup;
}
}
if (optind > 1)
Expand All @@ -765,7 +849,8 @@ int main(int argc, char **argv)

if (argc < 2) {
uci_usage();
return 0;
ret = 0;
goto cleanup;
}

ret = uci_cmd(argc - 1, argv + 1);
Expand All @@ -775,6 +860,7 @@ int main(int argc, char **argv)
if (ret == 255)
uci_usage();

cleanup:
uci_free_context(ctx);

return ret;
Expand Down
45 changes: 38 additions & 7 deletions delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

/* record a change that was done to a package */
void
uci_add_delta(struct uci_context *ctx, struct uci_list *list, int cmd, const char *section, const char *option, const char *value)
uci_add_delta(struct uci_context *ctx, struct uci_list *list, int cmd, const char *section, const char *option, const char *value, const char *comment)
{
struct uci_delta *h;
int size = strlen(section) + 1;
Expand All @@ -42,7 +42,7 @@ uci_add_delta(struct uci_context *ctx, struct uci_list *list, int cmd, const cha
if (value)
size += strlen(value) + 1;

h = uci_alloc_element(ctx, delta, option, size);
h = uci_alloc_element(ctx, (ctx->flags & UCI_FLAG_NO_COMMENTS) ? NULL : comment, delta, option, size);
ptr = uci_dataptr(h);
h->cmd = cmd;
h->section = strcpy(ptr, section);
Expand All @@ -66,6 +66,33 @@ uci_free_delta(struct uci_delta *h)
uci_free_element(&h->e);
}

static void uci_fprintf_escaped_comment(FILE *f, const char *comment)
{
if (!comment || !comment[0])
return;

/*
* Older uci versions just ignore the '#' and everything behind it, up
* to and including the newline, and expect the next change on the
* next line.
* To be compatible with those older versions, we do not output
* multiline strings here. Instead, we escape '\\' and '\n' in the
* comment. Older versions will then work, just not put the comments
* in the configuration file.
*/
fputc('#', f);
for (const char *readptr = comment; *readptr; readptr++) {
if (*readptr == '\\') {
fputc('\\', f);
fputc('\\', f);
} else if (*readptr == '\n') {
fputc('\\', f);
fputc('n', f);
} else
fputc(*readptr, f);
}
}

static void uci_delta_save(struct uci_context *ctx, FILE *f,
const char *name, const struct uci_delta *h)
{
Expand All @@ -92,7 +119,9 @@ static void uci_delta_save(struct uci_context *ctx, FILE *f,
else
fprintf(f, "'\\''");
}
fprintf(f, "'\n");
fprintf(f, "'");
uci_fprintf_escaped_comment(f, e->comment);
fprintf(f, "\n");
}
}

Expand All @@ -114,7 +143,7 @@ int uci_set_savedir(struct uci_context *ctx, const char *dir)
}
}
if (!exists)
e = uci_alloc_generic(ctx, UCI_TYPE_PATH, dir, sizeof(struct uci_element));
e = uci_alloc_generic(ctx, NULL, UCI_TYPE_PATH, dir, sizeof(struct uci_element));
uci_list_add(&ctx->delta_path, &e->list);

sdir = uci_strdup(ctx, dir);
Expand All @@ -138,7 +167,7 @@ int uci_add_delta_path(struct uci_context *ctx, const char *dir)
UCI_THROW(ctx, UCI_ERR_DUPLICATE);
}

e = uci_alloc_generic(ctx, UCI_TYPE_PATH, dir, sizeof(struct uci_element));
e = uci_alloc_generic(ctx, NULL, UCI_TYPE_PATH, dir, sizeof(struct uci_element));
/* Keep savedir at the end of ctx->delta_path list */
savedir = ctx->delta_path.prev;
uci_list_insert(savedir->prev, &e->list);
Expand Down Expand Up @@ -177,6 +206,8 @@ static inline int uci_parse_delta_tuple(struct uci_context *ctx, struct uci_ptr
arg += 1;

UCI_INTERNAL(uci_parse_ptr, ctx, ptr, arg);
if (!ptr->comment && pctx->commentbuf)
ptr->comment = pctx->commentbuf;

if (!ptr->section)
goto error;
Expand Down Expand Up @@ -221,7 +252,7 @@ static void uci_parse_delta_line(struct uci_context *ctx, struct uci_package *p)
goto error;

if (ctx->flags & UCI_FLAG_SAVED_DELTA)
uci_add_delta(ctx, &p->saved_delta, cmd, ptr.section, ptr.option, ptr.value);
uci_add_delta(ctx, &p->saved_delta, cmd, ptr.section, ptr.option, ptr.value, ptr.comment);

switch(cmd) {
case UCI_CMD_REORDER:
Expand Down Expand Up @@ -393,7 +424,7 @@ static void uci_filter_delta(struct uci_context *ctx, const char *name, const ch

if (!match && ptr.section) {
uci_add_delta(ctx, &list, c,
ptr.section, ptr.option, ptr.value);
ptr.section, ptr.option, ptr.value, ptr.comment);
}
}

Expand Down
Loading
Loading