1/* 2 * FreeBSD install - a package for the installation and maintainance 3 * of non-core utilities. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * Jordan K. Hubbard 15 * 18 July 1993 16 * 17 * This is the main body of the add module. 18 * 19 */ 20 21#include <sys/cdefs.h> 22__FBSDID("$FreeBSD$"); 23 24#include <err.h> 25#include <paths.h> 26#include "lib.h" 27#include "add.h" 28 29#include <libgen.h> 30#include <signal.h> 31#include <sys/wait.h> 32 33static int pkg_do(char *); 34static int sanity_check(char *); 35static char LogDir[FILENAME_MAX]; 36static int zapLogDir; /* Should we delete LogDir? */ 37 38int 39pkg_perform(char **pkgs) 40{ 41 int i, err_cnt = 0; 42 43 signal(SIGINT, cleanup); 44 signal(SIGHUP, cleanup); 45 46 if (AddMode == SLAVE) 47 err_cnt = pkg_do(NULL); 48 else { 49 for (i = 0; pkgs[i]; i++) 50 err_cnt += pkg_do(pkgs[i]); 51 } 52 return err_cnt; 53} 54 55/* 56 * This is seriously ugly code following. Written very fast! 57 * [And subsequently made even worse.. Sigh! This code was just born 58 * to be hacked, I guess.. :) -jkh] 59 */ 60static int 61pkg_do(char *pkg) 62{ 63 Package Plist; 64 char pkg_fullname[FILENAME_MAX]; 65 char playpen[FILENAME_MAX]; 66 char extract_contents[FILENAME_MAX]; 67 char *extract; 68 const char *where_to; 69 FILE *cfile; 70 int code; 71 PackingList p; 72 struct stat sb; 73 int inPlace, conflictsfound, errcode; 74 /* support for separate pre/post install scripts */ 75 int new_m = 0; 76 char pre_script[FILENAME_MAX] = INSTALL_FNAME; 77 char post_script[FILENAME_MAX]; 78 char pre_arg[FILENAME_MAX], post_arg[FILENAME_MAX]; 79 char *conflict[2]; 80 char **matched; 81 int fd; 82 83 conflictsfound = 0; 84 code = 0; 85 zapLogDir = 0; 86 LogDir[0] = '\0'; 87 strcpy(playpen, FirstPen); 88 inPlace = 0; 89 90 memset(&Plist, '\0', sizeof(Plist)); 91 92 /* Are we coming in for a second pass, everything already extracted? */ 93 if (!pkg) { 94 fgets(playpen, FILENAME_MAX, stdin); 95 playpen[strlen(playpen) - 1] = '\0'; /* pesky newline! */ 96 if (chdir(playpen) == FAIL) { 97 warnx("pkg_add in SLAVE mode can't chdir to %s", playpen); 98 return 1; 99 } 100 read_plist(&Plist, stdin); 101 where_to = playpen; 102 } 103 /* Nope - do it now */ 104 else { 105 /* Is it an ftp://foo.bar.baz/file.t[bg]z specification? */ 106 if (isURL(pkg)) { 107 if (!(where_to = fileGetURL(NULL, pkg, KeepPackage))) { 108 warnx("unable to fetch '%s' by URL", pkg); 109 return 1; 110 } 111 strcpy(pkg_fullname, pkg); 112 cfile = fopen(CONTENTS_FNAME, "r"); 113 if (!cfile) { 114 warnx( 115 "unable to open table of contents file '%s' - not a package?", 116 CONTENTS_FNAME); 117 goto bomb; 118 } 119 read_plist(&Plist, cfile); 120 fclose(cfile); 121 } 122 else { 123 strcpy(pkg_fullname, pkg); /* 124 * Copy for sanity's sake, 125 * could remove pkg_fullname 126 */ 127 if (strcmp(pkg, "-")) { 128 if (stat(pkg_fullname, &sb) == FAIL) { 129 warnx("can't stat package file '%s'", pkg_fullname); 130 goto bomb; 131 } 132 sprintf(extract_contents, "--fast-read %s", CONTENTS_FNAME); 133 extract = extract_contents; 134 } 135 else { 136 extract = NULL; 137 sb.st_size = 100000; /* Make up a plausible average size */ 138 } 139 if (!(where_to = make_playpen(playpen, sb.st_size * 4))) 140 errx(1, "unable to make playpen for %lld bytes", (long long)sb.st_size * 4); 141 /* Since we can call ourselves recursively, keep notes on where we came from */ 142 if (!getenv("_TOP")) 143 setenv("_TOP", where_to, 1); 144 if (unpack(pkg_fullname, extract)) { 145 warnx( 146 "unable to extract table of contents file from '%s' - not a package?", 147 pkg_fullname); 148 goto bomb; 149 } 150 cfile = fopen(CONTENTS_FNAME, "r"); 151 if (!cfile) { 152 warnx( 153 "unable to open table of contents file '%s' - not a package?", 154 CONTENTS_FNAME); 155 goto bomb; 156 } 157 read_plist(&Plist, cfile); 158 fclose(cfile); 159 160 /* Extract directly rather than moving? Oh goodie! */ 161 if (find_plist_option(&Plist, "extract-in-place")) { 162 if (Verbose) 163 printf("Doing in-place extraction for %s\n", pkg_fullname); 164 p = find_plist(&Plist, PLIST_CWD); 165 if (p) { 166 if (!isdir(p->name) && !Fake) { 167 if (Verbose) 168 printf("Desired prefix of %s does not exist, creating..\n", p->name); 169 vsystem("/bin/mkdir -p %s", p->name); 170 if (chdir(p->name) == -1) { 171 warn("unable to change directory to '%s'", p->name); 172 goto bomb; 173 } 174 } 175 where_to = p->name; 176 inPlace = 1; 177 } 178 else { 179 warnx( 180 "no prefix specified in '%s' - this is a bad package!", 181 pkg_fullname); 182 goto bomb; 183 } 184 } 185 186 /* 187 * Apply a crude heuristic to see how much space the package will 188 * take up once it's unpacked. I've noticed that most packages 189 * compress an average of 75%, so multiply by 4 for good measure. 190 */ 191 192 if (!extract && !inPlace && min_free(playpen) < sb.st_size * 4) { 193 warnx("projected size of %lld exceeds available free space.\n" 194"Please set your PKG_TMPDIR variable to point to a location with more\n" 195 "free space and try again", (long long)sb.st_size * 4); 196 warnx("not extracting %s\ninto %s, sorry!", 197 pkg_fullname, where_to); 198 goto bomb; 199 } 200 201 /* If this is a direct extract and we didn't want it, stop now */ 202 if (inPlace && Fake) 203 goto success; 204 205 /* Finally unpack the whole mess. If extract is null we 206 already + did so so don't bother doing it again. */ 207 if (extract && unpack(pkg_fullname, NULL)) { 208 warnx("unable to extract '%s'!", pkg_fullname); 209 goto bomb; 210 } 211 } 212 213 /* Check for sanity and dependencies */ 214 if (sanity_check(pkg)) 215 goto bomb; 216 217 /* If we're running in MASTER mode, just output the plist and return */ 218 if (AddMode == MASTER) { 219 printf("%s\n", where_playpen()); 220 write_plist(&Plist, stdout); 221 return 0; 222 } 223 } 224 225 /* 226 * If we have a prefix, delete the first one we see and add this 227 * one in place of it. 228 */ 229 if (Prefix) { 230 delete_plist(&Plist, FALSE, PLIST_CWD, NULL); 231 add_plist_top(&Plist, PLIST_CWD, Prefix); 232 } 233 234 setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : ".", 1); 235 /* Protect against old packages with bogus @name and origin fields */ 236 if (Plist.name == NULL) 237 Plist.name = "anonymous"; 238 if (Plist.origin == NULL) 239 Plist.origin = "anonymous/anonymous"; 240 241 /* 242 * See if we're already registered either with the same name (the same 243 * version) or some other version with the same origin. 244 */ 245 if ((isinstalledpkg(Plist.name) > 0 || 246 matchbyorigin(Plist.origin, NULL) != NULL) && !Force) { 247 warnx("package '%s' or its older version already installed%s", 248 Plist.name, FailOnAlreadyInstalled ? "" : " (ignored)"); 249 code = FailOnAlreadyInstalled != FALSE; 250 goto success; /* close enough for government work */ 251 } 252 253 /* Now check the packing list for conflicts */ 254 if (!IgnoreDeps){ 255 for (p = Plist.head; p != NULL; p = p->next) { 256 if (p->type == PLIST_CONFLICTS) { 257 int i; 258 conflict[0] = strdup(p->name); 259 conflict[1] = NULL; 260 matched = matchinstalled(MATCH_GLOB, conflict, &errcode); 261 free(conflict[0]); 262 if (errcode == 0 && matched != NULL) 263 for (i = 0; matched[i] != NULL; i++) 264 if (isinstalledpkg(matched[i]) > 0) { 265 warnx("package '%s' conflicts with %s", Plist.name, 266 matched[i]); 267 conflictsfound = 1; 268 } 269 270 continue; 271 } 272 } 273 if(conflictsfound) { 274 if(!Force) { 275 warnx("please use pkg_delete first to remove conflicting package(s) or -f to force installation"); 276 code = 1; 277 goto bomb; 278 } else 279 warnx("-f specified; proceeding anyway"); 280 } 281 282#if ENSURE_THAT_ALL_REQUIREMENTS_ARE_MET 283 /* 284 * Before attempting to do the slave mode bit, ensure that we've 285 * downloaded & processed everything we need. 286 * It's possible that we haven't already installed all of our 287 * dependencies if the dependency list was misgenerated due to 288 * other dynamic dependencies or if a dependency was added to a 289 * package without all REQUIRED_BY packages being regenerated. 290 */ 291 for (p = pkg ? Plist.head : NULL; p; p = p->next) { 292 const char *ext; 293 char *deporigin; 294 295 if (p->type != PLIST_PKGDEP) 296 continue; 297 deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL; 298 299 if (isinstalledpkg(p->name) <= 0 && 300 !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) { 301 char subpkg[FILENAME_MAX], *sep; 302 303 strlcpy(subpkg, pkg, sizeof subpkg); 304 if ((sep = strrchr(subpkg, '/')) != NULL) { 305 *sep = '\0'; 306 if ((sep = strrchr(subpkg, '/')) != NULL) { 307 *sep = '\0'; 308 strlcat(subpkg, "/All/", sizeof subpkg); 309 strlcat(subpkg, p->name, sizeof subpkg); 310 if ((ext = strrchr(pkg, '.')) == NULL) { 311 if (getenv("PACKAGESUFFIX")) 312 ext = getenv("PACKAGESUFFIX"); 313 else 314 ext = ".tbz"; 315 } 316 strlcat(subpkg, ext, sizeof subpkg); 317 pkg_do(subpkg); 318 } 319 } 320 } 321 } 322#endif 323 324 /* Now check the packing list for dependencies */ 325 for (p = Plist.head; p ; p = p->next) { 326 char *deporigin; 327 328 if (p->type != PLIST_PKGDEP) 329 continue; 330 deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL; 331 if (Verbose) { 332 printf("Package '%s' depends on '%s'", Plist.name, p->name); 333 if (deporigin != NULL) 334 printf(" with '%s' origin", deporigin); 335 printf(".\n"); 336 } 337 if (isinstalledpkg(p->name) <= 0 && 338 !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) { 339 char path[FILENAME_MAX]; 340 const char *cp = NULL; 341 342 if (!Fake) { 343 char prefixArg[2 + MAXPATHLEN]; /* "-P" + Prefix */ 344 if (PrefixRecursive) { 345 strlcpy(prefixArg, "-P", sizeof(prefixArg)); 346 strlcat(prefixArg, Prefix, sizeof(prefixArg)); 347 } 348 if (!isURL(pkg) && !getenv("PKG_ADD_BASE")) { 349 const char *ext; 350 351 ext = strrchr(pkg_fullname, '.'); 352 if (ext == NULL) { 353 if (getenv("PACKAGESUFFIX")) { 354 ext = getenv("PACKAGESUFFIX"); 355 } else { 356 ext = ".tbz"; 357 } 358 } 359 snprintf(path, FILENAME_MAX, "%s/%s%s", getenv("_TOP"), p->name, ext); 360 if (fexists(path)) 361 cp = path; 362 else 363 cp = fileFindByPath(pkg, p->name); 364 if (cp) { 365 if (Verbose) 366 printf("Loading it from %s.\n", cp); 367 if (vsystem("%s %s %s '%s'", PkgAddCmd, Verbose ? "-v " : "", PrefixRecursive ? prefixArg : "", cp)) { 368 warnx("autoload of dependency '%s' failed%s", 369 cp, Force ? " (proceeding anyway)" : "!"); 370 if (!Force) 371 ++code; 372 } 373 } 374 else { 375 warnx("could not find package %s %s", 376 p->name, Force ? " (proceeding anyway)" : "!"); 377 if (!Force) 378 ++code; 379 } 380 } 381 else if ((cp = fileGetURL(pkg, p->name, KeepPackage)) != NULL) { 382 if (Verbose) 383 printf("Finished loading %s via a URL\n", p->name); 384 if (!fexists("+CONTENTS")) { 385 warnx("autoloaded package %s has no +CONTENTS file?", 386 p->name); 387 if (!Force) 388 ++code; 389 } 390 else if (vsystem("(pwd; /bin/cat +CONTENTS) | %s %s %s %s -S", PkgAddCmd, Verbose ? "-v" : "", PrefixRecursive ? prefixArg : "", KeepPackage ? "-K" : "")) { 391 warnx("pkg_add of dependency '%s' failed%s", 392 p->name, Force ? " (proceeding anyway)" : "!"); 393 if (!Force) 394 ++code; 395 } 396 else if (Verbose) 397 printf("\t'%s' loaded successfully.\n", p->name); 398 /* Nuke the temporary playpen */ 399 leave_playpen(); 400 } 401 } 402 else { 403 if (Verbose) 404 printf("and was not found%s.\n", Force ? " (proceeding anyway)" : ""); 405 else 406 printf("Package dependency %s for %s not found%s\n", p->name, pkg, 407 Force ? " (proceeding anyway)" : "!"); 408 if (!Force) 409 ++code; 410 } 411 } 412 else if (Verbose) 413 printf(" - already installed.\n"); 414 } 415 } /* if (!IgnoreDeps) */ 416 417 if (code != 0) 418 goto bomb; 419 420 /* Look for the requirements file */ 421 if ((fd = open(REQUIRE_FNAME, O_RDWR)) != -1) { 422 fstat(fd, &sb); 423 fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */ 424 close(fd); 425 if (Verbose) 426 printf("Running requirements file first for %s..\n", Plist.name); 427 if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, Plist.name)) { 428 warnx("package %s fails requirements %s", pkg_fullname, 429 Force ? "installing anyway" : "- not installed"); 430 if (!Force) { 431 code = 1; 432 goto success; /* close enough for government work */ 433 } 434 } 435 } 436 437 /* 438 * Test whether to use the old method of passing tokens to installation 439 * scripts, and set appropriate variables.. 440 */ 441 442 if (fexists(POST_INSTALL_FNAME)) { 443 new_m = 1; 444 sprintf(post_script, "%s", POST_INSTALL_FNAME); 445 pre_arg[0] = '\0'; 446 post_arg[0] = '\0'; 447 } else { 448 if (fexists(INSTALL_FNAME)) { 449 sprintf(post_script, "%s", INSTALL_FNAME); 450 sprintf(pre_arg, "PRE-INSTALL"); 451 sprintf(post_arg, "POST-INSTALL"); 452 } 453 } 454 455 /* If we're really installing, and have an installation file, run it */ 456 if (!NoInstall && (fd = open(pre_script, O_RDWR)) != -1) { 457 fstat(fd, &sb); 458 fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */ 459 close(fd); 460 if (Verbose) 461 printf("Running pre-install for %s..\n", Plist.name); 462 if (!Fake && vsystem("./%s %s %s", pre_script, Plist.name, pre_arg)) { 463 warnx("install script returned error status"); 464 unlink(pre_script); 465 code = 1; 466 goto success; /* nothing to uninstall yet */ 467 } 468 } 469 470 /* Now finally extract the entire show if we're not going direct */ 471 if (!inPlace && !Fake) 472 extract_plist(".", &Plist); 473 474 if (!Fake && fexists(MTREE_FNAME)) { 475 if (Verbose) 476 printf("Running mtree for %s..\n", Plist.name); 477 p = find_plist(&Plist, PLIST_CWD); 478 if (Verbose) 479 printf("mtree -U -f %s -d -e -p %s >%s\n", MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL); 480 if (!Fake) { 481 if (vsystem("/usr/sbin/mtree -U -f %s -d -e -p %s >%s", MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL)) 482 warnx("mtree returned a non-zero status - continuing"); 483 } 484 } 485 486 /* Run the installation script one last time? */ 487 if (!NoInstall && (fd = open(post_script, O_RDWR)) != -1) { 488 fstat(fd, &sb); 489 fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */ 490 close(fd); 491 if (Verbose) 492 printf("Running post-install for %s..\n", Plist.name); 493 if (!Fake && vsystem("./%s %s %s", post_script, Plist.name, post_arg)) { 494 warnx("install script returned error status"); 495 unlink(post_script); 496 code = 1; 497 goto fail; 498 } 499 } 500 501 /* Time to record the deed? */ 502 if (!NoRecord && !Fake) { 503 char contents[FILENAME_MAX]; 504 char **depnames = NULL, **deporigins = NULL, ***depmatches; 505 int i, dep_count = 0; 506 FILE *contfile; 507 508 if (getuid() != 0) 509 warnx("not running as root - trying to record install anyway"); 510 sprintf(LogDir, "%s/%s", LOG_DIR, Plist.name); 511 zapLogDir = 1; 512 if (Verbose) 513 printf("Attempting to record package into %s..\n", LogDir); 514 if (make_hierarchy(LogDir, FALSE)) { 515 warnx("can't record package into '%s', you're on your own!", 516 LogDir); 517 bzero(LogDir, FILENAME_MAX); 518 code = 1; 519 goto success; /* close enough for government work */ 520 } 521 /* Make sure pkg_info can read the entry */ 522 fd = open(LogDir, O_RDWR); 523 fstat(fd, &sb); 524 fchmod(fd, sb.st_mode | S_IRALL | S_IXALL); /* be sure, chmod a+rx */ 525 close(fd); 526 move_file(".", DESC_FNAME, LogDir); 527 move_file(".", COMMENT_FNAME, LogDir); 528 if (fexists(INSTALL_FNAME)) 529 move_file(".", INSTALL_FNAME, LogDir); 530 if (fexists(POST_INSTALL_FNAME)) 531 move_file(".", POST_INSTALL_FNAME, LogDir); 532 if (fexists(DEINSTALL_FNAME)) 533 move_file(".", DEINSTALL_FNAME, LogDir); 534 if (fexists(POST_DEINSTALL_FNAME)) 535 move_file(".", POST_DEINSTALL_FNAME, LogDir); 536 if (fexists(REQUIRE_FNAME)) 537 move_file(".", REQUIRE_FNAME, LogDir); 538 if (fexists(DISPLAY_FNAME)) 539 move_file(".", DISPLAY_FNAME, LogDir); 540 if (fexists(MTREE_FNAME)) 541 move_file(".", MTREE_FNAME, LogDir); 542 sprintf(contents, "%s/%s", LogDir, CONTENTS_FNAME); 543 contfile = fopen(contents, "w"); 544 if (!contfile) { 545 warnx("can't open new contents file '%s'! can't register pkg", 546 contents); 547 goto success; /* can't log, but still keep pkg */ 548 } 549 write_plist(&Plist, contfile); 550 fclose(contfile); 551 for (p = Plist.head; p ; p = p->next) { 552 char *deporigin; 553 554 if (p->type != PLIST_PKGDEP) 555 continue; 556 deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : 557 NULL; 558 if (Verbose) { 559 printf("Trying to record dependency on package '%s'", p->name); 560 if (deporigin != NULL) 561 printf(" with '%s' origin", deporigin); 562 printf(".\n"); 563 } 564 565 if (deporigin) { 566 /* Defer to origin lookup */ 567 depnames = realloc(depnames, (dep_count + 1) * sizeof(*depnames)); 568 depnames[dep_count] = p->name; 569 deporigins = realloc(deporigins, (dep_count + 2) * sizeof(*deporigins)); 570 deporigins[dep_count] = deporigin; 571 deporigins[dep_count + 1] = NULL; 572 dep_count++; 573 } else { 574 /* No origin recorded, try to register on literal package name */ 575 sprintf(contents, "%s/%s/%s", LOG_DIR, p->name, 576 REQUIRED_BY_FNAME); 577 contfile = fopen(contents, "a"); 578 if (!contfile) { 579 warnx("can't open dependency file '%s'!\n" 580 "dependency registration is incomplete", contents); 581 } else { 582 fprintf(contfile, "%s\n", Plist.name); 583 if (fclose(contfile) == EOF) { 584 warnx("cannot properly close file %s", contents); 585 } 586 } 587 } 588 } 589 if (dep_count > 0) { 590 depmatches = matchallbyorigin((const char **)deporigins, NULL); 591 free(deporigins); 592 if (!IgnoreDeps && depmatches) { 593 for (i = 0; i < dep_count; i++) { 594 if (depmatches[i]) { 595 int j; 596 char **tmp = depmatches[i]; 597 for (j = 0; tmp[j] != NULL; j++) { 598 /* Origin looked up */ 599 sprintf(contents, "%s/%s/%s", LOG_DIR, tmp[j], 600 REQUIRED_BY_FNAME); 601 if (depnames[i] && strcmp(depnames[i], tmp[j]) != 0) 602 warnx("warning: package '%s' requires '%s', but '%s' " 603 "is installed", Plist.name, depnames[i], tmp[j]); 604 contfile = fopen(contents, "a"); 605 if (!contfile) { 606 warnx("can't open dependency file '%s'!\n" 607 "dependency registration is incomplete", contents); 608 } else { 609 fprintf(contfile, "%s\n", Plist.name); 610 if (fclose(contfile) == EOF) 611 warnx("cannot properly close file %s", contents); 612 } 613 } 614 } else if (depnames[i]) { 615 /* No package present with this origin, try literal package name */ 616 sprintf(contents, "%s/%s/%s", LOG_DIR, depnames[i], 617 REQUIRED_BY_FNAME); 618 contfile = fopen(contents, "a"); 619 if (!contfile) { 620 warnx("can't open dependency file '%s'!\n" 621 "dependency registration is incomplete", contents); 622 } else { 623 fprintf(contfile, "%s\n", Plist.name); 624 if (fclose(contfile) == EOF) { 625 warnx("cannot properly close file %s", contents); 626 } 627 } 628 } 629 } 630 } 631 } 632 if (Verbose) 633 printf("Package %s registered in %s\n", Plist.name, LogDir); 634 } 635 636 if ((p = find_plist(&Plist, PLIST_DISPLAY)) != NULL) { 637 FILE *fp; 638 char buf[BUFSIZ]; 639 640 snprintf(buf, sizeof buf, "%s/%s", LogDir, p->name); 641 fp = fopen(buf, "r"); 642 if (fp) { 643 putc('\n', stdout); 644 while (fgets(buf, sizeof(buf), fp)) 645 fputs(buf, stdout); 646 putc('\n', stdout); 647 (void) fclose(fp); 648 } else { 649 if (!Fake) { 650 warnx("cannot open %s as display file", buf); 651 } 652 } 653 } 654 655 goto success; 656 657 bomb: 658 code = 1; 659 goto success; 660 661 fail: 662 /* Nuke the whole (installed) show, XXX but don't clean directories */ 663 if (!Fake) 664 delete_package(FALSE, FALSE, &Plist); 665 666 success: 667 /* delete the packing list contents */ 668 free_plist(&Plist); 669 leave_playpen(); 670 return code; 671} 672 673static int 674sanity_check(char *pkg) 675{ 676 int code = 0; 677 678 if (!fexists(CONTENTS_FNAME)) { 679 warnx("package %s has no CONTENTS file!", pkg); 680 code = 1; 681 } 682 else if (!fexists(COMMENT_FNAME)) { 683 warnx("package %s has no COMMENT file!", pkg); 684 code = 1; 685 } 686 else if (!fexists(DESC_FNAME)) { 687 warnx("package %s has no DESC file!", pkg); 688 code = 1; 689 } 690 return code; 691} 692 693void 694cleanup(int sig) 695{ 696 static int in_cleanup = 0; 697 698 if (!in_cleanup) { 699 in_cleanup = 1; 700 if (sig) 701 printf("Signal %d received, cleaning up..\n", sig); 702 if (!Fake && zapLogDir && LogDir[0]) 703 vsystem("%s -rf %s", REMOVE_CMD, LogDir); 704 while (leave_playpen()) 705 ; 706 } 707 if (sig) 708 exit(1); 709} 710