perform.c revision 67454
1327Sjkh#ifndef lint
230221Scharnierstatic const char rcsid[] =
350479Speter  "$FreeBSD: head/usr.sbin/pkg_install/info/perform.c 67454 2000-10-23 07:01:31Z sobomax $";
4327Sjkh#endif
5327Sjkh
6327Sjkh/*
7327Sjkh * FreeBSD install - a package for the installation and maintainance
8327Sjkh * of non-core utilities.
9327Sjkh *
10327Sjkh * Redistribution and use in source and binary forms, with or without
11327Sjkh * modification, are permitted provided that the following conditions
12327Sjkh * are met:
13327Sjkh * 1. Redistributions of source code must retain the above copyright
14327Sjkh *    notice, this list of conditions and the following disclaimer.
15327Sjkh * 2. Redistributions in binary form must reproduce the above copyright
16327Sjkh *    notice, this list of conditions and the following disclaimer in the
17327Sjkh *    documentation and/or other materials provided with the distribution.
18327Sjkh *
19327Sjkh * Jordan K. Hubbard
20327Sjkh * 23 Aug 1993
21327Sjkh *
22327Sjkh * This is the main body of the info module.
23327Sjkh *
24327Sjkh */
25327Sjkh
26327Sjkh#include "lib.h"
27327Sjkh#include "info.h"
28327Sjkh
2949300Sjdp#include <fts.h>
30327Sjkh#include <signal.h>
3149637Sbillf#include <err.h>
32327Sjkh
3349300Sjdpstatic int fname_cmp(const FTSENT **, const FTSENT **);
34327Sjkhstatic int pkg_do(char *);
35327Sjkh
36327Sjkhint
37327Sjkhpkg_perform(char **pkgs)
38327Sjkh{
39327Sjkh    int i, err_cnt = 0;
407937Sjkh    char *tmp;
41327Sjkh
42327Sjkh    signal(SIGINT, cleanup);
43327Sjkh
447937Sjkh    tmp = getenv(PKG_DBDIR);
457937Sjkh    if (!tmp)
467937Sjkh	tmp = DEF_LOG_DIR;
47327Sjkh    /* Overriding action? */
4816404Sjkh    if (CheckPkg) {
4916404Sjkh	char buf[FILENAME_MAX];
50327Sjkh
5116404Sjkh	snprintf(buf, FILENAME_MAX, "%s/%s", tmp, CheckPkg);
5216404Sjkh	return abs(access(buf, R_OK));
5316404Sjkh    }
5416404Sjkh    else if (AllInstalled) {
5549300Sjdp	FTS *ftsp;
5649300Sjdp	FTSENT *f;
5749300Sjdp	char *paths[2];
588857Srgrimes
5916404Sjkh	if (!isdir(tmp))
6016404Sjkh	    return 1;
6149300Sjdp	paths[0] = tmp;
6249300Sjdp	paths[1] = NULL;
6349300Sjdp	ftsp = fts_open(paths, FTS_LOGICAL | FTS_NOCHDIR | FTS_NOSTAT,
6449300Sjdp	  fname_cmp);
6549300Sjdp	if (ftsp != NULL) {
6649300Sjdp	    while ((f = fts_read(ftsp)) != NULL) {
6749300Sjdp		if (f->fts_info == FTS_D && f->fts_level == 1) {
6849300Sjdp		    err_cnt += pkg_do(f->fts_name);
6949300Sjdp		    fts_set(ftsp, f, FTS_SKIP);
7049300Sjdp		}
7149300Sjdp	    }
7249300Sjdp	    fts_close(ftsp);
7316404Sjkh	}
74327Sjkh    }
7516404Sjkh    else
7616404Sjkh	for (i = 0; pkgs[i]; i++)
7716404Sjkh	    err_cnt += pkg_do(pkgs[i]);
78327Sjkh    return err_cnt;
79327Sjkh}
80327Sjkh
8111780Sjkhstatic char *Home;
8211780Sjkh
83327Sjkhstatic int
84327Sjkhpkg_do(char *pkg)
85327Sjkh{
868086Sjkh    Boolean installed = FALSE, isTMP = FALSE;
87327Sjkh    char log_dir[FILENAME_MAX];
888086Sjkh    char fname[FILENAME_MAX];
89327Sjkh    Package plist;
90327Sjkh    FILE *fp;
918086Sjkh    struct stat sb;
928142Sjkh    char *cp = NULL;
938086Sjkh    int code = 0;
94327Sjkh
958086Sjkh    if (isURL(pkg)) {
9611780Sjkh	if ((cp = fileGetURL(NULL, pkg)) != NULL) {
978086Sjkh	    strcpy(fname, cp);
988086Sjkh	    isTMP = TRUE;
998086Sjkh	}
1008086Sjkh    }
1019782Sache    else if (fexists(pkg) && isfile(pkg)) {
1028086Sjkh	int len;
103327Sjkh
1048423Sjkh	if (*pkg != '/') {
1058423Sjkh	    if (!getcwd(fname, FILENAME_MAX))
1068423Sjkh		upchuck("getcwd");
1078423Sjkh	    len = strlen(fname);
1088423Sjkh	    snprintf(&fname[len], FILENAME_MAX - len, "/%s", pkg);
1098423Sjkh	}
1108423Sjkh	else
1118423Sjkh	    strcpy(fname, pkg);
1128086Sjkh	cp = fname;
1138086Sjkh    }
1148086Sjkh    else {
11511780Sjkh	if ((cp = fileFindByPath(NULL, pkg)) != NULL)
1168086Sjkh	    strncpy(fname, cp, FILENAME_MAX);
1178086Sjkh    }
1188086Sjkh    if (cp) {
1193364Sjkh	/*
1203364Sjkh	 * Apply a crude heuristic to see how much space the package will
1213364Sjkh	 * take up once it's unpacked.  I've noticed that most packages
1223577Sjkh	 * compress an average of 75%, but we're only unpacking the + files so
1233577Sjkh	 * be very optimistic.
1243364Sjkh	 */
1253364Sjkh	if (stat(fname, &sb) == FAIL) {
12630221Scharnier	    warnx("can't stat package file '%s'", fname);
1278086Sjkh	    code = 1;
1288086Sjkh	    goto bail;
1293364Sjkh	}
13011780Sjkh	Home = make_playpen(PlayPen, sb.st_size / 2);
131327Sjkh	if (unpack(fname, "+*")) {
13230221Scharnier	    warnx("error during unpacking, no info for '%s' available", pkg);
1338086Sjkh	    code = 1;
1348086Sjkh	    goto bail;
135327Sjkh	}
136327Sjkh    }
1378086Sjkh    /* It's not an ininstalled package, try and find it among the installed */
138327Sjkh    else {
1397937Sjkh	char *tmp;
1407937Sjkh
1417937Sjkh	sprintf(log_dir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR,
1427937Sjkh		pkg);
143327Sjkh	if (!fexists(log_dir)) {
14430221Scharnier	    warnx("can't find package `%s' installed or in a file!", pkg);
145327Sjkh	    return 1;
146327Sjkh	}
147327Sjkh	if (chdir(log_dir) == FAIL) {
14830221Scharnier	    warnx("can't change directory to '%s'!", log_dir);
149327Sjkh	    return 1;
150327Sjkh	}
151327Sjkh	installed = TRUE;
152327Sjkh    }
153327Sjkh
154327Sjkh    /* Suck in the contents list */
155327Sjkh    plist.head = plist.tail = NULL;
156327Sjkh    fp = fopen(CONTENTS_FNAME, "r");
157327Sjkh    if (!fp) {
15830221Scharnier	warnx("unable to open %s file", CONTENTS_FNAME);
1598086Sjkh	code = 1;
1608086Sjkh	goto bail;
161327Sjkh    }
162327Sjkh    /* If we have a prefix, add it now */
163327Sjkh    read_plist(&plist, fp);
164327Sjkh    fclose(fp);
165327Sjkh
166327Sjkh    /*
167327Sjkh     * Index is special info type that has to override all others to make
168327Sjkh     * any sense.
169327Sjkh     */
170327Sjkh    if (Flags & SHOW_INDEX) {
1718086Sjkh	char tmp[FILENAME_MAX];
172327Sjkh
1738086Sjkh	snprintf(tmp, FILENAME_MAX, "%-19s ", pkg);
1748086Sjkh	show_index(tmp, COMMENT_FNAME);
175327Sjkh    }
176327Sjkh    else {
177327Sjkh	/* Start showing the package contents */
178411Sjkh	if (!Quiet)
179411Sjkh	    printf("%sInformation for %s:\n\n", InfoPrefix, pkg);
180327Sjkh	if (Flags & SHOW_COMMENT)
181379Sjkh	    show_file("Comment:\n", COMMENT_FNAME);
18266339Smarko	if (Flags & SHOW_REQUIRE)
18366339Smarko	    show_plist("Depends on:\n", &plist, PLIST_PKGDEP);
1844996Sjkh	if ((Flags & SHOW_REQBY) && !isemptyfile(REQUIRED_BY_FNAME))
1854996Sjkh	    show_file("Required by:\n", REQUIRED_BY_FNAME);
186327Sjkh	if (Flags & SHOW_DESC)
187379Sjkh	    show_file("Description:\n", DESC_FNAME);
1884996Sjkh	if ((Flags & SHOW_DISPLAY) && fexists(DISPLAY_FNAME))
1894996Sjkh	    show_file("Install notice:\n", DISPLAY_FNAME);
190327Sjkh	if (Flags & SHOW_PLIST)
191379Sjkh	    show_plist("Packing list:\n", &plist, (plist_t)-1);
192327Sjkh	if ((Flags & SHOW_INSTALL) && fexists(INSTALL_FNAME))
193379Sjkh	    show_file("Install script:\n", INSTALL_FNAME);
19441866Sjkh	if ((Flags & SHOW_INSTALL) && fexists(POST_INSTALL_FNAME))
19541866Sjkh	    show_file("Post-Install script:\n", POST_INSTALL_FNAME);
196327Sjkh	if ((Flags & SHOW_DEINSTALL) && fexists(DEINSTALL_FNAME))
197379Sjkh	    show_file("De-Install script:\n", DEINSTALL_FNAME);
19841866Sjkh	if ((Flags & SHOW_DEINSTALL) && fexists(POST_DEINSTALL_FNAME))
19941866Sjkh	    show_file("Post-DeInstall script:\n", POST_DEINSTALL_FNAME);
2004996Sjkh	if ((Flags & SHOW_MTREE) && fexists(MTREE_FNAME))
2014996Sjkh	    show_file("mtree file:\n", MTREE_FNAME);
202327Sjkh	if (Flags & SHOW_PREFIX)
203379Sjkh	    show_plist("Prefix(s):\n", &plist, PLIST_CWD);
204411Sjkh	if (Flags & SHOW_FILES)
205411Sjkh	    show_files("Files:\n", &plist);
20662775Ssobomax	if ((Flags & SHOW_SIZE) && installed)
20762775Ssobomax	    show_size("Package Size:\n", &plist);
20867454Ssobomax	if (Flags & SHOW_ORIGIN)
20967454Ssobomax	    show_origin("Origin:\n", &plist);
210411Sjkh	if (!Quiet)
211411Sjkh	    puts(InfoPrefix);
212327Sjkh    }
213327Sjkh    free_plist(&plist);
2148086Sjkh bail:
21533427Sjkh    leave_playpen();
2168086Sjkh    if (isTMP)
2178086Sjkh	unlink(fname);
2188086Sjkh    return code;
219327Sjkh}
220327Sjkh
221327Sjkhvoid
222327Sjkhcleanup(int sig)
223327Sjkh{
22433427Sjkh    static int in_cleanup = 0;
22533427Sjkh
22633427Sjkh    if (!in_cleanup) {
22733427Sjkh	in_cleanup = 1;
22833427Sjkh    	leave_playpen();
22933427Sjkh    }
23039068Sjkh    if (sig)
23139068Sjkh	exit(1);
232327Sjkh}
23349300Sjdp
23449300Sjdpstatic int
23549300Sjdpfname_cmp(const FTSENT **a, const FTSENT **b)
23649300Sjdp{
23749300Sjdp    return strcmp((*a)->fts_name, (*b)->fts_name);
23849300Sjdp}
239