perform.c revision 3574
1#ifndef lint 2static const char *rcsid = "$Id: perform.c,v 1.9 1994/10/04 16:07:43 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 add module. 22 * 23 */ 24 25#include "lib.h" 26#include "add.h" 27 28#include <signal.h> 29 30static int pkg_do(char *); 31static int sanity_check(char *); 32static char LogDir[FILENAME_MAX]; 33 34 35int 36pkg_perform(char **pkgs) 37{ 38 int i, err_cnt = 0; 39 40 signal(SIGINT, cleanup); 41 signal(SIGHUP, cleanup); 42 43 if (AddMode == SLAVE) 44 err_cnt = pkg_do(NULL); 45 else { 46 for (i = 0; pkgs[i]; i++) 47 err_cnt += pkg_do(pkgs[i]); 48 } 49 return err_cnt; 50} 51 52static Package Plist; 53 54/* This is seriously ugly code following. Written very fast! */ 55static int 56pkg_do(char *pkg) 57{ 58 char pkg_fullname[FILENAME_MAX]; 59 FILE *cfile; 60 int code = 0; 61 PackingList p; 62 struct stat sb; 63 64 /* Reset some state */ 65 if (Plist.head) 66 free_plist(&Plist); 67 LogDir[0] = '\0'; 68 if (AddMode == SLAVE) { 69 char tmp_dir[FILENAME_MAX]; 70 71 fgets(tmp_dir, FILENAME_MAX, stdin); 72 tmp_dir[strlen(tmp_dir) - 1] = '\0'; /* pesky newline! */ 73 if (chdir(tmp_dir) == FAIL) { 74 whinge("pkg_add in SLAVE mode can't chdir to %s.", tmp_dir); 75 return 1; 76 } 77 read_plist(&Plist, stdin); 78 } 79 else { 80 char home[FILENAME_MAX]; 81 82 if (!getcwd(home, FILENAME_MAX)) 83 upchuck("getcwd"); 84 85 if (pkg[0] == '/') /* full pathname? */ 86 strcpy(pkg_fullname, pkg); 87 else 88 sprintf(pkg_fullname, "%s/%s", home, pkg); 89 if (!fexists(pkg_fullname)) { 90 whinge("Can't find package '%s'.", pkg_fullname); 91 return 1; 92 } 93 /* 94 * Apply a crude heuristic to see how much space the package will 95 * take up once it's unpacked. I've noticed that most packages 96 * compress an average of 75%, so multiply by 4 for good measure. 97 */ 98 if (stat(pkg_fullname, &sb) == FAIL) { 99 whinge("Can't stat package file '%s'.", pkg_fullname); 100 return 1; 101 } 102 sb.st_size *= 4; 103 (void)make_playpen(PlayPen, sb.st_size); 104 if (unpack(pkg_fullname, NULL)) 105 return 1; 106 107 if (sanity_check(pkg_fullname)) 108 return 1; 109 110 cfile = fopen(CONTENTS_FNAME, "r"); 111 if (!cfile) { 112 whinge("Unable to open %s file.", CONTENTS_FNAME); 113 goto fail; 114 } 115 read_plist(&Plist, cfile); 116 fclose(cfile); 117 if (Prefix) { 118 /* 119 * If we have a prefix, delete the first one we see and add this 120 * one in place of it. 121 */ 122 delete_plist(&Plist, FALSE, PLIST_CWD, NULL); 123 add_plist_top(&Plist, PLIST_CWD, Prefix); 124 } 125 /* If we're running in MASTER mode, just output the plist and return */ 126 if (AddMode == MASTER) { 127 printf("%s\n", where_playpen()); 128 write_plist(&Plist, stdout); 129 return 0; 130 } 131 } 132 setenv(PKG_PREFIX_VNAME, 133 (p = find_plist(&Plist, PLIST_CWD)) ? p->name : NULL, 1); 134 PkgName = (p = find_plist(&Plist, PLIST_NAME)) ? p->name : "anonymous"; 135 if (fexists(REQUIRE_FNAME)) { 136 vsystem("chmod +x %s", REQUIRE_FNAME); /* be sure */ 137 if (Verbose) 138 printf("Running requirements file first for %s..\n", PkgName); 139 if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, PkgName)) { 140 whinge("Package %s fails requirements - not installed.", 141 pkg_fullname); 142 return 1; 143 } 144 } 145 if (!NoInstall && fexists(INSTALL_FNAME)) { 146 vsystem("chmod +x %s", INSTALL_FNAME); /* make sure */ 147 if (Verbose) 148 printf("Running install with PRE-INSTALL for %s..\n", PkgName); 149 if (!Fake && vsystem("./%s %s PRE-INSTALL", INSTALL_FNAME, PkgName)) { 150 whinge("Install script returned error status."); 151 goto fail; 152 } 153 } 154 extract_plist(home, &Plist); 155 if (!NoInstall && fexists(INSTALL_FNAME)) { 156 if (Verbose) 157 printf("Running install with POST-INSTALL for %s..\n", PkgName); 158 if (!Fake && vsystem("./%s %s POST-INSTALL", INSTALL_FNAME, PkgName)) { 159 whinge("Install script returned error status."); 160 goto fail; 161 } 162 } 163 if (!NoRecord && !Fake) { 164 char contents[FILENAME_MAX]; 165 FILE *cfile; 166 167 if (getuid() != 0) 168 whinge("Not running as root - trying to record install anyway."); 169 if (!PkgName) { 170 whinge("No package name! Can't record package, sorry."); 171 code = 1; 172 goto success; /* well, partial anyway */ 173 } 174 sprintf(LogDir, "%s/%s", LOG_DIR, PkgName); 175 if (Verbose) 176 printf("Attempting to record package into %s..\n", LogDir); 177 if (make_hierarchy(LogDir)) { 178 whinge("Can't record package into '%s', you're on your own!", 179 LogDir); 180 bzero(LogDir, FILENAME_MAX); 181 code = 1; 182 goto success; /* close enough for government work */ 183 } 184 /* Make sure pkg_info can read the entry */ 185 vsystem("chmod a+rx %s", LogDir); 186 if (fexists(DEINSTALL_FNAME)) 187 copy_file(".", DEINSTALL_FNAME, LogDir); 188 if (fexists(REQUIRE_FNAME)) 189 copy_file(".", REQUIRE_FNAME, LogDir); 190 sprintf(contents, "%s/%s", LogDir, CONTENTS_FNAME); 191 cfile = fopen(contents, "w"); 192 if (!cfile) { 193 whinge("Can't open new contents file '%s'! Can't register pkg.", 194 contents); 195 goto success; /* can't log, but still keep pkg */ 196 } 197 write_plist(&Plist, cfile); 198 fclose(cfile); 199 copy_file(".", DESC_FNAME, LogDir); 200 copy_file(".", COMMENT_FNAME, LogDir); 201 if (Verbose) 202 printf("Package %s registered in %s\n", PkgName, LogDir); 203 } 204 goto success; 205 206 fail: 207 /* Nuke the whole (installed) show */ 208 if (!Fake) 209 delete_package(FALSE, &Plist); 210 211 success: 212 /* delete the packing list contents */ 213 leave_playpen(); 214 215 return code; 216} 217 218static int 219sanity_check(char *pkg) 220{ 221 if (!fexists(CONTENTS_FNAME)) { 222 whinge("Package %s has no CONTENTS file!", pkg); 223 return 1; 224 } 225 if (!fexists(COMMENT_FNAME)) { 226 whinge("Package %s has no COMMENT file!", pkg); 227 return 1; 228 } 229 if (!fexists(DESC_FNAME)) { 230 whinge("Package %s has no DESC file!", pkg); 231 return 1; 232 } 233 return 0; 234} 235 236void 237cleanup(int signo) 238{ 239 if (signo) 240 printf("Signal %d received, cleaning up..\n", signo); 241 if (Plist.head) { 242 if (!Fake) 243 delete_package(FALSE, &Plist); 244 free_plist(&Plist); 245 } 246 if (!Fake && LogDir[0]) 247 vsystem("%s -rf %s", REMOVE_CMD, LogDir); 248 leave_playpen(); 249} 250