1/*
2 * src/utils.c		Utilities
3 *
4 *	This library is free software; you can redistribute it and/or
5 *	modify it under the terms of the GNU Lesser General Public
6 *	License as published by the Free Software Foundation version 2.1
7 *	of the License.
8 *
9 * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
10 */
11
12/**
13 * @defgroup cli Command Line Interface API
14 *
15 * @{
16 *
17 * These modules provide an interface for text based applications. The
18 * functions provided are wrappers for their libnl equivalent with
19 * added error handling. The functions check for allocation failures,
20 * invalid input, and unknown types and will print error messages
21 * accordingly via nl_cli_fatal().
22 */
23
24#include <netlink/cli/utils.h>
25
26/**
27 * Parse a text based 32 bit unsigned integer argument
28 * @arg arg		Integer in text form.
29 *
30 * Tries to convert the number provided in arg to a uint32_t. Will call
31 * nl_cli_fatal() if the conversion fails.
32 *
33 * @return 32bit unsigned integer.
34 */
35uint32_t nl_cli_parse_u32(const char *arg)
36{
37	unsigned long lval;
38	char *endptr;
39
40	lval = strtoul(arg, &endptr, 0);
41	if (endptr == arg || lval == ULONG_MAX)
42		nl_cli_fatal(EINVAL, "Unable to parse \"%s\", not a number.",
43			     arg);
44
45	return (uint32_t) lval;
46}
47
48void nl_cli_print_version(void)
49{
50	printf("libnl tools version %s\n", LIBNL_VERSION);
51	printf(
52	"Copyright (C) 2003-2010 Thomas Graf <tgraf@redhat.com>\n"
53	"\n"
54	"This program comes with ABSOLUTELY NO WARRANTY. This is free \n"
55	"software, and you are welcome to redistribute it under certain\n"
56	"conditions. See the GNU General Public License for details.\n"
57	);
58
59	exit(0);
60}
61
62/**
63 * Print error message and quit application
64 * @arg err		Error code.
65 * @arg fmt		Error message.
66 *
67 * Prints the formatted error message to stderr and quits the application
68 * using the provided error code.
69 */
70void nl_cli_fatal(int err, const char *fmt, ...)
71{
72	va_list ap;
73	char buf[256];
74
75	fprintf(stderr, "Error: ");
76
77	if (fmt) {
78		va_start(ap, fmt);
79		vfprintf(stderr, fmt, ap);
80		va_end(ap);
81		fprintf(stderr, "\n");
82	} else
83		fprintf(stderr, "%s\n", strerror_r(err, buf, sizeof(buf)));
84
85	exit(abs(err));
86}
87
88int nl_cli_connect(struct nl_sock *sk, int protocol)
89{
90	int err;
91
92	if ((err = nl_connect(sk, protocol)) < 0)
93		nl_cli_fatal(err, "Unable to connect netlink socket: %s",
94			     nl_geterror(err));
95
96	return err;
97}
98
99struct nl_sock *nl_cli_alloc_socket(void)
100{
101	struct nl_sock *sock;
102
103	if (!(sock = nl_socket_alloc()))
104		nl_cli_fatal(ENOBUFS, "Unable to allocate netlink socket");
105
106	return sock;
107}
108
109struct nl_addr *nl_cli_addr_parse(const char *str, int family)
110{
111	struct nl_addr *addr;
112	int err;
113
114	if ((err = nl_addr_parse(str, family, &addr)) < 0)
115		nl_cli_fatal(err, "Unable to parse address \"%s\": %s",
116			     str, nl_geterror(err));
117
118	return addr;
119}
120
121int nl_cli_parse_dumptype(const char *str)
122{
123	if (!strcasecmp(str, "brief"))
124		return NL_DUMP_LINE;
125	else if (!strcasecmp(str, "details") || !strcasecmp(str, "detailed"))
126		return NL_DUMP_DETAILS;
127	else if (!strcasecmp(str, "stats"))
128		return NL_DUMP_STATS;
129	else
130		nl_cli_fatal(EINVAL, "Invalid dump type \"%s\".\n", str);
131
132	return 0;
133}
134
135int nl_cli_confirm(struct nl_object *obj, struct nl_dump_params *params,
136		   int default_yes)
137{
138	nl_object_dump(obj, params);
139
140	for (;;) {
141		char buf[32] = { 0 };
142		int answer;
143
144		printf("Delete? (%c/%c) ",
145			default_yes ? 'Y' : 'y',
146			default_yes ? 'n' : 'N');
147
148		if (!fgets(buf, sizeof(buf), stdin)) {
149			fprintf(stderr, "Error while reading\n.");
150			continue;
151		}
152
153		switch ((answer = tolower(buf[0]))) {
154		case '\n':
155			answer = default_yes ? 'y' : 'n';
156		case 'y':
157		case 'n':
158			return answer == 'y';
159		}
160
161		fprintf(stderr, "Invalid input, try again.\n");
162	}
163
164	return 0;
165
166}
167
168struct nl_cache *nl_cli_alloc_cache(struct nl_sock *sock, const char *name,
169			    int (*ac)(struct nl_sock *, struct nl_cache **))
170{
171	struct nl_cache *cache;
172	int err;
173
174	if ((err = ac(sock, &cache)) < 0)
175		nl_cli_fatal(err, "Unable to allocate %s cache: %s",
176			     name, nl_geterror(err));
177
178	nl_cache_mngt_provide(cache);
179
180	return cache;
181}
182
183void nl_cli_load_module(const char *prefix, const char *name)
184{
185	char path[FILENAME_MAX+1];
186	void *handle;
187
188	snprintf(path, sizeof(path), "%s/%s/%s.so",
189		 PKGLIBDIR, prefix, name);
190
191	if (!(handle = dlopen(path, RTLD_NOW)))
192		nl_cli_fatal(ENOENT, "Unable to load module \"%s\": %s\n",
193			path, dlerror());
194}
195
196/** @} */
197