package.c revision 76521
159191Skris/* 259191Skris * The new sysinstall program. 359191Skris * 459191Skris * This is probably the last program in the `sysinstall' line - the next 559191Skris * generation being essentially a complete rewrite. 6142425Snectar * 759191Skris * $FreeBSD: head/usr.sbin/sysinstall/package.c 76521 2001-05-12 19:39:13Z olgeni $ 859191Skris * 959191Skris * Copyright (c) 1995 1059191Skris * Jordan Hubbard. All rights reserved. 1159191Skris * 1259191Skris * Redistribution and use in source and binary forms, with or without 1359191Skris * modification, are permitted provided that the following conditions 1459191Skris * are met: 1559191Skris * 1. Redistributions of source code must retain the above copyright 1659191Skris * notice, this list of conditions and the following disclaimer, 1759191Skris * verbatim and that no modifications are made prior to this 1859191Skris * point in the file. 1959191Skris * 2. Redistributions in binary form must reproduce the above copyright 2059191Skris * notice, this list of conditions and the following disclaimer in the 2159191Skris * documentation and/or other materials provided with the distribution. 2259191Skris * 2359191Skris * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 2459191Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2559191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2659191Skris * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 2759191Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2859191Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2959191Skris * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 3059191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3159191Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3259191Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3359191Skris * SUCH DAMAGE. 3459191Skris * 3559191Skris */ 3659191Skris 3759191Skris#include "sysinstall.h" 3859191Skris#include <sys/errno.h> 3959191Skris#include <sys/time.h> 4059191Skris#include <sys/param.h> 4159191Skris#include <sys/mount.h> 4259191Skris#include <sys/stat.h> 4359191Skris 4459191Skrisstatic Boolean sigpipe_caught; 4559191Skris 4659191Skrisstatic void 4759191Skriscatch_pipe(int sig) 4859191Skris{ 4959191Skris sigpipe_caught = TRUE; 5059191Skris} 5159191Skris 5259191Skrisextern PkgNode Top; 5359191Skris 5459191Skris/* Like package_extract, but assumes current media device and chases deps */ 5559191Skrisint 5659191Skrispackage_add(char *name) 5759191Skris{ 5859191Skris PkgNodePtr tmp, tmp2, *tmp3; 5959191Skris int i; 6059191Skris 61109998Smarkm if (!mediaVerify()) 6259191Skris return DITEM_FAILURE; 63142425Snectar 64142425Snectar if (!mediaDevice->init(mediaDevice)) 65109998Smarkm return DITEM_FAILURE; 66109998Smarkm 67160814Ssimon i = index_initialize("packages/INDEX"); 68160814Ssimon if (DITEM_STATUS(i) != DITEM_SUCCESS) 69160814Ssimon return i; 7059191Skris 7159191Skris tmp3 = strpbrk(name, "-") ? NULL : &tmp2; 7259191Skris tmp = index_search(&Top, name, tmp3); 7359191Skris if (tmp) 7459191Skris return index_extract(mediaDevice, &Top, tmp, FALSE); 7559191Skris else { 7659191Skris msgConfirm("Sorry, package %s was not found in the INDEX.", name); 7759191Skris return DITEM_FAILURE; 7859191Skris } 7959191Skris} 8059191Skris 8159191Skris/* For use by dispatch */ 8259191Skrisint 8359191SkrispackageAdd(dialogMenuItem *self) 8459191Skris{ 8559191Skris char *cp; 8659191Skris 8759191Skris cp = variable_get(VAR_PACKAGE); 8859191Skris if (!cp) { 8959191Skris msgDebug("packageAdd: No package name passed in package variable\n"); 9059191Skris return DITEM_FAILURE; 9159191Skris } 9259191Skris else 9359191Skris return package_add(cp); 9459191Skris} 95142425Snectar 9659191SkrisBoolean 97111147Snectarpackage_exists(char *name) 98109998Smarkm{ 99111147Snectar char fname[FILENAME_MAX]; 10059191Skris int status /* = vsystem("pkg_info -e %s", name) */; 10159191Skris 102111147Snectar /* XXX KLUDGE ALERT! This makes evil assumptions about how XXX 103109998Smarkm * packages register themselves and should *really be done with 104109998Smarkm * `pkg_info -e <name>' except that this it's too slow for an 105109998Smarkm * item check routine.. :-( 106109998Smarkm */ 107109998Smarkm snprintf(fname, FILENAME_MAX, "/var/db/pkg/%s", name); 108109998Smarkm status = access(fname, R_OK); 109111147Snectar if (isDebug()) 110109998Smarkm msgDebug("package check for %s returns %s.\n", name, status ? "failure" : "success"); 111160814Ssimon return !status; 112111147Snectar} 113160814Ssimon 114111147Snectar/* Extract a package based on a namespec and a media device */ 115160814Ssimonint 116160814Ssimonpackage_extract(Device *dev, char *name, Boolean depended) 117160814Ssimon{ 118160814Ssimon char path[511]; 11959191Skris int ret, last_msg = 0; 12059191Skris FILE *fp; 12159191Skris 12259191Skris /* Check to make sure it's not already there */ 12359191Skris if (package_exists(name)) 12459191Skris return DITEM_SUCCESS; 125 126 if (!dev->init(dev)) { 127 msgConfirm("Unable to initialize media type for package extract."); 128 return DITEM_FAILURE; 129 } 130 131 /* If necessary, initialize the ldconfig hints */ 132 if (!file_readable("/var/run/ld-elf.so.hints")) 133 vsystem("ldconfig /usr/lib /usr/lib/compat /usr/local/lib /usr/X11R6/lib"); 134 if (!file_readable("/var/run/ld.so.hints")) 135 vsystem("ldconfig -aout /usr/lib/aout /usr/lib/compat/aout /usr/local/lib/aout /usr/X11R6/lib/aout"); 136 137 /* Be initially optimistic */ 138 ret = DITEM_SUCCESS; 139 /* Make a couple of paranoid locations for temp files to live if user specified none */ 140 if (!variable_get(VAR_PKG_TMPDIR)) { 141 /* Set it to a location with as much space as possible */ 142 variable_set2(VAR_PKG_TMPDIR, "/usr/tmp", 0); 143 } 144 Mkdir(variable_get(VAR_PKG_TMPDIR)); 145 vsystem("chmod 1777 %s", variable_get(VAR_PKG_TMPDIR)); 146 147 if (!index(name, '/')) { 148 if (!strpbrk(name, "-_")) 149 sprintf(path, "packages/Latest/%s.tgz", name); 150 else 151 sprintf(path, "packages/All/%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); 152 } 153 else 154 sprintf(path, "%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); 155 156 /* We have a path, call the device strategy routine to get the file */ 157 fp = dev->get(dev, path, TRUE); 158 if (fp) { 159 int i = 0, tot, pfd[2]; 160 pid_t pid; 161 WINDOW *w = savescr(); 162 163 sigpipe_caught = FALSE; 164 signal(SIGPIPE, catch_pipe); 165 166 dialog_clear_norefresh(); 167 msgNotify("Adding %s%s\nfrom %s", path, depended ? " (as a dependency)" : "", dev->name); 168 pipe(pfd); 169 pid = fork(); 170 if (!pid) { 171 extern int _interactiveHack; 172 173 dup2(pfd[0], 0); close(pfd[0]); 174 if (!_interactiveHack) { 175 dup2(DebugFD, 1); 176 close(2); 177 } 178 close(pfd[1]); 179 180 /* Prevent pkg_add from wanting to interact in bad ways */ 181 setenv("PACKAGE_BUILDING", "t", 1); 182 setenv("BATCH", "t", 1); 183 184 if (isDebug()) 185 i = execl("/usr/sbin/pkg_add", "/usr/sbin/pkg_add", "-v", "-", 0); 186 else 187 i = execl("/usr/sbin/pkg_add", "/usr/sbin/pkg_add", "-", 0); 188 } 189 else { 190 char buf[BUFSIZ]; 191 struct timeval start, stop; 192 193 close(pfd[0]); 194 tot = 0; 195 (void)gettimeofday(&start, (struct timezone *)0); 196 197 while (!sigpipe_caught && (i = fread(buf, 1, BUFSIZ, fp)) > 0) { 198 int seconds; 199 200 tot += i; 201 /* Print statistics about how we're doing */ 202 (void) gettimeofday(&stop, (struct timezone *)0); 203 stop.tv_sec = stop.tv_sec - start.tv_sec; 204 stop.tv_usec = stop.tv_usec - start.tv_usec; 205 if (stop.tv_usec < 0) 206 stop.tv_sec--, stop.tv_usec += 1000000; 207 seconds = stop.tv_sec + (stop.tv_usec / 1000000.0); 208 if (!seconds) 209 seconds = 1; 210 if (seconds != last_msg) { 211 last_msg = seconds; 212 msgInfo("%10d bytes read from package %s @ %4.1f KBytes/second", tot, name, (tot / seconds) / 1000.0); 213 } 214 /* Write it out */ 215 if (sigpipe_caught || write(pfd[1], buf, i) != i) { 216 msgInfo("Write failure to pkg_add! Package may be corrupt."); 217 break; 218 } 219 } 220 close(pfd[1]); 221 fclose(fp); 222 if (sigpipe_caught) 223 msgInfo("pkg_add(1) apparently did not like the %s package.", name); 224 else if (i == -1) 225 msgInfo("I/O error while reading in the %s package.", name); 226 else 227 msgInfo("Package %s read successfully - waiting for pkg_add(1)", name); 228 refresh(); 229 i = waitpid(pid, &tot, 0); 230 dialog_clear_norefresh(); 231 if (sigpipe_caught || i < 0 || WEXITSTATUS(tot)) { 232 ret = DITEM_FAILURE; 233 if (variable_get(VAR_NO_CONFIRM)) 234 msgNotify("Add of package %s aborted, error code %d -\n" 235 "Please check the debug screen for more info.", name, WEXITSTATUS(tot)); 236 else 237 msgConfirm("Add of package %s aborted, error code %d -\n" 238 "Please check the debug screen for more info.", name, WEXITSTATUS(tot)); 239 } 240 else 241 msgNotify("Package %s was added successfully", name); 242 243 /* Now catch any stragglers */ 244 while (wait3(&tot, WNOHANG, NULL) > 0); 245 246 sleep(1); 247 restorescr(w); 248 } 249 } 250 else { 251 dialog_clear_norefresh(); 252 if (variable_get(VAR_NO_CONFIRM)) 253 msgNotify("Unable to fetch package %s from selected media.\n" 254 "No package add will be done.", name); 255 else 256 msgConfirm("Unable to fetch package %s from selected media.\n" 257 "No package add will be done.", name); 258 ret = DITEM_FAILURE; 259 } 260 signal(SIGPIPE, SIG_IGN); 261 return ret; 262} 263