]> git.ipfire.org Git - thirdparty/lldpd.git/blobdiff - src/client/lldpcli.c
lldpcli: document json0 output format
[thirdparty/lldpd.git] / src / client / lldpcli.c
index 5e0d027e666a0acccfbb87554e21370746faffd0..a7d9be4b4b20baf35433b0bf2283b013bc7167f9 100644 (file)
@@ -29,6 +29,7 @@
 #include <arpa/inet.h>
 #include <libgen.h>
 #include <dirent.h>
+#include <signal.h>
 #include <sys/queue.h>
 
 #include "client.h"
@@ -66,10 +67,14 @@ usage()
        fprintf(stderr, "\n");
 
        fprintf(stderr, "-d          Enable more debugging information.\n");
-       fprintf(stderr, "-u          Specify the Unix-domain socket used for communication with lldpd(8).\n");
-       fprintf(stderr, "-f format   Choose output format (plain, keyvalue or xml).\n");
+       fprintf(stderr, "-u socket   Specify the Unix-domain socket used for communication with lldpd(8).\n");
+       fprintf(stderr, "-f format   Choose output format (plain, keyvalue, json, json0"
+#if defined USE_XML
+           ", xml"
+#endif
+           ").\n");
        if (!is_lldpctl(NULL))
-               fprintf(stderr, "-c          Read the provided configuration file.\n");
+               fprintf(stderr, "-c conf     Read the provided configuration file.\n");
 
        fprintf(stderr, "\n");
 
@@ -134,7 +139,7 @@ cmd_update(struct lldpctl_conn_t *conn, struct writer *w,
                lldpctl_atom_dec_ref(config);
                return 0;
        }
-       log_info("lldpctl", "immediate retransmission requested successfuly");
+       log_info("lldpctl", "immediate retransmission requested successfully");
        lldpctl_atom_dec_ref(config);
        return 1;
 }
