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