aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
authorDavid M. Syzdek <david@syzdek.net>2022-05-24 04:47:20 -0800
committerDavid M. Syzdek <david@syzdek.net>2022-05-24 04:47:20 -0800
commit3e36e5a1dfbc793faaf50c3e744cbcfa62b5912b (patch)
tree48eb15c11aee9952114770968292f1a705c1a18d /src
parent81ce536fac4233490e6e60f87c1f83326e34c44d (diff)
downloaddmstools-3e36e5a1dfbc793faaf50c3e744cbcfa62b5912b.tar.gz
dmstools-3e36e5a1dfbc793faaf50c3e744cbcfa62b5912b.tar.bz2
dmstools-3e36e5a1dfbc793faaf50c3e744cbcfa62b5912b.tar.xz
dmstools-3e36e5a1dfbc793faaf50c3e744cbcfa62b5912b.zip
urldesc: adding utility
Diffstat (limited to 'src')
-rw-r--r--src/urldesc.c565
1 files changed, 565 insertions, 0 deletions
diff --git a/src/urldesc.c b/src/urldesc.c
new file mode 100644
index 0000000..bed12d2
--- /dev/null
+++ b/src/urldesc.c
@@ -0,0 +1,565 @@
1/*
2 * DMS Tools and Utilities
3 * Copyright (C) 2022 David M. Syzdek <david@syzdek.net>.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of David M. Syzdek nor the
16 * names of its contributors may be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID M. SYZDEK BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31#define _SCT_SRC_DMSTOOLS_C 1
32
33///////////////
34// //
35// Headers //
36// //
37///////////////
38
39#ifdef HAVE_CONFIG_H
40#include <config.h>
41#endif
42
43#include <stdio.h>
44#include <string.h>
45#include <inttypes.h>
46#include <stdarg.h>
47#include <getopt.h>
48#include <arpa/inet.h>
49#include <sys/types.h>
50#include <sys/socket.h>
51#include <stdlib.h>
52#include <netdb.h>
53
54#include <bindle_prefix.h>
55
56
57///////////////////
58// //
59// Definitions //
60// //
61///////////////////
62
63#ifndef PROGRAM_NAME
64#define PROGRAM_NAME "urldesc"
65#endif
66#ifndef PACKAGE_BUGREPORT
67#define PACKAGE_BUGREPORT "david@syzdek.net"
68#endif
69#ifndef PACKAGE_COPYRIGHT
70#define PACKAGE_COPYRIGHT ""
71#endif
72#ifndef PACKAGE_NAME
73#define PACKAGE_NAME ""
74#endif
75#ifndef PACKAGE_VERSION
76#define PACKAGE_VERSION ""
77#endif
78
79#define MY_OPT_SCHEME 0x00000001UL
80#define MY_OPT_USERINFO 0x00000002UL
81#define MY_OPT_HOST 0x00000004UL
82#define MY_OPT_PORT 0x00000008UL
83#define MY_OPT_PATH 0x00000010UL
84#define MY_OPT_QUERY 0x00000020UL
85#define MY_OPT_FRAGMENT 0x00000040UL
86#define MY_OPT_ADDRESS 0x00000080UL
87#define MY_OPT_SERVICE 0x00000100UL
88#define MY_OPT_FIELDS 0x000001FFUL
89
90#define MY_OPT_VERBOSE 0x00010000UL
91#define MY_OPT_QUIET 0x00020000UL
92#define MY_OPT_NORESOLVE 0x00040000UL
93#define MY_OPT_SHORT 0x00080000UL
94#define MY_OPT_IPV4 0x00100000UL
95#define MY_OPT_IPV6 0x00200000UL
96
97
98/////////////////
99// //
100// Datatypes //
101// //
102/////////////////
103
104
105//////////////////
106// //
107// Prototypes //
108// //
109//////////////////
110
111int
112main(
113 int argc,
114 char * argv[] );
115
116
117static int
118my_error(
119 unsigned opts,
120 const char * fmt,
121 ... );
122
123
124static int
125my_parse_url(
126 unsigned opts,
127 const char * url );
128
129
130static void
131my_print_detail(
132 unsigned opts,
133 const char * url,
134 BindleURLDesc * budp );
135
136
137static void
138my_print_detail_field(
139 unsigned opts,
140 unsigned opt,
141 const char * fld,
142 const char * val );
143
144
145static void
146my_print_short(
147 unsigned opts,
148 BindleURLDesc * budp );
149
150
151static void
152my_print_url(
153 unsigned opts,
154 BindleURLDesc * budp );
155
156
157/////////////////
158// //
159// Functions //
160// //
161/////////////////
162
163int
164main(
165 int argc,
166 char * argv[] )
167{
168 int c;
169 int opt_index;
170 int opt;
171 int rc;
172 unsigned opts;
173
174 // getopt options
175 static char short_opt[] = "46hnVvqs";
176 static struct option long_opt[] =
177 {
178 {"debug", no_argument, NULL, 'd' },
179 {"help", no_argument, NULL, 'h' },
180 {"quiet", no_argument, NULL, 'q' },
181 {"silent", no_argument, NULL, 'q' },
182 {"short", no_argument, NULL, 's' },
183 {"version", no_argument, NULL, 'V' },
184 {"verbose", no_argument, NULL, 'v' },
185 {"scheme", no_argument, NULL, MY_OPT_SCHEME },
186 {"userinfo", no_argument, NULL, MY_OPT_USERINFO },
187 {"host", no_argument, NULL, MY_OPT_HOST },
188 {"service", no_argument, NULL, MY_OPT_SERVICE },
189 {"port", no_argument, NULL, MY_OPT_PORT },
190 {"path", no_argument, NULL, MY_OPT_PATH },
191 {"query", no_argument, NULL, MY_OPT_QUERY },
192 {"fragment", no_argument, NULL, MY_OPT_FRAGMENT },
193 {"address", no_argument, NULL, MY_OPT_ADDRESS },
194 { NULL, 0, NULL, 0 }
195 };
196
197 opts = 0;
198
199 while((c = getopt_long(argc, argv, short_opt, long_opt, &opt_index)) != -1)
200 {
201 switch(c)
202 {
203 case -1: /* no more arguments */
204 case 0: /* long options toggles */
205 break;
206
207 case MY_OPT_SCHEME:
208 case MY_OPT_USERINFO:
209 case MY_OPT_HOST:
210 case MY_OPT_PORT:
211 case MY_OPT_SERVICE:
212 case MY_OPT_PATH:
213 case MY_OPT_QUERY:
214 case MY_OPT_FRAGMENT:
215 case MY_OPT_ADDRESS:
216 opts |= c;
217 break;
218
219 case '4':
220 opts |= MY_OPT_IPV4;
221 opts &= ~MY_OPT_IPV6;
222 break;
223
224 case '6':
225 opts |= MY_OPT_IPV6;
226 opts &= ~MY_OPT_IPV4;
227 break;
228
229 case 'd':
230 opt = BNDL_DEBUG_ANY;
231 dmstools_set_option(NULL, BNDL_OPT_DEBUG_LEVEL, &opt);
232 break;
233
234 case 'h':
235 printf("Usage: %s [OPTIONS] url1 [ url2 [ ... [ urlN ] ] ]\n", PROGRAM_NAME);
236 printf("OPTIONS:\n");
237 printf(" -4 use IPv4 addresses only\n");
238 printf(" -6 use IPv6 addresses only\n");
239 printf(" -d, --debug print debug messages\n");
240 printf(" -h, --help print this help and exit\n");
241 printf(" -n do not resolve hostname\n");
242 printf(" -q, --quiet, --silent do not print messages\n");
243 printf(" -V, --version print version number and exit\n");
244 printf(" -v, --verbose print verbose messages\n");
245 printf(" --scheme print URL scheme\n");
246 printf(" --userinfo print URL user info\n");
247 printf(" --host print URL host\n");
248 printf(" --service print URL service\n");
249 printf(" --port print URL port\n");
250 printf(" --path print URL path\n");
251 printf(" --query print URL query\n");
252 printf(" --fragment print URL fragment\n");
253 printf(" --address print URL address\n");
254 printf("\n");
255 return(0);
256
257 case 'n':
258 opts |= MY_OPT_NORESOLVE;
259 break;
260
261 case 'q':
262 opts |= MY_OPT_QUIET;
263 opts &= ~MY_OPT_VERBOSE;
264 break;
265
266 case 's':
267 opts |= MY_OPT_SHORT;
268 break;
269
270 case 'V':
271 printf("%s (%s) %s\n", PACKAGE_NAME, PACKAGE_NAME, PACKAGE_VERSION);
272 return(0);
273
274 case 'v':
275 opts |= MY_OPT_VERBOSE;
276 opts &= ~MY_OPT_QUIET;
277 break;
278
279 case '?':
280 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
281 return(1);
282
283 default:
284 fprintf(stderr, "%s: unrecognized option `--%c'\n", PROGRAM_NAME, c);
285 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
286 return(1);
287 };
288 };
289 if (optind == argc)
290 {
291 fprintf(stderr, "%s: missing required argument\n", PROGRAM_NAME);
292 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
293 return(1);
294 };
295
296 // loop through URLs
297 while (optind < argc)
298 {
299 if ((rc = my_parse_url(opts, argv[optind])) != 0)
300 return(rc);
301 optind++;
302 };
303
304 return(0);
305}
306
307
308int
309my_error(
310 unsigned opts,
311 const char * fmt,
312 ... )
313{
314 va_list args;
315 if ((opts & MY_OPT_QUIET))
316 return(1);
317 fprintf(stderr, "%s: ", PROGRAM_NAME);
318 va_start(args, fmt);
319 vfprintf(stderr, fmt, args);
320 va_end(args);
321 fprintf(stderr, "\n");
322 return(1);
323}
324
325
326int
327my_parse_url(
328 unsigned opts,
329 const char * url )
330{
331 int rc;
332 int family;
333 BindleURLDesc * budp;
334
335 if ((rc = dmstools_urldesc_parse(url, &budp)) != 0)
336 {
337 my_error(opts, "dmstools_urldesc_parse(): %s", strerror(rc));
338 return(1);
339 };
340
341 if (!(opts & MY_OPT_NORESOLVE))
342 {
343 family = ((opts & MY_OPT_IPV4)) ? AF_INET : 0;
344 family = ((opts & MY_OPT_IPV6)) ? AF_INET6 : family;
345 if ((rc = dmstools_urldesc_resolve(budp, family)) != 0)
346 {
347 my_error(opts, "dmstools_urldesc_resolve(): %s", gai_strerror(rc));
348 dmstools_urldesc_free(budp);
349 return(2);
350 };
351 };
352
353 if ((opts & MY_OPT_QUIET))
354 {
355 dmstools_urldesc_free(budp);
356 return(0);
357 };
358
359 if ((opts & MY_OPT_SHORT))
360 {
361 my_print_short(opts, budp);
362 } else if ((opts & MY_OPT_VERBOSE))
363 {
364 if (!(opts & MY_OPT_FIELDS))
365 opts |= MY_OPT_FIELDS;
366 my_print_detail(opts, url, budp);
367 } else
368 {
369 if (!(opts & MY_OPT_FIELDS))
370 opts |= MY_OPT_FIELDS;
371 my_print_url(opts, budp);
372 };
373
374 dmstools_urldesc_free(budp);
375
376 return(0);
377}
378
379
380void
381my_print_detail(
382 unsigned opts,
383 const char * url,
384 BindleURLDesc * budp )
385{
386 int pos;
387 char buff[INET6_ADDRSTRLEN+INET_ADDRSTRLEN];
388 struct sockaddr ** sas;
389 struct sockaddr_in sa;
390 struct sockaddr_in6 sa6;
391
392 printf("%s\n", url);
393 my_print_detail_field(opts, MY_OPT_SCHEME, "Scheme:", budp->bud_scheme);
394 my_print_detail_field(opts, MY_OPT_USERINFO, "User Info:", budp->bud_userinfo);
395 my_print_detail_field(opts, MY_OPT_HOST, "Host:", budp->bud_host);
396 if ((budp->bud_sockaddrs))
397 {
398 sas = (struct sockaddr **)budp->bud_sockaddrs;
399 for(pos = 0; ((sas[pos])); pos++)
400 {
401 if (sas[pos]->sa_family == AF_INET)
402 {
403 memcpy(&sa, sas[pos], sizeof(sa));
404 inet_ntop(AF_INET, &sa.sin_addr, buff, sizeof(buff));
405 } else {
406 memcpy(&sa6, sas[pos], sizeof(sa6));
407 inet_ntop(AF_INET6, &sa6.sin6_addr, buff, sizeof(buff));
408 };
409 my_print_detail_field(opts, MY_OPT_ADDRESS, ((!(pos)) ? "Address:" : ""), buff);
410 };
411 };
412 if ((budp->bud_port))
413 {
414 snprintf(buff, sizeof(buff), "%u", (unsigned)budp->bud_port);
415 my_print_detail_field(opts, MY_OPT_PORT, "Port:", buff);
416 };
417 my_print_detail_field(opts, MY_OPT_SERVICE, "Service:", budp->bud_service);
418 my_print_detail_field(opts, MY_OPT_PATH, "Path:", budp->bud_path);
419 my_print_detail_field(opts, MY_OPT_QUERY, "Query:", budp->bud_query);
420 my_print_detail_field(opts, MY_OPT_FRAGMENT, "Fragment:", budp->bud_fragment);
421 printf("\n");
422
423 return;
424}
425
426
427void
428my_print_detail_field(
429 unsigned opts,
430 unsigned opt,
431 const char * fld,
432 const char * val )
433{
434 if (!(opts & opt))
435 return;
436 if (!(val))
437 return;
438 printf(" %-15s %s\n", fld, val);
439 return;
440}
441
442
443void
444my_print_short(
445 unsigned opts,
446 BindleURLDesc * budp )
447{
448 int family;
449 int pos;
450 char addr[INET6_ADDRSTRLEN+INET_ADDRSTRLEN];
451 struct sockaddr ** sas;
452 struct sockaddr_in sa;
453 struct sockaddr_in6 sa6;
454
455 if ( ((opts & MY_OPT_SCHEME)) && ((budp->bud_scheme)) ) printf("%s\n", budp->bud_scheme);
456 if ( ((opts & MY_OPT_USERINFO)) && ((budp->bud_userinfo)) ) printf("%s\n", budp->bud_userinfo);
457 if ( ((opts & MY_OPT_HOST)) && ((budp->bud_host)) ) printf("%s\n", budp->bud_host);
458 if ( ((opts & MY_OPT_SERVICE)) && ((budp->bud_service)) ) printf("%s\n", budp->bud_service);
459 if ( ((opts & MY_OPT_PATH)) && ((budp->bud_path)) ) printf("%s\n", budp->bud_path);
460 if ( ((opts & MY_OPT_QUERY)) && ((budp->bud_query)) ) printf("%s\n", budp->bud_query);
461 if ( ((opts & MY_OPT_FRAGMENT)) && ((budp->bud_fragment)) ) printf("%s\n", budp->bud_fragment);
462
463 if ( ((opts & MY_OPT_PORT)) && ((budp->bud_port)) )
464 printf("%u\n", (unsigned)budp->bud_port);
465
466 if (!(opts & MY_OPT_ADDRESS))
467 return;
468 if (!(budp->bud_sockaddrs))
469 return;
470
471 family = ((opts & MY_OPT_IPV4)) ? AF_INET : AF_UNSPEC;
472 family = ((opts & MY_OPT_IPV6)) ? AF_INET6 : family;
473 sas = (struct sockaddr **)budp->bud_sockaddrs;
474
475 for(pos = 0; ((sas[pos])); pos++)
476 {
477 if ((sas[pos]->sa_family == AF_INET6) && ((family == AF_INET6)||(family == AF_UNSPEC)))
478 {
479 memcpy(&sa6, sas[pos], sizeof(sa6));
480 inet_ntop(AF_INET6, &sa6.sin6_addr, addr, sizeof(addr));
481 printf("%s\n", addr);
482 return;
483 };
484 };
485 for(pos = 0; ((sas[pos])); pos++)
486 {
487 if ((sas[pos]->sa_family == AF_INET) && ((family == AF_INET)||(family == AF_UNSPEC)))
488 {
489 memcpy(&sa, sas[pos], sizeof(sa));
490 inet_ntop(AF_INET, &sa.sin_addr, addr, sizeof(addr));
491 printf("%s\n", addr);
492 return;
493 };
494 };
495
496 return;
497}
498
499
500void
501my_print_url(
502 unsigned opts,
503 BindleURLDesc * budp )
504{
505 BindleURLDesc bud;
506 char port[16];
507 int family;
508 int pos;
509 char addr[INET6_ADDRSTRLEN+INET_ADDRSTRLEN];
510 struct sockaddr ** sas;
511 struct sockaddr_in sa;
512 struct sockaddr_in6 sa6;
513 char * url;
514
515 memset(&bud, 0, sizeof(bud));
516
517 if ( ((opts & MY_OPT_PORT)) && ((budp->bud_port)) )
518 {
519 snprintf(port, sizeof(port), "%u", (unsigned)budp->bud_port);
520 bud.bud_service = port;
521 };
522
523 if ( ((opts & MY_OPT_ADDRESS)) && ((budp->bud_sockaddrs)) )
524 {
525 family = ((opts & MY_OPT_IPV4)) ? AF_INET : AF_UNSPEC;
526 family = ((opts & MY_OPT_IPV6)) ? AF_INET6 : family;
527 sas = (struct sockaddr **)budp->bud_sockaddrs;
528 for(pos = 0; ((sas[pos])); pos++)
529 {
530 if ((sas[pos]->sa_family == AF_INET6) && ((family == AF_INET6)||(family == AF_UNSPEC)))
531 {
532 family = AF_INET6;
533 memcpy(&sa6, sas[pos], sizeof(sa6));
534 inet_ntop(AF_INET6, &sa6.sin6_addr, addr, sizeof(addr));
535 };
536 if ((sas[pos]->sa_family == AF_INET) && ((family == AF_INET)||(family == AF_UNSPEC)))
537 {
538 memcpy(&sa, sas[pos], sizeof(sa));
539 inet_ntop(AF_INET, &sa.sin_addr, addr, sizeof(addr));
540 };
541 bud.bud_host = addr;
542 };
543 };
544
545 if ((opts & MY_OPT_SCHEME)) bud.bud_scheme = budp->bud_scheme;
546 if ((opts & MY_OPT_USERINFO)) bud.bud_userinfo = budp->bud_userinfo;
547 if ((opts & MY_OPT_HOST)) bud.bud_host = budp->bud_host;
548 if ((opts & MY_OPT_SERVICE)) bud.bud_service = budp->bud_service;
549 if ((opts & MY_OPT_PATH)) bud.bud_path = budp->bud_path;
550 if ((opts & MY_OPT_QUERY)) bud.bud_query = budp->bud_query;
551 if ((opts & MY_OPT_FRAGMENT)) bud.bud_fragment = budp->bud_fragment;
552
553 if ((url = dmstools_urldesc2str(&bud)) == NULL)
554 {
555 my_error(opts, "out of virtual memory");
556 return;
557 };
558 printf("%s\n", url);
559 free(url);
560
561 return;
562}
563
564
565// end of source file