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 * 711499Sjkh * Copyright (c) 1995 811499Sjkh * Jordan Hubbard. All rights reserved. 911499Sjkh * 1011499Sjkh * Redistribution and use in source and binary forms, with or without 1111499Sjkh * modification, are permitted provided that the following conditions 1211499Sjkh * are met: 1311499Sjkh * 1. Redistributions of source code must retain the above copyright 1411499Sjkh * notice, this list of conditions and the following disclaimer, 1511499Sjkh * verbatim and that no modifications are made prior to this 1611499Sjkh * point in the file. 1711499Sjkh * 2. Redistributions in binary form must reproduce the above copyright 1811499Sjkh * notice, this list of conditions and the following disclaimer in the 1911499Sjkh * documentation and/or other materials provided with the distribution. 2011499Sjkh * 2111499Sjkh * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 2211499Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2311499Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2411499Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 2511499Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2611499Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2711499Sjkh * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 2811499Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2911499Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3011499Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3111499Sjkh * SUCH DAMAGE. 3211499Sjkh * 33124068Sobrien * $FreeBSD$ 3411499Sjkh */ 3511499Sjkh 3621243Sjkh#include "sysinstall.h" 3711499Sjkh#include <sys/errno.h> 3815883Sjkh#include <sys/time.h> 3911499Sjkh#include <sys/param.h> 4011499Sjkh#include <sys/mount.h> 4111499Sjkh#include <sys/stat.h> 4211499Sjkh 4350780Sjkhstatic Boolean sigpipe_caught; 4424106Sjkh 4524106Sjkhstatic void 4624106Sjkhcatch_pipe(int sig) 4724106Sjkh{ 4824106Sjkh sigpipe_caught = TRUE; 4924106Sjkh} 5024106Sjkh 5147055Sjkhextern PkgNode Top; 5247055Sjkh 5347055Sjkh/* Like package_extract, but assumes current media device and chases deps */ 5411650Sjkhint 5511650Sjkhpackage_add(char *name) 5611650Sjkh{ 5789775Ssteve PkgNodePtr tmp; 58184180Skensmith int i, current, low, high; 5947055Sjkh 6011650Sjkh if (!mediaVerify()) 6115242Sjkh return DITEM_FAILURE; 6250780Sjkh 6379065Sdd if (!DEVICE_INIT(mediaDevice)) 6450780Sjkh return DITEM_FAILURE; 6550780Sjkh 6647055Sjkh i = index_initialize("packages/INDEX"); 6747055Sjkh if (DITEM_STATUS(i) != DITEM_SUCCESS) 6847055Sjkh return i; 6950780Sjkh 7089775Ssteve tmp = index_search(&Top, name, &tmp); 71184180Skensmith if (tmp) { 72184180Skensmith if (have_volumes) { 73184180Skensmith low = low_volume; 74184180Skensmith high = high_volume; 75184180Skensmith } else 76184180Skensmith low = high = 0; 77184180Skensmith for (current = low; current <= high; current++) 78184180Skensmith i = index_extract(mediaDevice, &Top, tmp, FALSE, current); 79184180Skensmith return i; 80184180Skensmith } else { 8147055Sjkh msgConfirm("Sorry, package %s was not found in the INDEX.", name); 8254587Sjkh return DITEM_FAILURE; 8347055Sjkh } 8411650Sjkh} 8511650Sjkh 8626613Sjkh/* For use by dispatch */ 8726613Sjkhint 8826613SjkhpackageAdd(dialogMenuItem *self) 8926613Sjkh{ 9026613Sjkh char *cp; 9126613Sjkh 9229539Spst cp = variable_get(VAR_PACKAGE); 9326613Sjkh if (!cp) { 9426613Sjkh msgDebug("packageAdd: No package name passed in package variable\n"); 9526613Sjkh return DITEM_FAILURE; 9626613Sjkh } 9726613Sjkh else 9826613Sjkh return package_add(cp); 9926613Sjkh} 10026613Sjkh 10115788SjkhBoolean 102124068Sobrienpackage_installed(char *name) 10315788Sjkh{ 10416688Sjkh char fname[FILENAME_MAX]; 10516688Sjkh int status /* = vsystem("pkg_info -e %s", name) */; 10615788Sjkh 10716688Sjkh /* XXX KLUDGE ALERT! This makes evil assumptions about how XXX 10816688Sjkh * packages register themselves and should *really be done with 109252600Sdteske * `pkg_info -e <name>' except that this is too slow for an 11016688Sjkh * item check routine.. :-( 11116688Sjkh */ 11216688Sjkh snprintf(fname, FILENAME_MAX, "/var/db/pkg/%s", name); 11316688Sjkh status = access(fname, R_OK); 11422102Sjkh if (isDebug()) 11522102Sjkh msgDebug("package check for %s returns %s.\n", name, status ? "failure" : "success"); 11615788Sjkh return !status; 11715788Sjkh} 11815788Sjkh 11911499Sjkh/* Extract a package based on a namespec and a media device */ 12011499Sjkhint 12114738Sjkhpackage_extract(Device *dev, char *name, Boolean depended) 12211499Sjkh{ 12395825Sobrien char path[MAXPATHLEN]; 12495825Sobrien const char *PkgExts[] = { "", ".tbz", ".tbz2", ".tgz" }; 125156123Sjhb int last_msg, pathend, ret; 126156123Sjhb size_t ext; 12720315Sjkh FILE *fp; 12811499Sjkh 12995825Sobrien last_msg = 0; 13095825Sobrien 13119385Sjkh /* Check to make sure it's not already there */ 132124070Sobrien if (package_installed(name)) 13319385Sjkh return DITEM_SUCCESS; 13419385Sjkh 13579065Sdd if (!DEVICE_INIT(dev)) { 13611672Sjkh msgConfirm("Unable to initialize media type for package extract."); 13715242Sjkh return DITEM_FAILURE; 13811553Sjkh } 13911499Sjkh 14047179Sjkh /* If necessary, initialize the ldconfig hints */ 14176521Solgeni if (!file_readable("/var/run/ld-elf.so.hints")) 142203690Sbrucec vsystem("ldconfig /usr/lib /usr/lib/compat /usr/local/lib"); 14347179Sjkh 14414738Sjkh /* Be initially optimistic */ 14554587Sjkh ret = DITEM_SUCCESS; 14612129Sjkh /* Make a couple of paranoid locations for temp files to live if user specified none */ 14730424Sjkh if (!variable_get(VAR_PKG_TMPDIR)) { 14814670Sjkh /* Set it to a location with as much space as possible */ 14993595Sobrien variable_set2(VAR_PKG_TMPDIR, "/var/tmp", 0); 15012129Sjkh } 15130424Sjkh Mkdir(variable_get(VAR_PKG_TMPDIR)); 15230424Sjkh vsystem("chmod 1777 %s", variable_get(VAR_PKG_TMPDIR)); 15312129Sjkh 15447179Sjkh if (!index(name, '/')) { 15547179Sjkh if (!strpbrk(name, "-_")) 15695825Sobrien pathend = snprintf(path, sizeof path, "packages/Latest/%s", name); 15747179Sjkh else 15895825Sobrien pathend = snprintf(path, sizeof path, "packages/All/%s", name); 15947179Sjkh } 16016823Sjkh else 16195825Sobrien pathend = snprintf(path, sizeof path, "%s", name); 16247041Sjkh 16347047Sjkh /* We have a path, call the device strategy routine to get the file */ 16495825Sobrien for (ext = 0 ; ext < sizeof PkgExts / sizeof PkgExts[0]; ++ext) { 16595825Sobrien strlcpy(path + pathend, PkgExts[ext], sizeof path - pathend); 16695825Sobrien if ((fp = DEVICE_GET(dev, path, TRUE))) 16795825Sobrien break; 16895825Sobrien } 16995825Sobrien 17020315Sjkh if (fp) { 17124106Sjkh int i = 0, tot, pfd[2]; 17214670Sjkh pid_t pid; 17354722Sjkh WINDOW *w = savescr(); 17412184Sjkh 17547221Sjkh sigpipe_caught = FALSE; 17624106Sjkh signal(SIGPIPE, catch_pipe); 17747221Sjkh 17854767Sjkh dialog_clear_norefresh(); 17914738Sjkh msgNotify("Adding %s%s\nfrom %s", path, depended ? " (as a dependency)" : "", dev->name); 18014670Sjkh pipe(pfd); 18114670Sjkh pid = fork(); 18214670Sjkh if (!pid) { 18314670Sjkh dup2(pfd[0], 0); close(pfd[0]); 18494051Sobrien dup2(DebugFD, 1); dup2(1, 2); 18514670Sjkh close(pfd[1]); 18668552Sjkh 18768552Sjkh /* Prevent pkg_add from wanting to interact in bad ways */ 18868552Sjkh setenv("BATCH", "t", 1); 18968552Sjkh 19011499Sjkh if (isDebug()) 19179452Sbrian i = execl("/usr/sbin/pkg_add", "/usr/sbin/pkg_add", "-v", "-", 19279452Sbrian (char *)0); 19347181Sjkh else 19479452Sbrian i = execl("/usr/sbin/pkg_add", "/usr/sbin/pkg_add", "-", 19579452Sbrian (char *)0); 19611499Sjkh } 19711672Sjkh else { 19814670Sjkh char buf[BUFSIZ]; 19915883Sjkh struct timeval start, stop; 20014670Sjkh 20115470Sjkh close(pfd[0]); 20214670Sjkh tot = 0; 20315883Sjkh (void)gettimeofday(&start, (struct timezone *)0); 20415883Sjkh 20524106Sjkh while (!sigpipe_caught && (i = fread(buf, 1, BUFSIZ, fp)) > 0) { 20615883Sjkh int seconds; 20715242Sjkh 20814670Sjkh tot += i; 20915883Sjkh /* Print statistics about how we're doing */ 21015883Sjkh (void) gettimeofday(&stop, (struct timezone *)0); 21115883Sjkh stop.tv_sec = stop.tv_sec - start.tv_sec; 21215883Sjkh stop.tv_usec = stop.tv_usec - start.tv_usec; 21315883Sjkh if (stop.tv_usec < 0) 21415883Sjkh stop.tv_sec--, stop.tv_usec += 1000000; 21515883Sjkh seconds = stop.tv_sec + (stop.tv_usec / 1000000.0); 21615883Sjkh if (!seconds) 21715883Sjkh seconds = 1; 21829501Sjkh if (seconds != last_msg) { 21929501Sjkh last_msg = seconds; 22075322Sjkh msgInfo("%10d bytes read from package %s @ %4.1f KBytes/second", tot, name, (tot / seconds) / 1000.0); 22129501Sjkh } 22215883Sjkh /* Write it out */ 22324106Sjkh if (sigpipe_caught || write(pfd[1], buf, i) != i) { 22415883Sjkh msgInfo("Write failure to pkg_add! Package may be corrupt."); 22515883Sjkh break; 22615883Sjkh } 22714670Sjkh } 22814670Sjkh close(pfd[1]); 22920315Sjkh fclose(fp); 23024106Sjkh if (sigpipe_caught) 23124106Sjkh msgInfo("pkg_add(1) apparently did not like the %s package.", name); 23224106Sjkh else if (i == -1) 23324106Sjkh msgInfo("I/O error while reading in the %s package.", name); 23415942Sjkh else 23524106Sjkh msgInfo("Package %s read successfully - waiting for pkg_add(1)", name); 23614738Sjkh refresh(); 23714670Sjkh i = waitpid(pid, &tot, 0); 23854805Sjkh dialog_clear_norefresh(); 23924106Sjkh if (sigpipe_caught || i < 0 || WEXITSTATUS(tot)) { 24054587Sjkh ret = DITEM_FAILURE; 24148482Sjkh if (variable_get(VAR_NO_CONFIRM)) 24248482Sjkh msgNotify("Add of package %s aborted, error code %d -\n" 24348482Sjkh "Please check the debug screen for more info.", name, WEXITSTATUS(tot)); 24448482Sjkh else 24548482Sjkh msgConfirm("Add of package %s aborted, error code %d -\n" 24648482Sjkh "Please check the debug screen for more info.", name, WEXITSTATUS(tot)); 24714670Sjkh } 24814670Sjkh else 24914670Sjkh msgNotify("Package %s was added successfully", name); 25018706Sjkh 25118706Sjkh /* Now catch any stragglers */ 25218890Sjkh while (wait3(&tot, WNOHANG, NULL) > 0); 25318706Sjkh 25415419Sjkh sleep(1); 25515419Sjkh restorescr(w); 25611672Sjkh } 25711499Sjkh } 25811672Sjkh else { 25954805Sjkh dialog_clear_norefresh(); 26048482Sjkh if (variable_get(VAR_NO_CONFIRM)) 26148482Sjkh msgNotify("Unable to fetch package %s from selected media.\n" 26248482Sjkh "No package add will be done.", name); 26348482Sjkh else 26448482Sjkh msgConfirm("Unable to fetch package %s from selected media.\n" 26548482Sjkh "No package add will be done.", name); 26654587Sjkh ret = DITEM_FAILURE; 26711672Sjkh } 26847221Sjkh signal(SIGPIPE, SIG_IGN); 26954854Sjkh return ret; 27011499Sjkh} 271