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