1327Sjkh/*
2228990Suqs * FreeBSD install - a package for the installation and maintenance
3327Sjkh * of non-core utilities.
4327Sjkh *
5327Sjkh * Redistribution and use in source and binary forms, with or without
6327Sjkh * modification, are permitted provided that the following conditions
7327Sjkh * are met:
8327Sjkh * 1. Redistributions of source code must retain the above copyright
9327Sjkh *    notice, this list of conditions and the following disclaimer.
10327Sjkh * 2. Redistributions in binary form must reproduce the above copyright
11327Sjkh *    notice, this list of conditions and the following disclaimer in the
12327Sjkh *    documentation and/or other materials provided with the distribution.
13327Sjkh *
14327Sjkh * Jordan K. Hubbard
15327Sjkh * 23 Aug 1993
16327Sjkh *
17327Sjkh * Various display routines for the info module.
18327Sjkh *
19327Sjkh */
20327Sjkh
2193520Sobrien#include <sys/cdefs.h>
2293520Sobrien__FBSDID("$FreeBSD$");
2393520Sobrien
24222035Sflz#include "lib.h"
25327Sjkh#include "info.h"
2649637Sbillf#include <err.h>
2762775Ssobomax#include <stdlib.h>
2862775Ssobomax#include <sys/types.h>
2962775Ssobomax#include <sys/stat.h>
3071965Sjkh#include <md5.h>
3149637Sbillf
32327Sjkhvoid
3384745Ssobomaxshow_file(const char *title, const char *fname)
34327Sjkh{
35327Sjkh    FILE *fp;
36327Sjkh    char line[1024];
37327Sjkh    int n;
38327Sjkh
39411Sjkh    if (!Quiet)
40411Sjkh	printf("%s%s", InfoPrefix, title);
41327Sjkh    fp = fopen(fname, "r");
42115324Slioux    if (fp == (FILE *) NULL)
439781Sache	printf("ERROR: show_file: Can't open '%s' for reading!\n", fname);
449781Sache    else {
45115324Slioux	int append_nl = 0;
4616549Sjkh	while ((n = fread(line, 1, 1024, fp)) != 0)
479781Sache	    fwrite(line, 1, n, stdout);
489781Sache	fclose(fp);
49115324Slioux	append_nl = (line[n - 1] != '\n');	/* Do we have a trailing \n ? */
50115324Slioux	if (append_nl)
51115324Slioux	   printf("\n");
52327Sjkh    }
53327Sjkh    printf("\n");	/* just in case */
54327Sjkh}
55327Sjkh
565399Sswallacevoid
5784745Ssobomaxshow_index(const char *title, const char *fname)
585399Sswallace{
595399Sswallace    FILE *fp;
605399Sswallace    char line[MAXINDEXSIZE+2];
618857Srgrimes
62115324Slioux    strlcpy(line, "???\n", sizeof(line));
63115324Slioux
64240682Sbapt    if (!Quiet) {
655399Sswallace        printf("%s%s", InfoPrefix, title);
66240682Sbapt        fflush(stdout);
67240682Sbapt    }
685399Sswallace    fp = fopen(fname, "r");
69115324Slioux    if (fp == (FILE *) NULL) {
7030221Scharnier        warnx("show_file: can't open '%s' for reading", fname);
71115324Slioux    } else {
72115324Slioux    	if(fgets(line, MAXINDEXSIZE + 1, fp)) {
73115324Slioux		size_t line_length = strlen(line);
74115324Slioux
75115324Slioux		if (line[line_length - 1] != '\n') {	/* Do we have a trailing \n ? */
76115324Slioux			line[line_length] = '\n';	/* Add a trailing \n */
77115324Slioux			line[line_length + 1] = '\0';	/* Terminate string */
78115324Slioux		}
79115324Slioux	}
80115324Slioux	fclose(fp);
818857Srgrimes    }
82115324Slioux    fputs(line, stdout);
838857Srgrimes}
845399Sswallace
8584745Ssobomax/* Show a packing list item type.  If showall is TRUE, show all */
86327Sjkhvoid
8784745Ssobomaxshow_plist(const char *title, Package *plist, plist_t type, Boolean showall)
88327Sjkh{
89327Sjkh    PackingList p;
90327Sjkh    Boolean ign = FALSE;
91154102Skrion    char *prefix = NULL;
92327Sjkh
93240682Sbapt    if (!Quiet) {
94411Sjkh	printf("%s%s", InfoPrefix, title);
95240682Sbapt	fflush(stdout);
96240682Sbapt    }
97327Sjkh    p = plist->head;
98327Sjkh    while (p) {
9984745Ssobomax	if (p->type != type && showall != TRUE) {
100327Sjkh	    p = p->next;
101327Sjkh	    continue;
102327Sjkh	}
103327Sjkh	switch(p->type) {
104327Sjkh	case PLIST_FILE:
105327Sjkh	    if (ign) {
106411Sjkh		printf(Quiet ? "%s\n" : "File: %s (ignored)\n", p->name);
107327Sjkh		ign = FALSE;
108327Sjkh	    }
109327Sjkh	    else
110411Sjkh		printf(Quiet ? "%s\n" : "File: %s\n", p->name);
111327Sjkh	    break;
1128857Srgrimes
113327Sjkh	case PLIST_CWD:
114154102Skrion	    if (!prefix)
115154102Skrion		prefix = p->name;
116154102Skrion	    printf(Quiet ? "@cwd %s\n" : "\tCWD to %s\n", (p->name == NULL) ? prefix : p->name);
117327Sjkh	    break;
118327Sjkh
1194996Sjkh	case PLIST_SRC:
1204996Sjkh	    printf(Quiet ? "@srcdir %s\n" : "\tSRCDIR to %s\n", p->name);
1214996Sjkh	    break;
1224996Sjkh
123327Sjkh	case PLIST_CMD:
124411Sjkh	    printf(Quiet ? "@exec %s\n" : "\tEXEC '%s'\n", p->name);
125327Sjkh	    break;
126327Sjkh
12730531Sjkh	case PLIST_UNEXEC:
12830531Sjkh	    printf(Quiet ? "@unexec %s\n" : "\tUNEXEC '%s'\n", p->name);
12930531Sjkh	    break;
13030531Sjkh
131327Sjkh	case PLIST_CHMOD:
132411Sjkh	    printf(Quiet ? "@chmod %s\n" : "\tCHMOD to %s\n",
133411Sjkh		   p->name ? p->name : "(clear default)");
134327Sjkh	    break;
135327Sjkh
136327Sjkh	case PLIST_CHOWN:
137411Sjkh	    printf(Quiet ? "@chown %s\n" : "\tCHOWN to %s\n",
138411Sjkh		   p->name ? p->name : "(clear default)");
139327Sjkh	    break;
140327Sjkh
141327Sjkh	case PLIST_CHGRP:
142411Sjkh	    printf(Quiet ? "@chgrp %s\n" : "\tCHGRP to %s\n",
143411Sjkh		   p->name ? p->name : "(clear default)");
144327Sjkh	    break;
145327Sjkh
146327Sjkh	case PLIST_COMMENT:
147411Sjkh	    printf(Quiet ? "@comment %s\n" : "\tComment: %s\n", p->name);
148327Sjkh	    break;
149327Sjkh
150147381Skrion	case PLIST_NOINST:
151147381Skrion	    printf(Quiet ? "@noinst %s\n" : "\tNot installed: %s\n", p->name);
152147381Skrion	    break;
153147381Skrion
154327Sjkh	case PLIST_IGNORE:
155327Sjkh	    ign = TRUE;
156327Sjkh	    break;
157327Sjkh
1584996Sjkh	case PLIST_IGNORE_INST:
1594996Sjkh	    printf(Quiet ? "@ignore_inst ??? doesn't belong here.\n" :
1604996Sjkh		   "\tIgnore next file installation directive (doesn't belong)\n");
1614996Sjkh	    ign = TRUE;
1624996Sjkh	    break;
1634996Sjkh
164327Sjkh	case PLIST_NAME:
165411Sjkh	    printf(Quiet ? "@name %s\n" : "\tPackage name: %s\n", p->name);
166327Sjkh	    break;
167327Sjkh
1684996Sjkh	case PLIST_DISPLAY:
1694996Sjkh	    printf(Quiet ? "@display %s\n" : "\tInstall message file: %s\n", p->name);
1704996Sjkh	    break;
1714996Sjkh
1724996Sjkh	case PLIST_PKGDEP:
17396076Ssobomax	    printf(Quiet ? "@pkgdep %s\n" : "Dependency: %s\n", p->name);
1744996Sjkh	    break;
1754996Sjkh
17696076Ssobomax	case PLIST_DEPORIGIN:
17796076Ssobomax	    printf(Quiet ? "@comment DEPORIGIN:%s\n" :
17896076Ssobomax		"\tdependency origin: %s\n", p->name);
17996076Ssobomax	    break;
18096076Ssobomax
181113594Skris	case PLIST_CONFLICTS:
182113594Skris	    printf(Quiet ? "@conflicts %s\n" : "Conflicts: %s\n", p->name);
183113594Skris	    break;
184113594Skris
1854996Sjkh	case PLIST_MTREE:
1864996Sjkh	    printf(Quiet ? "@mtree %s\n" : "\tPackage mtree file: %s\n", p->name);
1874996Sjkh	    break;
1884996Sjkh
1894996Sjkh	case PLIST_DIR_RM:
1904996Sjkh	    printf(Quiet ? "@dirrm %s\n" : "\tDeinstall directory remove: %s\n", p->name);
1914996Sjkh	    break;
1924996Sjkh
19381218Skris	case PLIST_OPTION:
19481218Skris	    printf(Quiet ? "@option %s\n" :
19581218Skris		"\tOption \"%s\" controlling package installation behaviour\n",
19681218Skris		p->name);
19781218Skris	    break;
19881218Skris
19996065Ssobomax	case PLIST_ORIGIN:
20096065Ssobomax	    printf(Quiet ? "@comment ORIGIN:%s\n" :
20196065Ssobomax		"\tPackage origin: %s\n", p->name);
20296065Ssobomax	    break;
20396065Ssobomax
204327Sjkh	default:
20530221Scharnier	    cleanup(0);
20696388Salfred	    errx(2, "%s: unknown command type %d (%s)",
20796392Salfred		__func__, p->type, p->name);
208327Sjkh	    break;
209327Sjkh	}
210327Sjkh	p = p->next;
211327Sjkh    }
212327Sjkh}
213327Sjkh
214226708Sdelphijstatic const char *
215226697Semasteelide_root(const char *dir)
216226697Semaste{
217226697Semaste    if (strcmp(dir, "/") == 0)
218226697Semaste	return "";
219226697Semaste    return dir;
220226697Semaste}
221226697Semaste
222411Sjkh/* Show all files in the packing list (except ignored ones) */
223411Sjkhvoid
22484745Ssobomaxshow_files(const char *title, Package *plist)
225411Sjkh{
226411Sjkh    PackingList p;
227411Sjkh    Boolean ign = FALSE;
228166552Spav    char *prefix = NULL;
22984745Ssobomax    const char *dir = ".";
230411Sjkh
231411Sjkh    if (!Quiet)
232411Sjkh	printf("%s%s", InfoPrefix, title);
233411Sjkh    p = plist->head;
234411Sjkh    while (p) {
235411Sjkh	switch(p->type) {
236411Sjkh	case PLIST_FILE:
237411Sjkh	    if (!ign)
238226697Semaste		printf("%s/%s\n", elide_root(dir), p->name);
239411Sjkh	    ign = FALSE;
240411Sjkh	    break;
2418857Srgrimes
242411Sjkh	case PLIST_CWD:
243166552Spav	    if (!prefix)
244166552Spav		prefix = p->name;
245166552Spav	    if (p->name == NULL)
246166552Spav		dir = prefix;
247166552Spav	    else
248166552Spav		dir = p->name;
249411Sjkh	    break;
250411Sjkh
251411Sjkh	case PLIST_IGNORE:
252411Sjkh	    ign = TRUE;
253411Sjkh	    break;
25462775Ssobomax
25562775Ssobomax        /* Silence GCC in the -Wall mode */
25662775Ssobomax	default:
25762775Ssobomax	    break;
258411Sjkh	}
259411Sjkh	p = p->next;
260411Sjkh    }
261411Sjkh}
26262775Ssobomax
26362775Ssobomax/* Calculate and show size of all installed package files (except ignored ones) */
26462775Ssobomaxvoid
26584745Ssobomaxshow_size(const char *title, Package *plist)
26662775Ssobomax{
26762775Ssobomax    PackingList p;
26862775Ssobomax    Boolean ign = FALSE;
26984745Ssobomax    const char *dir = ".";
27062775Ssobomax    struct stat sb;
27162775Ssobomax    char tmp[FILENAME_MAX];
27262775Ssobomax    unsigned long size = 0;
27362775Ssobomax    long blksize;
274108455Smike    int headerlen;
27562775Ssobomax    char *descr;
276166552Spav    char *prefix = NULL;
27762775Ssobomax
27862775Ssobomax    descr = getbsize(&headerlen, &blksize);
279240682Sbapt    if (!Quiet) {
28062775Ssobomax	printf("%s%s", InfoPrefix, title);
281240682Sbapt        fflush(stdout);
282240682Sbapt    }
28362775Ssobomax    for (p = plist->head; p != NULL; p = p->next) {
28462775Ssobomax	switch (p->type) {
28562775Ssobomax	case PLIST_FILE:
28662775Ssobomax	    if (!ign) {
287226697Semaste		snprintf(tmp, FILENAME_MAX, "%s/%s", elide_root(dir), p->name);
28862775Ssobomax		if (!lstat(tmp, &sb)) {
28962775Ssobomax		    size += sb.st_size;
29062775Ssobomax		    if (Verbose)
29162775Ssobomax			printf("%lu\t%s\n", (unsigned long) howmany(sb.st_size, blksize), tmp);
29262775Ssobomax		}
29362775Ssobomax	    }
29462775Ssobomax	    ign = FALSE;
29562775Ssobomax	    break;
29662775Ssobomax
29762775Ssobomax	case PLIST_CWD:
298166552Spav	    if (!prefix)
299166552Spav		prefix = p->name;
300166552Spav	    if (p->name == NULL)
301166552Spav		dir = prefix;
302166552Spav	    else
303166552Spav		dir = p->name;
30462775Ssobomax	    break;
30562775Ssobomax
30662775Ssobomax	case PLIST_IGNORE:
30762775Ssobomax	    ign = TRUE;
30862775Ssobomax	    break;
30962775Ssobomax
31062775Ssobomax	/* Silence GCC in the -Wall mode */
31162775Ssobomax	default:
31262775Ssobomax	    break;
31362775Ssobomax	}
31462775Ssobomax    }
31562775Ssobomax    if (!Quiet)
31662775Ssobomax	printf("%lu\t(%s)\n", howmany(size, blksize), descr);
31762775Ssobomax    else
318112579Smdodd	if (UseBlkSz)
319112579Smdodd		printf("%lu\n", howmany(size, blksize));
320112579Smdodd	else
321112579Smdodd		printf("%lu\n", size);
32262775Ssobomax}
32367454Ssobomax
32471965Sjkh/* Show files that don't match the recorded checksum */
325240682Sbaptint
32684745Ssobomaxshow_cksum(const char *title, Package *plist)
32771965Sjkh{
32871965Sjkh    PackingList p;
32984745Ssobomax    const char *dir = ".";
330166552Spav    char *prefix = NULL;
33171965Sjkh    char tmp[FILENAME_MAX];
332240682Sbapt    int errcode = 0;
33371965Sjkh
334240682Sbapt    if (!Quiet) {
33571965Sjkh	printf("%s%s", InfoPrefix, title);
336240682Sbapt	fflush(stdout);
337240682Sbapt    }
33871965Sjkh
33971965Sjkh    for (p = plist->head; p != NULL; p = p->next)
340166552Spav	if (p->type == PLIST_CWD) {
341166552Spav	    if (!prefix)
342166552Spav		prefix = p->name;
343166552Spav	    if (p->name == NULL)
344166552Spav		dir = prefix;
345166552Spav	    else
346166552Spav		dir = p->name;
347166552Spav	} else if (p->type == PLIST_FILE) {
348226697Semaste	    snprintf(tmp, FILENAME_MAX, "%s/%s", elide_root(dir), p->name);
349240682Sbapt	    if (!fexists(tmp)) {
350150522Skrion		warnx("%s doesn't exist", tmp);
351240682Sbapt		errcode = 1;
352240682Sbapt	    } else if (p->next && p->next->type == PLIST_COMMENT &&
35395933Ssobomax	             (strncmp(p->next->name, "MD5:", 4) == 0)) {
35495933Ssobomax		char *cp = NULL, buf[33];
35595933Ssobomax
35695933Ssobomax		/*
35795933Ssobomax		 * For packing lists whose version is 1.1 or greater, the md5
35895933Ssobomax		 * hash for a symlink is calculated on the string returned
35995933Ssobomax		 * by readlink().
36095933Ssobomax		 */
36195933Ssobomax		if (issymlink(tmp) && verscmp(plist, 1, 0) > 0) {
36295933Ssobomax		    int len;
36395933Ssobomax		    char linkbuf[FILENAME_MAX];
36495933Ssobomax
36595933Ssobomax		    if ((len = readlink(tmp, linkbuf, FILENAME_MAX)) > 0)
36695933Ssobomax			cp = MD5Data((unsigned char *)linkbuf, len, buf);
36795933Ssobomax		} else if (isfile(tmp) || verscmp(plist, 1, 1) < 0)
36895933Ssobomax		    cp = MD5File(tmp, buf);
36995933Ssobomax
37095933Ssobomax		if (cp != NULL) {
37195933Ssobomax		    /* Mismatch? */
37271965Sjkh		    if (strcmp(cp, p->next->name + 4))
37371965Sjkh			printf("%s fails the original MD5 checksum\n", tmp);
37471965Sjkh		    else if (Verbose)
37571965Sjkh			printf("%s matched the original MD5 checksum\n", tmp);
37672034Ssobomax		}
37771965Sjkh	    }
37871965Sjkh	}
379240682Sbapt    return (errcode);
38071965Sjkh}
38171965Sjkh
38267454Ssobomax/* Show an "origin" path (usually category/portname) */
38367454Ssobomaxvoid
38484745Ssobomaxshow_origin(const char *title, Package *plist)
38567454Ssobomax{
38667454Ssobomax
387240682Sbapt    if (!Quiet) {
38867454Ssobomax	printf("%s%s", InfoPrefix, title);
389240682Sbapt	fflush(stdout);
390240682Sbapt    }
39196030Ssobomax    printf("%s\n", plist->origin != NULL ? plist->origin : "");
39267454Ssobomax}
39384750Ssobomax
39484750Ssobomax/* Show revision number of the packing list */
39584750Ssobomaxvoid
39684750Ssobomaxshow_fmtrev(const char *title, Package *plist)
39784750Ssobomax{
39896030Ssobomax
399240682Sbapt    if (!Quiet) {
40084750Ssobomax	printf("%s%s", InfoPrefix, title);
401240682Sbapt	fflush(stdout);
402240682Sbapt    }
40384750Ssobomax    printf("%d.%d\n", plist->fmtver_maj, plist->fmtver_mnr);
40484750Ssobomax}
405