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