+
+ return 0;
+}
+
+static int cmd_top(int argc, char *argv[]) {
+#ifdef HAVE_CURSES
+ if(!connect_tincd())
+ return 1;
+
+ top(fd);
+ return 0;
+#else
+ fprintf(stderr, "This version of tincctl was compiled without support for the curses library.\n");
+ return 1;
+#endif
+}
+
+static int cmd_pcap(int argc, char *argv[]) {
+ if(!connect_tincd())
+ return 1;
+
+ pcap(fd, stdout, argc > 1 ? atoi(argv[1]) : 0);
+ return 0;
+}
+
+static int cmd_log(int argc, char *argv[]) {
+ if(!connect_tincd())
+ return 1;
+
+ logcontrol(fd, stdout, argc > 1 ? atoi(argv[1]) : -1);
+ return 0;
+}
+
+static int cmd_pid(int argc, char *argv[]) {
+ if(!connect_tincd())
+ return 1;
+
+ printf("%d\n", pid);
+ return 0;
+}
+
+static int rstrip(char *value) {
+ int len = strlen(value);
+ while(len && strchr("\t\r\n ", value[len - 1]))
+ value[--len] = 0;
+ return len;
+}
+
+static char *get_my_name() {
+ FILE *f = fopen(tinc_conf, "r");
+ if(!f) {
+ fprintf(stderr, "Could not open %s: %s\n", tinc_conf, strerror(errno));
+ return NULL;
+ }
+
+ char buf[4096];
+ char *value;
+ while(fgets(buf, sizeof buf, f)) {
+ int len = strcspn(buf, "\t =");
+ value = buf + len;
+ value += strspn(value, "\t ");
+ if(*value == '=') {
+ value++;
+ value += strspn(value, "\t ");
+ }
+ if(!rstrip(value))
+ continue;
+ buf[len] = 0;
+ if(strcasecmp(buf, "Name"))
+ continue;
+ if(*value) {
+ fclose(f);
+ return strdup(value);
+ }
+ }
+
+ fclose(f);
+ fprintf(stderr, "Could not find Name in %s.\n", tinc_conf);
+ return NULL;
+}
+
+static char *hostvariables[] = {
+ "Address",
+ "Port",
+ "PublicKey",
+ "Subnet",
+ NULL,
+};
+
+static int cmd_config(int argc, char *argv[]) {
+ if(argc < 2) {
+ fprintf(stderr, "Invalid number of arguments.\n");
+ return 1;
+ }
+
+ int action = 0;
+ if(!strcasecmp(argv[1], "add")) {
+ argv++, argc--, action = 1;
+ } else if(!strcasecmp(argv[1], "del")) {
+ argv++, argc--, action = -1;
+ } else if(!strcasecmp(argv[1], "replace") || !strcasecmp(argv[1], "set") || !strcasecmp(argv[1], "change")) {
+ argv++, argc--, action = 0;
+ }
+
+ if(argc < 2) {
+ fprintf(stderr, "Invalid number of arguments.\n");
+ return 1;
+ }
+
+ // Concatenate the rest of the command line
+ strncpy(line, argv[1], sizeof line - 1);
+ for(int i = 2; i < argc; i++) {
+ strncat(line, " ", sizeof line - 1 - strlen(line));
+ strncat(line, argv[i], sizeof line - 1 - strlen(line));
+ }
+
+ // Liberal parsing into node name, variable name and value.
+ char *node = NULL;
+ char *variable;
+ char *value;
+ int len;
+
+ len = strcspn(line, "\t =");
+ value = line + len;
+ value += strspn(value, "\t ");
+ if(*value == '=') {
+ value++;
+ value += strspn(value, "\t ");
+ }
+ line[len] = '\0';
+ variable = strchr(line, '.');
+ if(variable) {
+ node = line;
+ *variable++ = 0;
+ } else {
+ variable = line;
+ }
+
+ if(!*variable) {
+ fprintf(stderr, "No variable given.\n");
+ return 1;