package.c revision 54854
111499Sjkh/* 211499Sjkh * The new sysinstall program. 311499Sjkh * 411499Sjkh * This is probably the last program in the `sysinstall' line - the next 511499Sjkh * generation being essentially a complete rewrite. 611499Sjkh * 750479Speter * $FreeBSD: head/usr.sbin/sysinstall/package.c 54854 1999-12-20 00:16:10Z jkh $ 811499Sjkh * 911499Sjkh * Copyright (c) 1995 1011499Sjkh * Jordan Hubbard. All rights reserved. 1111499Sjkh * 1211499Sjkh * Redistribution and use in source and binary forms, with or without 1311499Sjkh * modification, are permitted provided that the following conditions 1411499Sjkh * are met: 1511499Sjkh * 1. Redistributions of source code must retain the above copyright 1611499Sjkh * notice, this list of conditions and the following disclaimer, 1711499Sjkh * verbatim and that no modifications are made prior to this 1811499Sjkh * point in the file. 1911499Sjkh * 2. Redistributions in binary form must reproduce the above copyright 2011499Sjkh * notice, this list of conditions and the following disclaimer in the 2111499Sjkh * documentation and/or other materials provided with the distribution. 2211499Sjkh * 2311499Sjkh * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 2411499Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2511499Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2611499Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 2711499Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2811499Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2911499Sjkh * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 3011499Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3111499Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3211499Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3311499Sjkh * SUCH DAMAGE. 3411499Sjkh * 3511499Sjkh */ 3611499Sjkh 3721243Sjkh#include "sysinstall.h" 3811499Sjkh#include <sys/errno.h> 3915883Sjkh#include <sys/time.h> 4011499Sjkh#include <sys/param.h> 4111499Sjkh#include <sys/mount.h> 4211499Sjkh#include <sys/stat.h> 4311499Sjkh 4450780Sjkhstatic Boolean sigpipe_caught; 4524106Sjkh 4624106Sjkhstatic void 4724106Sjkhcatch_pipe(int sig) 4824106Sjkh{ 4924106Sjkh sigpipe_caught = TRUE; 5024106Sjkh} 5124106Sjkh 5247055Sjkhextern PkgNode Top; 5347055Sjkh 5447055Sjkh/* Like package_extract, but assumes current media device and chases deps */ 5511650Sjkhint 5611650Sjkhpackage_add(char *name) 5711650Sjkh{ 5847184Sjkh PkgNodePtr tmp, tmp2, *tmp3; 5947055Sjkh int i; 6047055Sjkh 6111650Sjkh if (!mediaVerify()) 6215242Sjkh return DITEM_FAILURE; 6350780Sjkh 6450780Sjkh if (!mediaDevice->init(mediaDevice)) 6550780Sjkh return DITEM_FAILURE; 6650780Sjkh 6747055Sjkh i = index_initialize("packages/INDEX"); 6847055Sjkh if (DITEM_STATUS(i) != DITEM_SUCCESS) 6947055Sjkh return i; 7050780Sjkh 7148624Sjkh tmp3 = strpbrk(name, "-") ? NULL : &tmp2; 7247184Sjkh tmp = index_search(&Top, name, tmp3); 7347055Sjkh if (tmp) 7447221Sjkh return index_extract(mediaDevice, &Top, tmp, FALSE); 7547055Sjkh else { 7647055Sjkh msgConfirm("Sorry, package %s was not found in the INDEX.", name); 7754587Sjkh return DITEM_FAILURE; 7847055Sjkh } 7911650Sjkh} 8011650Sjkh 8126613Sjkh/* For use by dispatch */ 8226613Sjkhint 8326613SjkhpackageAdd(dialogMenuItem *self) 8426613Sjkh{ 8526613Sjkh char *cp; 8626613Sjkh 8729539Spst cp = variable_get(VAR_PACKAGE); 8826613Sjkh if (!cp) { 8926613Sjkh msgDebug("packageAdd: No package name passed in package variable\n"); 9026613Sjkh return DITEM_FAILURE; 9126613Sjkh } 9226613Sjkh else 9326613Sjkh return package_add(cp); 9426613Sjkh} 9526613Sjkh 9615788SjkhBoolean 9715788Sjkhpackage_exists(char *name) 9815788Sjkh{ 9916688Sjkh char fname[FILENAME_MAX]; 10016688Sjkh int status /* = vsystem("pkg_info -e %s", name) */; 10115788Sjkh 10216688Sjkh /* XXX KLUDGE ALERT! This makes evil assumptions about how XXX 10316688Sjkh * packages register themselves and should *really be done with 10416688Sjkh * `pkg_info -e <name>' except that this it's too slow for an 10516688Sjkh * item check routine.. :-( 10616688Sjkh */ 10716688Sjkh snprintf(fname, FILENAME_MAX, "/var/db/pkg/%s", name); 10816688Sjkh status = access(fname, R_OK); 10922102Sjkh if (isDebug()) 11022102Sjkh msgDebug("package check for %s returns %s.\n", name, status ? "failure" : "success"); 11115788Sjkh return !status; 11215788Sjkh} 11315788Sjkh 11411499Sjkh/* Extract a package based on a namespec and a media device */ 11511499Sjkhint 11614738Sjkhpackage_extract(Device *dev, char *name, Boolean depended) 11711499Sjkh{ 11847047Sjkh char path[511]; 11929501Sjkh int ret, last_msg = 0; 12020315Sjkh FILE *fp; 12111499Sjkh 12219385Sjkh /* Check to make sure it's not already there */ 12319385Sjkh if (package_exists(name)) 12419385Sjkh return DITEM_SUCCESS; 12519385Sjkh 12611553Sjkh if (!dev->init(dev)) { 12711672Sjkh msgConfirm("Unable to initialize media type for package extract."); 12815242Sjkh return DITEM_FAILURE; 12911553Sjkh } 13011499Sjkh 13147179Sjkh /* If necessary, initialize the ldconfig hints */ 13247179Sjkh if (!file_readable("/var/run/ld.so.hints")) 13354835Sjkh vsystem("ldconfig /usr/lib /usr/lib/compat /usr/local/lib /usr/X11R6/lib"); 13447179Sjkh 13514738Sjkh /* Be initially optimistic */ 13654587Sjkh ret = DITEM_SUCCESS; 13712129Sjkh /* Make a couple of paranoid locations for temp files to live if user specified none */ 13830424Sjkh if (!variable_get(VAR_PKG_TMPDIR)) { 13914670Sjkh /* Set it to a location with as much space as possible */ 14043685Sjkh variable_set2(VAR_PKG_TMPDIR, "/usr/tmp", 0); 14112129Sjkh } 14230424Sjkh Mkdir(variable_get(VAR_PKG_TMPDIR)); 14330424Sjkh vsystem("chmod 1777 %s", variable_get(VAR_PKG_TMPDIR)); 14412129Sjkh 14547179Sjkh if (!index(name, '/')) { 14647179Sjkh if (!strpbrk(name, "-_")) 14747179Sjkh sprintf(path, "packages/Latest/%s.tgz", name); 14847179Sjkh else 14947179Sjkh sprintf(path, "packages/All/%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); 15047179Sjkh } 15116823Sjkh else 15216823Sjkh sprintf(path, "%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); 15347041Sjkh 15447047Sjkh /* We have a path, call the device strategy routine to get the file */ 15520315Sjkh fp = dev->get(dev, path, TRUE); 15620315Sjkh if (fp) { 15724106Sjkh int i = 0, tot, pfd[2]; 15814670Sjkh pid_t pid; 15954722Sjkh WINDOW *w = savescr(); 16012184Sjkh 16147221Sjkh sigpipe_caught = FALSE; 16224106Sjkh signal(SIGPIPE, catch_pipe); 16347221Sjkh 16454767Sjkh dialog_clear_norefresh(); 16514738Sjkh msgNotify("Adding %s%s\nfrom %s", path, depended ? " (as a dependency)" : "", dev->name); 16614670Sjkh pipe(pfd); 16714670Sjkh pid = fork(); 16814670Sjkh if (!pid) { 16914670Sjkh dup2(pfd[0], 0); close(pfd[0]); 17014670Sjkh dup2(DebugFD, 1); 17123647Sjkh close(2); 17214670Sjkh close(pfd[1]); 17311499Sjkh if (isDebug()) 17447181Sjkh i = execl("/usr/sbin/pkg_add", "/usr/sbin/pkg_add", "-v", "-", 0); 17547181Sjkh else 17647181Sjkh i = execl("/usr/sbin/pkg_add", "/usr/sbin/pkg_add", "-", 0); 17711499Sjkh } 17811672Sjkh else { 17914670Sjkh char buf[BUFSIZ]; 18015883Sjkh struct timeval start, stop; 18114670Sjkh 18215470Sjkh close(pfd[0]); 18314670Sjkh tot = 0; 18415883Sjkh (void)gettimeofday(&start, (struct timezone *)0); 18515883Sjkh 18624106Sjkh while (!sigpipe_caught && (i = fread(buf, 1, BUFSIZ, fp)) > 0) { 18715883Sjkh int seconds; 18815242Sjkh 18914670Sjkh tot += i; 19015883Sjkh /* Print statistics about how we're doing */ 19115883Sjkh (void) gettimeofday(&stop, (struct timezone *)0); 19215883Sjkh stop.tv_sec = stop.tv_sec - start.tv_sec; 19315883Sjkh stop.tv_usec = stop.tv_usec - start.tv_usec; 19415883Sjkh if (stop.tv_usec < 0) 19515883Sjkh stop.tv_sec--, stop.tv_usec += 1000000; 19615883Sjkh seconds = stop.tv_sec + (stop.tv_usec / 1000000.0); 19715883Sjkh if (!seconds) 19815883Sjkh seconds = 1; 19929501Sjkh if (seconds != last_msg) { 20029501Sjkh last_msg = seconds; 20129501Sjkh msgInfo("%10d bytes read from package %s @ %4.1f KBytes/second", tot, name, (tot / seconds) / 1024.0); 20229501Sjkh } 20315883Sjkh /* Write it out */ 20424106Sjkh if (sigpipe_caught || write(pfd[1], buf, i) != i) { 20515883Sjkh msgInfo("Write failure to pkg_add! Package may be corrupt."); 20615883Sjkh break; 20715883Sjkh } 20814670Sjkh } 20914670Sjkh close(pfd[1]); 21020315Sjkh fclose(fp); 21124106Sjkh if (sigpipe_caught) 21224106Sjkh msgInfo("pkg_add(1) apparently did not like the %s package.", name); 21324106Sjkh else if (i == -1) 21424106Sjkh msgInfo("I/O error while reading in the %s package.", name); 21515942Sjkh else 21624106Sjkh msgInfo("Package %s read successfully - waiting for pkg_add(1)", name); 21714738Sjkh refresh(); 21814670Sjkh i = waitpid(pid, &tot, 0); 21954805Sjkh dialog_clear_norefresh(); 22024106Sjkh if (sigpipe_caught || i < 0 || WEXITSTATUS(tot)) { 22154587Sjkh ret = DITEM_FAILURE; 22248482Sjkh if (variable_get(VAR_NO_CONFIRM)) 22348482Sjkh msgNotify("Add of package %s aborted, error code %d -\n" 22448482Sjkh "Please check the debug screen for more info.", name, WEXITSTATUS(tot)); 22548482Sjkh else 22648482Sjkh msgConfirm("Add of package %s aborted, error code %d -\n" 22748482Sjkh "Please check the debug screen for more info.", name, WEXITSTATUS(tot)); 22814670Sjkh } 22914670Sjkh else 23014670Sjkh msgNotify("Package %s was added successfully", name); 23118706Sjkh 23218706Sjkh /* Now catch any stragglers */ 23318890Sjkh while (wait3(&tot, WNOHANG, NULL) > 0); 23418706Sjkh 23515419Sjkh sleep(1); 23615419Sjkh restorescr(w); 23711672Sjkh } 23811499Sjkh } 23911672Sjkh else { 24054805Sjkh dialog_clear_norefresh(); 24148482Sjkh if (variable_get(VAR_NO_CONFIRM)) 24248482Sjkh msgNotify("Unable to fetch package %s from selected media.\n" 24348482Sjkh "No package add will be done.", name); 24448482Sjkh else 24548482Sjkh msgConfirm("Unable to fetch package %s from selected media.\n" 24648482Sjkh "No package add will be done.", name); 24754587Sjkh ret = DITEM_FAILURE; 24811672Sjkh } 24947221Sjkh signal(SIGPIPE, SIG_IGN); 25054854Sjkh return ret; 25111499Sjkh} 252