package.c revision 18890
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 * 718890Sjkh * $Id: package.c,v 1.47 1996/10/06 03:18:55 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 3711499Sjkh#include <stdio.h> 3811499Sjkh#include <string.h> 3911499Sjkh#include <stdlib.h> 4011499Sjkh#include <sys/errno.h> 4115883Sjkh#include <sys/time.h> 4211499Sjkh#include <sys/param.h> 4311499Sjkh#include <sys/mount.h> 4411499Sjkh#include <sys/stat.h> 4511499Sjkh#include "sysinstall.h" 4611499Sjkh 4711650Sjkh/* Like package_extract, but assumes current media device */ 4811650Sjkhint 4911650Sjkhpackage_add(char *name) 5011650Sjkh{ 5111650Sjkh if (!mediaVerify()) 5215242Sjkh return DITEM_FAILURE; 5314738Sjkh return package_extract(mediaDevice, name, FALSE); 5411650Sjkh} 5511650Sjkh 5615788SjkhBoolean 5715788Sjkhpackage_exists(char *name) 5815788Sjkh{ 5916688Sjkh char fname[FILENAME_MAX]; 6016688Sjkh int status /* = vsystem("pkg_info -e %s", name) */; 6115788Sjkh 6216688Sjkh /* XXX KLUDGE ALERT! This makes evil assumptions about how XXX 6316688Sjkh * packages register themselves and should *really be done with 6416688Sjkh * `pkg_info -e <name>' except that this it's too slow for an 6516688Sjkh * item check routine.. :-( 6616688Sjkh */ 6716688Sjkh snprintf(fname, FILENAME_MAX, "/var/db/pkg/%s", name); 6816688Sjkh status = access(fname, R_OK); 6915788Sjkh msgDebug("package check for %s returns %s.\n", name, 7015788Sjkh status ? "failure" : "success"); 7115788Sjkh return !status; 7215788Sjkh} 7315788Sjkh 7415942Sjkh/* SIGPIPE handler */ 7515942Sjkhstatic Boolean sigpipe_caught = FALSE; 7615942Sjkh 7715942Sjkhstatic void 7815942Sjkhcatch_pipe(int sig) 7915942Sjkh{ 8015942Sjkh sigpipe_caught = TRUE; 8115942Sjkh} 8215942Sjkh 8311499Sjkh/* Extract a package based on a namespec and a media device */ 8411499Sjkhint 8514738Sjkhpackage_extract(Device *dev, char *name, Boolean depended) 8611499Sjkh{ 8711499Sjkh char path[511]; 8811718Sjkh int fd, ret; 8911499Sjkh 9012232Sjkh /* If necessary, initialize the ldconfig hints */ 9112232Sjkh if (!file_readable("/var/run/ld.so.hints")) 9212232Sjkh vsystem("ldconfig /usr/lib /usr/local/lib /usr/X11R6/lib"); 9312232Sjkh 9415788Sjkh /* Check to make sure it's not already there */ 9515788Sjkh if (package_exists(name)) 9615242Sjkh return DITEM_SUCCESS; 9711536Sjkh 9811553Sjkh if (!dev->init(dev)) { 9911672Sjkh msgConfirm("Unable to initialize media type for package extract."); 10015242Sjkh return DITEM_FAILURE; 10111553Sjkh } 10211499Sjkh 10314738Sjkh /* Be initially optimistic */ 10415467Sjkh ret = DITEM_SUCCESS | DITEM_RESTORE; 10512129Sjkh /* Make a couple of paranoid locations for temp files to live if user specified none */ 10612129Sjkh if (!variable_get("PKG_TMPDIR")) { 10714670Sjkh /* Set it to a location with as much space as possible */ 10814670Sjkh variable_set2("PKG_TMPDIR", "/usr/tmp"); 10912129Sjkh } 11018734Sjkh Mkdir(variable_get("PKG_TMPDIR")); 11112129Sjkh 11216823Sjkh if (!index(name, '/')) 11316823Sjkh sprintf(path, "packages/All/%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); 11416823Sjkh else 11516823Sjkh sprintf(path, "%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); 11611553Sjkh fd = dev->get(dev, path, TRUE); 11711499Sjkh if (fd >= 0) { 11814670Sjkh int i, tot, pfd[2]; 11914670Sjkh pid_t pid; 12012184Sjkh 12117380Sjkh signal(SIGPIPE, catch_pipe); 12214738Sjkh msgNotify("Adding %s%s\nfrom %s", path, depended ? " (as a dependency)" : "", dev->name); 12314670Sjkh pipe(pfd); 12414670Sjkh pid = fork(); 12514670Sjkh if (!pid) { 12614670Sjkh dup2(pfd[0], 0); close(pfd[0]); 12714670Sjkh dup2(DebugFD, 1); 12815419Sjkh close(2); 12914670Sjkh close(pfd[1]); 13017034Sjkh chroot(variable_get(VAR_INSTALL_ROOT)); 13114670Sjkh i = execl("/usr/sbin/pkg_add", "/usr/sbin/pkg_add", "-", 0); 13211499Sjkh if (isDebug()) 13314670Sjkh msgDebug("pkg_add returns %d status\n", i); 13411499Sjkh } 13511672Sjkh else { 13614670Sjkh char buf[BUFSIZ]; 13715419Sjkh WINDOW *w = savescr(); 13815883Sjkh struct timeval start, stop; 13914670Sjkh 14015470Sjkh close(pfd[0]); 14114670Sjkh tot = 0; 14215883Sjkh (void)gettimeofday(&start, (struct timezone *)0); 14315883Sjkh 14415942Sjkh while (!sigpipe_caught && (i = read(fd, buf, BUFSIZ)) > 0) { 14515883Sjkh int seconds; 14615242Sjkh 14714670Sjkh tot += i; 14815883Sjkh /* Print statistics about how we're doing */ 14915883Sjkh (void) gettimeofday(&stop, (struct timezone *)0); 15015883Sjkh stop.tv_sec = stop.tv_sec - start.tv_sec; 15115883Sjkh stop.tv_usec = stop.tv_usec - start.tv_usec; 15215883Sjkh if (stop.tv_usec < 0) 15315883Sjkh stop.tv_sec--, stop.tv_usec += 1000000; 15415883Sjkh seconds = stop.tv_sec + (stop.tv_usec / 1000000.0); 15515883Sjkh if (!seconds) 15615883Sjkh seconds = 1; 15717065Sjkh msgInfo("%10d bytes read from package %s @ %4.1f KBytes/second", tot, name, (tot / seconds) / 1024.0); 15815883Sjkh /* Write it out */ 15915883Sjkh if (write(pfd[1], buf, i) != i) { 16015883Sjkh msgInfo("Write failure to pkg_add! Package may be corrupt."); 16115883Sjkh break; 16215883Sjkh } 16314670Sjkh } 16414670Sjkh close(pfd[1]); 16515470Sjkh dev->close(dev, fd); 16615942Sjkh if (sigpipe_caught) 16715942Sjkh msgDebug("Caught SIGPIPE while trying to install the %s package.\n", name); 16815942Sjkh else 16915942Sjkh msgInfo("Package %s read successfully - waiting for pkg_add", name); 17014738Sjkh refresh(); 17114670Sjkh i = waitpid(pid, &tot, 0); 17215942Sjkh if (sigpipe_caught || i < 0 || WEXITSTATUS(tot)) { 17315942Sjkh if (variable_get(VAR_NO_CONFIRM)) 17415942Sjkh msgNotify("Add of package %s aborted due to some error -\n" 17515942Sjkh "Please check the debug screen for more info.", name); 17615942Sjkh else 17715942Sjkh msgConfirm("Add of package %s aborted due to some error -\n" 17815942Sjkh "Please check the debug screen for more info.", name); 17914670Sjkh } 18014670Sjkh else 18114670Sjkh msgNotify("Package %s was added successfully", name); 18218706Sjkh 18318706Sjkh /* Now catch any stragglers */ 18418890Sjkh while (wait3(&tot, WNOHANG, NULL) > 0); 18518706Sjkh 18615419Sjkh sleep(1); 18715419Sjkh restorescr(w); 18815942Sjkh sigpipe_caught = FALSE; 18911672Sjkh } 19011499Sjkh } 19111672Sjkh else { 19211553Sjkh msgDebug("pkg_extract: get operation returned %d\n", fd); 19317404Sjkh dialog_clear_norefresh(); 19411672Sjkh if (variable_get(VAR_NO_CONFIRM)) 19511672Sjkh msgNotify("Unable to fetch package %s from selected media.\n" 19611799Sjkh "No package add will be done.", name); 19711672Sjkh else { 19811672Sjkh msgConfirm("Unable to fetch package %s from selected media.\n" 19911799Sjkh "No package add will be done.", name); 20011672Sjkh } 20115467Sjkh ret = DITEM_FAILURE | DITEM_RESTORE; 20211672Sjkh } 20315419Sjkh return ret; 20411499Sjkh} 205