Add an easy way to edit a configuration file.
[tinc] / src / tincctl.c
index 46688f3..6725b8b 100644 (file)
@@ -832,6 +832,11 @@ static int cmd_connect(int argc, char *argv[]) {
                return 1;
        }
 
+       if(!check_id(argv[2])) {
+               fprintf(stderr, "Invalid name for node.\n");
+               return 1;
+       }
+
        if(!connect_tincd())
                return 1;
 
@@ -850,6 +855,11 @@ static int cmd_disconnect(int argc, char *argv[]) {
                return 1;
        }
 
+       if(!check_id(argv[2])) {
+               fprintf(stderr, "Invalid name for node.\n");
+               return 1;
+       }
+
        if(!connect_tincd())
                return 1;
 
@@ -1018,6 +1028,11 @@ static int cmd_config(int argc, char *argv[]) {
                }
        }
 
+       if(node && !check_id(node)) {
+               fprintf(stderr, "Invalid name for node.\n");
+               return 1;
+       }
+
        // Open the right configuration file.
        char *filename;
        if(node)
@@ -1151,6 +1166,15 @@ static int cmd_config(int argc, char *argv[]) {
        return 0;
 }
 
+bool check_id(const char *name) {
+       for(int i = 0; i < strlen(name); i++) {
+               if(!isalnum(name[i]) && name[i] != '_')
+                       return false;
+       }
+
+       return true;
+}
+
 static int cmd_init(int argc, char *argv[]) {
        if(!access(tinc_conf, F_OK)) {
                fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf);
@@ -1184,11 +1208,9 @@ static int cmd_init(int argc, char *argv[]) {
                }
        }
 
-       for(int i = 0; i < strlen(name); i++) {
-               if(!isalnum(name[i]) && name[i] != '_') {
-                       fprintf(stderr, "Invalid Name! Only a-z, A-Z, 0-9 and _ are allowed characters.\n");
-                       return 1;
-               }
+       if(!check_id(name)) {
+               fprintf(stderr, "Invalid Name! Only a-z, A-Z, 0-9 and _ are allowed characters.\n");
+               return 1;
        }
 
        if(mkdir(CONFDIR, 0755) && errno != EEXIST) {
@@ -1247,6 +1269,59 @@ static int cmd_version(int argc, char *argv[]) {
        return 0;
 }
 
+static const char *conffiles[] = {
+       "tinc.conf",
+       "tinc-up",
+       "tinc-down",
+       "subnet-up",
+       "subnet-down",
+       "host-up",
+       "host-down",
+       NULL,
+};
+
+static int cmd_edit(int argc, char *argv[]) {
+       if(argc != 2) {
+               fprintf(stderr, "Invalid number of arguments.\n");
+               return 1;
+       }
+
+       char *filename = NULL;
+
+       if(strncmp(argv[1], "hosts/", 6)) {
+               for(int i = 0; conffiles[i]; i++) {
+                       if(!strcmp(argv[1], conffiles[i])) {
+                               xasprintf(&filename, "%s/%s", confbase, argv[1]);
+                               break;
+                       }
+               }
+       } else {
+               argv[1] += 6;
+       }
+
+       if(!filename) {
+               xasprintf(&filename, "%s/%s", hosts_dir, argv[1]);
+               char *dash = strchr(argv[1], '-');
+               if(dash) {
+                       *dash++ = 0;
+                       if((strcmp(dash, "up") && strcmp(dash, "down")) || !check_id(argv[1])) {
+                               fprintf(stderr, "Invalid configuration filename.\n");
+                               return 1;
+                       }
+               }
+       }
+
+#ifndef HAVE_MINGW
+       char *editor = getenv("VISUAL") ?: getenv("EDITOR") ?: "vi";
+#else
+       char *editor = "edit"
+#endif
+
+       char *command;
+       xasprintf(&command, "\"%s\" \"%s\"", editor, filename);
+       return system(command);
+}
+
 static const struct {
        const char *command;
        int (*function)(int argc, char *argv[]);
@@ -1272,6 +1347,7 @@ static const struct {
        {"generate-ecdsa-keys", cmd_generate_ecdsa_keys},
        {"help", cmd_help},
        {"version", cmd_version},
+       {"edit", cmd_edit},
        {NULL, NULL},
 };