Пример #1
0
/**
 * Append a new input file/directory to the list of inputs.
 *
 * @param arg       Directory or file name to add.
 * @param inputs    List of inputs
 * @param acceptdir 1 if we accept a directory, 0 otherwise
 */
static void
input_append(const char *arg, struct inputs *inputs, int acceptdir, int warn)
{
	struct stat statbuf;
	if (stat(arg, &statbuf) == -1) {
		if (warn) {
			log_warn("lldpctl", "cannot find configuration file/directory %s",
			    arg);
		} else {
			log_debug("lldpctl", "cannot find configuration file/directory %s",
			    arg);
		}
		return;
	}

	if (!S_ISDIR(statbuf.st_mode)) {
		struct input *input = malloc(sizeof(struct input));
		if (!input) {
			log_warn("lldpctl", "not enough memory to process %s",
			    arg);
			return;
		}
		log_debug("lldpctl", "input: %s", arg);
		input->name = strdup(arg);
		TAILQ_INSERT_TAIL(inputs, input, next);
		return;
	}
	if (!acceptdir) {
		log_debug("lldpctl", "skip directory %s",
		    arg);
		return;
	}

	struct dirent **namelist = NULL;
	int n =	scandir(arg, &namelist, filter, alphasort);
	if (n < 0) {
		log_warnx("lldpctl", "unable to read directory %s",
		    arg);
		return;
	}
	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, 1);
			free(fullname);
		}
		free(namelist[i]);
	}
	free(namelist);
}
Пример #2
0
int
main(int argc, char *argv[])
{
	int ch, debug = 1, rc = EXIT_FAILURE;
	const char *fmt = "plain";
	lldpctl_conn_t *conn = NULL;
	const char *options = is_lldpctl(argv[0])?"hdvf:":"hdsvf:c:u:";

	int gotinputs = 0;
	struct inputs inputs;
	TAILQ_INIT(&inputs);

	ctlname = lldpctl_get_default_transport();

	signal(SIGHUP, SIG_IGN);

	/* Initialize logging */
	while ((ch = getopt(argc, argv, options)) != -1) {
		switch (ch) {
		case 'd': debug++; break;
		case 's': debug--; break;
		}
	}
	log_init(debug, __progname);

	/* Get and parse command line options */
	optind = 1;
	while ((ch = getopt(argc, argv, options)) != -1) {
		switch (ch) {
		case 'd': break;
		case 's': break;
		case 'h':
			usage();
			break;
		case 'u':
			ctlname = optarg;
			break;
		case 'v':
			fprintf(stdout, "%s\n", PACKAGE_VERSION);
			exit(0);
			break;
		case 'f':
			fmt = optarg;
			break;
		case 'c':
			gotinputs = 1;
			input_append(optarg, &inputs, 1);
			break;
		default:
			usage();
		}
	}

	/* Disable SIGPIPE */
	signal(SIGPIPE, SIG_IGN);

	/* Register commands */
	root = register_commands();

	/* Make a connection */
	log_debug("lldpctl", "connect to lldpd");
	conn = lldpctl_new_name(ctlname, NULL, NULL, NULL);
	if (conn == NULL) goto end;

	/* Process file inputs */
	while (gotinputs && !TAILQ_EMPTY(&inputs)) {
		/* coverity[use_after_free]
		   TAILQ_REMOVE does the right thing */
		struct input *first = TAILQ_FIRST(&inputs);
		log_debug("lldpctl", "process: %s", first->name);
		FILE *file = fopen(first->name, "r");
		if (file) {
			size_t len;
			char *line;
			while ((line = fgetln(file, &len))) {
				line = strndup(line, len);
				if (line[len - 1] == '\n') {
					line[len - 1] = '\0';
					parse_and_exec(conn, fmt, line);
				}
				free(line);
			}
			fclose(file);
		} else {
			log_warn("lldpctl", "unable to open %s",
			    first->name);
		}
		TAILQ_REMOVE(&inputs, first, next);
		free(first->name);
		free(first);
	}

	/* Process additional arguments. First if we are lldpctl (interfaces) */
	if (is_lldpctl(NULL)) {
		char *line = NULL;
		for (int i = optind; i < argc; i++) {
			char *prev = line;
			if (asprintf(&line, "%s%s%s",
				prev?prev:"show neigh ports ", argv[i],
				(i == argc - 1)?" details":",") == -1) {
				log_warnx("lldpctl", "not enough memory to build list of interfaces");
				free(prev);
				goto end;
			}
			free(prev);
		}
		if (line == NULL && (line = strdup("show neigh details")) == NULL) {
			log_warnx("lldpctl", "not enough memory to build command line");
			goto end;
		}
		log_debug("lldpctl", "execute %s", line);
		if (parse_and_exec(conn, fmt, line) != -1)
			rc = EXIT_SUCCESS;
		free(line);
		goto end;
	}

	/* Then, if we are regular lldpcli (command line) */
	if (optind < argc) {
		const char **cargv;
		int cargc;
		cargv = &((const char **)argv)[optind];
		cargc = argc - optind;
		if (cmd_exec(conn, fmt, cargc, cargv) != -1)
			rc = EXIT_SUCCESS;
		goto end;
	}

	if (gotinputs) {
		rc = EXIT_SUCCESS;
		goto end;
	}

	/* Interactive session */
#ifdef HAVE_LIBREADLINE
	rl_bind_key('?',  cmd_help);
	rl_bind_key('\t', cmd_complete);
#endif
	const char *line;
	do {
		if ((line = readline(prompt()))) {
			int n = parse_and_exec(conn, fmt, line);
			(void)n;
#ifdef HAVE_READLINE_HISTORY
			if (n != 0) add_history(line);
#endif
		}
	} while (!must_exit && line != NULL);
	rc = EXIT_SUCCESS;

end:
	while (!TAILQ_EMPTY(&inputs)) {
		/* coverity[use_after_free]
		   TAILQ_REMOVE does the right thing */
		struct input *first = TAILQ_FIRST(&inputs);
		TAILQ_REMOVE(&inputs, first, next);
		free(first->name);
		free(first);
	}
	if (conn) lldpctl_release(conn);
	if (root) commands_free(root);
	return rc;
}