perform.c revision 13946
1#ifndef lint
2static const char *rcsid = "$Id: perform.c,v 1.28 1995/10/25 15:38:01 jkh Exp $";
3#endif
4
5/*
6 * FreeBSD install - a package for the installation and maintainance
7 * of non-core utilities.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * Jordan K. Hubbard
19 * 18 July 1993
20 *
21 * This is the main body of the create module.
22 *
23 */
24
25#include "lib.h"
26#include "create.h"
27
28#include <errno.h>
29#include <signal.h>
30#include <sys/syslimits.h>
31#include <unistd.h>
32
33static void sanity_check(void);
34static void make_dist(char *, char *, char *, Package *);
35
36static char *home;
37
38int
39pkg_perform(char **pkgs)
40{
41    char *pkg = *pkgs;		/* Only one arg to create */
42    char *cp;
43    FILE *pkg_in, *fp;
44    Package plist;
45    char *suffix;  /* What we tack on to the end of the finished package */
46
47    /* Preliminary setup */
48    sanity_check();
49    if (Verbose && !PlistOnly)
50	printf("Creating package %s\n", pkg);
51    get_dash_string(&Comment);
52    get_dash_string(&Desc);
53    if (!strcmp(Contents, "-"))
54	pkg_in = stdin;
55    else {
56	pkg_in = fopen(Contents, "r");
57	if (!pkg_in)
58	    barf("Unable to open contents file '%s' for input.", Contents);
59    }
60    plist.head = plist.tail = NULL;
61
62    /* Break the package name into base and desired suffix (if any) */
63    if ((cp = rindex(pkg, '.')) != NULL) {
64	suffix = cp + 1;
65	*cp = '\0';
66    }
67    else
68	suffix = "tgz";
69
70    /* Stick the dependencies, if any, at the top */
71    if (Pkgdeps) {
72	if (Verbose && !PlistOnly)
73	    printf("Registering depends:");
74	while (Pkgdeps) {
75	    cp = strsep(&Pkgdeps, " \t\n");
76	    if (*cp) {
77		add_plist(&plist, PLIST_PKGDEP, cp);
78		if (Verbose && !PlistOnly)
79		    printf(" %s", cp);
80	    }
81	}
82	if (Verbose && !PlistOnly)
83	    printf(".\n");
84    }
85    /* Slurp in the packing list */
86    read_plist(&plist, pkg_in);
87
88    /* Prefix should override the packing list */
89    if (Prefix) {
90	delete_plist(&plist, FALSE, PLIST_CWD, NULL);
91	add_plist_top(&plist, PLIST_CWD, Prefix);
92    }
93    /*
94     * Run down the list and see if we've named it, if not stick in a name
95     * at the top.
96     */
97    if (find_plist(&plist, PLIST_NAME) == NULL)
98	add_plist_top(&plist, PLIST_NAME, basename_of(pkg));
99
100    /*
101     * We're just here for to dump out a revised plist for the FreeBSD ports
102     * hack.  It's not a real create in progress.
103     */
104    if (PlistOnly) {
105	write_plist(&plist, stdout);
106	exit(0);
107    }
108
109    /* Make a directory to stomp around in */
110    home = make_playpen(PlayPen, 0);
111    signal(SIGINT, cleanup);
112    signal(SIGHUP, cleanup);
113
114    /* Make first "real contents" pass over it */
115    check_list(home, &plist);
116    (void) umask(022);	/* make sure gen'ed directories, files don't have
117			   group or other write bits. */
118    /* copy_plist(home, &plist); */
119    /* mark_plist(&plist); */
120
121    /* Now put the release specific items in */
122    add_plist(&plist, PLIST_CWD, ".");
123    write_file(COMMENT_FNAME, Comment);
124    add_plist(&plist, PLIST_IGNORE, NULL);
125    add_plist(&plist, PLIST_FILE, COMMENT_FNAME);
126    write_file(DESC_FNAME, Desc);
127    add_plist(&plist, PLIST_IGNORE, NULL);
128    add_plist(&plist, PLIST_FILE, DESC_FNAME);
129
130    if (Install) {
131	copy_file(home, Install, INSTALL_FNAME);
132	add_plist(&plist, PLIST_IGNORE, NULL);
133	add_plist(&plist, PLIST_FILE, INSTALL_FNAME);
134    }
135    if (DeInstall) {
136	copy_file(home, DeInstall, DEINSTALL_FNAME);
137	add_plist(&plist, PLIST_IGNORE, NULL);
138	add_plist(&plist, PLIST_FILE, DEINSTALL_FNAME);
139    }
140    if (Require) {
141	copy_file(home, Require, REQUIRE_FNAME);
142	add_plist(&plist, PLIST_IGNORE, NULL);
143	add_plist(&plist, PLIST_FILE, REQUIRE_FNAME);
144    }
145    if (Display) {
146	copy_file(home, Display, DISPLAY_FNAME);
147	add_plist(&plist, PLIST_IGNORE, NULL);
148	add_plist(&plist, PLIST_FILE, DISPLAY_FNAME);
149	add_plist(&plist, PLIST_DISPLAY, DISPLAY_FNAME);
150    }
151    if (Mtree) {
152	copy_file(home, Mtree, MTREE_FNAME);
153	add_plist(&plist, PLIST_IGNORE, NULL);
154	add_plist(&plist, PLIST_FILE, MTREE_FNAME);
155	add_plist(&plist, PLIST_MTREE, MTREE_FNAME);
156    }
157
158    /* Run through the list again, picking up extra "local" items */
159    /* check_list(".", &plist); */
160    /* copy_plist(".", &plist); */
161    /* mark_plist(&plist); */
162
163    /* Finally, write out the packing list */
164    fp = fopen(CONTENTS_FNAME, "w");
165    if (!fp)
166	barf("Can't open file %s for writing.", CONTENTS_FNAME);
167    write_plist(&plist, fp);
168    if (fclose(fp))
169	barf("Error while closing %s.", CONTENTS_FNAME);
170
171    /* And stick it into a tar ball */
172    make_dist(home, pkg, suffix, &plist);
173
174    /* Cleanup */
175    free(Comment);
176    free(Desc);
177    free_plist(&plist);
178    cleanup(0);
179    return TRUE;	/* Success */
180}
181
182static void
183make_dist(char *home, char *pkg, char *suffix, Package *plist)
184{
185    char tball[FILENAME_MAX];
186    PackingList p;
187    int ret, max, len;
188    char *args[50];	/* Much more than enough. */
189    int nargs = 0;
190    int pipefds[2];
191    FILE *totar;
192    pid_t pid;
193
194    args[nargs++] = "tar";	/* argv[0] */
195
196    if (*pkg == '/')
197	snprintf(tball, FILENAME_MAX, "%s.%s", pkg, suffix);
198    else
199	snprintf(tball, FILENAME_MAX, "%s/%s.%s", home, pkg, suffix);
200
201    args[nargs++] = "-c";
202    args[nargs++] = "-f";
203    args[nargs++] = tball;
204    if (index(suffix, 'z'))	/* Compress/gzip? */
205	args[nargs++] = "-z";
206    if (Dereference)
207	args[nargs++] = "-h";
208    if (ExcludeFrom) {
209	args[nargs++] = "-X";
210	args[nargs++] = ExcludeFrom;
211    }
212    args[nargs++] = "-T";	/* Take filenames from file instead of args. */
213    args[nargs++] = "-";	/* Use stdin for the file. */
214    args[nargs] = NULL;
215
216    if (Verbose)
217	printf("Creating gzip'd tar ball in '%s'\n", tball);
218
219    /* Set up a pipe for passing the filenames, and fork off a tar process. */
220    if (pipe(pipefds) == -1)
221	barf("Cannot create pipe: %s", strerror(errno));
222    if ((pid = fork()) == -1)
223	barf("Cannot fork process for tar: %s", strerror(errno));
224    if (pid == 0) {	/* The child */
225	dup2(pipefds[0], 0);
226	close(pipefds[1]);
227	execv("/usr/bin/tar", args);
228	barf("Failed to execute tar command: %s", strerror(errno));
229    }
230
231    /* Meanwhile, back in the parent process ... */
232    close(pipefds[0]);
233    if ((totar = fdopen(pipefds[1], "w")) == NULL)
234	barf("fdopen failed: %s", strerror(errno));
235
236    fprintf(totar, "%s\n", CONTENTS_FNAME);
237    fprintf(totar, "%s\n", COMMENT_FNAME);
238    fprintf(totar, "%s\n", DESC_FNAME);
239
240    if (Install)
241	fprintf(totar, "%s\n", INSTALL_FNAME);
242    if (DeInstall)
243	fprintf(totar, "%s\n", DEINSTALL_FNAME);
244    if (Require)
245	fprintf(totar, "%s\n", REQUIRE_FNAME);
246    if (Display)
247	fprintf(totar, "%s\n", DISPLAY_FNAME);
248    if (Mtree)
249	fprintf(totar, "%s\n", MTREE_FNAME);
250
251    for (p = plist->head; p; p = p->next) {
252	if (p->type == PLIST_FILE)
253	    fprintf(totar, "%s\n", p->name);
254	else if (p->type == PLIST_CWD || p->type == PLIST_SRC)
255	    fprintf(totar, "-C\n%s\n", p->name);
256	else if (p->type == PLIST_IGNORE)
257	     p = p->next;
258    }
259
260    fclose(totar);
261    wait(&ret);
262    /* assume either signal or bad exit is enough for us */
263    if (ret)
264	barf("tar command failed with code %d", ret);
265}
266
267static void
268sanity_check()
269{
270    if (!Comment)
271	barf("Required package comment string is missing (-c comment).");
272    if (!Desc)
273	barf("Required package description string is missing (-d desc).");
274    if (!Contents)
275	barf("Required package contents list is missing (-f [-]file).");
276}
277
278
279/* Clean up those things that would otherwise hang around */
280void
281cleanup(int sig)
282{
283    leave_playpen(home);
284}
285