1*a3cefe7fSPierre Pronchery /*
2*a3cefe7fSPierre Pronchery * bomtool/main.c
3*a3cefe7fSPierre Pronchery * main() routine, printer functions
4*a3cefe7fSPierre Pronchery *
5*a3cefe7fSPierre Pronchery * Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
6*a3cefe7fSPierre Pronchery * pkgconf authors (see AUTHORS).
7*a3cefe7fSPierre Pronchery *
8*a3cefe7fSPierre Pronchery * Permission to use, copy, modify, and/or distribute this software for any
9*a3cefe7fSPierre Pronchery * purpose with or without fee is hereby granted, provided that the above
10*a3cefe7fSPierre Pronchery * copyright notice and this permission notice appear in all copies.
11*a3cefe7fSPierre Pronchery *
12*a3cefe7fSPierre Pronchery * This software is provided 'as is' and without any warranty, express or
13*a3cefe7fSPierre Pronchery * implied. In no event shall the authors be liable for any damages arising
14*a3cefe7fSPierre Pronchery * from the use of this software.
15*a3cefe7fSPierre Pronchery */
16*a3cefe7fSPierre Pronchery
17*a3cefe7fSPierre Pronchery #include "libpkgconf/config.h"
18*a3cefe7fSPierre Pronchery #include <libpkgconf/stdinc.h>
19*a3cefe7fSPierre Pronchery #include <libpkgconf/libpkgconf.h>
20*a3cefe7fSPierre Pronchery #include "getopt_long.h"
21*a3cefe7fSPierre Pronchery
22*a3cefe7fSPierre Pronchery #define PKG_VERSION (((uint64_t) 1) << 1)
23*a3cefe7fSPierre Pronchery #define PKG_ABOUT (((uint64_t) 1) << 2)
24*a3cefe7fSPierre Pronchery #define PKG_HELP (((uint64_t) 1) << 3)
25*a3cefe7fSPierre Pronchery
26*a3cefe7fSPierre Pronchery static const char *spdx_version = "SPDX-2.2";
27*a3cefe7fSPierre Pronchery static const char *bom_license = "CC0-1.0";
28*a3cefe7fSPierre Pronchery static const char *document_ref = "SPDXRef-DOCUMENT";
29*a3cefe7fSPierre Pronchery
30*a3cefe7fSPierre Pronchery static pkgconf_client_t pkg_client;
31*a3cefe7fSPierre Pronchery static uint64_t want_flags;
32*a3cefe7fSPierre Pronchery static size_t maximum_package_count = 0;
33*a3cefe7fSPierre Pronchery static int maximum_traverse_depth = 2000;
34*a3cefe7fSPierre Pronchery FILE *error_msgout = NULL;
35*a3cefe7fSPierre Pronchery
36*a3cefe7fSPierre Pronchery static bool
error_handler(const char * msg,const pkgconf_client_t * client,void * data)37*a3cefe7fSPierre Pronchery error_handler(const char *msg, const pkgconf_client_t *client, void *data)
38*a3cefe7fSPierre Pronchery {
39*a3cefe7fSPierre Pronchery (void) client;
40*a3cefe7fSPierre Pronchery (void) data;
41*a3cefe7fSPierre Pronchery fprintf(error_msgout, "%s", msg);
42*a3cefe7fSPierre Pronchery return true;
43*a3cefe7fSPierre Pronchery }
44*a3cefe7fSPierre Pronchery
45*a3cefe7fSPierre Pronchery static const char *
sbom_spdx_identity(pkgconf_pkg_t * pkg)46*a3cefe7fSPierre Pronchery sbom_spdx_identity(pkgconf_pkg_t *pkg)
47*a3cefe7fSPierre Pronchery {
48*a3cefe7fSPierre Pronchery static char buf[PKGCONF_ITEM_SIZE];
49*a3cefe7fSPierre Pronchery
50*a3cefe7fSPierre Pronchery snprintf(buf, sizeof buf, "%sC64%s", pkg->id, pkg->version);
51*a3cefe7fSPierre Pronchery
52*a3cefe7fSPierre Pronchery return buf;
53*a3cefe7fSPierre Pronchery }
54*a3cefe7fSPierre Pronchery
55*a3cefe7fSPierre Pronchery static const char *
sbom_name(pkgconf_pkg_t * world)56*a3cefe7fSPierre Pronchery sbom_name(pkgconf_pkg_t *world)
57*a3cefe7fSPierre Pronchery {
58*a3cefe7fSPierre Pronchery static char buf[PKGCONF_BUFSIZE];
59*a3cefe7fSPierre Pronchery pkgconf_node_t *node;
60*a3cefe7fSPierre Pronchery
61*a3cefe7fSPierre Pronchery pkgconf_strlcpy(buf, "SBOM-SPDX", sizeof buf);
62*a3cefe7fSPierre Pronchery
63*a3cefe7fSPierre Pronchery PKGCONF_FOREACH_LIST_ENTRY(world->required.head, node)
64*a3cefe7fSPierre Pronchery {
65*a3cefe7fSPierre Pronchery pkgconf_dependency_t *dep = node->data;
66*a3cefe7fSPierre Pronchery pkgconf_pkg_t *match = dep->match;
67*a3cefe7fSPierre Pronchery
68*a3cefe7fSPierre Pronchery if ((dep->flags & PKGCONF_PKG_DEPF_QUERY) != PKGCONF_PKG_DEPF_QUERY)
69*a3cefe7fSPierre Pronchery continue;
70*a3cefe7fSPierre Pronchery
71*a3cefe7fSPierre Pronchery if (!dep->match)
72*a3cefe7fSPierre Pronchery continue;
73*a3cefe7fSPierre Pronchery
74*a3cefe7fSPierre Pronchery pkgconf_strlcat(buf, "-", sizeof buf);
75*a3cefe7fSPierre Pronchery pkgconf_strlcat(buf, sbom_spdx_identity(match), sizeof buf);
76*a3cefe7fSPierre Pronchery }
77*a3cefe7fSPierre Pronchery
78*a3cefe7fSPierre Pronchery return buf;
79*a3cefe7fSPierre Pronchery }
80*a3cefe7fSPierre Pronchery
81*a3cefe7fSPierre Pronchery static void
write_sbom_header(pkgconf_client_t * client,pkgconf_pkg_t * world)82*a3cefe7fSPierre Pronchery write_sbom_header(pkgconf_client_t *client, pkgconf_pkg_t *world)
83*a3cefe7fSPierre Pronchery {
84*a3cefe7fSPierre Pronchery (void) client;
85*a3cefe7fSPierre Pronchery (void) world;
86*a3cefe7fSPierre Pronchery
87*a3cefe7fSPierre Pronchery printf("SPDXVersion: %s\n", spdx_version);
88*a3cefe7fSPierre Pronchery printf("DataLicense: %s\n", bom_license);
89*a3cefe7fSPierre Pronchery printf("SPDXID: %s\n", document_ref);
90*a3cefe7fSPierre Pronchery printf("DocumentName: %s\n", sbom_name(world));
91*a3cefe7fSPierre Pronchery printf("DocumentNamespace: https://spdx.org/spdxdocs/bomtool-%s\n", PACKAGE_VERSION);
92*a3cefe7fSPierre Pronchery printf("Creator: Tool: bomtool %s\n", PACKAGE_VERSION);
93*a3cefe7fSPierre Pronchery
94*a3cefe7fSPierre Pronchery printf("\n\n");
95*a3cefe7fSPierre Pronchery }
96*a3cefe7fSPierre Pronchery
97*a3cefe7fSPierre Pronchery static const char *
sbom_identity(pkgconf_pkg_t * pkg)98*a3cefe7fSPierre Pronchery sbom_identity(pkgconf_pkg_t *pkg)
99*a3cefe7fSPierre Pronchery {
100*a3cefe7fSPierre Pronchery static char buf[PKGCONF_ITEM_SIZE];
101*a3cefe7fSPierre Pronchery
102*a3cefe7fSPierre Pronchery snprintf(buf, sizeof buf, "%s@%s", pkg->id, pkg->version);
103*a3cefe7fSPierre Pronchery
104*a3cefe7fSPierre Pronchery return buf;
105*a3cefe7fSPierre Pronchery }
106*a3cefe7fSPierre Pronchery
107*a3cefe7fSPierre Pronchery static void
write_sbom_package(pkgconf_client_t * client,pkgconf_pkg_t * pkg,void * unused)108*a3cefe7fSPierre Pronchery write_sbom_package(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *unused)
109*a3cefe7fSPierre Pronchery {
110*a3cefe7fSPierre Pronchery (void) client;
111*a3cefe7fSPierre Pronchery (void) unused;
112*a3cefe7fSPierre Pronchery
113*a3cefe7fSPierre Pronchery if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL)
114*a3cefe7fSPierre Pronchery return;
115*a3cefe7fSPierre Pronchery
116*a3cefe7fSPierre Pronchery printf("##### Package: %s\n\n", sbom_identity(pkg));
117*a3cefe7fSPierre Pronchery
118*a3cefe7fSPierre Pronchery printf("PackageName: %s\n", sbom_identity(pkg));
119*a3cefe7fSPierre Pronchery printf("SPDXID: SPDXRef-Package-%s\n", sbom_spdx_identity(pkg));
120*a3cefe7fSPierre Pronchery printf("PackageVersion: %s\n", pkg->version);
121*a3cefe7fSPierre Pronchery printf("PackageDownloadLocation: NOASSERTION\n");
122*a3cefe7fSPierre Pronchery printf("PackageVerificationCode: NOASSERTION\n");
123*a3cefe7fSPierre Pronchery
124*a3cefe7fSPierre Pronchery /* XXX: What about projects? */
125*a3cefe7fSPierre Pronchery if (pkg->maintainer != NULL)
126*a3cefe7fSPierre Pronchery printf("PackageSupplier: Person: %s\n", pkg->maintainer);
127*a3cefe7fSPierre Pronchery
128*a3cefe7fSPierre Pronchery if (pkg->url != NULL)
129*a3cefe7fSPierre Pronchery printf("PackageHomePage: %s\n", pkg->url);
130*a3cefe7fSPierre Pronchery
131*a3cefe7fSPierre Pronchery printf("PackageLicenseDeclared: %s\n", pkg->license != NULL ? pkg->license : "NOASSERTION");
132*a3cefe7fSPierre Pronchery
133*a3cefe7fSPierre Pronchery if (pkg->copyright != NULL)
134*a3cefe7fSPierre Pronchery printf("PackageCopyrightText: <text>%s</text>\n", pkg->copyright);
135*a3cefe7fSPierre Pronchery
136*a3cefe7fSPierre Pronchery if (pkg->description != NULL)
137*a3cefe7fSPierre Pronchery printf("PackageSummary: <text>%s</text>\n", pkg->description);
138*a3cefe7fSPierre Pronchery
139*a3cefe7fSPierre Pronchery printf("\n\n");
140*a3cefe7fSPierre Pronchery }
141*a3cefe7fSPierre Pronchery
142*a3cefe7fSPierre Pronchery static void
write_sbom_relationships(pkgconf_client_t * client,pkgconf_pkg_t * pkg,void * unused)143*a3cefe7fSPierre Pronchery write_sbom_relationships(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *unused)
144*a3cefe7fSPierre Pronchery {
145*a3cefe7fSPierre Pronchery (void) client;
146*a3cefe7fSPierre Pronchery (void) unused;
147*a3cefe7fSPierre Pronchery
148*a3cefe7fSPierre Pronchery char baseref[PKGCONF_ITEM_SIZE];
149*a3cefe7fSPierre Pronchery pkgconf_node_t *node;
150*a3cefe7fSPierre Pronchery
151*a3cefe7fSPierre Pronchery if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL)
152*a3cefe7fSPierre Pronchery return;
153*a3cefe7fSPierre Pronchery
154*a3cefe7fSPierre Pronchery snprintf(baseref, sizeof baseref, "SPDXRef-Package-%sC64%s", pkg->id, pkg->version);
155*a3cefe7fSPierre Pronchery
156*a3cefe7fSPierre Pronchery PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node)
157*a3cefe7fSPierre Pronchery {
158*a3cefe7fSPierre Pronchery pkgconf_dependency_t *dep = node->data;
159*a3cefe7fSPierre Pronchery pkgconf_pkg_t *match = dep->match;
160*a3cefe7fSPierre Pronchery
161*a3cefe7fSPierre Pronchery if (!dep->match)
162*a3cefe7fSPierre Pronchery continue;
163*a3cefe7fSPierre Pronchery
164*a3cefe7fSPierre Pronchery printf("Relationship: %s DEPENDS_ON SPDXRef-Package-%s\n", baseref, sbom_spdx_identity(match));
165*a3cefe7fSPierre Pronchery printf("Relationship: SPDXRef-Package-%s DEPENDENCY_OF %s\n", sbom_spdx_identity(match), baseref);
166*a3cefe7fSPierre Pronchery }
167*a3cefe7fSPierre Pronchery
168*a3cefe7fSPierre Pronchery PKGCONF_FOREACH_LIST_ENTRY(pkg->requires_private.head, node)
169*a3cefe7fSPierre Pronchery {
170*a3cefe7fSPierre Pronchery pkgconf_dependency_t *dep = node->data;
171*a3cefe7fSPierre Pronchery pkgconf_pkg_t *match = dep->match;
172*a3cefe7fSPierre Pronchery
173*a3cefe7fSPierre Pronchery if (!dep->match)
174*a3cefe7fSPierre Pronchery continue;
175*a3cefe7fSPierre Pronchery
176*a3cefe7fSPierre Pronchery printf("Relationship: %s DEPENDS_ON SPDXRef-Package-%s\n", baseref, sbom_spdx_identity(match));
177*a3cefe7fSPierre Pronchery printf("Relationship: SPDXRef-Package-%s DEV_DEPENDENCY_OF %s\n", sbom_spdx_identity(match), baseref);
178*a3cefe7fSPierre Pronchery }
179*a3cefe7fSPierre Pronchery
180*a3cefe7fSPierre Pronchery if (pkg->required.head != NULL || pkg->requires_private.head != NULL)
181*a3cefe7fSPierre Pronchery printf("\n\n");
182*a3cefe7fSPierre Pronchery }
183*a3cefe7fSPierre Pronchery
184*a3cefe7fSPierre Pronchery static bool
generate_sbom_from_world(pkgconf_client_t * client,pkgconf_pkg_t * world)185*a3cefe7fSPierre Pronchery generate_sbom_from_world(pkgconf_client_t *client, pkgconf_pkg_t *world)
186*a3cefe7fSPierre Pronchery {
187*a3cefe7fSPierre Pronchery int eflag;
188*a3cefe7fSPierre Pronchery pkgconf_node_t *node;
189*a3cefe7fSPierre Pronchery
190*a3cefe7fSPierre Pronchery write_sbom_header(client, world);
191*a3cefe7fSPierre Pronchery
192*a3cefe7fSPierre Pronchery eflag = pkgconf_pkg_traverse(client, world, write_sbom_package, NULL, maximum_traverse_depth, 0);
193*a3cefe7fSPierre Pronchery if (eflag != PKGCONF_PKG_ERRF_OK)
194*a3cefe7fSPierre Pronchery return false;
195*a3cefe7fSPierre Pronchery
196*a3cefe7fSPierre Pronchery eflag = pkgconf_pkg_traverse(client, world, write_sbom_relationships, NULL, maximum_traverse_depth, 0);
197*a3cefe7fSPierre Pronchery if (eflag != PKGCONF_PKG_ERRF_OK)
198*a3cefe7fSPierre Pronchery return false;
199*a3cefe7fSPierre Pronchery
200*a3cefe7fSPierre Pronchery PKGCONF_FOREACH_LIST_ENTRY(world->required.head, node)
201*a3cefe7fSPierre Pronchery {
202*a3cefe7fSPierre Pronchery pkgconf_dependency_t *dep = node->data;
203*a3cefe7fSPierre Pronchery pkgconf_pkg_t *match = dep->match;
204*a3cefe7fSPierre Pronchery
205*a3cefe7fSPierre Pronchery if (!dep->match)
206*a3cefe7fSPierre Pronchery continue;
207*a3cefe7fSPierre Pronchery
208*a3cefe7fSPierre Pronchery printf("Relationship: %s DESCRIBES SPDXRef-Package-%s\n", document_ref, sbom_spdx_identity(match));
209*a3cefe7fSPierre Pronchery }
210*a3cefe7fSPierre Pronchery
211*a3cefe7fSPierre Pronchery return true;
212*a3cefe7fSPierre Pronchery }
213*a3cefe7fSPierre Pronchery
214*a3cefe7fSPierre Pronchery static int
version(void)215*a3cefe7fSPierre Pronchery version(void)
216*a3cefe7fSPierre Pronchery {
217*a3cefe7fSPierre Pronchery printf("bomtool %s\n", PACKAGE_VERSION);
218*a3cefe7fSPierre Pronchery return EXIT_SUCCESS;
219*a3cefe7fSPierre Pronchery }
220*a3cefe7fSPierre Pronchery
221*a3cefe7fSPierre Pronchery static int
about(void)222*a3cefe7fSPierre Pronchery about(void)
223*a3cefe7fSPierre Pronchery {
224*a3cefe7fSPierre Pronchery printf("bomtool (%s %s)\n", PACKAGE_NAME, PACKAGE_VERSION);
225*a3cefe7fSPierre Pronchery printf("Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021\n");
226*a3cefe7fSPierre Pronchery printf(" pkgconf authors (see AUTHORS in documentation directory).\n\n");
227*a3cefe7fSPierre Pronchery printf("Permission to use, copy, modify, and/or distribute this software for any\n");
228*a3cefe7fSPierre Pronchery printf("purpose with or without fee is hereby granted, provided that the above\n");
229*a3cefe7fSPierre Pronchery printf("copyright notice and this permission notice appear in all copies.\n\n");
230*a3cefe7fSPierre Pronchery printf("This software is provided 'as is' and without any warranty, express or\n");
231*a3cefe7fSPierre Pronchery printf("implied. In no event shall the authors be liable for any damages arising\n");
232*a3cefe7fSPierre Pronchery printf("from the use of this software.\n\n");
233*a3cefe7fSPierre Pronchery printf("Report bugs at <%s>.\n", PACKAGE_BUGREPORT);
234*a3cefe7fSPierre Pronchery return EXIT_SUCCESS;
235*a3cefe7fSPierre Pronchery }
236*a3cefe7fSPierre Pronchery
237*a3cefe7fSPierre Pronchery static int
usage(void)238*a3cefe7fSPierre Pronchery usage(void)
239*a3cefe7fSPierre Pronchery {
240*a3cefe7fSPierre Pronchery printf("usage: bomtool [--flags] [modules]\n");
241*a3cefe7fSPierre Pronchery
242*a3cefe7fSPierre Pronchery printf("\nbasic options:\n\n");
243*a3cefe7fSPierre Pronchery
244*a3cefe7fSPierre Pronchery printf(" --help this message\n");
245*a3cefe7fSPierre Pronchery printf(" --about print bomtool version and license to stdout\n");
246*a3cefe7fSPierre Pronchery printf(" --version print bomtool version to stdout\n");
247*a3cefe7fSPierre Pronchery
248*a3cefe7fSPierre Pronchery return EXIT_SUCCESS;
249*a3cefe7fSPierre Pronchery }
250*a3cefe7fSPierre Pronchery
251*a3cefe7fSPierre Pronchery int
main(int argc,char * argv[])252*a3cefe7fSPierre Pronchery main(int argc, char *argv[])
253*a3cefe7fSPierre Pronchery {
254*a3cefe7fSPierre Pronchery int ret = EXIT_SUCCESS;
255*a3cefe7fSPierre Pronchery pkgconf_list_t pkgq = PKGCONF_LIST_INITIALIZER;
256*a3cefe7fSPierre Pronchery unsigned int want_client_flags = PKGCONF_PKG_PKGF_SEARCH_PRIVATE;
257*a3cefe7fSPierre Pronchery pkgconf_cross_personality_t *personality = pkgconf_cross_personality_default();
258*a3cefe7fSPierre Pronchery pkgconf_pkg_t world = {
259*a3cefe7fSPierre Pronchery .id = "virtual:world",
260*a3cefe7fSPierre Pronchery .realname = "virtual world package",
261*a3cefe7fSPierre Pronchery .flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
262*a3cefe7fSPierre Pronchery };
263*a3cefe7fSPierre Pronchery
264*a3cefe7fSPierre Pronchery error_msgout = stderr;
265*a3cefe7fSPierre Pronchery
266*a3cefe7fSPierre Pronchery struct pkg_option options[] = {
267*a3cefe7fSPierre Pronchery { "version", no_argument, &want_flags, PKG_VERSION, },
268*a3cefe7fSPierre Pronchery { "about", no_argument, &want_flags, PKG_ABOUT, },
269*a3cefe7fSPierre Pronchery { "help", no_argument, &want_flags, PKG_HELP, },
270*a3cefe7fSPierre Pronchery { NULL, 0, NULL, 0 }
271*a3cefe7fSPierre Pronchery };
272*a3cefe7fSPierre Pronchery
273*a3cefe7fSPierre Pronchery while ((ret = pkg_getopt_long_only(argc, argv, "", options, NULL)) != -1)
274*a3cefe7fSPierre Pronchery {
275*a3cefe7fSPierre Pronchery switch (ret)
276*a3cefe7fSPierre Pronchery {
277*a3cefe7fSPierre Pronchery case '?':
278*a3cefe7fSPierre Pronchery case ':':
279*a3cefe7fSPierre Pronchery return EXIT_FAILURE;
280*a3cefe7fSPierre Pronchery default:
281*a3cefe7fSPierre Pronchery break;
282*a3cefe7fSPierre Pronchery }
283*a3cefe7fSPierre Pronchery }
284*a3cefe7fSPierre Pronchery
285*a3cefe7fSPierre Pronchery pkgconf_client_init(&pkg_client, error_handler, NULL, personality);
286*a3cefe7fSPierre Pronchery
287*a3cefe7fSPierre Pronchery /* we have determined what features we want most likely. in some cases, we override later. */
288*a3cefe7fSPierre Pronchery pkgconf_client_set_flags(&pkg_client, want_client_flags);
289*a3cefe7fSPierre Pronchery
290*a3cefe7fSPierre Pronchery /* at this point, want_client_flags should be set, so build the dir list */
291*a3cefe7fSPierre Pronchery pkgconf_client_dir_list_build(&pkg_client, personality);
292*a3cefe7fSPierre Pronchery
293*a3cefe7fSPierre Pronchery if ((want_flags & PKG_ABOUT) == PKG_ABOUT)
294*a3cefe7fSPierre Pronchery return about();
295*a3cefe7fSPierre Pronchery
296*a3cefe7fSPierre Pronchery if ((want_flags & PKG_VERSION) == PKG_VERSION)
297*a3cefe7fSPierre Pronchery return version();
298*a3cefe7fSPierre Pronchery
299*a3cefe7fSPierre Pronchery if ((want_flags & PKG_HELP) == PKG_HELP)
300*a3cefe7fSPierre Pronchery return usage();
301*a3cefe7fSPierre Pronchery
302*a3cefe7fSPierre Pronchery while (1)
303*a3cefe7fSPierre Pronchery {
304*a3cefe7fSPierre Pronchery const char *package = argv[pkg_optind];
305*a3cefe7fSPierre Pronchery
306*a3cefe7fSPierre Pronchery if (package == NULL)
307*a3cefe7fSPierre Pronchery break;
308*a3cefe7fSPierre Pronchery
309*a3cefe7fSPierre Pronchery /* check if there is a limit to the number of packages allowed to be included, if so and we have hit
310*a3cefe7fSPierre Pronchery * the limit, stop adding packages to the queue.
311*a3cefe7fSPierre Pronchery */
312*a3cefe7fSPierre Pronchery if (maximum_package_count > 0 && pkgq.length > maximum_package_count)
313*a3cefe7fSPierre Pronchery break;
314*a3cefe7fSPierre Pronchery
315*a3cefe7fSPierre Pronchery while (isspace((unsigned char)package[0]))
316*a3cefe7fSPierre Pronchery package++;
317*a3cefe7fSPierre Pronchery
318*a3cefe7fSPierre Pronchery /* skip empty packages */
319*a3cefe7fSPierre Pronchery if (package[0] == '\0') {
320*a3cefe7fSPierre Pronchery pkg_optind++;
321*a3cefe7fSPierre Pronchery continue;
322*a3cefe7fSPierre Pronchery }
323*a3cefe7fSPierre Pronchery
324*a3cefe7fSPierre Pronchery if (argv[pkg_optind + 1] == NULL || !PKGCONF_IS_OPERATOR_CHAR(*(argv[pkg_optind + 1])))
325*a3cefe7fSPierre Pronchery {
326*a3cefe7fSPierre Pronchery pkgconf_queue_push(&pkgq, package);
327*a3cefe7fSPierre Pronchery pkg_optind++;
328*a3cefe7fSPierre Pronchery }
329*a3cefe7fSPierre Pronchery else
330*a3cefe7fSPierre Pronchery {
331*a3cefe7fSPierre Pronchery char packagebuf[PKGCONF_BUFSIZE];
332*a3cefe7fSPierre Pronchery
333*a3cefe7fSPierre Pronchery snprintf(packagebuf, sizeof packagebuf, "%s %s %s", package, argv[pkg_optind + 1], argv[pkg_optind + 2]);
334*a3cefe7fSPierre Pronchery pkg_optind += 3;
335*a3cefe7fSPierre Pronchery
336*a3cefe7fSPierre Pronchery pkgconf_queue_push(&pkgq, packagebuf);
337*a3cefe7fSPierre Pronchery }
338*a3cefe7fSPierre Pronchery }
339*a3cefe7fSPierre Pronchery
340*a3cefe7fSPierre Pronchery if (pkgq.head == NULL)
341*a3cefe7fSPierre Pronchery {
342*a3cefe7fSPierre Pronchery fprintf(stderr, "Please specify at least one package name on the command line.\n");
343*a3cefe7fSPierre Pronchery ret = EXIT_FAILURE;
344*a3cefe7fSPierre Pronchery goto out;
345*a3cefe7fSPierre Pronchery }
346*a3cefe7fSPierre Pronchery
347*a3cefe7fSPierre Pronchery ret = EXIT_SUCCESS;
348*a3cefe7fSPierre Pronchery
349*a3cefe7fSPierre Pronchery if (!pkgconf_queue_solve(&pkg_client, &pkgq, &world, maximum_traverse_depth))
350*a3cefe7fSPierre Pronchery {
351*a3cefe7fSPierre Pronchery ret = EXIT_FAILURE;
352*a3cefe7fSPierre Pronchery goto out;
353*a3cefe7fSPierre Pronchery }
354*a3cefe7fSPierre Pronchery
355*a3cefe7fSPierre Pronchery if (!generate_sbom_from_world(&pkg_client, &world))
356*a3cefe7fSPierre Pronchery {
357*a3cefe7fSPierre Pronchery ret = EXIT_FAILURE;
358*a3cefe7fSPierre Pronchery goto out;
359*a3cefe7fSPierre Pronchery }
360*a3cefe7fSPierre Pronchery
361*a3cefe7fSPierre Pronchery out:
362*a3cefe7fSPierre Pronchery pkgconf_solution_free(&pkg_client, &world);
363*a3cefe7fSPierre Pronchery pkgconf_queue_free(&pkgq);
364*a3cefe7fSPierre Pronchery pkgconf_cross_personality_deinit(personality);
365*a3cefe7fSPierre Pronchery pkgconf_client_deinit(&pkg_client);
366*a3cefe7fSPierre Pronchery
367*a3cefe7fSPierre Pronchery return ret;
368*a3cefe7fSPierre Pronchery }
369