1/*	$NetBSD: show.c,v 1.5 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: show.c,v 1.5 2021/04/10 19:49:59 nia Exp $");
11
12/*
13 * FreeBSD install - a package for the installation and maintainance
14 * of non-core utilities.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 *
25 * Jordan K. Hubbard
26 * 23 Aug 1993
27 *
28 * Various display routines for the info module.
29 *
30 */
31/*-
32 * Copyright (c) 1999-2008 The NetBSD Foundation, Inc.
33 * All rights reserved.
34 *
35 * This code is derived from software contributed to The NetBSD Foundation
36 * by Hubert Feyrer <hubert@feyrer.de>.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 *    notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 *    notice, this list of conditions and the following disclaimer in the
45 *    documentation and/or other materials provided with the distribution.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
48 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
49 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
50 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
51 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 * POSSIBILITY OF SUCH DAMAGE.
58 */
59
60#if HAVE_ERR_H
61#include <err.h>
62#endif
63
64#include "defs.h"
65#include "lib.h"
66#include "info.h"
67
68/* Structure to define entries for the "show table" */
69typedef struct show_t {
70	pl_ent_t sh_type;	/* type of entry */
71	const char *sh_quiet;	/* message when quiet */
72	const char *sh_verbose;	/* message when verbose */
73}       show_t;
74
75/*
76 * The entries in this table must be ordered the same as
77 * pl_ent_t constants
78 */
79static const show_t showv[] = {
80	{PLIST_FILE, "", "\tFile: "},
81	{PLIST_CWD, "@cwd ", "\tCWD to: "},
82	{PLIST_CMD, "@exec ", "\tEXEC ''"},
83	{PLIST_CHMOD, "@chmod ", "\tCHMOD to "},
84	{PLIST_CHOWN, "@chown ", "\tCHOWN to "},
85	{PLIST_CHGRP, "@chgrp ", "\tCHGRP to "},
86	{PLIST_COMMENT, "@comment ", "\tComment: "},
87	{PLIST_IGNORE, "@ignore", "Ignore next file:"},
88	{PLIST_NAME, "@name ", "\tPackage name: "},
89	{PLIST_UNEXEC, "@unexec ", "\tUNEXEC ''"},
90	{PLIST_SRC, "@src: ", "\tSRC to: "},
91	{PLIST_DISPLAY, "@display ", "\tInstall message file: "},
92	{PLIST_PKGDEP, "@pkgdep ", "\tPackage depends on: "},
93	{PLIST_DIR_RM, "@dirrm ", "\tObsolete deinstall directory removal hint: "},
94	{PLIST_OPTION, "@option ", "\tPackage has option: "},
95	{PLIST_PKGCFL, "@pkgcfl ", "\tPackage conflicts with: "},
96	{PLIST_BLDDEP, "@blddep ", "\tPackage depends exactly on: "},
97	{PLIST_PKGDIR, "@pkgdir ", "\tManaged directory: "},
98	{-1, NULL, NULL}
99};
100
101static int print_string_as_var(const char *, const char *);
102
103void
104show_file(const char *buf, const char *title, Boolean separator)
105{
106	size_t len;
107
108	if (!Quiet)
109		printf("%s%s", InfoPrefix, title);
110
111	len = strlen(buf);
112	if (len == 0 || buf[len - 1] != '\n')
113		puts(buf);
114	else
115		fputs(buf, stdout);
116
117	if (!Quiet || separator)
118		printf("\n");
119}
120
121void
122show_var(const char *buf, const char *variable)
123{
124	char   *value;
125
126	if (buf == NULL)
127		return;
128
129	if ((value = var_get_memory(buf, variable)) != NULL) {
130		(void) printf("%s\n", value);
131		free(value);
132	}
133}
134
135void
136show_index(const char *buf, const char *title)
137{
138	size_t len;
139
140	if (!Quiet)
141		printf("%s%s", InfoPrefix, title);
142
143	len = strlen(buf);
144	if (len == 0 || buf[len - 1] != '\n')
145		puts(buf);
146	else
147		fputs(buf, stdout);
148}
149
150/*
151 * Show a packing list item type.  If type is PLIST_SHOW_ALL, show all
152 */
153void
154show_plist(const char *title, package_t *plist, pl_ent_t type)
155{
156	plist_t *p;
157	Boolean ign;
158
159	if (!Quiet) {
160		printf("%s%s", InfoPrefix, title);
161	}
162	for (ign = FALSE, p = plist->head; p; p = p->next) {
163		if (p->type == type || type == PLIST_SHOW_ALL) {
164			switch (p->type) {
165			case PLIST_FILE:
166				printf("%s%s",
167				    Quiet ? showv[p->type].sh_quiet :
168				    showv[p->type].sh_verbose, p->name);
169				if (ign) {
170					if (!Quiet) {
171						printf(" (ignored)");
172					}
173					ign = FALSE;
174				}
175				break;
176			case PLIST_CHMOD:
177			case PLIST_CHOWN:
178			case PLIST_CHGRP:
179				printf("%s%s",
180				    Quiet ?  showv[p->type].sh_quiet :
181				    showv[p->type].sh_verbose,
182				    p->name ? p->name : "(clear default)");
183				break;
184			case PLIST_IGNORE:
185				printf("%s", Quiet ? showv[p->type].sh_quiet :
186				    showv[p->type].sh_verbose);
187				ign = TRUE;
188				break;
189			case PLIST_CWD:
190			case PLIST_CMD:
191			case PLIST_SRC:
192			case PLIST_UNEXEC:
193			case PLIST_COMMENT:
194			case PLIST_NAME:
195			case PLIST_DISPLAY:
196			case PLIST_PKGDEP:
197			case PLIST_DIR_RM:
198			case PLIST_OPTION:
199			case PLIST_PKGCFL:
200			case PLIST_BLDDEP:
201			case PLIST_PKGDIR:
202				printf("%s%s",
203				    Quiet ? showv[p->type].sh_quiet :
204				    showv[p->type].sh_verbose,
205				    p->name ? p->name : "(null)");
206				break;
207			default:
208				warnx("unknown command type %d (%s)", p->type, p->name);
209			}
210			(void) fputc('\n', stdout);
211		}
212	}
213}
214
215/*
216 * Show all files in the packing list (except ignored ones)
217 */
218void
219show_files(const char *title, package_t *plist)
220{
221	plist_t *p;
222	Boolean ign;
223	const char *dir = ".";
224
225	if (!Quiet) {
226		printf("%s%s", InfoPrefix, title);
227	}
228	for (ign = FALSE, p = plist->head; p; p = p->next) {
229		switch (p->type) {
230		case PLIST_FILE:
231			if (!ign) {
232				printf("%s%s%s\n", dir,
233					(strcmp(dir, "/") == 0) ? "" : "/", p->name);
234			}
235			ign = FALSE;
236			break;
237		case PLIST_CWD:
238			dir = p->name;
239			break;
240		case PLIST_IGNORE:
241			ign = TRUE;
242			break;
243		default:
244			break;
245		}
246	}
247}
248
249/*
250 * Show dependencies (packages this pkg requires)
251 */
252void
253show_depends(const char *title, package_t *plist)
254{
255	plist_t *p;
256	int     nodepends;
257
258	nodepends = 1;
259	for (p = plist->head; p && nodepends; p = p->next) {
260		switch (p->type) {
261		case PLIST_PKGDEP:
262			nodepends = 0;
263			break;
264		default:
265			break;
266		}
267	}
268	if (nodepends)
269		return;
270
271	if (!Quiet) {
272		printf("%s%s", InfoPrefix, title);
273	}
274	for (p = plist->head; p; p = p->next) {
275		switch (p->type) {
276		case PLIST_PKGDEP:
277			printf("%s\n", p->name);
278			break;
279		default:
280			break;
281		}
282	}
283
284	printf("\n");
285}
286
287/*
288 * Show exact dependencies (packages this pkg was built with)
289 */
290void
291show_bld_depends(const char *title, package_t *plist)
292{
293	plist_t *p;
294	int     nodepends;
295
296	nodepends = 1;
297	for (p = plist->head; p && nodepends; p = p->next) {
298		switch (p->type) {
299		case PLIST_BLDDEP:
300			nodepends = 0;
301			break;
302		default:
303			break;
304		}
305	}
306	if (nodepends)
307		return;
308
309	if (!Quiet) {
310		printf("%s%s", InfoPrefix, title);
311	}
312	for (p = plist->head; p; p = p->next) {
313		switch (p->type) {
314		case PLIST_BLDDEP:
315			printf("%s\n", p->name);
316			break;
317		default:
318			break;
319		}
320	}
321
322	printf("\n");
323}
324
325
326/*
327 * Show entry for pkg_summary.txt file.
328 */
329void
330show_summary(struct pkg_meta *meta, package_t *plist, const char *binpkgfile)
331{
332	static const char *bi_vars[] = {
333		"PKGPATH",
334		"CATEGORIES",
335		"PROVIDES",
336		"REQUIRES",
337		"PKG_OPTIONS",
338		"OPSYS",
339		"OS_VERSION",
340		"MACHINE_ARCH",
341		"LICENSE",
342		"HOMEPAGE",
343		"PKGTOOLS_VERSION",
344		"BUILD_DATE",
345		"PREV_PKGPATH",
346		"SUPERSEDES",
347		NULL
348	};
349
350	plist_t *p;
351	struct stat st;
352
353	for (p = plist->head; p; p = p->next) {
354		switch (p->type) {
355		case PLIST_NAME:
356			printf("PKGNAME=%s\n", p->name);
357			break;
358		case PLIST_PKGDEP:
359			printf("DEPENDS=%s\n", p->name);
360			break;
361		case PLIST_PKGCFL:
362			printf("CONFLICTS=%s\n", p->name);
363			break;
364
365		default:
366			break;
367		}
368	}
369
370	print_string_as_var("COMMENT", meta->meta_comment);
371	if (meta->meta_size_pkg)
372		print_string_as_var("SIZE_PKG", meta->meta_size_pkg);
373
374	if (meta->meta_build_info)
375		var_copy_list(meta->meta_build_info, bi_vars);
376	else
377		warnx("Build information missing");
378
379	if (binpkgfile != NULL && stat(binpkgfile, &st) == 0) {
380	    const char *base;
381
382	    base = strrchr(binpkgfile, '/');
383	    if (base == NULL)
384		base = binpkgfile;
385	    else
386		base++;
387	    printf("FILE_NAME=%s\n", base);
388	    printf("FILE_SIZE=%" MY_PRIu64 "\n", (uint64_t)st.st_size);
389	    /* XXX: DIGETS */
390	}
391
392	print_string_as_var("DESCRIPTION", meta->meta_desc);
393	putc('\n', stdout);
394}
395
396/*
397 * Print the contents of file fname as value of variable var to stdout.
398 */
399static int
400print_string_as_var(const char *var, const char *str)
401{
402	const char *eol;
403
404	while ((eol = strchr(str, '\n')) != NULL) {
405		printf("%s=%.*s\n", var, (int)(eol - str), str);
406		str = eol + 1;
407	}
408	if (*str)
409		printf("%s=%s\n", var, str);
410
411	return 0;
412}
413
414void
415show_list(lpkg_head_t *pkghead, const char *title)
416{
417	lpkg_t *lpp;
418
419	if (!Quiet)
420		printf("%s%s", InfoPrefix, title);
421
422	while ((lpp = TAILQ_FIRST(pkghead)) != NULL) {
423		TAILQ_REMOVE(pkghead, lpp, lp_link);
424		puts(lpp->lp_name);
425		free_lpkg(lpp);
426	}
427
428	if (!Quiet)
429		printf("\n");
430}
431