perform.c revision 39068
1327Sjkh#ifndef lint
230221Scharnierstatic const char rcsid[] =
339068Sjkh	"$Id: perform.c,v 1.52 1998/09/08 03:02:45 jkh Exp $";
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 * 18 July 1993
21327Sjkh *
22327Sjkh * This is the main body of the add module.
23327Sjkh *
24327Sjkh */
25327Sjkh
2630221Scharnier#include <err.h>
27327Sjkh#include "lib.h"
28327Sjkh#include "add.h"
29327Sjkh
30327Sjkh#include <signal.h>
314996Sjkh#include <sys/wait.h>
32327Sjkh
33327Sjkhstatic int pkg_do(char *);
34327Sjkhstatic int sanity_check(char *);
35327Sjkhstatic char LogDir[FILENAME_MAX];
3637728Seivindstatic int zapLogDir;		/* Should we delete LogDir? */
37327Sjkh
38327Sjkhint
39327Sjkhpkg_perform(char **pkgs)
40327Sjkh{
41327Sjkh    int i, err_cnt = 0;
42327Sjkh
43327Sjkh    signal(SIGINT, cleanup);
44327Sjkh    signal(SIGHUP, cleanup);
45327Sjkh
46382Sjkh    if (AddMode == SLAVE)
47382Sjkh	err_cnt = pkg_do(NULL);
48382Sjkh    else {
49382Sjkh	for (i = 0; pkgs[i]; i++)
50382Sjkh	    err_cnt += pkg_do(pkgs[i]);
51382Sjkh    }
52327Sjkh    return err_cnt;
53327Sjkh}
54327Sjkh
55327Sjkhstatic Package Plist;
5611780Sjkhstatic char *Home;
57327Sjkh
588083Sjkh/*
598083Sjkh * This is seriously ugly code following.  Written very fast!
608083Sjkh * [And subsequently made even worse..  Sigh!  This code was just born
618083Sjkh * to be hacked, I guess.. :) -jkh]
628083Sjkh */
63327Sjkhstatic int
64327Sjkhpkg_do(char *pkg)
65327Sjkh{
66327Sjkh    char pkg_fullname[FILENAME_MAX];
6711780Sjkh    char playpen[FILENAME_MAX];
687998Sjkh    char extract_contents[FILENAME_MAX];
6914582Sjkh    char *where_to, *tmp, *extract;
70327Sjkh    FILE *cfile;
7111780Sjkh    int code;
721545Sjkh    PackingList p;
733364Sjkh    struct stat sb;
7411780Sjkh    int inPlace;
75327Sjkh
7611780Sjkh    code = 0;
7737728Seivind    zapLogDir = 0;
78327Sjkh    LogDir[0] = '\0';
7911780Sjkh    strcpy(playpen, FirstPen);
8011780Sjkh    inPlace = 0;
818075Sjkh
828083Sjkh    /* Are we coming in for a second pass, everything already extracted? */
8311780Sjkh    if (!pkg) {
8411780Sjkh	fgets(playpen, FILENAME_MAX, stdin);
8511780Sjkh	playpen[strlen(playpen) - 1] = '\0'; /* pesky newline! */
8611780Sjkh	if (chdir(playpen) == FAIL) {
8730221Scharnier	    warnx("pkg_add in SLAVE mode can't chdir to %s", playpen);
88382Sjkh	    return 1;
89382Sjkh	}
90382Sjkh	read_plist(&Plist, stdin);
9111780Sjkh	where_to = playpen;
92327Sjkh    }
938083Sjkh    /* Nope - do it now */
94382Sjkh    else {
9511780Sjkh	/* Is it an ftp://foo.bar.baz/file.tgz specification? */
968083Sjkh	if (isURL(pkg)) {
9711780Sjkh	    if (!(Home = fileGetURL(NULL, pkg))) {
9830221Scharnier		warnx("unable to fetch `%s' by URL", pkg);
998083Sjkh		return 1;
1008083Sjkh	    }
10111780Sjkh	    where_to = Home;
10211780Sjkh	    strcpy(pkg_fullname, pkg);
10311780Sjkh	    cfile = fopen(CONTENTS_FNAME, "r");
10411780Sjkh	    if (!cfile) {
10530221Scharnier		warnx(
10630221Scharnier		"unable to open table of contents file `%s' - not a package?",
10730221Scharnier		CONTENTS_FNAME);
10811780Sjkh		goto bomb;
10911780Sjkh	    }
11011780Sjkh	    read_plist(&Plist, cfile);
11111780Sjkh	    fclose(cfile);
112382Sjkh	}
1138083Sjkh	else {
11414582Sjkh	    strcpy(pkg_fullname, pkg);		/* copy for sanity's sake, could remove pkg_fullname */
11514582Sjkh	    if (strcmp(pkg, "-")) {
11614582Sjkh		if (stat(pkg_fullname, &sb) == FAIL) {
11730221Scharnier		    warnx("can't stat package file '%s'", pkg_fullname);
11814582Sjkh		    goto bomb;
11914582Sjkh		}
12014582Sjkh		sprintf(extract_contents, "--fast-read %s", CONTENTS_FNAME);
12114582Sjkh		extract = extract_contents;
12211780Sjkh	    }
12322750Sjkh	    else {
12414582Sjkh		extract = NULL;
12522750Sjkh		sb.st_size = 100000;	/* Make up a plausible average size */
12622750Sjkh	    }
12711780Sjkh	    Home = make_playpen(playpen, sb.st_size * 4);
12811780Sjkh	    if (!Home)
12938583Sjkh		errx(1, "unable to make playpen for %d bytes", sb.st_size * 4);
13011780Sjkh	    where_to = Home;
13138583Sjkh	    /* Since we can call ourselves recursively, keep notes on where we came from */
13238583Sjkh	    if (!getenv("_TOP"))
13338583Sjkh		setenv("_TOP", Home, 1);
13414582Sjkh	    if (unpack(pkg_fullname, extract)) {
13530221Scharnier		warnx(
13630221Scharnier	"unable to extract table of contents file from `%s' - not a package?",
13730221Scharnier		pkg_fullname);
13811780Sjkh		goto bomb;
13911780Sjkh	    }
14011780Sjkh	    cfile = fopen(CONTENTS_FNAME, "r");
14111780Sjkh	    if (!cfile) {
14230221Scharnier		warnx(
14330221Scharnier	"unable to open table of contents file `%s' - not a package?",
14430221Scharnier		CONTENTS_FNAME);
14511780Sjkh		goto bomb;
14611780Sjkh	    }
14711780Sjkh	    read_plist(&Plist, cfile);
14811780Sjkh	    fclose(cfile);
1497998Sjkh
15011780Sjkh	    /* Extract directly rather than moving?  Oh goodie! */
15111780Sjkh	    if (find_plist_option(&Plist, "extract-in-place")) {
15211780Sjkh		if (Verbose)
15311780Sjkh		    printf("Doing in-place extraction for %s\n", pkg_fullname);
15411780Sjkh		p = find_plist(&Plist, PLIST_CWD);
15511780Sjkh		if (p) {
15611780Sjkh		    if (!isdir(p->name) && !Fake) {
15711780Sjkh			if (Verbose)
15811780Sjkh			    printf("Desired prefix of %s does not exist, creating..\n", p->name);
15911780Sjkh			vsystem("mkdir -p %s", p->name);
16011780Sjkh			if (chdir(p->name) == -1) {
16130221Scharnier			    warn("unable to change directory to `%s'", p->name);
16211780Sjkh			    goto bomb;
16311780Sjkh			}
1647998Sjkh		    }
16511780Sjkh		    where_to = p->name;
16611780Sjkh		    inPlace = 1;
1677998Sjkh		}
16811780Sjkh		else {
16930221Scharnier		    warnx(
17030221Scharnier		"no prefix specified in `%s' - this is a bad package!",
17130221Scharnier			pkg_fullname);
17211780Sjkh		    goto bomb;
17311780Sjkh		}
1747998Sjkh	    }
17511780Sjkh
17611780Sjkh	    /*
17711780Sjkh	     * Apply a crude heuristic to see how much space the package will
17811780Sjkh	     * take up once it's unpacked.  I've noticed that most packages
17911780Sjkh	     * compress an average of 75%, so multiply by 4 for good measure.
18011780Sjkh	     */
18111780Sjkh
18214582Sjkh	    if (!inPlace && min_free(playpen) < sb.st_size * 4) {
18330221Scharnier		warnx("projected size of %d exceeds available free space.\n"
18430221Scharnier"Please set your PKG_TMPDIR variable to point to a location with more\n"
18530221Scharnier		       "free space and try again", sb.st_size * 4);
18630221Scharnier		warnx("not extracting %s\ninto %s, sorry!",
18730221Scharnier			pkg_fullname, where_to);
1888083Sjkh		goto bomb;
1897998Sjkh	    }
1909786Sjkh
19111780Sjkh	    /* If this is a direct extract and we didn't want it, stop now */
19211780Sjkh	    if (inPlace && Fake)
19311780Sjkh		goto success;
1947998Sjkh
19511780Sjkh	    /* Finally unpack the whole mess */
19611780Sjkh	    if (unpack(pkg_fullname, NULL)) {
19730221Scharnier		warnx("unable to extract `%s'!", pkg_fullname);
19811780Sjkh		goto bomb;
19911780Sjkh	    }
20011780Sjkh	}
20114582Sjkh
20211780Sjkh	/* Check for sanity and dependencies */
20311780Sjkh	if (sanity_check(pkg))
2047998Sjkh	    goto bomb;
20511780Sjkh
20611780Sjkh	/* If we're running in MASTER mode, just output the plist and return */
20711780Sjkh	if (AddMode == MASTER) {
20811780Sjkh	    printf("%s\n", where_playpen());
20911780Sjkh	    write_plist(&Plist, stdout);
21011780Sjkh	    return 0;
2117996Sjkh	}
21211780Sjkh    }
213327Sjkh
21411780Sjkh    /*
21511780Sjkh     * If we have a prefix, delete the first one we see and add this
21611780Sjkh     * one in place of it.
21711780Sjkh     */
21811780Sjkh    if (Prefix) {
21911780Sjkh	delete_plist(&Plist, FALSE, PLIST_CWD, NULL);
22011780Sjkh	add_plist_top(&Plist, PLIST_CWD, Prefix);
22111780Sjkh    }
2227998Sjkh
22311780Sjkh    setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : ".", 1);
22411780Sjkh    /* Protect against old packages with bogus @name fields */
22511780Sjkh    PkgName = (p = find_plist(&Plist, PLIST_NAME)) ? p->name : "anonymous";
2267998Sjkh
22711780Sjkh    /* See if we're already registered */
22811780Sjkh    sprintf(LogDir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, PkgName);
22917373Sjkh    if (isdir(LogDir) && !Force) {
23030221Scharnier	warnx("package `%s' already recorded as installed", PkgName);
23111780Sjkh	code = 1;
23211780Sjkh	goto success;	/* close enough for government work */
23311780Sjkh    }
2347998Sjkh
23511780Sjkh    /* Now check the packing list for dependencies */
23611780Sjkh    for (p = Plist.head; p ; p = p->next) {
23711780Sjkh	if (p->type != PLIST_PKGDEP)
23811780Sjkh	    continue;
23911780Sjkh	if (Verbose)
24011780Sjkh	    printf("Package `%s' depends on `%s'.\n", PkgName, p->name);
24118929Sjkh	if (vsystem("pkg_info -e %s", p->name)) {
24211780Sjkh	    char path[FILENAME_MAX], *cp = NULL;
2438083Sjkh
24418929Sjkh	    if (!Fake) {
24518929Sjkh		if (!isURL(pkg) && !getenv("PKG_ADD_BASE")) {
24638583Sjkh		    snprintf(path, FILENAME_MAX, "%s/%s.tgz", getenv("_TOP"), p->name);
24718929Sjkh		    if (fexists(path))
24818929Sjkh			cp = path;
24918929Sjkh		    else
25018929Sjkh			cp = fileFindByPath(pkg, p->name);
25118929Sjkh		    if (cp) {
25218929Sjkh			if (Verbose)
25318929Sjkh			    printf("Loading it from %s.\n", cp);
25430533Sjkh			if (vsystem("pkg_add %s%s", Verbose ? "-v " : "", cp)) {
25530221Scharnier			    warnx("autoload of dependency `%s' failed%s",
25630221Scharnier				cp, Force ? " (proceeding anyway)" : "!");
25718929Sjkh			    if (!Force)
25818929Sjkh				++code;
25918929Sjkh			}
26018929Sjkh		    }
26138931Sjkh		    else {
26238931Sjkh			warnx("could not find package %s %s",
26338931Sjkh			      p->name, Force ? " (proceeding anyway)" : "!");
26438931Sjkh			if (!Force)
26538931Sjkh			    ++code;
26638931Sjkh		    }
26718929Sjkh		}
26818929Sjkh		else if ((cp = fileGetURL(pkg, p->name)) != NULL) {
2698075Sjkh		    if (Verbose)
27018929Sjkh			printf("Finished loading %s over FTP.\n", p->name);
27118929Sjkh		    if (!fexists("+CONTENTS")) {
27230221Scharnier			warnx("autoloaded package %s has no +CONTENTS file?",
27330221Scharnier				p->name);
2748075Sjkh			if (!Force)
2758075Sjkh			    ++code;
2768075Sjkh		    }
27718929Sjkh		    else if (vsystem("(pwd; cat +CONTENTS) | pkg_add %s-S", Verbose ? "-v " : "")) {
27830221Scharnier			warnx("pkg_add of dependency `%s' failed%s",
27930221Scharnier				p->name, Force ? " (proceeding anyway)" : "!");
28018929Sjkh			if (!Force)
28118929Sjkh			    ++code;
28218929Sjkh		    }
28318929Sjkh		    else if (Verbose)
28418929Sjkh			printf("\t`%s' loaded successfully.\n", p->name);
28518929Sjkh		    /* Nuke the temporary playpen */
28633427Sjkh		    leave_playpen();
2878075Sjkh		}
28811780Sjkh	    }
28911780Sjkh	    else {
29011780Sjkh		if (Verbose)
29111780Sjkh		    printf("and was not found%s.\n", Force ? " (proceeding anyway)" : "");
29211780Sjkh		else
29311780Sjkh		    printf("Package dependency %s for %s not found%s\n", p->name, pkg,
29411780Sjkh			   Force ? " (proceeding anyway)" : "!");
29511780Sjkh		if (!Force)
29611780Sjkh		    ++code;
29711780Sjkh	    }
2988075Sjkh	}
29911780Sjkh	else if (Verbose)
30011780Sjkh	    printf(" - already installed.\n");
301327Sjkh    }
3027713Sjkh
30316087Sjkh    if (code != 0)
30416087Sjkh	goto bomb;
30516087Sjkh
3068075Sjkh    /* Look for the requirements file */
307327Sjkh    if (fexists(REQUIRE_FNAME)) {
308327Sjkh	vsystem("chmod +x %s", REQUIRE_FNAME);	/* be sure */
309327Sjkh	if (Verbose)
310327Sjkh	    printf("Running requirements file first for %s..\n", PkgName);
31132665Sjkh	if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, PkgName)) {
31230221Scharnier	    warnx("package %s fails requirements %s", pkg_fullname,
31330221Scharnier		   Force ? "installing anyway" : "- not installed");
3144996Sjkh	    if (!Force) {
3154996Sjkh		code = 1;
3164996Sjkh		goto success;	/* close enough for government work */
3174996Sjkh	    }
318327Sjkh	}
319327Sjkh    }
3208075Sjkh
3218075Sjkh    /* If we're really installing, and have an installation file, run it */
322327Sjkh    if (!NoInstall && fexists(INSTALL_FNAME)) {
323327Sjkh	vsystem("chmod +x %s", INSTALL_FNAME);	/* make sure */
324327Sjkh	if (Verbose)
325327Sjkh	    printf("Running install with PRE-INSTALL for %s..\n", PkgName);
32632665Sjkh	if (!Fake && vsystem("./%s %s PRE-INSTALL", INSTALL_FNAME, PkgName)) {
32730221Scharnier	    warnx("install script returned error status");
3287998Sjkh	    unlink(INSTALL_FNAME);
3294996Sjkh	    code = 1;
3304996Sjkh	    goto success;		/* nothing to uninstall yet */
331327Sjkh	}
332327Sjkh    }
3338075Sjkh
3348075Sjkh    /* Now finally extract the entire show if we're not going direct */
33511780Sjkh    if (!inPlace && !Fake)
33611780Sjkh	extract_plist(".", &Plist);
3378075Sjkh
3388075Sjkh    if (!Fake && fexists(MTREE_FNAME)) {
3394996Sjkh	if (Verbose)
3404996Sjkh	    printf("Running mtree for %s..\n", PkgName);
3414996Sjkh	p = find_plist(&Plist, PLIST_CWD);
3424996Sjkh	if (Verbose)
34311780Sjkh	    printf("mtree -U -f %s -d -e -p %s\n", MTREE_FNAME, p ? p->name : "/");
3448115Sjkh	if (!Fake) {
34511780Sjkh	    if (vsystem("/usr/sbin/mtree -U -f %s -d -e -p %s", MTREE_FNAME, p ? p->name : "/"))
34630221Scharnier		warnx("mtree returned a non-zero status - continuing");
3478115Sjkh	}
3487998Sjkh	unlink(MTREE_FNAME);
3494996Sjkh    }
3508075Sjkh
3518083Sjkh    /* Run the installation script one last time? */
352327Sjkh    if (!NoInstall && fexists(INSTALL_FNAME)) {
353327Sjkh	if (Verbose)
354327Sjkh	    printf("Running install with POST-INSTALL for %s..\n", PkgName);
35532665Sjkh	if (!Fake && vsystem("./%s %s POST-INSTALL", INSTALL_FNAME, PkgName)) {
35630221Scharnier	    warnx("install script returned error status");
3577998Sjkh	    unlink(INSTALL_FNAME);
3584996Sjkh	    code = 1;
359327Sjkh	    goto fail;
360327Sjkh	}
3617998Sjkh	unlink(INSTALL_FNAME);
362327Sjkh    }
3638075Sjkh
3648083Sjkh    /* Time to record the deed? */
365327Sjkh    if (!NoRecord && !Fake) {
366382Sjkh	char contents[FILENAME_MAX];
367382Sjkh	FILE *cfile;
368382Sjkh
3694996Sjkh	umask(022);
370327Sjkh	if (getuid() != 0)
37130221Scharnier	    warnx("not running as root - trying to record install anyway");
372327Sjkh	if (!PkgName) {
37330221Scharnier	    warnx("no package name! can't record package, sorry");
374327Sjkh	    code = 1;
375327Sjkh	    goto success;	/* well, partial anyway */
376327Sjkh	}
37711780Sjkh	sprintf(LogDir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, PkgName);
37837728Seivind	zapLogDir = 1;
379327Sjkh	if (Verbose)
380327Sjkh	    printf("Attempting to record package into %s..\n", LogDir);
381327Sjkh	if (make_hierarchy(LogDir)) {
38230221Scharnier	    warnx("can't record package into '%s', you're on your own!",
383327Sjkh		   LogDir);
384327Sjkh	    bzero(LogDir, FILENAME_MAX);
385327Sjkh	    code = 1;
386327Sjkh	    goto success;	/* close enough for government work */
387327Sjkh	}
388477Sjkh	/* Make sure pkg_info can read the entry */
389477Sjkh	vsystem("chmod a+rx %s", LogDir);
390327Sjkh	if (fexists(DEINSTALL_FNAME))
3917998Sjkh	    move_file(".", DEINSTALL_FNAME, LogDir);
392327Sjkh	if (fexists(REQUIRE_FNAME))
3937998Sjkh	    move_file(".", REQUIRE_FNAME, LogDir);
394382Sjkh	sprintf(contents, "%s/%s", LogDir, CONTENTS_FNAME);
395382Sjkh	cfile = fopen(contents, "w");
396382Sjkh	if (!cfile) {
39730221Scharnier	    warnx("can't open new contents file '%s'! can't register pkg",
39830221Scharnier		contents);
399382Sjkh	    goto success; /* can't log, but still keep pkg */
400382Sjkh	}
401382Sjkh	write_plist(&Plist, cfile);
402382Sjkh	fclose(cfile);
4037998Sjkh	move_file(".", DESC_FNAME, LogDir);
4047998Sjkh	move_file(".", COMMENT_FNAME, LogDir);
4054996Sjkh	if (fexists(DISPLAY_FNAME))
4067998Sjkh	    move_file(".", DISPLAY_FNAME, LogDir);
4074996Sjkh	for (p = Plist.head; p ; p = p->next) {
4084996Sjkh	    if (p->type != PLIST_PKGDEP)
4094996Sjkh		continue;
4104996Sjkh	    if (Verbose)
41111780Sjkh		printf("Attempting to record dependency on package `%s'\n", p->name);
41211780Sjkh	    sprintf(contents, "%s/%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR,
4137937Sjkh	    	    basename_of(p->name), REQUIRED_BY_FNAME);
4144996Sjkh	    cfile = fopen(contents, "a");
4159202Srgrimes	    if (!cfile)
41630221Scharnier		warnx("can't open dependency file '%s'!\n"
41730221Scharnier		       "dependency registration is incomplete", contents);
4189202Srgrimes	    else {
41911780Sjkh		fprintf(cfile, "%s\n", PkgName);
4209202Srgrimes		if (fclose(cfile) == EOF)
42130221Scharnier		    warnx("cannot properly close file %s", contents);
4224996Sjkh	    }
4234996Sjkh	}
424327Sjkh	if (Verbose)
425327Sjkh	    printf("Package %s registered in %s\n", PkgName, LogDir);
426327Sjkh    }
4278857Srgrimes
42816549Sjkh    if ((p = find_plist(&Plist, PLIST_DISPLAY)) != NULL) {
4294996Sjkh	FILE *fp;
4304996Sjkh	char buf[BUFSIZ];
43116549Sjkh
43221650Sjkh	snprintf(buf, sizeof buf, "%s/%s", LogDir, p->name);
43321650Sjkh	fp = fopen(buf, "r");
4344996Sjkh	if (fp) {
4354996Sjkh	    putc('\n', stdout);
4364996Sjkh	    while (fgets(buf, sizeof(buf), fp))
4374996Sjkh		fputs(buf, stdout);
4384996Sjkh	    putc('\n', stdout);
4394996Sjkh	    (void) fclose(fp);
4404996Sjkh	} else
44130221Scharnier	    warnx("cannot open %s as display file", buf);
4424996Sjkh    }
4434996Sjkh
444327Sjkh    goto success;
445327Sjkh
4467998Sjkh bomb:
4477998Sjkh    code = 1;
4487998Sjkh    goto success;
4497998Sjkh
450327Sjkh fail:
4514996Sjkh    /* Nuke the whole (installed) show, XXX but don't clean directories */
452327Sjkh    if (!Fake)
4534996Sjkh	delete_package(FALSE, FALSE, &Plist);
454327Sjkh
455327Sjkh success:
456327Sjkh    /* delete the packing list contents */
45711780Sjkh    free_plist(&Plist);
45833427Sjkh    leave_playpen();
459327Sjkh    return code;
460327Sjkh}
461327Sjkh
462327Sjkhstatic int
463327Sjkhsanity_check(char *pkg)
464327Sjkh{
4658075Sjkh    int code = 0;
4668075Sjkh
467327Sjkh    if (!fexists(CONTENTS_FNAME)) {
46830221Scharnier	warnx("package %s has no CONTENTS file!", pkg);
4698075Sjkh	code = 1;
470327Sjkh    }
4718075Sjkh    else if (!fexists(COMMENT_FNAME)) {
47230221Scharnier	warnx("package %s has no COMMENT file!", pkg);
4738075Sjkh	code = 1;
474327Sjkh    }
4758075Sjkh    else if (!fexists(DESC_FNAME)) {
47630221Scharnier	warnx("package %s has no DESC file!", pkg);
4778075Sjkh	code = 1;
478327Sjkh    }
4798075Sjkh    return code;
480327Sjkh}
481327Sjkh
482327Sjkhvoid
48339068Sjkhcleanup(int sig)
484327Sjkh{
48533427Sjkh    static int in_cleanup = 0;
48633427Sjkh
48733427Sjkh    if (!in_cleanup) {
48833427Sjkh	in_cleanup = 1;
48939068Sjkh    	if (sig)
49039068Sjkh	    printf("Signal %d received, cleaning up..\n", sig);
49137728Seivind    	if (!Fake && zapLogDir && LogDir[0])
49239068Sjkh	    vsystem("%s -rf %s", REMOVE_CMD, LogDir);
49333427Sjkh    	leave_playpen();
49433427Sjkh    }
49539068Sjkh    if (sig)
49639068Sjkh	exit(1);
497327Sjkh}
498