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