1/*	$NetBSD: main.c,v 1.4 2021/04/10 19:49:59 nia Exp $	*/
2
3#if HAVE_CONFIG_H
4#include "config.h"
5#endif
6#include <nbcompat.h>
7#if HAVE_SYS_CDEFS_H
8#include <sys/cdefs.h>
9#endif
10__RCSID("$NetBSD: main.c,v 1.4 2021/04/10 19:49:59 nia Exp $");
11
12/*
13 *
14 * FreeBSD install - a package for the installation and maintainance
15 * of non-core utilities.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 *    notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 *    notice, this list of conditions and the following disclaimer in the
24 *    documentation and/or other materials provided with the distribution.
25 *
26 * Jordan K. Hubbard
27 * 18 July 1993
28 *
29 * This is the add module.
30 *
31 */
32
33#if HAVE_SYS_IOCTL_H
34#include <sys/ioctl.h>
35#endif
36
37#if HAVE_ERR_H
38#include <err.h>
39#endif
40
41#include "lib.h"
42#include "info.h"
43
44static const char Options[] = ".aBbcDde:E:fFhIiK:kLl:mNnpQ:qrRsSuvVX";
45
46int     Flags = 0;
47enum which Which = WHICH_LIST;
48Boolean File2Pkg = FALSE;
49Boolean Quiet = FALSE;
50const char   *InfoPrefix = "";
51const char   *BuildInfoVariable = "";
52lpkg_head_t pkgs;
53
54static void
55usage(void)
56{
57	fprintf(stderr, "%s\n%s\n%s\n%s\n",
58	    "usage: pkg_info [-BbcDdFfhIikLmNnpqRrSsVvX] [-E pkg-name] [-e pkg-name]",
59	    "                [-K pkg_dbdir] [-l prefix] pkg-name ...",
60	    "       pkg_info [-a | -u] [flags]",
61	    "       pkg_info [-Q variable] pkg-name ...");
62	exit(1);
63}
64
65int
66main(int argc, char **argv)
67{
68	char *CheckPkg = NULL;
69	char *BestCheckPkg = NULL;
70	lpkg_t *lpp;
71	int     ch;
72	int	rc;
73
74	setprogname(argv[0]);
75	while ((ch = getopt(argc, argv, Options)) != -1)
76		switch (ch) {
77		case '.':	/* for backward compatibility */
78			break;
79
80		case 'a':
81			Which = WHICH_ALL;
82			break;
83
84		case 'B':
85			Flags |= SHOW_BUILD_INFO;
86			break;
87
88		case 'b':
89			Flags |= SHOW_BUILD_VERSION;
90			break;
91
92		case 'c':
93			Flags |= SHOW_COMMENT;
94			break;
95
96		case 'D':
97			Flags |= SHOW_DISPLAY;
98			break;
99
100		case 'd':
101			Flags |= SHOW_DESC;
102			break;
103
104		case 'E':
105			BestCheckPkg = optarg;
106			break;
107
108		case 'e':
109			CheckPkg = optarg;
110			break;
111
112		case 'f':
113			Flags |= SHOW_PLIST;
114			break;
115
116		case 'F':
117			File2Pkg = 1;
118			break;
119
120		case 'I':
121			Flags |= SHOW_INDEX;
122			break;
123
124		case 'i':
125			Flags |= SHOW_INSTALL;
126			break;
127
128		case 'K':
129			pkgdb_set_dir(optarg, 3);
130			break;
131
132		case 'k':
133			Flags |= SHOW_DEINSTALL;
134			break;
135
136		case 'L':
137			Flags |= SHOW_FILES;
138			break;
139
140		case 'l':
141			InfoPrefix = optarg;
142			break;
143
144		case 'm':
145			Flags |= SHOW_MTREE;
146			break;
147
148		case 'N':
149			Flags |= SHOW_BLD_DEPENDS;
150			break;
151
152		case 'n':
153			Flags |= SHOW_DEPENDS;
154			break;
155
156		case 'p':
157			Flags |= SHOW_PREFIX;
158			break;
159
160		case 'Q':
161			Flags |= SHOW_BI_VAR;
162			BuildInfoVariable = optarg;
163			break;
164
165		case 'q':
166			Quiet = TRUE;
167			break;
168
169		case 'r':
170			Flags |= SHOW_FULL_REQBY;
171			break;
172
173		case 'R':
174			Flags |= SHOW_REQBY;
175			break;
176
177		case 's':
178			Flags |= SHOW_PKG_SIZE;
179			break;
180
181		case 'S':
182			Flags |= SHOW_ALL_SIZE;
183			break;
184
185		case 'u':
186			Which = WHICH_USER;
187			break;
188
189		case 'v':
190			Verbose = TRUE;
191			/* Reasonable definition of 'everything' */
192			Flags = SHOW_COMMENT | SHOW_DESC | SHOW_PLIST | SHOW_INSTALL |
193			    SHOW_DEINSTALL | SHOW_DISPLAY | SHOW_MTREE |
194			    SHOW_REQBY | SHOW_BLD_DEPENDS | SHOW_DEPENDS | SHOW_PKG_SIZE | SHOW_ALL_SIZE;
195			break;
196
197		case 'V':
198			show_version();
199			/* NOTREACHED */
200
201		case 'X':
202			Flags |= SHOW_SUMMARY;
203			break;
204
205		case 'h':
206		case '?':
207		default:
208			usage();
209			/* NOTREACHED */
210		}
211
212	argc -= optind;
213	argv += optind;
214
215	pkg_install_config();
216
217	if (argc == 0 && !Flags && !CheckPkg) {
218		/* No argument or relevant flags specified - assume -I */
219		Flags = SHOW_INDEX;
220		/* assume -a if neither -u nor -a is given */
221		if (Which == WHICH_LIST)
222			Which = WHICH_ALL;
223	}
224
225	if (CheckPkg != NULL && BestCheckPkg != NULL) {
226		warnx("-E and -e are mutally exlusive");
227		usage();
228	}
229
230	if (argc != 0 && CheckPkg != NULL) {
231		warnx("can't give any additional arguments to -e");
232		usage();
233	}
234
235	if (argc != 0 && BestCheckPkg != NULL) {
236		warnx("can't give any additional arguments to -E");
237		usage();
238	}
239
240	if (argc != 0 && Which != WHICH_LIST) {
241		warnx("can't use both -a/-u and package name");
242		usage();
243	}
244
245	/* Set some reasonable defaults */
246	if (!Flags)
247		Flags = SHOW_COMMENT | SHOW_DESC | SHOW_REQBY
248			| SHOW_DEPENDS | SHOW_DISPLAY;
249
250	/* -Fe /filename -> change CheckPkg to real packagename */
251	if (CheckPkg) {
252		if (File2Pkg) {
253			char   *s;
254
255			if (!pkgdb_open(ReadOnly))
256				err(EXIT_FAILURE, "cannot open pkgdb");
257
258			s = pkgdb_retrieve(CheckPkg);
259
260			if (s == NULL)
261				errx(EXIT_FAILURE, "No matching pkg for %s.", CheckPkg);
262			CheckPkg = xstrdup(s);
263
264			pkgdb_close();
265		}
266		return CheckForPkg(CheckPkg);
267	}
268
269	if (BestCheckPkg)
270		return CheckForBestPkg(BestCheckPkg);
271
272	TAILQ_INIT(&pkgs);
273
274	/* Get all the remaining package names, if any */
275	if (File2Pkg && Which == WHICH_LIST)
276		if (!pkgdb_open(ReadOnly)) {
277			err(EXIT_FAILURE, "cannot open pkgdb");
278		}
279	while (*argv) {
280		/* pkgdb: if -F flag given, don't add pkgnames to the "pkgs"
281		 * queue but rather resolve the given filenames to pkgnames
282		 * using pkgdb_retrieve, then add them. */
283		if (File2Pkg) {
284			char   *s;
285
286			s = pkgdb_retrieve(*argv);
287
288			if (s) {
289				lpp = alloc_lpkg(s);
290				TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link);
291			} else
292				errx(EXIT_FAILURE, "No matching pkg for %s.", *argv);
293		} else {
294			if (ispkgpattern(*argv)) {
295				switch (add_installed_pkgs_by_pattern(*argv, &pkgs)) {
296				case 0:
297					errx(EXIT_FAILURE, "No matching pkg for %s.", *argv);
298				case -1:
299					errx(EXIT_FAILURE, "Error during search in pkgdb for %s", *argv);
300				}
301			} else {
302				const char *dbdir;
303				size_t dbdirlen;
304
305				dbdir = pkgdb_get_dir();
306				dbdirlen = strlen(dbdir);
307				if (**argv == '/' &&
308				    strncmp(*argv, dbdir, dbdirlen) == 0 &&
309				    (*argv)[dbdirlen] == '/') {
310					*argv += dbdirlen + 1;
311					if (**argv && (*argv)[strlen(*argv) - 1] == '/') {
312						(*argv)[strlen(*argv) - 1] = 0;
313					}
314				}
315				lpp = alloc_lpkg(*argv);
316				TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link);
317			}
318		}
319		argv++;
320	}
321
322	if (File2Pkg)
323		pkgdb_close();
324
325	/* If no packages, yelp */
326	if (TAILQ_FIRST(&pkgs) == NULL && Which == WHICH_LIST && !CheckPkg)
327		warnx("missing package name(s)"), usage();
328
329	rc = pkg_perform(&pkgs);
330	exit(rc);
331	/* NOTREACHED */
332}
333