package.c revision 47221
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 * 747221Sjkh * $Id: package.c,v 1.74 1999/05/14 14:57:59 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 4447221Sjkhstatic 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; 6347221Sjkh 6447221Sjkh if (!mediaDevice->init(mediaDevice)) 6547221Sjkh return DITEM_FAILURE; 6647221Sjkh 6747055Sjkh i = index_initialize("packages/INDEX"); 6847055Sjkh if (DITEM_STATUS(i) != DITEM_SUCCESS) 6947055Sjkh return i; 7047221Sjkh 7147221Sjkh 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); 7747055Sjkh return DITEM_FAILURE | DITEM_RESTORE; 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")) 13347179Sjkh vsystem("ldconfig /usr/lib /usr/local/lib /usr/X11R6/lib"); 13447179Sjkh 13514738Sjkh /* Be initially optimistic */ 13615467Sjkh ret = DITEM_SUCCESS | DITEM_RESTORE; 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; 15912184Sjkh 16047221Sjkh sigpipe_caught = FALSE; 16124106Sjkh signal(SIGPIPE, catch_pipe); 16247221Sjkh 16314738Sjkh msgNotify("Adding %s%s\nfrom %s", path, depended ? " (as a dependency)" : "", dev->name); 16414670Sjkh pipe(pfd); 16514670Sjkh pid = fork(); 16614670Sjkh if (!pid) { 16714670Sjkh dup2(pfd[0], 0); close(pfd[0]); 16814670Sjkh dup2(DebugFD, 1); 16923647Sjkh close(2); 17014670Sjkh close(pfd[1]); 17111499Sjkh if (isDebug()) 17247181Sjkh i = execl("/usr/sbin/pkg_add", "/usr/sbin/pkg_add", "-v", "-", 0); 17347181Sjkh else 17447181Sjkh i = execl("/usr/sbin/pkg_add", "/usr/sbin/pkg_add", "-", 0); 17511499Sjkh } 17611672Sjkh else { 17714670Sjkh char buf[BUFSIZ]; 17815419Sjkh WINDOW *w = savescr(); 17915883Sjkh struct timeval start, stop; 18014670Sjkh 18115470Sjkh close(pfd[0]); 18214670Sjkh tot = 0; 18315883Sjkh (void)gettimeofday(&start, (struct timezone *)0); 18415883Sjkh 18524106Sjkh while (!sigpipe_caught && (i = fread(buf, 1, BUFSIZ, fp)) > 0) { 18615883Sjkh int seconds; 18715242Sjkh 18814670Sjkh tot += i; 18915883Sjkh /* Print statistics about how we're doing */ 19015883Sjkh (void) gettimeofday(&stop, (struct timezone *)0); 19115883Sjkh stop.tv_sec = stop.tv_sec - start.tv_sec; 19215883Sjkh stop.tv_usec = stop.tv_usec - start.tv_usec; 19315883Sjkh if (stop.tv_usec < 0) 19415883Sjkh stop.tv_sec--, stop.tv_usec += 1000000; 19515883Sjkh seconds = stop.tv_sec + (stop.tv_usec / 1000000.0); 19615883Sjkh if (!seconds) 19715883Sjkh seconds = 1; 19829501Sjkh if (seconds != last_msg) { 19929501Sjkh last_msg = seconds; 20029501Sjkh msgInfo("%10d bytes read from package %s @ %4.1f KBytes/second", tot, name, (tot / seconds) / 1024.0); 20129501Sjkh } 20215883Sjkh /* Write it out */ 20324106Sjkh if (sigpipe_caught || write(pfd[1], buf, i) != i) { 20415883Sjkh msgInfo("Write failure to pkg_add! Package may be corrupt."); 20515883Sjkh break; 20615883Sjkh } 20714670Sjkh } 20814670Sjkh close(pfd[1]); 20920315Sjkh fclose(fp); 21024106Sjkh if (sigpipe_caught) 21124106Sjkh msgInfo("pkg_add(1) apparently did not like the %s package.", name); 21224106Sjkh else if (i == -1) 21324106Sjkh msgInfo("I/O error while reading in the %s package.", name); 21415942Sjkh else 21524106Sjkh msgInfo("Package %s read successfully - waiting for pkg_add(1)", name); 21614738Sjkh refresh(); 21714670Sjkh i = waitpid(pid, &tot, 0); 21824106Sjkh if (sigpipe_caught || i < 0 || WEXITSTATUS(tot)) { 21946653Sjkh ret = DITEM_FAILURE | DITEM_RESTORE; 22015942Sjkh if (variable_get(VAR_NO_CONFIRM)) 22122721Sjkh msgNotify("Add of package %s aborted, error code %d -\n" 22222721Sjkh "Please check the debug screen for more info.", name, WEXITSTATUS(tot)); 22315942Sjkh else 22422721Sjkh msgConfirm("Add of package %s aborted, error code %d -\n" 22523647Sjkh "Please check the debug screen for more info.", name, WEXITSTATUS(tot)); 22614670Sjkh } 22714670Sjkh else 22814670Sjkh msgNotify("Package %s was added successfully", name); 22918706Sjkh 23018706Sjkh /* Now catch any stragglers */ 23118890Sjkh while (wait3(&tot, WNOHANG, NULL) > 0); 23218706Sjkh 23315419Sjkh sleep(1); 23415419Sjkh restorescr(w); 23511672Sjkh } 23611499Sjkh } 23711672Sjkh else { 23817404Sjkh dialog_clear_norefresh(); 23911672Sjkh if (variable_get(VAR_NO_CONFIRM)) 24011672Sjkh msgNotify("Unable to fetch package %s from selected media.\n" 24111799Sjkh "No package add will be done.", name); 24223516Sjkh else 24311672Sjkh msgConfirm("Unable to fetch package %s from selected media.\n" 24411799Sjkh "No package add will be done.", name); 24515467Sjkh ret = DITEM_FAILURE | DITEM_RESTORE; 24611672Sjkh } 24747221Sjkh signal(SIGPIPE, SIG_IGN); 24815419Sjkh return ret; 24911499Sjkh} 250