]> git.ipfire.org Git - thirdparty/lldpd.git/blame - src/client/lldpctl.c
lldpctl: remove "unconfigure" commands (not implemented)
[thirdparty/lldpd.git] / src / client / lldpctl.c
CommitLineData
4b292b55
VB
1/* -*- mode: c; c-file-style: "openbsd" -*- */
2/*
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <unistd.h>
21#include <time.h>
22#include <errno.h>
4e5f34c5 23#include <string.h>
4b292b55
VB
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <arpa/inet.h>
9a775667 28#include <histedit.h>
4b292b55 29
4b292b55
VB
30#include "client.h"
31
4b292b55
VB
32#ifdef HAVE___PROGNAME
33extern const char *__progname;
34#else
35# define __progname "lldpctl"
36#endif
37
9a775667
VB
38/* Global for completion */
39static struct cmd_node *root = NULL;
4b292b55
VB
40
41static void
9a775667 42usage()
4b292b55 43{
9a775667 44 fprintf(stderr, "Usage: %s [OPTIONS ...] [COMMAND ...]\n", __progname);
4b292b55
VB
45 fprintf(stderr, "Version: %s\n", PACKAGE_STRING);
46
47 fprintf(stderr, "\n");
48
49 fprintf(stderr, "-d Enable more debugging information.\n");
4b292b55 50 fprintf(stderr, "-f format Choose output format (plain, keyvalue or xml).\n");
4b292b55
VB
51
52 fprintf(stderr, "\n");
53
54 fprintf(stderr, "see manual page lldpctl(8) for more information\n");
55 exit(1);
56}
57
9a775667
VB
58static int
59is_privileged()
60{
61 return (!(getuid() != geteuid() || getgid() != getegid()));
62}
63
64static char*
65prompt(EditLine *el)
66{
67 int privileged = is_privileged();
68 if (privileged)
69 return "[lldpctl] # ";
70 return "[lldpctl] $ ";
71}
72
73static int must_exit = 0;
74/**
75 * Exit the interpreter.
76 */
77static int
78cmd_exit(struct lldpctl_conn_t *conn, struct writer *w,
79 struct cmd_env *env, void *arg)
4e90a9e0 80{
9a775667
VB
81 log_info("lldpctl", "quit lldpctl");
82 must_exit = 1;
83 return 1;
84}
85
86/**
87 * Send an "update" request.
88 */
89static int
90cmd_update(struct lldpctl_conn_t *conn, struct writer *w,
91 struct cmd_env *env, void *arg)
92{
93 log_info("lldpctl", "ask for global update");
94
95 lldpctl_atom_t *config = lldpctl_get_configuration(conn);
96 if (config == NULL) {
97 log_warnx("lldpctl", "unable to get configuration from lldpd. %s",
98 lldpctl_last_strerror(conn));
99 return 0;
4e90a9e0 100 }
9a775667
VB
101 if (lldpctl_atom_set_int(config,
102 lldpctl_k_config_tx_interval, -1) == NULL) {
103 log_warnx("lldpctl", "unable to ask lldpd for immediate retransmission. %s",
104 lldpctl_last_strerror(conn));
105 lldpctl_atom_dec_ref(config);
106 return 0;
4e90a9e0 107 }
9a775667
VB
108 log_info("lldpctl", "immediate retransmission requested successfuly");
109 lldpctl_atom_dec_ref(config);
110 return 1;
111}
112
113static unsigned char
114_cmd_complete(EditLine *el, int ch, int all)
115{
116 int rc = CC_ERROR;
117 Tokenizer *eltok;
118 if ((eltok = tok_init(NULL)) == NULL)
119 goto end;
120
121 const LineInfo *li = el_line(el);
122
123 const char **argv;
124 char *compl;
125 int argc, cursorc, cursoro;
126 if (tok_line(eltok, li, &argc, &argv, &cursorc, &cursoro) != 0)
127 goto end;
128 compl = commands_complete(root, argc, argv, cursorc, cursoro, all);
129 if (compl) {
130 el_deletestr(el, cursoro);
131 if (el_insertstr(el, compl) == -1) {
132 free(compl);
133 goto end;
134 }
135 free(compl);
136 rc = CC_REDISPLAY;
137 goto end;
138 }
139 /* No completion or several completion available. We beep. */
140 el_beep(el);
141 rc = CC_REDISPLAY;
142end:
143 if (eltok) tok_end(eltok);
144 return rc;
145}
146
147static unsigned char
148cmd_complete(EditLine *el, int ch)
149{
150 return _cmd_complete(el, ch, 0);
151}
152
153static unsigned char
154cmd_help(EditLine *el, int ch)
155{
156 return _cmd_complete(el, ch, 1);
157}
158
159static struct cmd_node*
160register_commands()
161{
162 root = commands_root();
163 register_commands_show(root);
164 register_commands_watch(root);
165 if (is_privileged()) {
166 commands_new(
167 commands_new(root, "update", "Update information and send LLDPU on all ports",
168 NULL, NULL, NULL),
169 NEWLINE, "Update information and send LLDPU on all ports",
170 NULL, cmd_update, NULL);
171 register_commands_configure(root);
172 }
173 commands_new(
174 commands_new(root, "exit", "Exit interpreter", NULL, NULL, NULL),
175 NEWLINE, "Exit interpreter", NULL, cmd_exit, NULL);
176 return root;
4e90a9e0
VB
177}
178
4b292b55
VB
179int
180main(int argc, char *argv[])
181{
9a775667 182 int ch, debug = 1, rc = EXIT_FAILURE;
4e90a9e0 183 char *fmt = "plain";
4b292b55 184 lldpctl_conn_t *conn;
9a775667
VB
185 struct writer *w;
186
187 EditLine *el;
188 History *elhistory;
189 HistEvent elhistev;
190 Tokenizer *eltok;
4b292b55
VB
191
192 /* Get and parse command line options */
9a775667 193 while ((ch = getopt(argc, argv, "hdvf:")) != -1) {
4b292b55
VB
194 switch (ch) {
195 case 'h':
196 usage();
197 break;
198 case 'd':
199 debug++;
200 break;
201 case 'v':
202 fprintf(stdout, "%s\n", PACKAGE_VERSION);
203 exit(0);
204 break;
4b292b55
VB
205 case 'f':
206 fmt = optarg;
207 break;
4b292b55
VB
208 default:
209 usage();
210 }
211 }
212
213 log_init(debug, __progname);
214
9a775667
VB
215 /* Register commands */
216 root = register_commands();
217
218 /* Init editline */
219 log_debug("lldpctl", "init editline");
220 el = el_init("lldpctl", stdin, stdout, stderr);
221 if (el == NULL) {
222 log_warnx("lldpctl", "unable to setup editline");
223 goto end;
224 }
225 el_set(el, EL_PROMPT, prompt);
226 el_set(el, EL_SIGNAL, 0);
227 el_set(el, EL_EDITOR, "emacs");
228 /* If on a TTY, setup completion */
229 if (isatty(STDERR_FILENO)) {
230 el_set(el, EL_ADDFN, "command_complete",
231 "Execute completion", cmd_complete);
232 el_set(el, EL_ADDFN, "command_help",
233 "Show completion", cmd_help);
234 el_set(el, EL_BIND, "^I", "command_complete", NULL);
235 el_set(el, EL_BIND, "?", "command_help", NULL);
4b292b55
VB
236 }
237
9a775667
VB
238 /* Init history */
239 elhistory = history_init();
240 if (elhistory == NULL) {
241 log_warnx("lldpctl", "unable to enable history");
242 } else {
243 history(elhistory, &elhistev, H_SETSIZE, 800);
244 el_set(el, EL_HIST, history, elhistory);
4e90a9e0
VB
245 }
246
9a775667
VB
247 /* Init tokenizer */
248 eltok = tok_init(NULL);
249 if (eltok == NULL) {
250 log_warnx("lldpctl", "unable to initialize tokenizer");
251 goto end;
252 }
253
254 /* Make a connection */
255 log_debug("lldpctl", "connect to lldpd");
256 conn = lldpctl_new(NULL, NULL, NULL);
257 if (conn == NULL)
258 exit(EXIT_FAILURE);
259
260 while (!must_exit) {
261 const char *line;
262 const char **argv;
263 int count, n, argc;
264
265 /* Read a new line. */
266 line = el_gets(el, &count);
267 if (line == NULL) break;
268
269 /* Tokenize it */
270 log_debug("lldpctl", "tokenize command line");
271 n = tok_str(eltok, line, &argc, &argv);
272 switch (n) {
273 case -1:
274 log_warnx("lldpctl", "internal error while tokenizing");
275 goto end;
276 case 1:
277 case 2:
278 case 3:
279 /* TODO: handle multiline statements */
280 log_warnx("lldpctl", "unmatched quotes");
281 tok_reset(eltok);
282 continue;
8729d69f 283 }
9a775667
VB
284 if (argc == 0) {
285 tok_reset(eltok);
286 continue;
8729d69f 287 }
9a775667
VB
288 if (elhistory) history(elhistory, &elhistev, H_ENTER, line);
289
290 /* Init output formatter */
291 if (strcmp(fmt, "plain") == 0) w = txt_init(stdout);
292 else if (strcmp(fmt, "keyvalue") == 0) w = kv_init(stdout);
293#ifdef USE_XML
294 else if (strcmp(fmt, "xml") == 0) w = xml_init(stdout);
8b7150e4
VB
295#endif
296#ifdef USE_JSON
9a775667 297 else if (strcmp(fmt, "json") == 0) w = json_init(stdout);
4e90a9e0 298#endif
9a775667 299 else w = txt_init(stdout);
4e90a9e0 300
9a775667
VB
301 /* Execute command */
302 if (commands_execute(conn, w,
303 root, argc, argv) != 0)
304 log_info("lldpctl", "an error occurred while executing last command");
305 w->finish(w);
306 tok_reset(eltok);
307 }
4b292b55 308
9a775667
VB
309 rc = EXIT_SUCCESS;
310end:
311 if (conn) lldpctl_release(conn);
312 if (eltok) tok_end(eltok);
313 if (elhistory) history_end(elhistory);
314 if (el) el_end(el);
315 if (root) commands_free(root);
316 return rc;
4b292b55 317}