@@ -156,10 +161,10 @@ cmd_pause_resume(lldpctl_conn_t *conn, int pause)
                return 0;
        }
        if (lldpctl_atom_get_int(config, lldpctl_k_config_paused) == pause) {
-               log_info("lldpctl", "lldpd is already %s",
+               log_debug("lldpctl", "lldpd is already %s",
                    pause?"paused":"resumed");
                lldpctl_atom_dec_ref(config);
-               return 0;
+               return 1;
        }
        if (lldpctl_atom_set_int(config,
                lldpctl_k_config_paused, pause) == NULL) {
@@ -205,7 +210,7 @@ _cmd_complete(int all)
        if (tokenize_line(line, &argc, &argv) != 0)
                goto end;
 
-       char *compl = commands_complete(root, argc, (const char **)argv, all);
+       char *compl = commands_complete(root, argc, (const char **)argv, all, is_privileged());
        if (compl && strlen(argv[argc-1]) < strlen(compl)) {
                if (rl_insert_text(compl + strlen(argv[argc-1])) < 0) {
                        free(compl);
@@ -246,7 +251,7 @@ readline(const char *p)
        fflush(stderr);
        if (fgets(line, sizeof(line) - 2, stdin) == NULL)
                return NULL;
-       return line;
+       return strdup(line);
 }
 #endif
 
@@ -267,17 +272,19 @@ cmd_exec(lldpctl_conn_t *conn, const char *fmt, int argc, const char **argv)
 
        if      (strcmp(fmt, "plain")    == 0) w = txt_init(stdout);
        else if (strcmp(fmt, "keyvalue") == 0) w = kv_init(stdout);
+       else if (strcmp(fmt, "json")     == 0) w = json_init(stdout, 1);
+       else if (strcmp(fmt, "json0")    == 0) w = json_init(stdout, 0);
 #ifdef USE_XML
        else if (strcmp(fmt, "xml")      == 0) w = xml_init(stdout);
 #endif
-#ifdef USE_JSON
-       else if (strcmp(fmt, "json")     == 0) w = json_init(stdout);
-#endif
-       else w = txt_init(stdout);
+       else {
+               log_warnx("lldpctl", "unknown output format \"%s\"", fmt);
+               w = txt_init(stdout);
+       }
 
        /* Execute command */
        int rc = commands_execute(conn, w,
-           root, argc, argv);
+           root, argc, argv, is_privileged());
        if (rc != 0) {
                log_info("lldpctl", "an error occurred while executing last command");
                w->finish(w);
@@ -324,14 +331,14 @@ register_commands()
        root = commands_root();
        register_commands_show(root);
        register_commands_watch(root);
-       if (is_privileged()) {
-               commands_new(
-                       commands_new(root, "update", "Update information and send LLDPU on all ports",
-                           NULL, NULL, NULL),
-                       NEWLINE, "Update information and send LLDPU on all ports",
-                       NULL, cmd_update, NULL);
-               register_commands_configure(root);
-       }
+       commands_privileged(commands_new(
+               commands_new(root, "update", "Update information and send LLDPU on all ports",
+                   NULL, NULL, NULL),
+               NEWLINE, "Update information and send LLDPU on all ports",
+               NULL, cmd_update, NULL));
+       register_commands_configure(root);
+       commands_hidden(commands_new(root, "complete", "Get possible completions from a given command",
+               NULL, cmd_store_env_and_pop, "complete"));
        commands_new(root, "help", "Get help on a possible command",
            NULL, cmd_store_env_and_pop, "help");
        commands_new(
@@ -367,12 +374,17 @@ filter(const struct dirent *dir)
  * @param acceptdir 1 if we accept a directory, 0 otherwise
  */
 static void
-input_append(const char *arg, struct inputs *inputs, int acceptdir)
+input_append(const char *arg, struct inputs *inputs, int acceptdir, int warn)
 {
        struct stat statbuf;
        if (stat(arg, &statbuf) == -1) {
-               log_info("lldpctl", "cannot find configuration file/directory %s",
-                   arg);
+               if (warn) {
+                       log_warn("lldpctl", "cannot find configuration file/directory %s",
+                           arg);
+               } else {
+                       log_debug("lldpctl", "cannot find configuration file/directory %s",
+                           arg);
+               }
                return;
        }
 
@@ -404,7 +416,7 @@ input_append(const char *arg, struct inputs *inputs, int acceptdir)
        for (int i=0; i < n; i++) {
                char *fullname;
                if (asprintf(&fullname, "%s/%s", arg, namelist[i]->d_name) != -1) {
-                       input_append(fullname, inputs, 0);
+                       input_append(fullname, inputs, 0, 1);
                        free(fullname);
                }
                free(namelist[i]);
@@ -415,32 +427,35 @@ input_append(const char *arg, struct inputs *inputs, int acceptdir)
 int
 main(int argc, char *argv[])
 {
-       int ch, debug = 1, rc = EXIT_FAILURE;
+       int ch, debug = 0, use_syslog = 0, rc = EXIT_FAILURE;
        const char *fmt = "plain";
        lldpctl_conn_t *conn = NULL;
-       const char *options = is_lldpctl(argv[0])?"hdvf:":"hdsvf:c:u:";
+       const char *options = is_lldpctl(argv[0])?"hdvf:u:":"hdsvf:c:C:u:";
 
-       int gotinputs = 0;
+       int gotinputs = 0, version = 0;
        struct inputs inputs;
        TAILQ_INIT(&inputs);
 
        ctlname = lldpctl_get_default_transport();
 
-       /* Initialize logging */
-       while ((ch = getopt(argc, argv, options)) != -1) {
-               switch (ch) {
-               case 'd': debug++; break;
-               case 's': debug--; break;
-               }
-       }
-       log_init(debug, __progname);
+       signal(SIGHUP, SIG_IGN);
 
        /* Get and parse command line options */
        optind = 1;
        while ((ch = getopt(argc, argv, options)) != -1) {
                switch (ch) {
-               case 'd': break;
-               case 's': break;
+               case 'd':
+                       if (use_syslog)
+                               use_syslog = 0;
+                       else
+                               debug++;
+                       break;
+               case 's':
+                       if (debug == 0)
+                               use_syslog = 1;
+                       else
+                               debug--;
+                       break;
                case 'h':
                        usage();
                        break;
@@ -448,21 +463,38 @@ main(int argc, char *argv[])
                        ctlname = optarg;
                        break;
                case 'v':
-                       fprintf(stdout, "%s\n", PACKAGE_VERSION);
-                       exit(0);
+                       version++;
                        break;
                case 'f':
                        fmt = optarg;
                        break;
+               case 'C':
                case 'c':
-                       gotinputs = 1;
-                       input_append(optarg, &inputs, 1);
+                       if (!gotinputs) {
+                               log_init(use_syslog, debug, __progname);
+                               lldpctl_log_level(debug + 1);
+                               gotinputs = 1;
+                       }
+                       input_append(optarg, &inputs, 1, ch == 'c');
                        break;
                default:
                        usage();
                }
        }
 
+       if (version) {
+               version_display(stdout, "lldpcli", version > 1);
+               exit(0);
+       }
+
+       if (!gotinputs) {
+               log_init(use_syslog, debug, __progname);
+               lldpctl_log_level(debug + 1);
+       }
+
+       /* Disable SIGPIPE */
+       signal(SIGPIPE, SIG_IGN);
+
        /* Register commands */
        root = register_commands();
 
@@ -479,16 +511,17 @@ main(int argc, char *argv[])
                log_debug("lldpctl", "process: %s", first->name);
                FILE *file = fopen(first->name, "r");
                if (file) {
-                       size_t len;
+                       size_t n;
+                       ssize_t len;
                        char *line;
-                       while ((line = fgetln(file, &len))) {
-                               line = strndup(line, len);
+                       while (line = NULL, len = 0, (len = getline(&line, &n, file)) > 0) {
                                if (line[len - 1] == '\n') {
                                        line[len - 1] = '\0';
                                        parse_and_exec(conn, fmt, line);
                                }
                                free(line);
                        }
+                       free(line);
                        fclose(file);
                } else {
                        log_warn("lldpctl", "unable to open %s",
@@ -530,7 +563,7 @@ main(int argc, char *argv[])
                int cargc;
                cargv = &((const char **)argv)[optind];
                cargc = argc - optind;
-               if (cmd_exec(conn, fmt, cargc, cargv) != -1)
+               if (cmd_exec(conn, fmt, cargc, cargv) == 1)
                        rc = EXIT_SUCCESS;
                goto end;
        }
@@ -545,14 +578,16 @@ main(int argc, char *argv[])
        rl_bind_key('?',  cmd_help);
        rl_bind_key('\t', cmd_complete);
 #endif
-       const char *line;
+       char *line = NULL;
        do {
                if ((line = readline(prompt()))) {
                        int n = parse_and_exec(conn, fmt, line);
-                       (void)n;
+                       if (n != 0) {
 #ifdef HAVE_READLINE_HISTORY
-                       if (n != 0) add_history(line);
+                               add_history(line);
 #endif
+                       }
+                       free(line);
                }
        } while (!must_exit && line != NULL);
        rc = EXIT_SUCCESS;