4 Copyright (C) 2006-2009 Jonathan Zarate
21 #include "nvram_convert.h"
25 __attribute__ ((noreturn
))
26 static void help(void)
30 "Copyright (C) 2006-2009 Jonathan Zarate\n\n"
31 "Usage: nvram set <key=value> | get <key> | unset <key> | "
32 "ren <key> <key> | commit | show [--nosort|--nostat] | "
33 "find <text> | defaults <--yes|--initcheck> | backup <filename> | "
34 "restore <filename> [--test] [--force] [--forceall] [--nocommit] | "
35 "export <--quote|--c|--dump|--dump0|--set|--tab> | "
36 "import [--forceall] | "
37 "setfb64 <key> <filename> | getfb64 <key> <filename>"
43 static void getall(char *buffer
)
45 if (nvram_getall(buffer
, NVRAM_SPACE
) != 0) {
46 fprintf(stderr
, "Error reading NVRAM\n");
51 static int set_main(int argc
, char **argv
)
55 if ((b
= strdup(argv
[1])) == NULL
) {
56 fprintf(stderr
, "Not enough memory");
59 if ((p
= strchr(b
, '=')) != NULL
) {
67 static int get_main(int argc
, char **argv
)
71 if ((p
= nvram_get(argv
[1])) != NULL
) {
78 static int unset_main(int argc
, char **argv
)
84 static int ren_main(int argc
, char **argv
)
88 if ((p
= nvram_get(argv
[1])) == NULL
) {
89 fprintf(stderr
, "Unable to find %s\n", argv
[1]);
92 if (strcmp(argv
[1], argv
[2]) != 0) {
93 nvram_set(argv
[2], p
);
99 static int show_main(int argc
, char **argv
)
102 char buffer
[NVRAM_SPACE
];
109 for (n
= 1; n
< argc
; ++n
) {
110 if (strcmp(argv
[n
], "--nostat") == 0) stat
= 0;
111 else if (strcmp(argv
[n
], "--nosort") == 0) sort
= 0;
116 system("nvram show --nostat --nosort | sort"); // smallest and easiest way :)
122 for (p
= buffer
; *p
; p
+= strlen(p
) + 1) {
125 if (!isprint(*q
)) *q
= ' ';
132 n
= sizeof(struct nvram_header
) + (p
- buffer
);
133 printf("---\n%d entries, %d bytes used, %d bytes free.\n", count
, n
, NVRAM_SPACE
- n
);
138 static int find_main(int argc
, char **argv
)
143 snprintf(cmd
, sizeof(cmd
), "nvram show --nostat --nosort | sort | grep \"%s\"", argv
[1]);
145 return (r
== -1) ? 1 : WEXITSTATUS(r
);
148 static int defaults_main(int argc
, char **argv
)
157 if (strcmp(argv
[1], "--yes") == 0) {
160 else if (strcmp(argv
[1], "--initcheck") != 0) {
164 if ((!nvram_match("restore_defaults", "0")) || (!nvram_match("os_name", "linux"))) {
168 #if 0 // --need to test--
169 // prevent lockout if upgrading from DD-WRT v23 SP2+ w/ encrypted password
170 if (nvram_match("nvram_ver", "2")) {
171 nvram_unset("nvram_ver");
173 // If username is "", root or admin, then nvram_ver was probably a left-over
174 // from an old DD-WRT installation (ex: DD-WRT -> Linksys (reset) ->
175 // Tomato) and we don't need to do anything. Otherwise, reset.
176 if ((p
= nvram_get("httpd_username")) != NULL
) {
177 if ((*p
!= 0) && (strcmp(p
, "root") != 0) && (strcmp(p
, "admin") != 0)) {
178 nvram_unset("httpd_passwd");
179 nvram_unset("httpd_username"); // not used here, but dd will try to re-encrypt this
185 if (force
) nvram_unset("nvram_ver"); // prep to prevent problems later
189 for (t
= defaults
; t
->key
; t
++) {
190 if (((p
= nvram_get(t
->key
)) == NULL
) || (force
)) {
191 if (t
->value
== NULL
) {
198 nvram_set(t
->key
, t
->value
);
202 else if (strncmp(t
->key
, "wl_", 3) == 0) {
205 strcat(s
, t
->key
+ 3);
206 if (nvram_get(s
) == NULL
) nvram_set(s
, nvram_safe_get(t
->key
));
211 if ((strtoul(nvram_safe_get("boardflags"), NULL
, 0) & BFL_ENETVLAN
) ||
212 (check_hw_type() == HW_BCM4712
)) t
= if_vlan
;
214 for (; t
->key
; t
++) {
215 if (((p
= nvram_get(t
->key
)) == NULL
) || (*p
== 0) || (force
)) {
216 nvram_set(t
->key
, t
->value
);
218 // if (!force) cprintf("SET %s=%s\n", t->key, t->value);
223 for (i
= 0; i
< 20; i
++) {
224 sprintf(s
, "wl0_wds%d", i
);
227 for (i
= 0; i
< LED_COUNT
; ++i
) {
228 sprintf(s
, "led_%s", led_names
[i
]);
233 for (i
= 1; i
< 50; i
++) {
234 sprintf(s
, "rrule%d", i
);
239 if (!nvram_match("boot_wait", "on")) {
240 nvram_set("boot_wait", "on");
244 nvram_set("os_name", "linux");
245 nvram_set("os_version", tomato_version
);
246 nvram_set("os_date", tomato_buildtime
);
248 /* if (nvram_match("dirty", "1")) {
249 nvram_unset("dirty");
253 if ((commit
) || (force
)) {
254 printf("Saving...\n");
258 printf("No change was necessary.\n");
263 static int commit_main(int argc
, char **argv
)
267 printf("Commit... ");
279 static int export_main(int argc
, char **argv
)
282 char buffer
[NVRAM_SPACE
];
287 static const char *start
[4] = { "\"", "nvram set \"", "{ \"", "" };
288 static const char *stop
[4] = { "\"", "\"", "\" },", "" };
294 if (strcmp(argv
[1], "--dump") == 0) {
295 for (p
= buffer
; *p
; p
+= strlen(p
) + 1) {
300 if (strcmp(argv
[1], "--dump0") == 0) {
301 for (p
= buffer
; *p
; p
+= strlen(p
) + 1) { }
302 fwrite(buffer
, p
- buffer
, 1, stdout
);
306 if (strcmp(argv
[1], "--c") == 0) mode
= X_C
;
307 else if (strcmp(argv
[1], "--set") == 0) mode
= X_SET
;
308 else if (strcmp(argv
[1], "--tab") == 0) mode
= X_TAB
;
309 else if (strcmp(argv
[1], "--quote") == 0) mode
= X_QUOTE
;
314 printf("%s", start
[mode
]);
331 if ((eq
== 0) && (mode
> X_SET
)) {
332 printf((mode
== X_C
) ? "\", \"" : "\t");
337 if (!isprint(*p
)) printf("\\x%02x", *p
);
343 printf("%s\n", stop
[mode
]);
349 static int in_defaults(const char *key
)
354 for (t
= defaults
; t
->key
; t
++) {
355 if (strcmp(t
->key
, key
) == 0) return 1;
358 if ((strncmp(key
, "rrule", 5) == 0) && ((n
= atoi(key
+ 5)) > 0) && (n
< 50)) return 1;
363 static int import_main(int argc
, char **argv
)
374 if (strcmp(argv
[1], "--forceall") == 0) {
379 if ((f
= fopen(argv
[1], "r")) == NULL
) {
380 printf("Error opening file.\n");
384 same
= skip
= set
= 0;
386 while (fgets(s
, sizeof(s
), f
) != NULL
) {
388 while ((--n
> 0) && (isspace(s
[n
]))) ;
389 if ((n
<= 0) || (s
[n
] != '"')) continue;
393 while (isspace(*k
)) ++k
;
394 if (*k
!= '"') continue;
397 if ((v
= strchr(k
, '=')) == NULL
) continue;
419 printf("Error unescaping %s=%s\n", k
, v
);
430 if ((all
) || (in_defaults(k
))) {
431 if (nvram_match(k
, v
)) {
433 // printf("SAME: %s=%s\n", k, v);
437 printf("%s=%s\n", k
, v
);
443 // printf("SKIP: %s=%s\n", k, v);
449 printf("---\n%d skipped, %d same, %d set\n", skip
, same
, set
);
453 #define V1 0x31464354L
458 char buffer
[NVRAM_SPACE
];
461 static int backup_main(int argc
, char **argv
)
473 data
.hwid
= check_hw_type();
476 while (*p
!= 0) p
+= strlen(p
) + 1;
478 size
= (sizeof(data
) - sizeof(data
.buffer
)) + (p
- data
.buffer
) + 1;
480 strcpy(tmp
, "/tmp/nvramXXXXXX");
482 if (f_write(tmp
, &data
, size
, 0, 0) != size
) {
483 printf("Error saving file.\n");
486 sprintf(s
, "gzip < %s > %s", tmp
, argv
[1]);
492 printf("Error compressing file.\n");
500 static int restore_main(int argc
, char **argv
)
511 char current
[NVRAM_SPACE
];
524 for (i
= 1; i
< argc
; ++i
) {
525 if (argv
[i
][0] == '-') {
526 if (strcmp(argv
[i
], "--test") == 0) {
529 else if (strcmp(argv
[i
], "--force") == 0) {
532 else if (strcmp(argv
[i
], "--forceall") == 0) {
535 else if (strcmp(argv
[i
], "--nocommit") == 0) {
548 strcpy(tmp
, "/tmp/nvramXXXXXX");
550 sprintf(s
, "gzip -d < %s > %s", name
, tmp
);
551 if (system(s
) != 0) {
553 printf("Error decompressing file.\n");
558 if ((size
<= (sizeof(data
) - sizeof(data
.buffer
))) || (size
> sizeof(data
)) ||
559 (f_read(tmp
, &data
, sizeof(data
)) != size
)) {
561 printf("Invalid data size or read error.\n");
567 if (data
.sig
!= V1
) {
568 printf("Invalid signature: %08lX / %08lX\n", data
.sig
, V1
);
572 hw
= check_hw_type();
573 if ((data
.hwid
!= hw
) && (!force
)) {
574 printf("Invalid hardware type: %08lX / %08lX\n", data
.hwid
, hw
);
580 size
-= sizeof(data
) - sizeof(data
.buffer
);
581 if ((data
.buffer
[size
- 1] != 0) || (data
.buffer
[size
- 2] != 0)) {
583 printf("Corrupted data area.\n");
591 if ((bv
= strchr(bk
, '=')) == NULL
) {
595 if (strcmp(bk
, "et0macaddr") == 0) {
596 if (!nvram_match(bk
, bv
+ 1)) {
598 printf("Cannot restore on a different router.\n");
605 if (((b
- data
.buffer
) + 1) != size
) {
606 printf("Extra data found at the end.\n");
614 if (!wait_action_idle(10)) {
615 printf("System busy.\n");
618 set_action(ACT_SW_RESTORE
);
622 nset
= nunset
= nsame
= 0;
628 bv
= strchr(bk
, '=');
631 if ((force
!= 1) || (in_defaults(bk
))) {
632 if (!nvram_match(bk
, bv
)) {
633 if (test
) printf("nvram set \"%s=%s\"\n", bk
, bv
);
634 else nvram_set(bk
, bv
);
653 if ((cv
= strchr(ck
, '=')) == NULL
) {
654 printf("Invalid data in NVRAM: %s.", ck
);
659 if ((force
!= 1) || (in_defaults(ck
))) {
665 bv
= strchr(bk
, '=');
667 cmp
= strcmp(bk
, ck
);
673 if (test
) printf("nvram unset \"%s\"\n", ck
);
674 else nvram_unset(ck
);
680 if ((nset
== 0) && (nunset
== 0)) commit
= 0;
681 printf("\nPerformed %d set and %d unset operations. %d required no changes.\n%s\n",
682 nset
, nunset
, nsame
, commit
? "Committing..." : "Not commiting.");
686 set_action(ACT_IDLE
);
687 if (commit
) nvram_commit();
693 static int test_main(int argc
, char **argv
)
696 static const char *extra[] = {
697 "clkfreq", "pa0b0", "pa0b1", "pa0b2", "pa0itssit", "pa0maxpwr",
698 "sdram_config", "sdram_init", "sdram_ncdl", "vlan0ports", NULL };
701 char buffer
[NVRAM_SPACE
];
703 const defaults_t
*rest
;
704 struct nvram_convert
*conv
;
706 printf("Unknown keys:\n");
711 e
= k
+ strlen(k
) + 1;
712 if ((v
= strchr(k
, '=')) != NULL
) {
714 for (rest
= defaults
; rest
->key
; ++rest
) {
715 if (strcmp(k
, rest
->key
) == 0) break;
717 if (rest
->key
== NULL
) {
718 for (conv
= nvram_converts
; conv
->name
; ++conv
) {
719 if ((strcmp(k
, conv
->name
) == 0) || (strcmp(k
, conv
->wl0_name
) == 0)) break;
721 if (conv
->name
== NULL
) {
722 printf("%s=%s\n", k
, v
+ 1);
724 for (x = extra; *x; ++x) {
725 if (strcmp(k, *x) == 0) break;
728 printf("nvram unset \"%s\"\n", k);
735 printf("WARNING: '%s' doesn't have a '=' delimiter\n", k
);
745 static int setfb64_main(int argc
, char **argv
)
747 if (!nvram_set_file(argv
[1], argv
[2], 10240)) {
748 fprintf(stderr
, "Unable to set %s or read %s\n", argv
[1], argv
[2]);
754 static int getfb64_main(int argc
, char **argv
)
756 if (!nvram_get_file(argv
[1], argv
[2], 10240)) {
757 fprintf(stderr
, "Unable to get %s or write %s\n", argv
[1], argv
[2]);
763 // -----------------------------------------------------------------------------
768 int (*main
)(int argc
, char *argv
[]);
771 static const applets_t applets
[] = {
772 { "set", 3, set_main
},
773 { "get", 3, get_main
},
774 { "unset", 3, unset_main
},
775 { "ren", 4, ren_main
},
776 { "show", -2, show_main
},
777 { "commit", 2, commit_main
},
778 { "find", 3, find_main
},
779 { "export", 3, export_main
},
780 { "import", -3, import_main
},
781 { "defaults", 3, defaults_main
},
782 { "backup", 3, backup_main
},
783 { "restore", -3, restore_main
},
784 { "setfb64", 4, setfb64_main
},
785 { "getfb64", 4, getfb64_main
},
786 // { "test", 2, test_main },
790 int main(int argc
, char **argv
)
797 if (strcmp(argv
[1], a
->name
) == 0) {
798 if ((argc
!= a
->args
) && ((a
->args
> 0) || (argc
< -(a
->args
)))) help();
799 return a
->main(argc
- 1, argv
+ 1);