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