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