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 * 18 July 1993
16327Sjkh *
17327Sjkh * This is the main body of the create module.
18327Sjkh *
19327Sjkh */
20327Sjkh
2193520Sobrien#include <sys/cdefs.h>
2293520Sobrien__FBSDID("$FreeBSD$");
2393520Sobrien
24222035Sflz#include "lib.h"
25327Sjkh#include "create.h"
26327Sjkh
2730221Scharnier#include <err.h>
2883663Ssobomax#include <libgen.h>
29327Sjkh#include <signal.h>
3089458Ssobomax#include <stdlib.h>
31179352Skeramida#include <sys/types.h>
32179352Skeramida#include <sys/stat.h>
338051Sjkh#include <sys/syslimits.h>
3416549Sjkh#include <sys/wait.h>
3513946Sjdp#include <unistd.h>
36327Sjkh
37327Sjkhstatic void sanity_check(void);
3884745Ssobomaxstatic void make_dist(const char *, const char *, const char *, Package *);
39147043Ssobomaxstatic int create_from_installed_recursive(const char *, const char *);
40147043Ssobomaxstatic int create_from_installed(const char *, const char *, const char *);
41327Sjkh
42327Sjkhint
43327Sjkhpkg_perform(char **pkgs)
44327Sjkh{
45194497Sbrian    static const char *home;
46327Sjkh    char *pkg = *pkgs;		/* Only one arg to create */
4711780Sjkh    char *cp;
48327Sjkh    FILE *pkg_in, *fp;
49327Sjkh    Package plist;
5038933Sjkh    int len;
5184745Ssobomax    const char *suf;
52327Sjkh
53327Sjkh    /* Preliminary setup */
5484670Ssobomax    if (InstalledPkg == NULL)
5584670Ssobomax	sanity_check();
567986Sjkh    if (Verbose && !PlistOnly)
57327Sjkh	printf("Creating package %s\n", pkg);
58327Sjkh
5941530Sasami    /* chop suffix off if already specified, remembering if we want to compress  */
6038933Sjkh    len = strlen(pkg);
6149637Sbillf    if (len > 4) {
62102384Sobrien	if (!strcmp(&pkg[len - 4], ".tbz")) {
63102384Sobrien	    Zipper = BZIP2;
64102384Sobrien	    pkg[len - 4] = '\0';
65102384Sobrien	}
66102384Sobrien	else if (!strcmp(&pkg[len - 4], ".tgz")) {
6795161Sobrien	    Zipper = GZIP;
6841530Sasami	    pkg[len - 4] = '\0';
6941530Sasami	}
70213718Sflz	else if (!strcmp(&pkg[len - 4], ".txz")) {
71213718Sflz	    Zipper = XZ;
72213718Sflz	    pkg[len - 4] = '\0';
73213718Sflz	}
7441530Sasami	else if (!strcmp(&pkg[len - 4], ".tar")) {
7595161Sobrien	    Zipper = NONE;
7641530Sasami	    pkg[len - 4] = '\0';
7741530Sasami	}
7849637Sbillf    }
7995161Sobrien    if (Zipper == BZIP2) {
80101302Sobrien	suf = "tbz";
81102384Sobrien	setenv("BZIP2", "--best", 0);
8295161Sobrien    } else if (Zipper == GZIP) {
8341530Sasami	suf = "tgz";
8489458Ssobomax	setenv("GZIP", "-9", 0);
85213718Sflz    } else if (Zipper == XZ) {
86213718Sflz	suf = "txz";
8789458Ssobomax    } else
8841530Sasami	suf = "tar";
89327Sjkh
90147043Ssobomax    if (InstalledPkg != NULL) {
91152210Skrion	char *pkgglob[] = { InstalledPkg, NULL };
92152210Skrion	char **matched, **pkgs;
93152210Skrion	int i, error;
94152210Skrion
95152210Skrion	pkgs = pkgglob;
96152210Skrion	if (MatchType != MATCH_EXACT) {
97152210Skrion		matched = matchinstalled(MatchType, pkgs, &error);
98152210Skrion		if (!error && matched != NULL)
99152210Skrion			pkgs = matched;
100152210Skrion		else if (MatchType != MATCH_GLOB)
101152210Skrion	    		errx(1, "no packages match pattern");
102152210Skrion	}
103152210Skrion	/*
104152210Skrion	 * Is there is only one installed package matching the pattern,
105152210Skrion	 * we need to respect the optional pkg-filename parameter.  If,
106152210Skrion	 * however, the pattern matches several packages, this parameter
107152210Skrion	 * makes no sense and is ignored.
108152210Skrion	 */
109152210Skrion	if (pkgs[1] == NULL) {
110152210Skrion	    if (pkg == InstalledPkg)
111152210Skrion		pkg = *pkgs;
112152210Skrion	    InstalledPkg = *pkgs;
113152210Skrion	    if (!Recursive)
114152210Skrion		return (create_from_installed(InstalledPkg, pkg, suf));
115152210Skrion	    return (create_from_installed_recursive(pkg, suf));
116152210Skrion	}
117152210Skrion	for (i = 0; pkgs[i] != NULL; i++) {
118152210Skrion	    InstalledPkg = pkg = pkgs[i];
119152210Skrion	    if (!Recursive)
120152210Skrion		create_from_installed(pkg, pkg, suf);
121152210Skrion	    else
122152210Skrion	        create_from_installed_recursive(pkg, suf);
123152210Skrion	}
124152210Skrion	return TRUE;
125147043Ssobomax    }
12684670Ssobomax
12784670Ssobomax    get_dash_string(&Comment);
12884670Ssobomax    get_dash_string(&Desc);
12984670Ssobomax    if (!strcmp(Contents, "-"))
13084670Ssobomax	pkg_in = stdin;
13184670Ssobomax    else {
13284670Ssobomax	pkg_in = fopen(Contents, "r");
13384670Ssobomax	if (!pkg_in) {
13484670Ssobomax	    cleanup(0);
13596388Salfred	    errx(2, "%s: unable to open contents file '%s' for input",
13696392Salfred		__func__, Contents);
13784670Ssobomax	}
13884670Ssobomax    }
13984670Ssobomax    plist.head = plist.tail = NULL;
14084670Ssobomax
1417713Sjkh    /* Stick the dependencies, if any, at the top */
1427733Sjkh    if (Pkgdeps) {
14396076Ssobomax	char **deps, *deporigin;
14474295Ssobomax	int i;
14574295Ssobomax	int ndeps = 0;
14674295Ssobomax
1477991Sjkh	if (Verbose && !PlistOnly)
1487733Sjkh	    printf("Registering depends:");
14974295Ssobomax
15074295Ssobomax	/* Count number of dependencies */
15174295Ssobomax	for (cp = Pkgdeps; cp != NULL && *cp != '\0';
15274295Ssobomax			   cp = strpbrk(++cp, " \t\n")) {
15374295Ssobomax	    ndeps++;
15474295Ssobomax	}
15574295Ssobomax
15674295Ssobomax	if (ndeps != 0) {
15774295Ssobomax	    /* Create easy to use NULL-terminated list */
15874295Ssobomax	    deps = alloca(sizeof(*deps) * ndeps + 1);
15974295Ssobomax	    if (deps == NULL) {
16096392Salfred		errx(2, "%s: alloca() failed", __func__);
16174295Ssobomax		/* Not reached */
16274295Ssobomax	    }
16390985Ssobomax	    for (i = 0; Pkgdeps;) {
16474295Ssobomax		cp = strsep(&Pkgdeps, " \t\n");
16590985Ssobomax		if (*cp) {
16674295Ssobomax		    deps[i] = cp;
16790985Ssobomax		    i++;
16890985Ssobomax		}
16974295Ssobomax	    }
17090985Ssobomax	    ndeps = i;
17174295Ssobomax	    deps[ndeps] = NULL;
17274295Ssobomax
17374295Ssobomax	    sortdeps(deps);
17474295Ssobomax	    for (i = 0; i < ndeps; i++) {
17596076Ssobomax		deporigin = strchr(deps[i], ':');
17696076Ssobomax		if (deporigin != NULL) {
17796076Ssobomax		    *deporigin = '\0';
17896076Ssobomax		    add_plist_top(&plist, PLIST_DEPORIGIN, ++deporigin);
17996076Ssobomax		}
18074295Ssobomax		add_plist_top(&plist, PLIST_PKGDEP, deps[i]);
1817992Sjkh		if (Verbose && !PlistOnly)
18274295Ssobomax		    printf(" %s", deps[i]);
1837733Sjkh	    }
1847713Sjkh	}
18574295Ssobomax
1867991Sjkh	if (Verbose && !PlistOnly)
1877733Sjkh	    printf(".\n");
1887713Sjkh    }
18926473Sjkh
190113594Skris    /* Put the conflicts directly after the dependencies, if any */
191113594Skris    if (Conflicts) {
192113594Skris	if (Verbose && !PlistOnly)
193113594Skris	    printf("Registering conflicts:");
194113594Skris	while (Conflicts) {
195113594Skris	   cp = strsep(&Conflicts, " \t\n");
196113594Skris	   if (*cp) {
197113594Skris		add_plist(&plist, PLIST_CONFLICTS, cp);
198113594Skris		if (Verbose && !PlistOnly)
199113594Skris		    printf(" %s", cp);
200113594Skris	   }
201113594Skris	}
202113594Skris	if (Verbose && !PlistOnly)
203113594Skris	    printf(".\n");
204113594Skris    }
205113594Skris
20626473Sjkh    /* If a SrcDir override is set, add it now */
20726473Sjkh    if (SrcDir) {
20826473Sjkh	if (Verbose && !PlistOnly)
20926473Sjkh	    printf("Using SrcDir value of %s\n", SrcDir);
21026473Sjkh	add_plist(&plist, PLIST_SRC, SrcDir);
21126473Sjkh    }
21226473Sjkh
213327Sjkh    /* Slurp in the packing list */
214327Sjkh    read_plist(&plist, pkg_in);
215327Sjkh
21631166Sjkh    /* Prefix should add an @cwd to the packing list */
217231300Seadler    if (Prefix) {
218240682Sbapt	if (Prefix[0] != '/') {
219240682Sbapt		char resolved_prefix[PATH_MAX];
220240682Sbapt		if (realpath(Prefix, resolved_prefix) == NULL)
221240682Sbapt		    err(EXIT_FAILURE, "couldn't resolve path for prefix: %s", Prefix);
222240682Sbapt		add_plist_top(&plist, PLIST_CWD, resolved_prefix);
223240682Sbapt	} else {
224240682Sbapt		add_plist_top(&plist, PLIST_CWD, Prefix);
225240682Sbapt	}
226231300Seadler    }
22796066Ssobomax
22896066Ssobomax    /* Add the origin if asked, at the top */
22996066Ssobomax    if (Origin)
23096066Ssobomax	add_plist_top(&plist, PLIST_ORIGIN, Origin);
23196066Ssobomax
232379Sjkh    /*
233379Sjkh     * Run down the list and see if we've named it, if not stick in a name
234379Sjkh     * at the top.
235379Sjkh     */
2361546Sjkh    if (find_plist(&plist, PLIST_NAME) == NULL)
23781571Sobrien	add_plist_top(&plist, PLIST_NAME, basename(pkg));
238379Sjkh
23984750Ssobomax    if (asprintf(&cp, "PKG_FORMAT_REVISION:%d.%d", PLIST_FMT_VER_MAJOR,
24084750Ssobomax		 PLIST_FMT_VER_MINOR) == -1) {
24196392Salfred	errx(2, "%s: asprintf() failed", __func__);
24284750Ssobomax    }
24384750Ssobomax    add_plist_top(&plist, PLIST_COMMENT, cp);
24484750Ssobomax    free(cp);
24584750Ssobomax
2467986Sjkh    /*
2477986Sjkh     * We're just here for to dump out a revised plist for the FreeBSD ports
2487986Sjkh     * hack.  It's not a real create in progress.
2497986Sjkh     */
2507986Sjkh    if (PlistOnly) {
25127192Sjkh	check_list(home, &plist);
2527986Sjkh	write_plist(&plist, stdout);
2537986Sjkh	exit(0);
2547986Sjkh    }
2557986Sjkh
256327Sjkh    /* Make a directory to stomp around in */
2573577Sjkh    home = make_playpen(PlayPen, 0);
258327Sjkh    signal(SIGINT, cleanup);
259327Sjkh    signal(SIGHUP, cleanup);
260327Sjkh
261327Sjkh    /* Make first "real contents" pass over it */
262327Sjkh    check_list(home, &plist);
26376739Ssobomax    (void) umask(022);	/*
26476739Ssobomax			 * Make sure gen'ed directories, files don't have
26576739Ssobomax			 * group or other write bits.
26676739Ssobomax			 */
2678000Sjkh    /* copy_plist(home, &plist); */
2688000Sjkh    /* mark_plist(&plist); */
269327Sjkh
270327Sjkh    /* Now put the release specific items in */
271231300Seadler    if (!Prefix) {
272231300Seadler	add_plist(&plist, PLIST_CWD, ".");
273231300Seadler    }
274327Sjkh    write_file(COMMENT_FNAME, Comment);
275327Sjkh    add_plist(&plist, PLIST_IGNORE, NULL);
276327Sjkh    add_plist(&plist, PLIST_FILE, COMMENT_FNAME);
277131277Seik    add_cksum(&plist, plist.tail, COMMENT_FNAME);
278327Sjkh    write_file(DESC_FNAME, Desc);
279327Sjkh    add_plist(&plist, PLIST_IGNORE, NULL);
280327Sjkh    add_plist(&plist, PLIST_FILE, DESC_FNAME);
281131277Seik    add_cksum(&plist, plist.tail, DESC_FNAME);
282327Sjkh
283327Sjkh    if (Install) {
284327Sjkh	copy_file(home, Install, INSTALL_FNAME);
285327Sjkh	add_plist(&plist, PLIST_IGNORE, NULL);
286327Sjkh	add_plist(&plist, PLIST_FILE, INSTALL_FNAME);
287131277Seik	add_cksum(&plist, plist.tail, INSTALL_FNAME);
288327Sjkh    }
28941866Sjkh    if (PostInstall) {
29041866Sjkh	copy_file(home, PostInstall, POST_INSTALL_FNAME);
29141866Sjkh	add_plist(&plist, PLIST_IGNORE, NULL);
29241866Sjkh	add_plist(&plist, PLIST_FILE, POST_INSTALL_FNAME);
293131277Seik	add_cksum(&plist, plist.tail, POST_INSTALL_FNAME);
29441866Sjkh    }
295327Sjkh    if (DeInstall) {
296327Sjkh	copy_file(home, DeInstall, DEINSTALL_FNAME);
297327Sjkh	add_plist(&plist, PLIST_IGNORE, NULL);
298327Sjkh	add_plist(&plist, PLIST_FILE, DEINSTALL_FNAME);
299131277Seik	add_cksum(&plist, plist.tail, DEINSTALL_FNAME);
300327Sjkh    }
30141866Sjkh    if (PostDeInstall) {
30241866Sjkh	copy_file(home, PostDeInstall, POST_DEINSTALL_FNAME);
30341866Sjkh	add_plist(&plist, PLIST_IGNORE, NULL);
30441866Sjkh	add_plist(&plist, PLIST_FILE, POST_DEINSTALL_FNAME);
305131277Seik	add_cksum(&plist, plist.tail, POST_DEINSTALL_FNAME);
30641866Sjkh    }
307327Sjkh    if (Require) {
308327Sjkh	copy_file(home, Require, REQUIRE_FNAME);
309327Sjkh	add_plist(&plist, PLIST_IGNORE, NULL);
310327Sjkh	add_plist(&plist, PLIST_FILE, REQUIRE_FNAME);
311131277Seik	add_cksum(&plist, plist.tail, REQUIRE_FNAME);
312327Sjkh    }
3134996Sjkh    if (Display) {
3144996Sjkh	copy_file(home, Display, DISPLAY_FNAME);
3154996Sjkh	add_plist(&plist, PLIST_IGNORE, NULL);
3164996Sjkh	add_plist(&plist, PLIST_FILE, DISPLAY_FNAME);
317131277Seik	add_cksum(&plist, plist.tail, DISPLAY_FNAME);
3184996Sjkh	add_plist(&plist, PLIST_DISPLAY, DISPLAY_FNAME);
3194996Sjkh    }
3204996Sjkh    if (Mtree) {
3214996Sjkh	copy_file(home, Mtree, MTREE_FNAME);
3224996Sjkh	add_plist(&plist, PLIST_IGNORE, NULL);
3234996Sjkh	add_plist(&plist, PLIST_FILE, MTREE_FNAME);
324131277Seik	add_cksum(&plist, plist.tail, MTREE_FNAME);
3254996Sjkh	add_plist(&plist, PLIST_MTREE, MTREE_FNAME);
3264996Sjkh    }
327327Sjkh
328327Sjkh    /* Finally, write out the packing list */
329327Sjkh    fp = fopen(CONTENTS_FNAME, "w");
33039068Sjkh    if (!fp) {
33139068Sjkh	cleanup(0);
33296388Salfred	errx(2, "%s: can't open file %s for writing",
33396392Salfred	    __func__, CONTENTS_FNAME);
33439068Sjkh    }
335327Sjkh    write_plist(&plist, fp);
33639068Sjkh    if (fclose(fp)) {
33739068Sjkh	cleanup(0);
33896388Salfred	errx(2, "%s: error while closing %s",
33996392Salfred	    __func__, CONTENTS_FNAME);
34039068Sjkh    }
341327Sjkh
342327Sjkh    /* And stick it into a tar ball */
34341530Sasami    make_dist(home, pkg, suf, &plist);
344327Sjkh
345327Sjkh    /* Cleanup */
346327Sjkh    free(Comment);
347327Sjkh    free(Desc);
348327Sjkh    free_plist(&plist);
34933427Sjkh    leave_playpen();
350327Sjkh    return TRUE;	/* Success */
351327Sjkh}
352327Sjkh
353327Sjkhstatic void
35484745Ssobomaxmake_dist(const char *homedir, const char *pkg, const char *suff, Package *plist)
355327Sjkh{
356179352Skeramida    struct stat sb;
357327Sjkh    char tball[FILENAME_MAX];
3588419Sjkh    PackingList p;
35916549Sjkh    int ret;
36084745Ssobomax    const char *args[50];	/* Much more than enough. */
3618419Sjkh    int nargs = 0;
36213946Sjdp    int pipefds[2];
36313946Sjdp    FILE *totar;
36413946Sjdp    pid_t pid;
36584745Ssobomax    const char *cname;
366154102Skrion    char *prefix = NULL;
367327Sjkh
368154102Skrion
3698419Sjkh    args[nargs++] = "tar";	/* argv[0] */
3708419Sjkh
3712389Sadam    if (*pkg == '/')
37284745Ssobomax	snprintf(tball, FILENAME_MAX, "%s.%s", pkg, suff);
3732389Sadam    else
37484745Ssobomax	snprintf(tball, FILENAME_MAX, "%s/%s.%s", homedir, pkg, suff);
3758419Sjkh
376179352Skeramida    /*
377179352Skeramida     * If the package tarball exists already, and we are running in `no
378179352Skeramida     * clobber' mode, skip this package.
379179352Skeramida     */
380179352Skeramida    if (stat(tball, &sb) == 0 && Regenerate == FALSE) {
381179352Skeramida	if (Verbose)
382179352Skeramida	    printf("Skipping package '%s'.  It already exists.\n", tball);
383179352Skeramida	return;
384179352Skeramida    }
385179352Skeramida
3868419Sjkh    args[nargs++] = "-c";
3878419Sjkh    args[nargs++] = "-f";
3888419Sjkh    args[nargs++] = tball;
38984745Ssobomax    if (strchr(suff, 'z')) {	/* Compress/gzip/bzip2? */
39095161Sobrien	if (Zipper == BZIP2) {
39195161Sobrien	    args[nargs++] = "-j";
39271373Ssobomax	    cname = "bzip'd ";
39371373Ssobomax	}
394213718Sflz	else if (Zipper == XZ) {
395213718Sflz	    args[nargs++] = "-J";
396213718Sflz	    cname = "xz'd ";
397213718Sflz	}
39871373Ssobomax	else {
39971373Ssobomax	    args[nargs++] = "-z";
40071373Ssobomax	    cname = "gzip'd ";
40171373Ssobomax	}
40271373Ssobomax    } else {
40371373Ssobomax	cname = "";
40471373Ssobomax    }
4051520Salm    if (Dereference)
4068419Sjkh	args[nargs++] = "-h";
4078419Sjkh    if (ExcludeFrom) {
4088419Sjkh	args[nargs++] = "-X";
4098419Sjkh	args[nargs++] = ExcludeFrom;
4108419Sjkh    }
41113946Sjdp    args[nargs++] = "-T";	/* Take filenames from file instead of args. */
41213946Sjdp    args[nargs++] = "-";	/* Use stdin for the file. */
41313946Sjdp    args[nargs] = NULL;
4148419Sjkh
415327Sjkh    if (Verbose)
41671373Ssobomax	printf("Creating %star ball in '%s'\n", cname, tball);
4178419Sjkh
41813946Sjdp    /* Set up a pipe for passing the filenames, and fork off a tar process. */
41939068Sjkh    if (pipe(pipefds) == -1) {
42039068Sjkh	cleanup(0);
42196392Salfred	errx(2, "%s: cannot create pipe", __func__);
42239068Sjkh    }
42339068Sjkh    if ((pid = fork()) == -1) {
42439068Sjkh	cleanup(0);
42596392Salfred	errx(2, "%s: cannot fork process for tar", __func__);
42639068Sjkh    }
42713946Sjdp    if (pid == 0) {	/* The child */
42813946Sjdp	dup2(pipefds[0], 0);
42914728Sjdp	close(pipefds[0]);
43013946Sjdp	close(pipefds[1]);
43184745Ssobomax	execv("/usr/bin/tar", (char * const *)(uintptr_t)args);
43230221Scharnier	cleanup(0);
43396392Salfred	errx(2, "%s: failed to execute tar command", __func__);
43413946Sjdp    }
4358419Sjkh
43613946Sjdp    /* Meanwhile, back in the parent process ... */
43713946Sjdp    close(pipefds[0]);
43839068Sjkh    if ((totar = fdopen(pipefds[1], "w")) == NULL) {
43939068Sjkh	cleanup(0);
44096392Salfred	errx(2, "%s: fdopen failed", __func__);
44139068Sjkh    }
44213946Sjdp
44313946Sjdp    fprintf(totar, "%s\n", CONTENTS_FNAME);
44413946Sjdp    fprintf(totar, "%s\n", COMMENT_FNAME);
44513946Sjdp    fprintf(totar, "%s\n", DESC_FNAME);
44613946Sjdp
4478419Sjkh    if (Install)
44813946Sjdp	fprintf(totar, "%s\n", INSTALL_FNAME);
44941866Sjkh    if (PostInstall)
45041866Sjkh	fprintf(totar, "%s\n", POST_INSTALL_FNAME);
4518419Sjkh    if (DeInstall)
45213946Sjdp	fprintf(totar, "%s\n", DEINSTALL_FNAME);
45341866Sjkh    if (PostDeInstall)
45441866Sjkh	fprintf(totar, "%s\n", POST_DEINSTALL_FNAME);
4558419Sjkh    if (Require)
45613946Sjdp	fprintf(totar, "%s\n", REQUIRE_FNAME);
4578419Sjkh    if (Display)
45813946Sjdp	fprintf(totar, "%s\n", DISPLAY_FNAME);
4598419Sjkh    if (Mtree)
46013946Sjdp	fprintf(totar, "%s\n", MTREE_FNAME);
4618419Sjkh
4628000Sjkh    for (p = plist->head; p; p = p->next) {
4638419Sjkh	if (p->type == PLIST_FILE)
46413946Sjdp	    fprintf(totar, "%s\n", p->name);
465154102Skrion	else if (p->type == PLIST_CWD && p->name == NULL)
466154102Skrion	    fprintf(totar, "-C\n%s\n", prefix);
467131277Seik	else if (p->type == PLIST_CWD && BaseDir && p->name && p->name[0] == '/')
468131277Seik	    fprintf(totar, "-C\n%s%s\n", BaseDir, p->name);
46913946Sjdp	else if (p->type == PLIST_CWD || p->type == PLIST_SRC)
47013946Sjdp	    fprintf(totar, "-C\n%s\n", p->name);
4718000Sjkh	else if (p->type == PLIST_IGNORE)
4728000Sjkh	     p = p->next;
473154102Skrion	if (p->type == PLIST_CWD && !prefix)
474154102Skrion	    prefix = p->name;
475154102Skrion
4768000Sjkh    }
47713946Sjdp
47813946Sjdp    fclose(totar);
47913946Sjdp    wait(&ret);
4808419Sjkh    /* assume either signal or bad exit is enough for us */
48139068Sjkh    if (ret) {
48239068Sjkh	cleanup(0);
48396392Salfred	errx(2, "%s: tar command failed with code %d", __func__, ret);
48439068Sjkh    }
485327Sjkh}
486327Sjkh
487327Sjkhstatic void
488327Sjkhsanity_check()
489327Sjkh{
49039068Sjkh    if (!Comment) {
49139068Sjkh	cleanup(0);
49296388Salfred	errx(2, "%s: required package comment string is missing (-c comment)",
49396392Salfred	    __func__);
49439068Sjkh    }
49539068Sjkh    if (!Desc) {
49639068Sjkh	cleanup(0);
49796388Salfred	errx(2,	"%s: required package description string is missing (-d desc)",
49896392Salfred	    __func__);
49939068Sjkh    }
50039068Sjkh    if (!Contents) {
50139068Sjkh	cleanup(0);
50296388Salfred	errx(2,	"%s: required package contents list is missing (-f [-]file)",
50396392Salfred	    __func__);
50439068Sjkh    }
505327Sjkh}
506327Sjkh
507327Sjkh
508327Sjkh/* Clean up those things that would otherwise hang around */
509327Sjkhvoid
510327Sjkhcleanup(int sig)
511327Sjkh{
51233427Sjkh    int in_cleanup = 0;
51333427Sjkh
51433427Sjkh    if (!in_cleanup) {
51533427Sjkh	in_cleanup = 1;
51633427Sjkh    	leave_playpen();
51733427Sjkh    }
51837914Sjkh    if (sig)
51937914Sjkh	exit(1);
520327Sjkh}
52184670Ssobomax
52284670Ssobomaxstatic int
523147043Ssobomaxcreate_from_installed_recursive(const char *pkg, const char *suf)
52484670Ssobomax{
52584670Ssobomax    FILE *fp;
52684670Ssobomax    Package plist;
527147043Ssobomax    PackingList p;
528147043Ssobomax    char tmp[PATH_MAX];
529147043Ssobomax    int rval;
530147043Ssobomax
531147043Ssobomax    if (!create_from_installed(InstalledPkg, pkg, suf))
532147043Ssobomax	return FALSE;
533147043Ssobomax    snprintf(tmp, sizeof(tmp), "%s/%s/%s", LOG_DIR, InstalledPkg, CONTENTS_FNAME);
534147043Ssobomax    if (!fexists(tmp)) {
535147043Ssobomax	warnx("can't find package '%s' installed!", InstalledPkg);
536147043Ssobomax	return FALSE;
537147043Ssobomax    }
538147043Ssobomax    /* Suck in the contents list */
539147043Ssobomax    plist.head = plist.tail = NULL;
540147043Ssobomax    fp = fopen(tmp, "r");
541147043Ssobomax    if (!fp) {
542147043Ssobomax	warnx("unable to open %s file", tmp);
543147043Ssobomax	return FALSE;
544147043Ssobomax    }
545147043Ssobomax    read_plist(&plist, fp);
546147043Ssobomax    fclose(fp);
547147043Ssobomax    rval = TRUE;
548147043Ssobomax    for (p = plist.head; p ; p = p->next) {
549147043Ssobomax	if (p->type != PLIST_PKGDEP)
550147043Ssobomax	    continue;
551147043Ssobomax	if (Verbose)
552147043Ssobomax	    printf("Creating package %s\n", p->name);
553147043Ssobomax	if (!create_from_installed(p->name, p->name, suf)) {
554147043Ssobomax	    rval = FALSE;
555147043Ssobomax	    break;
556147043Ssobomax	}
557147043Ssobomax    }
558147043Ssobomax    free_plist(&plist);
559147043Ssobomax    return rval;
560147043Ssobomax}
561147043Ssobomax
562147043Ssobomaxstatic int
563147043Ssobomaxcreate_from_installed(const char *ipkg, const char *pkg, const char *suf)
564147043Ssobomax{
565147043Ssobomax    FILE *fp;
566147043Ssobomax    Package plist;
56784745Ssobomax    char homedir[MAXPATHLEN], log_dir[FILENAME_MAX];
56884670Ssobomax
569147043Ssobomax    snprintf(log_dir, sizeof(log_dir), "%s/%s", LOG_DIR, ipkg);
57084670Ssobomax    if (!fexists(log_dir)) {
571147043Ssobomax	warnx("can't find package '%s' installed!", ipkg);
57296300Ssobomax	return FALSE;
57384670Ssobomax    }
57484745Ssobomax    getcwd(homedir, sizeof(homedir));
57584670Ssobomax    if (chdir(log_dir) == FAIL) {
57684670Ssobomax	warnx("can't change directory to '%s'!", log_dir);
57796300Ssobomax	return FALSE;
57884670Ssobomax    }
57984670Ssobomax    /* Suck in the contents list */
58084670Ssobomax    plist.head = plist.tail = NULL;
58184670Ssobomax    fp = fopen(CONTENTS_FNAME, "r");
58284670Ssobomax    if (!fp) {
58384670Ssobomax	warnx("unable to open %s file", CONTENTS_FNAME);
58496300Ssobomax	return FALSE;
58584670Ssobomax    }
58684670Ssobomax    read_plist(&plist, fp);
58784670Ssobomax    fclose(fp);
58884670Ssobomax
589132789Skan    Install = isfile(INSTALL_FNAME) ? (char *)INSTALL_FNAME : NULL;
590132789Skan    PostInstall = isfile(POST_INSTALL_FNAME) ?
591132789Skan	(char *)POST_INSTALL_FNAME : NULL;
592132789Skan    DeInstall = isfile(DEINSTALL_FNAME) ? (char *)DEINSTALL_FNAME : NULL;
593132789Skan    PostDeInstall = isfile(POST_DEINSTALL_FNAME) ?
594132789Skan	(char *)POST_DEINSTALL_FNAME : NULL;
595132789Skan    Require = isfile(REQUIRE_FNAME) ? (char *)REQUIRE_FNAME : NULL;
596132789Skan    Display = isfile(DISPLAY_FNAME) ? (char *)DISPLAY_FNAME : NULL;
597132789Skan    Mtree = isfile(MTREE_FNAME) ?  (char *)MTREE_FNAME : NULL;
59896300Ssobomax
59984745Ssobomax    make_dist(homedir, pkg, suf, &plist);
60084670Ssobomax
60184670Ssobomax    free_plist(&plist);
602147043Ssobomax    if (chdir(homedir) == FAIL) {
603147043Ssobomax	warnx("can't change directory to '%s'!", homedir);
604147043Ssobomax	return FALSE;
605147043Ssobomax    }
60684670Ssobomax    return TRUE;
60784670Ssobomax}
608