libnl  3.4.0
utils.c
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 #include <locale.h>
26 
27 #include "lib/defs.h"
28 
29 #ifdef HAVE_DLFCN_H
30 #include <dlfcn.h>
31 #endif
32 
33 /**
34  * Parse a text based 32 bit unsigned integer argument
35  * @arg arg Integer in text form.
36  *
37  * Tries to convert the number provided in arg to a uint32_t. Will call
38  * nl_cli_fatal() if the conversion fails.
39  *
40  * @return 32bit unsigned integer.
41  */
42 uint32_t nl_cli_parse_u32(const char *arg)
43 {
44  unsigned long lval;
45  char *endptr;
46 
47  lval = strtoul(arg, &endptr, 0);
48  if (endptr == arg || lval == ULONG_MAX)
49  nl_cli_fatal(EINVAL, "Unable to parse \"%s\", not a number.",
50  arg);
51 
52  return (uint32_t) lval;
53 }
54 
55 void nl_cli_print_version(void)
56 {
57  printf("libnl tools version %s\n", LIBNL_VERSION);
58  printf(
59  "Copyright (C) 2003-2010 Thomas Graf <tgraf@redhat.com>\n"
60  "\n"
61  "This program comes with ABSOLUTELY NO WARRANTY. This is free \n"
62  "software, and you are welcome to redistribute it under certain\n"
63  "conditions. See the GNU General Public License for details.\n"
64  );
65 
66  exit(0);
67 }
68 
69 /**
70  * Print error message and quit application
71  * @arg err Error code.
72  * @arg fmt Error message.
73  *
74  * Prints the formatted error message to stderr and quits the application
75  * using the provided error code.
76  */
77 void nl_cli_fatal(int err, const char *fmt, ...)
78 {
79  va_list ap;
80 
81  fprintf(stderr, "Error: ");
82 
83  if (fmt) {
84  va_start(ap, fmt);
85  vfprintf(stderr, fmt, ap);
86  va_end(ap);
87  fprintf(stderr, "\n");
88  } else {
89  char *buf;
90 #ifdef HAVE_STRERROR_L
91  locale_t loc = newlocale(LC_MESSAGES_MASK, "", (locale_t)0);
92  if (loc == (locale_t)0) {
93  if (errno == ENOENT)
94  loc = newlocale(LC_MESSAGES_MASK,
95  "POSIX", (locale_t)0);
96  if (loc == (locale_t)0)
97  buf = "newlocale() failed";
98  }
99  if (loc != (locale_t)0)
100  buf = strerror_l(err, loc);
101 #else
102  buf = strerror(err);
103 #endif
104  fprintf(stderr, "%s\n", buf);
105 #ifdef HAVE_STRERROR_L
106  if (loc != (locale_t)0)
107  freelocale(loc);
108 #endif
109  }
110 
111  exit(abs(err));
112 }
113 
114 int nl_cli_connect(struct nl_sock *sk, int protocol)
115 {
116  int err;
117 
118  if ((err = nl_connect(sk, protocol)) < 0)
119  nl_cli_fatal(err, "Unable to connect netlink socket: %s",
120  nl_geterror(err));
121 
122  return err;
123 }
124 
125 struct nl_sock *nl_cli_alloc_socket(void)
126 {
127  struct nl_sock *sock;
128 
129  if (!(sock = nl_socket_alloc()))
130  nl_cli_fatal(ENOBUFS, "Unable to allocate netlink socket");
131 
132  return sock;
133 }
134 
135 struct nl_addr *nl_cli_addr_parse(const char *str, int family)
136 {
137  struct nl_addr *addr;
138  int err;
139 
140  if ((err = nl_addr_parse(str, family, &addr)) < 0)
141  nl_cli_fatal(err, "Unable to parse address \"%s\": %s",
142  str, nl_geterror(err));
143 
144  return addr;
145 }
146 
147 int nl_cli_parse_dumptype(const char *str)
148 {
149  if (!strcasecmp(str, "brief"))
150  return NL_DUMP_LINE;
151  else if (!strcasecmp(str, "details") || !strcasecmp(str, "detailed"))
152  return NL_DUMP_DETAILS;
153  else if (!strcasecmp(str, "stats"))
154  return NL_DUMP_STATS;
155  else
156  nl_cli_fatal(EINVAL, "Invalid dump type \"%s\".\n", str);
157 
158  return 0;
159 }
160 
161 int nl_cli_confirm(struct nl_object *obj, struct nl_dump_params *params,
162  int default_yes)
163 {
164  nl_object_dump(obj, params);
165 
166  for (;;) {
167  char buf[32] = { 0 };
168  int answer;
169 
170  printf("Delete? (%c/%c) ",
171  default_yes ? 'Y' : 'y',
172  default_yes ? 'n' : 'N');
173 
174  if (!fgets(buf, sizeof(buf), stdin)) {
175  fprintf(stderr, "Error while reading\n.");
176  continue;
177  }
178 
179  switch ((answer = tolower(buf[0]))) {
180  case '\n':
181  answer = default_yes ? 'y' : 'n';
182  /* fall through */
183  case 'y':
184  case 'n':
185  return answer == 'y';
186  }
187 
188  fprintf(stderr, "Invalid input, try again.\n");
189  }
190 
191  return 0;
192 
193 }
194 
195 struct nl_cache *nl_cli_alloc_cache(struct nl_sock *sock, const char *name,
196  int (*ac)(struct nl_sock *, struct nl_cache **))
197 {
198  struct nl_cache *cache;
199  int err;
200 
201  if ((err = ac(sock, &cache)) < 0)
202  nl_cli_fatal(err, "Unable to allocate %s cache: %s",
203  name, nl_geterror(err));
204 
205  nl_cache_mngt_provide(cache);
206 
207  return cache;
208 }
209 
210 struct nl_cache *nl_cli_alloc_cache_flags(struct nl_sock *sock,
211  const char *name, unsigned int flags,
212  int (*ac)(struct nl_sock *, struct nl_cache **,
213  unsigned int))
214 {
215  struct nl_cache *cache;
216  int err;
217 
218  if ((err = ac(sock, &cache, flags)) < 0)
219  nl_cli_fatal(err, "Unable to allocate %s cache: %s",
220  name, nl_geterror(err));
221 
222  nl_cache_mngt_provide(cache);
223 
224  return cache;
225 }
226 
227 void nl_cli_load_module(const char *prefix, const char *name)
228 {
229  char path[FILENAME_MAX+1];
230 
231  snprintf(path, sizeof(path), "%s/%s/%s.so",
232  PKGLIBDIR, prefix, name);
233 
234 #ifdef HAVE_DLFCN_H
235  {
236  void *handle;
237 
238  if (!(handle = dlopen(path, RTLD_NOW))) {
239  nl_cli_fatal(ENOENT, "Unable to load module \"%s\": %s\n",
240  path, dlerror());
241  }
242  }
243 #else
244  nl_cli_fatal(ENOTSUP, "Unable to load module \"%s\": built without dynamic libraries support\n",
245  path);
246 #endif
247 }
248 
249 /** @} */
Dump object briefly on one line.
Definition: types.h:22
void nl_cache_mngt_provide(struct nl_cache *cache)
Provide a cache for global use.
Definition: cache_mngt.c:332
int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result)
Allocate abstract address based on character string.
Definition: addr.c:298
Dump all attributes but no statistics.
Definition: types.h:23
struct nl_sock * nl_socket_alloc(void)
Allocate new netlink socket.
Definition: socket.c:205
int nl_connect(struct nl_sock *sk, int protocol)
Create file descriptor and bind socket.
Definition: nl.c:103
void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
Dump this object according to the specified parameters.
Definition: object.c:288
uint32_t nl_cli_parse_u32(const char *arg)
Parse a text based 32 bit unsigned integer argument.
Definition: utils.c:42
void nl_cli_fatal(int err, const char *fmt,...)
Print error message and quit application.
Definition: utils.c:77
Dumping parameters.
Definition: types.h:33
Dump all attributes including statistics.
Definition: types.h:24