package.c revision 29501
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 * 729501Sjkh * $Id: package.c,v 1.62 1997/06/13 17:55:32 jkh Exp $ 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 4424106Sjkhstatic Boolean sigpipe_caught = FALSE; 4524106Sjkh 4624106Sjkhstatic void 4724106Sjkhcatch_pipe(int sig) 4824106Sjkh{ 4924106Sjkh sigpipe_caught = TRUE; 5024106Sjkh} 5124106Sjkh 5211650Sjkh/* Like package_extract, but assumes current media device */ 5311650Sjkhint 5411650Sjkhpackage_add(char *name) 5511650Sjkh{ 5611650Sjkh if (!mediaVerify()) 5715242Sjkh return DITEM_FAILURE; 5814738Sjkh return package_extract(mediaDevice, name, FALSE); 5911650Sjkh} 6011650Sjkh 6126613Sjkh/* For use by dispatch */ 6226613Sjkhint 6326613SjkhpackageAdd(dialogMenuItem *self) 6426613Sjkh{ 6526613Sjkh char *cp; 6626613Sjkh 6726613Sjkh cp = variable_get("package"); 6826613Sjkh if (!cp) { 6926613Sjkh msgDebug("packageAdd: No package name passed in package variable\n"); 7026613Sjkh return DITEM_FAILURE; 7126613Sjkh } 7226613Sjkh else 7326613Sjkh return package_add(cp); 7426613Sjkh} 7526613Sjkh 7615788SjkhBoolean 7715788Sjkhpackage_exists(char *name) 7815788Sjkh{ 7916688Sjkh char fname[FILENAME_MAX]; 8016688Sjkh int status /* = vsystem("pkg_info -e %s", name) */; 8115788Sjkh 8216688Sjkh /* XXX KLUDGE ALERT! This makes evil assumptions about how XXX 8316688Sjkh * packages register themselves and should *really be done with 8416688Sjkh * `pkg_info -e <name>' except that this it's too slow for an 8516688Sjkh * item check routine.. :-( 8616688Sjkh */ 8716688Sjkh snprintf(fname, FILENAME_MAX, "/var/db/pkg/%s", name); 8816688Sjkh status = access(fname, R_OK); 8922102Sjkh if (isDebug()) 9022102Sjkh msgDebug("package check for %s returns %s.\n", name, status ? "failure" : "success"); 9115788Sjkh return !status; 9215788Sjkh} 9315788Sjkh 9411499Sjkh/* Extract a package based on a namespec and a media device */ 9511499Sjkhint 9614738Sjkhpackage_extract(Device *dev, char *name, Boolean depended) 9711499Sjkh{ 9811499Sjkh char path[511]; 9929501Sjkh int ret, last_msg = 0; 10020315Sjkh FILE *fp; 10111499Sjkh 10219385Sjkh /* Check to make sure it's not already there */ 10319385Sjkh if (package_exists(name)) 10419385Sjkh return DITEM_SUCCESS; 10519385Sjkh 10612232Sjkh /* If necessary, initialize the ldconfig hints */ 10712232Sjkh if (!file_readable("/var/run/ld.so.hints")) 10812232Sjkh vsystem("ldconfig /usr/lib /usr/local/lib /usr/X11R6/lib"); 10912232Sjkh 11011553Sjkh if (!dev->init(dev)) { 11111672Sjkh msgConfirm("Unable to initialize media type for package extract."); 11215242Sjkh return DITEM_FAILURE; 11311553Sjkh } 11411499Sjkh 11514738Sjkh /* Be initially optimistic */ 11615467Sjkh ret = DITEM_SUCCESS | DITEM_RESTORE; 11712129Sjkh /* Make a couple of paranoid locations for temp files to live if user specified none */ 11812129Sjkh if (!variable_get("PKG_TMPDIR")) { 11914670Sjkh /* Set it to a location with as much space as possible */ 12014670Sjkh variable_set2("PKG_TMPDIR", "/usr/tmp"); 12112129Sjkh } 12218734Sjkh Mkdir(variable_get("PKG_TMPDIR")); 12312129Sjkh 12416823Sjkh if (!index(name, '/')) 12516823Sjkh sprintf(path, "packages/All/%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); 12616823Sjkh else 12716823Sjkh sprintf(path, "%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); 12820315Sjkh fp = dev->get(dev, path, TRUE); 12920315Sjkh if (fp) { 13024106Sjkh int i = 0, tot, pfd[2]; 13114670Sjkh pid_t pid; 13212184Sjkh 13324106Sjkh signal(SIGPIPE, catch_pipe); 13414738Sjkh msgNotify("Adding %s%s\nfrom %s", path, depended ? " (as a dependency)" : "", dev->name); 13514670Sjkh pipe(pfd); 13614670Sjkh pid = fork(); 13714670Sjkh if (!pid) { 13814670Sjkh dup2(pfd[0], 0); close(pfd[0]); 13914670Sjkh dup2(DebugFD, 1); 14023647Sjkh close(2); 14114670Sjkh close(pfd[1]); 14214670Sjkh i = execl("/usr/sbin/pkg_add", "/usr/sbin/pkg_add", "-", 0); 14311499Sjkh if (isDebug()) 14414670Sjkh msgDebug("pkg_add returns %d status\n", i); 14511499Sjkh } 14611672Sjkh else { 14714670Sjkh char buf[BUFSIZ]; 14815419Sjkh WINDOW *w = savescr(); 14915883Sjkh struct timeval start, stop; 15014670Sjkh 15115470Sjkh close(pfd[0]); 15214670Sjkh tot = 0; 15315883Sjkh (void)gettimeofday(&start, (struct timezone *)0); 15415883Sjkh 15524106Sjkh while (!sigpipe_caught && (i = fread(buf, 1, BUFSIZ, fp)) > 0) { 15615883Sjkh int seconds; 15715242Sjkh 15814670Sjkh tot += i; 15915883Sjkh /* Print statistics about how we're doing */ 16015883Sjkh (void) gettimeofday(&stop, (struct timezone *)0); 16115883Sjkh stop.tv_sec = stop.tv_sec - start.tv_sec; 16215883Sjkh stop.tv_usec = stop.tv_usec - start.tv_usec; 16315883Sjkh if (stop.tv_usec < 0) 16415883Sjkh stop.tv_sec--, stop.tv_usec += 1000000; 16515883Sjkh seconds = stop.tv_sec + (stop.tv_usec / 1000000.0); 16615883Sjkh if (!seconds) 16715883Sjkh seconds = 1; 16829501Sjkh if (seconds != last_msg) { 16929501Sjkh last_msg = seconds; 17029501Sjkh msgInfo("%10d bytes read from package %s @ %4.1f KBytes/second", tot, name, (tot / seconds) / 1024.0); 17129501Sjkh } 17215883Sjkh /* Write it out */ 17324106Sjkh if (sigpipe_caught || write(pfd[1], buf, i) != i) { 17415883Sjkh msgInfo("Write failure to pkg_add! Package may be corrupt."); 17515883Sjkh break; 17615883Sjkh } 17714670Sjkh } 17814670Sjkh close(pfd[1]); 17920315Sjkh fclose(fp); 18024106Sjkh if (sigpipe_caught) 18124106Sjkh msgInfo("pkg_add(1) apparently did not like the %s package.", name); 18224106Sjkh else if (i == -1) 18324106Sjkh msgInfo("I/O error while reading in the %s package.", name); 18415942Sjkh else 18524106Sjkh msgInfo("Package %s read successfully - waiting for pkg_add(1)", name); 18614738Sjkh refresh(); 18714670Sjkh i = waitpid(pid, &tot, 0); 18824106Sjkh if (sigpipe_caught || i < 0 || WEXITSTATUS(tot)) { 18915942Sjkh if (variable_get(VAR_NO_CONFIRM)) 19022721Sjkh msgNotify("Add of package %s aborted, error code %d -\n" 19122721Sjkh "Please check the debug screen for more info.", name, WEXITSTATUS(tot)); 19215942Sjkh else 19322721Sjkh msgConfirm("Add of package %s aborted, error code %d -\n" 19423647Sjkh "Please check the debug screen for more info.", name, WEXITSTATUS(tot)); 19514670Sjkh } 19614670Sjkh else 19714670Sjkh msgNotify("Package %s was added successfully", name); 19818706Sjkh 19918706Sjkh /* Now catch any stragglers */ 20018890Sjkh while (wait3(&tot, WNOHANG, NULL) > 0); 20118706Sjkh 20215419Sjkh sleep(1); 20315419Sjkh restorescr(w); 20424106Sjkh sigpipe_caught = FALSE; 20511672Sjkh } 20611499Sjkh } 20711672Sjkh else { 20817404Sjkh dialog_clear_norefresh(); 20911672Sjkh if (variable_get(VAR_NO_CONFIRM)) 21011672Sjkh msgNotify("Unable to fetch package %s from selected media.\n" 21111799Sjkh "No package add will be done.", name); 21223516Sjkh else 21311672Sjkh msgConfirm("Unable to fetch package %s from selected media.\n" 21411799Sjkh "No package add will be done.", name); 21515467Sjkh ret = DITEM_FAILURE | DITEM_RESTORE; 21611672Sjkh } 21715419Sjkh return ret; 21811499Sjkh} 219