Revert "nvram [K24 part]: auto-detect the nvram size" (kernel 2.4, userspace and...
[tomato.git] / release / src / router / nvram / nvram.c
blob877642f2070b4ee78bd204d507618702ee282a47
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 return "1";
205 #endif
206 return t->value;
209 static void nv_fix_wl(const char *oldnv, const char *newnv)
211 char *p;
213 if (nvram_get(wl_nvname(newnv, 0, 0)) == NULL) {
214 p = nvram_get(oldnv);
215 if (p != NULL) nvram_set(wl_nvname(newnv, -1, 0), p);
216 nvram_unset(oldnv);
220 static int validate_main(int argc, char **argv)
222 const defaults_t *t;
223 char *p;
224 int i;
225 int force = 0;
226 int unit = 0;
228 for (i = 1; i < argc; ++i) {
229 if (strcmp(argv[i], "--restore") == 0) {
230 force = 1;
232 else if (strncmp(argv[i], "--wl", 4) == 0) {
233 unit = atoi(argv[i] + 4);
237 for (t = defaults; t->key; t++) {
238 if (strncmp(t->key, "wl_", 3) == 0) {
239 // sync wl_ and wlX_
240 p = wl_nvname(t->key + 3, unit, 0);
241 if (force || nvram_get(p) == NULL)
242 nvram_set(p, t->value);
245 return 0;
248 static int defaults_main(int argc, char **argv)
250 const defaults_t *t;
251 char *p;
252 char s[256];
253 int i, j;
254 int force = 0;
255 int commit = 0;
257 if (strcmp(argv[1], "--yes") == 0) {
258 force = 1;
260 else if (strcmp(argv[1], "--initcheck") != 0) {
261 help();
264 if ((!nvram_match("restore_defaults", "0")) || (!nvram_match("os_name", "linux"))) {
265 force = 1;
268 #if 0 // --need to test--
269 // prevent lockout if upgrading from DD-WRT v23 SP2+ w/ encrypted password
270 if (nvram_match("nvram_ver", "2")) {
271 nvram_unset("nvram_ver");
273 // If username is "", root or admin, then nvram_ver was probably a left-over
274 // from an old DD-WRT installation (ex: DD-WRT -> Linksys (reset) ->
275 // Tomato) and we don't need to do anything. Otherwise, reset.
276 if ((p = nvram_get("httpd_username")) != NULL) {
277 if ((*p != 0) && (strcmp(p, "root") != 0) && (strcmp(p, "admin") != 0)) {
278 nvram_unset("httpd_passwd");
279 nvram_unset("httpd_username"); // not used here, but dd will try to re-encrypt this
280 // filled below
284 #else
285 if (force) nvram_unset("nvram_ver"); // prep to prevent problems later
286 #endif
288 // keep the compatibility with old security_mode2, wds_enable, mac_wl - removeme after 1/1/2012
289 nv_fix_wl("security_mode2", "security_mode");
290 nv_fix_wl("wds_enable", "wds_enable");
291 nv_fix_wl("mac_wl", "macaddr");
293 for (t = defaults; t->key; t++) {
294 if (((p = nvram_get(t->key)) == NULL) || (force)) {
295 if (t->value == NULL) {
296 if (p != NULL) {
297 nvram_unset(t->key);
298 if (!force) _dprintf("%s=%s is not the default (NULL) - resetting\n", t->key, p);
299 commit = 1;
302 else {
303 nvram_set(t->key, nv_default_value(t));
304 if (!force) _dprintf("%s=%s is not the default (%s) - resetting\n", t->key, p ? p : "(NULL)", nv_default_value(t));
305 commit = 1;
308 else if (strncmp(t->key, "wl_", 3) == 0) {
309 // sync wl_ and wl0_
310 strcpy(s, "wl0_");
311 strcat(s, t->key + 3);
312 if (nvram_get(s) == NULL) nvram_set(s, nvram_safe_get(t->key));
316 // todo: moveme
317 if ((strtoul(nvram_safe_get("boardflags"), NULL, 0) & BFL_ENETVLAN) ||
318 (check_hw_type() == HW_BCM4712)) t = if_vlan;
319 else t = if_generic;
320 for (; t->key; t++) {
321 if (((p = nvram_get(t->key)) == NULL) || (*p == 0) || (force)) {
322 nvram_set(t->key, t->value);
323 commit = 1;
324 if (!force) _dprintf("%s=%s is not the default (%s) - resetting\n", t->key, p ? p : "(NULL)", t->value);
328 if (force) {
329 for (j = 0; j < 2; j++) {
330 for (i = 0; i < 20; i++) {
331 sprintf(s, "wl%d_wds%d", j, i);
332 nvram_unset(s);
336 for (i = 0; i < LED_COUNT; ++i) {
337 sprintf(s, "led_%s", led_names[i]);
338 nvram_unset(s);
341 // 0 = example
342 for (i = 1; i < 50; i++) {
343 sprintf(s, "rrule%d", i);
344 nvram_unset(s);
348 if (!nvram_match("boot_wait", "on")) {
349 nvram_set("boot_wait", "on");
350 commit = 1;
353 nvram_set("os_name", "linux");
354 nvram_set("os_version", tomato_version);
355 nvram_set("os_date", tomato_buildtime);
357 if ((commit) || (force)) {
358 printf("Saving...\n");
359 nvram_commit();
361 else {
362 printf("No change was necessary.\n");
364 return 0;
367 static int commit_main(int argc, char **argv)
369 int r;
371 printf("Commit... ");
372 fflush(stdout);
373 r = nvram_commit();
374 printf("done.\n");
375 return r ? 1 : 0;
378 static int erase_main(int argc, char **argv)
380 printf("Erasing nvram...\n");
381 return eval("mtd-erase", "-d", "nvram");
385 * Find nvram param name; return pointer which should be treated as const
386 * return NULL if not found.
388 * NOTE: This routine special-cases the variable wl_bss_enabled. It will
389 * return the normal default value if asked for wl_ or wl0_. But it will
390 * return 0 if asked for a virtual BSS reference like wl0.1_.
392 static const char *get_default_value(const char *name)
394 char *p;
395 const defaults_t *t;
396 char fixed_name[NVRAM_MAX_PARAM_LEN + 1];
398 if (strncmp(name, "wl", 2) == 0 && isdigit(name[2]) && ((p = strchr(name, '_'))))
399 snprintf(fixed_name, sizeof(fixed_name) - 1, "wl%s", p);
400 else
401 strncpy(fixed_name, name, sizeof(fixed_name));
403 if (strcmp(fixed_name, "wl_bss_enabled") == 0) {
404 if (name[3] == '.' || name[4] == '.') /* Virtual interface */
405 return "0";
408 for (t = defaults; t->key; t++) {
409 if (strcmp(t->key, name) == 0 || strcmp(t->key, fixed_name) == 0)
410 return (t->value ? : "");
413 return NULL;
416 #define X_QUOTE 0
417 #define X_SET 1
418 #define X_C 2
419 #define X_TAB 3
421 static int export_main(int argc, char **argv)
423 char *p;
424 char buffer[NVRAM_SPACE];
425 int eq;
426 int mode;
427 int all, n, skip;
428 char *bk, *bv, *v;
430 // C, set, quote
431 static const char *start[4] = { "\"", "nvram set ", "{ \"", "" };
432 static const char *stop[4] = { "\"", "\"", "\" },", "" };
435 getall(buffer);
436 p = buffer;
438 all = 1;
439 for (n = 1; n < argc; ++n) {
440 if (strcmp(argv[n], "--nodefaults") == 0) {
441 if (argc < 3) help();
442 all = 0;
443 if (n == 1) ++argv;
444 break;
448 if (strcmp(argv[1], "--dump") == 0) {
449 if (!all) help();
450 for (p = buffer; *p; p += strlen(p) + 1) {
451 puts(p);
453 return 0;
455 if (strcmp(argv[1], "--dump0") == 0) {
456 if (!all) help();
457 for (p = buffer; *p; p += strlen(p) + 1) { }
458 fwrite(buffer, p - buffer, 1, stdout);
459 return 0;
462 if (strcmp(argv[1], "--c") == 0) mode = X_C;
463 else if (strcmp(argv[1], "--set") == 0) mode = X_SET;
464 else if (strcmp(argv[1], "--tab") == 0) mode = X_TAB;
465 else if (strcmp(argv[1], "--quote") == 0) mode = X_QUOTE;
466 else help();
468 while (*p) {
469 eq = 0;
471 if (!all) {
472 skip = 0;
473 bk = p;
474 p += strlen(p) + 1;
475 bv = strchr(bk, '=');
476 *bv++ = 0;
478 if ((v = (char *)get_default_value(bk)) != NULL) {
479 skip = (strcmp(bv, v) == 0);
482 *(bv - 1) = '=';
483 if (skip)
484 continue;
485 else
486 p = bk;
489 printf("%s", start[mode]);
490 do {
491 switch (*p) {
492 case 9:
493 if (mode == X_SET) putchar(*p);
494 else printf("\\t");
495 break;
496 case 13:
497 if (mode == X_SET) putchar(*p);
498 else printf("\\r");
499 break;
500 case 10:
501 if (mode == X_SET) putchar(*p);
502 else printf("\\n");
503 break;
504 case '"':
505 case '\\':
506 printf("\\%c", *p);
507 break;
508 case '$':
509 case '`':
510 if (mode != X_SET) putchar(*p);
511 else printf("\\$");
512 break;
513 case '=':
514 if ((eq == 0) && (mode > X_QUOTE)) {
515 printf((mode == X_C) ? "\", \"" :
516 ((mode == X_SET) ? "=\"" : "\t"));
517 eq = 1;
518 break;
520 eq = 1;
521 default:
522 if (!isprint(*p)) printf("\\x%02x", *p);
523 else putchar(*p);
524 break;
526 ++p;
527 } while (*p);
528 printf("%s\n", stop[mode]);
529 ++p;
531 return 0;
534 static int in_defaults(const char *key)
536 const defaults_t *t;
537 int n;
539 for (t = defaults; t->key; t++) {
540 if (strcmp(t->key, key) == 0) return 1;
543 if ((strncmp(key, "rrule", 5) == 0) && ((n = atoi(key + 5)) > 0) && (n < 50)) return 1;
545 return 0;
548 static int import_main(int argc, char **argv)
550 FILE *f;
551 char s[10240];
552 int n;
553 char *k, *v;
554 char *p, *q;
555 int all;
556 int same, skip, set;
558 all = 0;
559 if (strcmp(argv[1], "--forceall") == 0) {
560 all = 1;
561 ++argv;
564 if ((f = fopen(argv[1], "r")) == NULL) {
565 printf("Error opening file.\n");
566 return 1;
569 same = skip = set = 0;
571 while (fgets(s, sizeof(s), f) != NULL) {
572 n = strlen(s);
573 while ((--n > 0) && (isspace(s[n]))) ;
574 if ((n <= 0) || (s[n] != '"')) continue;
575 s[n] = 0;
577 k = s;
578 while (isspace(*k)) ++k;
579 if (*k != '"') continue;
580 ++k;
582 if ((v = strchr(k, '=')) == NULL) continue;
583 *v++ = 0;
585 p = q = v;
586 while (*p) {
587 if (*p == '\\') {
588 ++p;
589 switch (*p) {
590 case 't':
591 *q++ = '\t';
592 break;
593 case 'r':
594 *q++ = '\n';
595 break;
596 case 'n':
597 *q++ = '\n';
598 break;
599 case '\\':
600 case '"':
601 *q++ = *p;
602 break;
603 default:
604 printf("Error unescaping %s=%s\n", k, v);
605 return 1;
608 else {
609 *q++ = *p;
611 ++p;
613 *q = 0;
615 if ((all) || (in_defaults(k))) {
616 if (nvram_match(k, v)) {
617 ++same;
618 // printf("SAME: %s=%s\n", k, v);
620 else {
621 ++set;
622 printf("%s=%s\n", k, v);
623 nvram_set(k, v);
626 else {
627 ++skip;
628 // printf("SKIP: %s=%s\n", k, v);
632 fclose(f);
634 printf("---\n%d skipped, %d same, %d set\n", skip, same, set);
635 return 0;
638 #define V1 0x31464354L
640 typedef struct {
641 unsigned long sig;
642 unsigned long hwid;
643 char buffer[NVRAM_SPACE];
644 } backup_t;
646 static int backup_main(int argc, char **argv)
648 backup_t data;
649 unsigned int size;
650 char *p;
651 char s[512];
652 char tmp[128];
653 int r;
655 getall(data.buffer);
657 data.sig = V1;
658 data.hwid = check_hw_type();
660 p = data.buffer;
661 while (*p != 0) p += strlen(p) + 1;
663 size = (sizeof(data) - sizeof(data.buffer)) + (p - data.buffer) + 1;
665 strcpy(tmp, "/tmp/nvramXXXXXX");
666 mktemp(tmp);
667 if (f_write(tmp, &data, size, 0, 0) != size) {
668 printf("Error saving file.\n");
669 return 1;
671 sprintf(s, "gzip < %s > %s", tmp, argv[1]);
672 r = system(s);
673 unlink(tmp);
675 if (r != 0) {
676 unlink(argv[1]);
677 printf("Error compressing file.\n");
678 return 1;
681 printf("Saved.\n");
682 return 0;
685 static int restore_main(int argc, char **argv)
687 char *name;
688 int test;
689 int force;
690 int commit;
691 backup_t data;
692 unsigned int size;
693 char s[512];
694 char tmp[128];
695 unsigned long hw;
696 char current[NVRAM_SPACE];
697 char *b, *bk, *bv;
698 char *c, *ck, *cv;
699 int nset;
700 int nunset;
701 int nsame;
702 int cmp;
703 int i;
705 test = 0;
706 force = 0;
707 commit = 1;
708 name = NULL;
709 for (i = 1; i < argc; ++i) {
710 if (argv[i][0] == '-') {
711 if (strcmp(argv[i], "--test") == 0) {
712 test = 1;
714 else if (strcmp(argv[i], "--force") == 0) {
715 force = 1;
717 else if (strcmp(argv[i], "--forceall") == 0) {
718 force = 2;
720 else if (strcmp(argv[i], "--nocommit") == 0) {
721 commit = 0;
723 else {
724 help();
727 else {
728 name = argv[i];
731 if (!name) help();
733 strcpy(tmp, "/tmp/nvramXXXXXX");
734 mktemp(tmp);
735 sprintf(s, "gzip -d < %s > %s", name, tmp);
736 if (system(s) != 0) {
737 unlink(tmp);
738 printf("Error decompressing file.\n");
739 return 1;
742 size = f_size(tmp);
743 if ((size <= (sizeof(data) - sizeof(data.buffer))) || (size > sizeof(data)) ||
744 (f_read(tmp, &data, sizeof(data)) != size)) {
745 unlink(tmp);
746 printf("Invalid data size or read error.\n");
747 return 1;
750 unlink(tmp);
752 if (data.sig != V1) {
753 printf("Invalid signature: %08lX / %08lX\n", data.sig, V1);
754 return 1;
757 hw = check_hw_type();
758 if ((data.hwid != hw) && (!force)) {
759 printf("Invalid hardware type: %08lX / %08lX\n", data.hwid, hw);
760 return 1;
763 // 1 - check data
765 size -= sizeof(data) - sizeof(data.buffer);
766 if ((data.buffer[size - 1] != 0) || (data.buffer[size - 2] != 0)) {
767 CORRUPT:
768 printf("Corrupted data area.\n");
769 return 1;
772 b = data.buffer;
773 while (*b) {
774 bk = b;
775 b += strlen(b) + 1;
776 if ((bv = strchr(bk, '=')) == NULL) {
777 goto CORRUPT;
779 *bv = 0;
780 if (strcmp(bk, "et0macaddr") == 0) {
781 if (!nvram_match(bk, bv + 1)) {
782 if (!force) {
783 printf("Cannot restore on a different router.\n");
784 return 1;
788 *bv = '=';
790 if (((b - data.buffer) + 1) != size) {
791 printf("Extra data found at the end.\n");
792 return 1;
796 // 2 - set
798 if (!test) {
799 if (!wait_action_idle(10)) {
800 printf("System busy.\n");
801 return 1;
803 set_action(ACT_SW_RESTORE);
804 led(LED_DIAG, 1);
807 nset = nunset = nsame = 0;
809 b = data.buffer;
810 while (*b) {
811 bk = b;
812 b += strlen(b) + 1;
813 bv = strchr(bk, '=');
814 *bv++ = 0;
816 if ((force != 1) || (in_defaults(bk))) {
817 if (!nvram_match(bk, bv)) {
818 if (test) printf("nvram set \"%s=%s\"\n", bk, bv);
819 else nvram_set(bk, bv);
820 ++nset;
822 else {
823 ++nsame;
827 *(bv - 1) = '=';
831 // 3 - unset
833 getall(current);
834 c = current;
835 while (*c) {
836 ck = c;
837 c += strlen(c) + 1;
838 if ((cv = strchr(ck, '=')) == NULL) {
839 printf("Invalid data in NVRAM: %s.", ck);
840 continue;
842 *cv++ = 0;
844 if ((force != 1) || (in_defaults(ck))) {
845 cmp = 1;
846 b = data.buffer;
847 while (*b) {
848 bk = b;
849 b += strlen(b) + 1;
850 bv = strchr(bk, '=');
851 *bv++ = 0;
852 cmp = strcmp(bk, ck);
853 *(bv - 1) = '=';
854 if (cmp == 0) break;
856 if (cmp != 0) {
857 ++nunset;
858 if (test) printf("nvram unset \"%s\"\n", ck);
859 else nvram_unset(ck);
865 if ((nset == 0) && (nunset == 0)) commit = 0;
866 printf("\nPerformed %d set and %d unset operations. %d required no changes.\n%s\n",
867 nset, nunset, nsame, commit ? "Committing..." : "Not commiting.");
868 fflush(stdout);
870 if (!test) {
871 set_action(ACT_IDLE);
872 if (commit) nvram_commit();
874 return 0;
877 #if 0
878 static int test_main(int argc, char **argv)
881 static const char *extra[] = {
882 "clkfreq", "pa0b0", "pa0b1", "pa0b2", "pa0itssit", "pa0maxpwr",
883 "sdram_config", "sdram_init", "sdram_ncdl", "vlan0ports", NULL };
884 const char **x;
886 char buffer[NVRAM_SPACE];
887 char *k, *v, *e;
888 const defaults_t *rest;
889 struct nvram_convert *conv;
891 printf("Unknown keys:\n");
893 getall(buffer);
894 k = buffer;
895 while (*k) {
896 e = k + strlen(k) + 1;
897 if ((v = strchr(k, '=')) != NULL) {
898 *v = 0;
899 for (rest = defaults; rest->key; ++rest) {
900 if (strcmp(k, rest->key) == 0) break;
902 if (rest->key == NULL) {
903 for (conv = nvram_converts; conv->name; ++conv) {
904 if ((strcmp(k, conv->name) == 0) || (strcmp(k, conv->wl0_name) == 0)) break;
906 if (conv->name == NULL) {
907 printf("%s=%s\n", k, v + 1);
909 for (x = extra; *x; ++x) {
910 if (strcmp(k, *x) == 0) break;
912 if (*x == NULL) {
913 printf("nvram unset \"%s\"\n", k);
919 else {
920 printf("WARNING: '%s' doesn't have a '=' delimiter\n", k);
922 k = e;
925 return 0;
927 #endif
930 static int setfb64_main(int argc, char **argv)
932 if (!nvram_set_file(argv[1], argv[2], 10240)) {
933 fprintf(stderr, "Unable to set %s or read %s\n", argv[1], argv[2]);
934 return 1;
936 return 0;
939 static int getfb64_main(int argc, char **argv)
941 if (!nvram_get_file(argv[1], argv[2], 10240)) {
942 fprintf(stderr, "Unable to get %s or write %s\n", argv[1], argv[2]);
943 return 1;
945 return 0;
948 // -----------------------------------------------------------------------------
950 typedef struct {
951 const char *name;
952 int args;
953 int (*main)(int argc, char *argv[]);
954 } applets_t;
956 static const applets_t applets[] = {
957 { "set", 3, set_main },
958 { "get", 3, get_main },
959 { "unset", 3, unset_main },
960 { "ren", 4, ren_main },
961 { "show", -2, show_main },
962 { "commit", 2, commit_main },
963 { "erase", 2, erase_main },
964 { "find", 3, find_main },
965 { "export", -3, export_main },
966 { "import", -3, import_main },
967 { "defaults", 3, defaults_main },
968 { "validate", -3, validate_main },
969 { "backup", 3, backup_main },
970 { "restore", -3, restore_main },
971 { "setfb64", 4, setfb64_main },
972 { "getfb64", 4, getfb64_main },
973 { "setfile", 4, f2n_main },
974 { "getfile", 4, n2f_main },
975 { "setfile2nvram", 3, save2f_main },
976 // { "test", 2, test_main },
977 { NULL, 0, NULL }
980 int main(int argc, char **argv)
982 const applets_t *a;
984 if (argc >= 2) {
985 a = applets;
986 while (a->name) {
987 if (strcmp(argv[1], a->name) == 0) {
988 if ((argc != a->args) && ((a->args > 0) || (argc < -(a->args)))) help();
989 return a->main(argc - 1, argv + 1);
991 ++a;
994 help();