Allow IPv6 address entry in tools>ping - Loosens valid character check
[tomato/davidwu.git] / release / src / router / nvram / nvram.c
blob91a62d759bbe6bba03967fec3dae82f3dd1c71fb
1 /*
3 NVRAM Utility
4 Copyright (C) 2006-2009 Jonathan Zarate
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <ctype.h>
13 #include <sys/wait.h>
15 #include <bcmdevs.h>
16 #include <bcmnvram.h>
17 #include <utils.h>
18 #include <shutils.h>
19 #include <shared.h>
21 #include "nvram_convert.h"
22 #include "defaults.h"
25 __attribute__ ((noreturn))
26 static void help(void)
28 printf(
29 "NVRAM Utility\n"
30 "Copyright (C) 2006-2009 Jonathan Zarate\n\n"
31 "Usage: nvram set <key=value> | get <key> | unset <key> |\n"
32 "ren <key> <key> | commit | erase | show [--nosort|--nostat] |\n"
33 "find <text> | defaults <--yes|--initcheck> | backup <filename> |\n"
34 "restore <filename> [--test] [--force] [--forceall] [--nocommit] |\n"
35 "export <--quote|--c|--set|--tab> [--nodefaults] |\n"
36 "export <--dump|--dump0> | import [--forceall] <filename> |\n"
37 "setfb64 <key> <filename> | getfb64 <key> <filename> |\n"
38 "setfile <key> <filename> | getfile <key> <filename> | setfile2nvram <filename>"
39 // "test"
40 "\n");
41 exit(1);
44 static void getall(char *buffer)
46 if (nvram_getall(buffer, NVRAM_SPACE) != 0) {
47 fprintf(stderr, "Error reading NVRAM\n");
48 exit(1);
52 static int set_main(int argc, char **argv)
54 char *b, *p;
56 if ((b = strdup(argv[1])) == NULL) {
57 fprintf(stderr, "Not enough memory");
58 return 1;
60 if ((p = strchr(b, '=')) != NULL) {
61 *p = 0;
62 nvram_set(b, p + 1);
63 return 0;
65 help();
68 static int get_main(int argc, char **argv)
70 char *p;
72 if ((p = nvram_get(argv[1])) != NULL) {
73 puts(p);
74 return 0;
76 return 1;
79 static int unset_main(int argc, char **argv)
81 nvram_unset(argv[1]);
82 return 0;
85 static int ren_main(int argc, char **argv)
87 char *p;
89 if ((p = nvram_get(argv[1])) == NULL) {
90 fprintf(stderr, "Unable to find %s\n", argv[1]);
91 return 1;
93 if (strcmp(argv[1], argv[2]) != 0) {
94 nvram_set(argv[2], p);
95 nvram_unset(argv[1]);
97 return 0;
100 extern int nvram_file2nvram(const char *name, const char *filename);
101 extern int nvram_nvram2file(const char *name, const char *filename);
103 static int f2n_main(int argc, char **argv)
105 return (nvram_file2nvram(argv[1], argv[2]));
109 static int n2f_main(int argc, char **argv)
111 return (nvram_nvram2file(argv[1], argv[2]));
114 static int save2f_main(int argc, char **argv)
116 char name[128] = "FILE:";
118 strcpy(name+5, argv[1]);
119 return (nvram_file2nvram(name, argv[1]));
122 static int show_main(int argc, char **argv)
124 char *p, *q;
125 char buffer[NVRAM_SPACE];
126 int n;
127 int count;
128 int show = 1;
129 int stat = 1;
130 int sort = 1;
132 for (n = 1; n < argc; ++n) {
133 if (strcmp(argv[n], "--nostat") == 0) stat = 0;
134 else if (strcmp(argv[n], "--nosort") == 0) sort = 0;
135 else help();
138 if (sort) {
139 system("nvram show --nostat --nosort | sort"); // smallest and easiest way :)
140 show = 0;
143 getall(buffer);
144 count = 0;
145 for (p = buffer; *p; p += strlen(p) + 1) {
146 q = p;
147 while (*q) {
148 if (!isprint(*q)) *q = ' ';
149 ++q;
151 if (show) puts(p);
152 ++count;
154 if (stat) {
155 n = sizeof(struct nvram_header) + (p - buffer);
156 printf("---\n%d entries, %d bytes used, %d bytes free.\n", count, n, NVRAM_SPACE - n);
158 return 0;
161 static int find_main(int argc, char **argv)
163 char cmd[512];
164 int r;
166 snprintf(cmd, sizeof(cmd), "nvram show --nostat --nosort | sort | grep \"%s\"", argv[1]);
167 r = system(cmd);
168 return (r == -1) ? 1 : WEXITSTATUS(r);
171 static const char *nv_default_value(const defaults_t *t)
173 int model = get_model();
175 if (strcmp(t->key, "wl_txpwr") == 0) {
176 switch (model) {
177 case MODEL_WHRG54S:
178 return "28";
179 #ifdef CONFIG_BCMWL5
180 case MODEL_RTN10:
181 case MODEL_RTN12:
182 case MODEL_RTN16:
183 return "17";
184 #endif
187 #ifdef TCONFIG_USB
188 else if (strcmp(t->key, "usb_enable") == 0) {
189 switch (model) {
190 case MODEL_WRTSL54GS:
191 case MODEL_WL500W:
192 case MODEL_WL500GP:
193 case MODEL_WL500GPv2:
194 case MODEL_WL500GE:
195 case MODEL_WL500GD:
196 case MODEL_WL520GU:
197 case MODEL_DIR320:
198 case MODEL_H618B:
199 case MODEL_WNR3500L:
200 case MODEL_RTN16:
201 case MODEL_WRT610Nv2:
202 case MODEL_F7D3301:
203 case MODEL_F7D3302:
204 case MODEL_F7D4301:
205 case MODEL_F7D4302:
206 case MODEL_F5D8235v3:
207 return "1";
210 #endif
211 return t->value;
214 static void nv_fix_wl(const char *oldnv, const char *newnv)
216 char *p;
218 if (nvram_get(wl_nvname(newnv, 0, 0)) == NULL) {
219 p = nvram_get(oldnv);
220 if (p != NULL) nvram_set(wl_nvname(newnv, -1, 0), p);
221 nvram_unset(oldnv);
225 static int validate_main(int argc, char **argv)
227 const defaults_t *t;
228 char *p;
229 int i;
230 int force = 0;
231 int unit = 0;
233 for (i = 1; i < argc; ++i) {
234 if (strcmp(argv[i], "--restore") == 0) {
235 force = 1;
237 else if (strncmp(argv[i], "--wl", 4) == 0) {
238 unit = atoi(argv[i] + 4);
242 for (t = defaults; t->key; t++) {
243 if (strncmp(t->key, "wl_", 3) == 0) {
244 // sync wl_ and wlX_
245 p = wl_nvname(t->key + 3, unit, 0);
246 if (force || nvram_get(p) == NULL)
247 nvram_set(p, t->value);
250 return 0;
253 static int defaults_main(int argc, char **argv)
255 const defaults_t *t;
256 char *p;
257 char s[256];
258 int i, j;
259 int force = 0;
260 int commit = 0;
262 if (strcmp(argv[1], "--yes") == 0) {
263 force = 1;
265 else if (strcmp(argv[1], "--initcheck") != 0) {
266 help();
269 if ((!nvram_match("restore_defaults", "0")) || (!nvram_match("os_name", "linux"))) {
270 force = 1;
273 #if 0 // --need to test--
274 // prevent lockout if upgrading from DD-WRT v23 SP2+ w/ encrypted password
275 if (nvram_match("nvram_ver", "2")) {
276 nvram_unset("nvram_ver");
278 // If username is "", root or admin, then nvram_ver was probably a left-over
279 // from an old DD-WRT installation (ex: DD-WRT -> Linksys (reset) ->
280 // Tomato) and we don't need to do anything. Otherwise, reset.
281 if ((p = nvram_get("httpd_username")) != NULL) {
282 if ((*p != 0) && (strcmp(p, "root") != 0) && (strcmp(p, "admin") != 0)) {
283 nvram_unset("httpd_passwd");
284 nvram_unset("httpd_username"); // not used here, but dd will try to re-encrypt this
285 // filled below
289 #else
290 if (force) nvram_unset("nvram_ver"); // prep to prevent problems later
291 #endif
293 // keep the compatibility with old security_mode2, wds_enable, mac_wl - removeme after 1/1/2012
294 nv_fix_wl("security_mode2", "security_mode");
295 nv_fix_wl("wds_enable", "wds_enable");
296 nv_fix_wl("mac_wl", "macaddr");
298 for (t = defaults; t->key; t++) {
299 if (((p = nvram_get(t->key)) == NULL) || (force)) {
300 if (t->value == NULL) {
301 if (p != NULL) {
302 nvram_unset(t->key);
303 if (!force) _dprintf("%s=%s is not the default (NULL) - resetting\n", t->key, p);
304 commit = 1;
307 else {
308 nvram_set(t->key, nv_default_value(t));
309 if (!force) _dprintf("%s=%s is not the default (%s) - resetting\n", t->key, p ? p : "(NULL)", nv_default_value(t));
310 commit = 1;
313 else if (strncmp(t->key, "wl_", 3) == 0) {
314 // sync wl_ and wl0_
315 strcpy(s, "wl0_");
316 strcat(s, t->key + 3);
317 if (nvram_get(s) == NULL) nvram_set(s, nvram_safe_get(t->key));
321 // todo: moveme
322 if ((strtoul(nvram_safe_get("boardflags"), NULL, 0) & BFL_ENETVLAN) ||
323 (check_hw_type() == HW_BCM4712)) t = if_vlan;
324 else t = if_generic;
325 for (; t->key; t++) {
326 if (((p = nvram_get(t->key)) == NULL) || (*p == 0) || (force)) {
327 nvram_set(t->key, t->value);
328 commit = 1;
329 if (!force) _dprintf("%s=%s is not the default (%s) - resetting\n", t->key, p ? p : "(NULL)", t->value);
333 if (force) {
334 for (j = 0; j < 2; j++) {
335 for (i = 0; i < 20; i++) {
336 sprintf(s, "wl%d_wds%d", j, i);
337 nvram_unset(s);
341 for (i = 0; i < LED_COUNT; ++i) {
342 sprintf(s, "led_%s", led_names[i]);
343 nvram_unset(s);
346 // 0 = example
347 for (i = 1; i < 50; i++) {
348 sprintf(s, "rrule%d", i);
349 nvram_unset(s);
353 if (!nvram_match("boot_wait", "on")) {
354 nvram_set("boot_wait", "on");
355 commit = 1;
358 nvram_set("os_name", "linux");
359 nvram_set("os_version", tomato_version);
360 nvram_set("os_date", tomato_buildtime);
362 if ((commit) || (force)) {
363 printf("Saving...\n");
364 nvram_commit();
366 else {
367 printf("No change was necessary.\n");
369 return 0;
372 static int commit_main(int argc, char **argv)
374 int r;
376 printf("Commit... ");
377 fflush(stdout);
378 r = nvram_commit();
379 printf("done.\n");
380 return r ? 1 : 0;
383 static int erase_main(int argc, char **argv)
385 printf("Erasing nvram...\n");
386 return eval("mtd-erase", "-d", "nvram");
390 * Find nvram param name; return pointer which should be treated as const
391 * return NULL if not found.
393 * NOTE: This routine special-cases the variable wl_bss_enabled. It will
394 * return the normal default value if asked for wl_ or wl0_. But it will
395 * return 0 if asked for a virtual BSS reference like wl0.1_.
397 static const char *get_default_value(const char *name)
399 char *p;
400 const defaults_t *t;
401 char fixed_name[NVRAM_MAX_PARAM_LEN + 1];
403 if (strncmp(name, "wl", 2) == 0 && isdigit(name[2]) && ((p = strchr(name, '_'))))
404 snprintf(fixed_name, sizeof(fixed_name) - 1, "wl%s", p);
405 else
406 strncpy(fixed_name, name, sizeof(fixed_name));
408 if (strcmp(fixed_name, "wl_bss_enabled") == 0) {
409 if (name[3] == '.' || name[4] == '.') /* Virtual interface */
410 return "0";
413 for (t = defaults; t->key; t++) {
414 if (strcmp(t->key, name) == 0 || strcmp(t->key, fixed_name) == 0)
415 return (t->value ? : "");
418 return NULL;
421 #define X_QUOTE 0
422 #define X_SET 1
423 #define X_C 2
424 #define X_TAB 3
426 static int export_main(int argc, char **argv)
428 char *p;
429 char buffer[NVRAM_SPACE];
430 int eq;
431 int mode;
432 int all, n, skip;
433 char *bk, *bv, *v;
435 // C, set, quote
436 static const char *start[4] = { "\"", "nvram set ", "{ \"", "" };
437 static const char *stop[4] = { "\"", "\"", "\" },", "" };
440 getall(buffer);
441 p = buffer;
443 all = 1;
444 for (n = 1; n < argc; ++n) {
445 if (strcmp(argv[n], "--nodefaults") == 0) {
446 if (argc < 3) help();
447 all = 0;
448 if (n == 1) ++argv;
449 break;
453 if (strcmp(argv[1], "--dump") == 0) {
454 if (!all) help();
455 for (p = buffer; *p; p += strlen(p) + 1) {
456 puts(p);
458 return 0;
460 if (strcmp(argv[1], "--dump0") == 0) {
461 if (!all) help();
462 for (p = buffer; *p; p += strlen(p) + 1) { }
463 fwrite(buffer, p - buffer, 1, stdout);
464 return 0;
467 if (strcmp(argv[1], "--c") == 0) mode = X_C;
468 else if (strcmp(argv[1], "--set") == 0) mode = X_SET;
469 else if (strcmp(argv[1], "--tab") == 0) mode = X_TAB;
470 else if (strcmp(argv[1], "--quote") == 0) mode = X_QUOTE;
471 else help();
473 while (*p) {
474 eq = 0;
476 if (!all) {
477 skip = 0;
478 bk = p;
479 p += strlen(p) + 1;
480 bv = strchr(bk, '=');
481 *bv++ = 0;
483 if ((v = (char *)get_default_value(bk)) != NULL) {
484 skip = (strcmp(bv, v) == 0);
487 *(bv - 1) = '=';
488 if (skip)
489 continue;
490 else
491 p = bk;
494 printf("%s", start[mode]);
495 do {
496 switch (*p) {
497 case 9:
498 if (mode == X_SET) putchar(*p);
499 else printf("\\t");
500 break;
501 case 13:
502 if (mode == X_SET) putchar(*p);
503 else printf("\\r");
504 break;
505 case 10:
506 if (mode == X_SET) putchar(*p);
507 else printf("\\n");
508 break;
509 case '"':
510 case '\\':
511 printf("\\%c", *p);
512 break;
513 case '$':
514 case '`':
515 if (mode != X_SET) putchar(*p);
516 else printf("\\$");
517 break;
518 case '=':
519 if ((eq == 0) && (mode > X_QUOTE)) {
520 printf((mode == X_C) ? "\", \"" :
521 ((mode == X_SET) ? "=\"" : "\t"));
522 eq = 1;
523 break;
525 eq = 1;
526 default:
527 if (!isprint(*p)) printf("\\x%02x", *p);
528 else putchar(*p);
529 break;
531 ++p;
532 } while (*p);
533 printf("%s\n", stop[mode]);
534 ++p;
536 return 0;
539 static int in_defaults(const char *key)
541 const defaults_t *t;
542 int n;
544 for (t = defaults; t->key; t++) {
545 if (strcmp(t->key, key) == 0) return 1;
548 if ((strncmp(key, "rrule", 5) == 0) && ((n = atoi(key + 5)) > 0) && (n < 50)) return 1;
550 return 0;
553 static int import_main(int argc, char **argv)
555 FILE *f;
556 char s[10240];
557 int n;
558 char *k, *v;
559 char *p, *q;
560 int all;
561 int same, skip, set;
563 all = 0;
564 if (strcmp(argv[1], "--forceall") == 0) {
565 all = 1;
566 ++argv;
569 if ((f = fopen(argv[1], "r")) == NULL) {
570 printf("Error opening file.\n");
571 return 1;
574 same = skip = set = 0;
576 while (fgets(s, sizeof(s), f) != NULL) {
577 n = strlen(s);
578 while ((--n > 0) && (isspace(s[n]))) ;
579 if ((n <= 0) || (s[n] != '"')) continue;
580 s[n] = 0;
582 k = s;
583 while (isspace(*k)) ++k;
584 if (*k != '"') continue;
585 ++k;
587 if ((v = strchr(k, '=')) == NULL) continue;
588 *v++ = 0;
590 p = q = v;
591 while (*p) {
592 if (*p == '\\') {
593 ++p;
594 switch (*p) {
595 case 't':
596 *q++ = '\t';
597 break;
598 case 'r':
599 *q++ = '\n';
600 break;
601 case 'n':
602 *q++ = '\n';
603 break;
604 case '\\':
605 case '"':
606 *q++ = *p;
607 break;
608 default:
609 printf("Error unescaping %s=%s\n", k, v);
610 return 1;
613 else {
614 *q++ = *p;
616 ++p;
618 *q = 0;
620 if ((all) || (in_defaults(k))) {
621 if (nvram_match(k, v)) {
622 ++same;
623 // printf("SAME: %s=%s\n", k, v);
625 else {
626 ++set;
627 printf("%s=%s\n", k, v);
628 nvram_set(k, v);
631 else {
632 ++skip;
633 // printf("SKIP: %s=%s\n", k, v);
637 fclose(f);
639 printf("---\n%d skipped, %d same, %d set\n", skip, same, set);
640 return 0;
643 #define V1 0x31464354L
645 typedef struct {
646 unsigned long sig;
647 unsigned long hwid;
648 char buffer[NVRAM_SPACE];
649 } backup_t;
651 static int backup_main(int argc, char **argv)
653 backup_t data;
654 unsigned int size;
655 char *p;
656 char s[512];
657 char tmp[128];
658 int r;
660 getall(data.buffer);
662 data.sig = V1;
663 data.hwid = check_hw_type();
665 p = data.buffer;
666 while (*p != 0) p += strlen(p) + 1;
668 size = (sizeof(data) - sizeof(data.buffer)) + (p - data.buffer) + 1;
670 strcpy(tmp, "/tmp/nvramXXXXXX");
671 mktemp(tmp);
672 if (f_write(tmp, &data, size, 0, 0) != size) {
673 printf("Error saving file.\n");
674 return 1;
676 sprintf(s, "gzip < %s > %s", tmp, argv[1]);
677 r = system(s);
678 unlink(tmp);
680 if (r != 0) {
681 unlink(argv[1]);
682 printf("Error compressing file.\n");
683 return 1;
686 printf("Saved.\n");
687 return 0;
690 static int restore_main(int argc, char **argv)
692 char *name;
693 int test;
694 int force;
695 int commit;
696 backup_t data;
697 unsigned int size;
698 char s[512];
699 char tmp[128];
700 unsigned long hw;
701 char current[NVRAM_SPACE];
702 char *b, *bk, *bv;
703 char *c, *ck, *cv;
704 int nset;
705 int nunset;
706 int nsame;
707 int cmp;
708 int i;
710 test = 0;
711 force = 0;
712 commit = 1;
713 name = NULL;
714 for (i = 1; i < argc; ++i) {
715 if (argv[i][0] == '-') {
716 if (strcmp(argv[i], "--test") == 0) {
717 test = 1;
719 else if (strcmp(argv[i], "--force") == 0) {
720 force = 1;
722 else if (strcmp(argv[i], "--forceall") == 0) {
723 force = 2;
725 else if (strcmp(argv[i], "--nocommit") == 0) {
726 commit = 0;
728 else {
729 help();
732 else {
733 name = argv[i];
736 if (!name) help();
738 strcpy(tmp, "/tmp/nvramXXXXXX");
739 mktemp(tmp);
740 sprintf(s, "gzip -d < %s > %s", name, tmp);
741 if (system(s) != 0) {
742 unlink(tmp);
743 printf("Error decompressing file.\n");
744 return 1;
747 size = f_size(tmp);
748 if ((size <= (sizeof(data) - sizeof(data.buffer))) || (size > sizeof(data)) ||
749 (f_read(tmp, &data, sizeof(data)) != size)) {
750 unlink(tmp);
751 printf("Invalid data size or read error.\n");
752 return 1;
755 unlink(tmp);
757 if (data.sig != V1) {
758 printf("Invalid signature: %08lX / %08lX\n", data.sig, V1);
759 return 1;
762 hw = check_hw_type();
763 if ((data.hwid != hw) && (!force)) {
764 printf("Invalid hardware type: %08lX / %08lX\n", data.hwid, hw);
765 return 1;
768 // 1 - check data
770 size -= sizeof(data) - sizeof(data.buffer);
771 if ((data.buffer[size - 1] != 0) || (data.buffer[size - 2] != 0)) {
772 CORRUPT:
773 printf("Corrupted data area.\n");
774 return 1;
777 b = data.buffer;
778 while (*b) {
779 bk = b;
780 b += strlen(b) + 1;
781 if ((bv = strchr(bk, '=')) == NULL) {
782 goto CORRUPT;
784 *bv = 0;
785 if (strcmp(bk, "et0macaddr") == 0) {
786 if (!nvram_match(bk, bv + 1)) {
787 if (!force) {
788 printf("Cannot restore on a different router.\n");
789 return 1;
793 *bv = '=';
795 if (((b - data.buffer) + 1) != size) {
796 printf("Extra data found at the end.\n");
797 return 1;
801 // 2 - set
803 if (!test) {
804 if (!wait_action_idle(10)) {
805 printf("System busy.\n");
806 return 1;
808 set_action(ACT_SW_RESTORE);
809 led(LED_DIAG, 1);
812 nset = nunset = nsame = 0;
814 b = data.buffer;
815 while (*b) {
816 bk = b;
817 b += strlen(b) + 1;
818 bv = strchr(bk, '=');
819 *bv++ = 0;
821 if ((force != 1) || (in_defaults(bk))) {
822 if (!nvram_match(bk, bv)) {
823 if (test) printf("nvram set \"%s=%s\"\n", bk, bv);
824 else nvram_set(bk, bv);
825 ++nset;
827 else {
828 ++nsame;
832 *(bv - 1) = '=';
836 // 3 - unset
838 getall(current);
839 c = current;
840 while (*c) {
841 ck = c;
842 c += strlen(c) + 1;
843 if ((cv = strchr(ck, '=')) == NULL) {
844 printf("Invalid data in NVRAM: %s.", ck);
845 continue;
847 *cv++ = 0;
849 if ((force != 1) || (in_defaults(ck))) {
850 cmp = 1;
851 b = data.buffer;
852 while (*b) {
853 bk = b;
854 b += strlen(b) + 1;
855 bv = strchr(bk, '=');
856 *bv++ = 0;
857 cmp = strcmp(bk, ck);
858 *(bv - 1) = '=';
859 if (cmp == 0) break;
861 if (cmp != 0) {
862 ++nunset;
863 if (test) printf("nvram unset \"%s\"\n", ck);
864 else nvram_unset(ck);
870 if ((nset == 0) && (nunset == 0)) commit = 0;
871 printf("\nPerformed %d set and %d unset operations. %d required no changes.\n%s\n",
872 nset, nunset, nsame, commit ? "Committing..." : "Not commiting.");
873 fflush(stdout);
875 if (!test) {
876 set_action(ACT_IDLE);
877 if (commit) nvram_commit();
879 return 0;
882 #if 0
883 static int test_main(int argc, char **argv)
886 static const char *extra[] = {
887 "clkfreq", "pa0b0", "pa0b1", "pa0b2", "pa0itssit", "pa0maxpwr",
888 "sdram_config", "sdram_init", "sdram_ncdl", "vlan0ports", NULL };
889 const char **x;
891 char buffer[NVRAM_SPACE];
892 char *k, *v, *e;
893 const defaults_t *rest;
894 struct nvram_convert *conv;
896 printf("Unknown keys:\n");
898 getall(buffer);
899 k = buffer;
900 while (*k) {
901 e = k + strlen(k) + 1;
902 if ((v = strchr(k, '=')) != NULL) {
903 *v = 0;
904 for (rest = defaults; rest->key; ++rest) {
905 if (strcmp(k, rest->key) == 0) break;
907 if (rest->key == NULL) {
908 for (conv = nvram_converts; conv->name; ++conv) {
909 if ((strcmp(k, conv->name) == 0) || (strcmp(k, conv->wl0_name) == 0)) break;
911 if (conv->name == NULL) {
912 printf("%s=%s\n", k, v + 1);
914 for (x = extra; *x; ++x) {
915 if (strcmp(k, *x) == 0) break;
917 if (*x == NULL) {
918 printf("nvram unset \"%s\"\n", k);
924 else {
925 printf("WARNING: '%s' doesn't have a '=' delimiter\n", k);
927 k = e;
930 return 0;
932 #endif
935 static int setfb64_main(int argc, char **argv)
937 if (!nvram_set_file(argv[1], argv[2], 10240)) {
938 fprintf(stderr, "Unable to set %s or read %s\n", argv[1], argv[2]);
939 return 1;
941 return 0;
944 static int getfb64_main(int argc, char **argv)
946 if (!nvram_get_file(argv[1], argv[2], 10240)) {
947 fprintf(stderr, "Unable to get %s or write %s\n", argv[1], argv[2]);
948 return 1;
950 return 0;
953 // -----------------------------------------------------------------------------
955 typedef struct {
956 const char *name;
957 int args;
958 int (*main)(int argc, char *argv[]);
959 } applets_t;
961 static const applets_t applets[] = {
962 { "set", 3, set_main },
963 { "get", 3, get_main },
964 { "unset", 3, unset_main },
965 { "ren", 4, ren_main },
966 { "show", -2, show_main },
967 { "commit", 2, commit_main },
968 { "erase", 2, erase_main },
969 { "find", 3, find_main },
970 { "export", -3, export_main },
971 { "import", -3, import_main },
972 { "defaults", 3, defaults_main },
973 { "validate", -3, validate_main },
974 { "backup", 3, backup_main },
975 { "restore", -3, restore_main },
976 { "setfb64", 4, setfb64_main },
977 { "getfb64", 4, getfb64_main },
978 { "setfile", 4, f2n_main },
979 { "getfile", 4, n2f_main },
980 { "setfile2nvram", 3, save2f_main },
981 // { "test", 2, test_main },
982 { NULL, 0, NULL }
985 int main(int argc, char **argv)
987 const applets_t *a;
989 if (argc >= 2) {
990 a = applets;
991 while (a->name) {
992 if (strcmp(argv[1], a->name) == 0) {
993 if ((argc != a->args) && ((a->args > 0) || (argc < -(a->args)))) help();
994 return a->main(argc - 1, argv + 1);
996 ++a;
999 help();