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