/*
 * The new sysinstall program.
 *
 * This is probably the last program in the `sysinstall' line - the next
 * generation being essentially a complete rewrite.
 *
 * $FreeBSD: src/release/sysinstall/dist.c,v 1.132.2.20 1999/12/18 02:30:08 jkh Exp $
 *
 * Copyright (c) 1995
 *	Jordan Hubbard.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer,
 *    verbatim and that no modifications are made prior to this
 *    point in the file.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include "sysinstall.h"
#include <sys/time.h>
#include <signal.h>
#include <libutil.h>

unsigned int Dists;
unsigned int DESDists;
unsigned int SrcDists;
unsigned int XF86Dists;
unsigned int XF86ServerDists;
unsigned int XF86FontDists;
#ifdef PC98
unsigned int Dists98;
unsigned int DistsIde;
unsigned int DistsIdeFlg;
#endif
#if defined(PC98) && defined(PC98SRC)
unsigned int Src98Dists;
#endif /* defined(PC98) && defined(PC98SRC) */

typedef struct _dist {
    char *my_name;
    char *my_dir;
    unsigned int *my_mask;
    unsigned int my_bit;
    struct _dist *my_dist;
} Distribution;

extern Distribution DistTable[];
#ifdef PC98
extern Distribution ide_kernel[];
#endif
extern Distribution DESDistTable[];
extern Distribution SrcDistTable[];
#if defined(PC98) && defined(PC98SRC)
extern Distribution Src98DistTable[];
#endif /* defined(PC98) && defined(PC98SRC) */
extern Distribution XF86DistTable[];
extern Distribution XF86FontDistTable[];
extern Distribution XF86ServerDistTable[];

/* The top-level distribution categories */
static Distribution DistTable[] = {
{ "bin",	"/",			&Dists,		DIST_BIN,		NULL		},
#ifdef PC98
{ "98bin",	"/",			&Dists,		DIST_98BIN,		NULL		},
{ "98bin",	"/",			&Dists98,	DIST_98BIN,		ide_kernel	},
#endif
{ "doc",	"/",			&Dists,		DIST_DOC,		NULL		},
#ifdef PC98
{ "98doc",	"/",			&Dists,		DIST_98DOC,		NULL		},
#endif
{ "games",	"/",			&Dists,		DIST_GAMES,		NULL		},
{ "manpages",	"/",			&Dists,		DIST_MANPAGES,		NULL		},
{ "catpages",	"/",			&Dists,		DIST_CATPAGES,		NULL		},
#ifdef JMAN
/*{ "jcatpage",	"/",			&Dists,		DIST_JCATPAGES,		NULL		}, */
{ "jcatman",	"/",			&Dists,		DIST_JCATPAGES,		NULL		},
#endif
{ "proflibs",	"/",			&Dists,		DIST_PROFLIBS,		NULL		},
{ "dict",	"/",			&Dists,		DIST_DICT,		NULL		},
{ "info",	"/",			&Dists,		DIST_INFO,		NULL		},
{ "src",	"/",			&Dists,		DIST_SRC,		SrcDistTable	},
#if defined(PC98) && defined(PC98SRC)
{ "98src",	"/",			&Dists,		DIST_98SRC,		Src98DistTable	},
#endif /* defined(PC98) && defined(PC98SRC) */
{ "des",	"/",			&Dists,		DIST_DES,		DESDistTable	},
#ifdef __i386__
{ "compat1x",	"/",			&Dists,		DIST_COMPAT1X,		NULL		},
{ "compat20",	"/",			&Dists,		DIST_COMPAT20,		NULL		},
{ "compat21",	"/",			&Dists,		DIST_COMPAT21,		NULL		},
{ "compat22",	"/",			&Dists,		DIST_COMPAT22,		NULL		},
#if __FreeBSD__ > 3
{ "compat3x",	"/",			&Dists,		DIST_COMPAT3X,		NULL		},
#endif
#endif
{ "ports",	"/usr",			&Dists,		DIST_PORTS,		NULL		},
{ "local",	"/",			&Dists,		DIST_LOCAL,		NULL		},
{ "XF86335",	"/usr",			&Dists,		DIST_XF86,		XF86DistTable	},
{ NULL },
};

/* The DES distribution (not for export!) */
static Distribution DESDistTable[] = {
{ "des",        "/",                    &DESDists,	DIST_DES_DES,		NULL		},
#if __FreeBSD__ > 3
  { "krb4",	"/",			&DESDists,	DIST_DES_KERBEROS4,	NULL		},
#else
{ "krb",	"/",			&DESDists,	DIST_DES_KERBEROS,	NULL		},
#endif
{ "ssecure",	"/usr/src",		&DESDists,	DIST_DES_SSECURE,	NULL		},
{ "scrypto",	"/usr/src",		&DESDists,	DIST_DES_SCRYPTO,	NULL		},
{ "skerbero",	"/usr/src",		&DESDists,	DIST_DES_SKERBEROS,	NULL		},
{ NULL },
};

#ifdef PC98
static Distribution ide_kernel[] = {
{ "ide2",	"/",			&DistsIde,	DIST_98IDE2,		NULL		},
{ "ide4",	"/",			&DistsIde,	DIST_98IDE4,		NULL		},
{ "uide",	"/",			&DistsIde,	DIST_98UIDE,		NULL		},
{ NULL },
};
#endif

/* The /usr/src distribution */
static Distribution SrcDistTable[] = {
{ "sbase",	"/usr/src",		&SrcDists,	DIST_SRC_BASE,		NULL		},
{ "scontrib",	"/usr/src",		&SrcDists,	DIST_SRC_CONTRIB,	NULL		},
{ "sgnu",	"/usr/src",		&SrcDists,	DIST_SRC_GNU,		NULL		},
{ "setc",	"/usr/src",		&SrcDists,	DIST_SRC_ETC,		NULL		},
{ "sgames",	"/usr/src",		&SrcDists,	DIST_SRC_GAMES,		NULL		},
{ "sinclude",	"/usr/src",		&SrcDists,	DIST_SRC_INCLUDE,	NULL		},
{ "slib",	"/usr/src",		&SrcDists,	DIST_SRC_LIB,		NULL		},
{ "slibexec",	"/usr/src",		&SrcDists,	DIST_SRC_LIBEXEC,	NULL		},
{ "srelease",	"/usr/src",		&SrcDists,	DIST_SRC_RELEASE,	NULL		},
{ "sbin",	"/usr/src",		&SrcDists,	DIST_SRC_BIN,		NULL		},
{ "ssbin",	"/usr/src",		&SrcDists,	DIST_SRC_SBIN,		NULL		},
{ "sshare",	"/usr/src",		&SrcDists,	DIST_SRC_SHARE,		NULL		},
{ "ssys",	"/usr/src",		&SrcDists,	DIST_SRC_SYS,		NULL		},
{ "subin",	"/usr/src",		&SrcDists,	DIST_SRC_UBIN,		NULL		},
{ "susbin",	"/usr/src",		&SrcDists,	DIST_SRC_USBIN,		NULL		},
{ NULL },
};

#if defined(PC98) && defined(PC98SRC)
/* The /usr/src distribution */
static Distribution Src98DistTable[] = {
{ "sbase",	"/usr/src",		&Src98Dists,	DIST_SRC_BASE,		NULL		},
{ "scontrib",	"/usr/src",		&Src98Dists,	DIST_SRC_CONTRIB,	NULL		},
{ "setc",	"/usr/src",		&Src98Dists,	DIST_SRC_ETC,		NULL		},
{ "slib",	"/usr/src",		&Src98Dists,	DIST_SRC_LIB,		NULL		},
{ "srelease",	"/usr/src",		&Src98Dists,	DIST_SRC_RELEASE,	NULL		},
{ "ssbin",	"/usr/src",		&Src98Dists,	DIST_SRC_SBIN,		NULL		},
{ "sshare",	"/usr/src",		&Src98Dists,	DIST_SRC_SHARE,		NULL		},
{ "ssys",	"/usr/src",		&Src98Dists,	DIST_SRC_SYS,		NULL		},
{ "subin",	"/usr/src",		&Src98Dists,	DIST_SRC_UBIN,		NULL		},
{ "susbin",	"/usr/src",		&Src98Dists,	DIST_SRC_USBIN,		NULL		},
#if 0
{ "sbase",	"/usr/src",		&Src98Dists,	DIST_SRC_BASE,		NULL		},
{ "scontrib",	"/usr/src",		&Src98Dists,	DIST_SRC_CONTRIB,	NULL		},
{ "sgnu",	"/usr/src",		&Src98Dists,	DIST_SRC_GNU,		NULL		},
{ "setc",	"/usr/src",		&Src98Dists,	DIST_SRC_ETC,		NULL		},
{ "sgames",	"/usr/src",		&Src98Dists,	DIST_SRC_GAMES,		NULL		},
{ "sinclude",	"/usr/src",		&Src98Dists,	DIST_SRC_INCLUDE,	NULL		},
{ "slib",	"/usr/src",		&Src98Dists,	DIST_SRC_LIB,		NULL		},
{ "slibexec",	"/usr/src",		&Src98Dists,	DIST_SRC_LIBEXEC,	NULL		},
{ "srelease",	"/usr/src",		&Src98Dists,	DIST_SRC_RELEASE,	NULL		},
{ "sbin",	"/usr/src",		&Src98Dists,	DIST_SRC_BIN,		NULL		},
{ "ssbin",	"/usr/src",		&Src98Dists,	DIST_SRC_SBIN,		NULL		},
{ "sshare",	"/usr/src",		&Src98Dists,	DIST_SRC_SHARE,		NULL		},
{ "ssys",	"/usr/src",		&Src98Dists,	DIST_SRC_SYS,		NULL		},
{ "subin",	"/usr/src",		&Src98Dists,	DIST_SRC_UBIN,		NULL		},
{ "susbin",	"/usr/src",		&Src98Dists,	DIST_SRC_USBIN,		NULL		},
#endif
{ NULL },
};
#endif /* defined(PC98) && defined(PC98SRC) */

/* The XFree86 distribution */
static Distribution XF86DistTable[] = {
{ "XF86335",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_FONTS,	XF86FontDistTable },
{ "XF86335",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_SERVER,	XF86ServerDistTable },
{ "Xsrc1",	"/usr/X11R6/src",	&XF86Dists,	DIST_XF86_SRC,		NULL		},
{ "Xsrcctrb",	"/usr/X11R6/src",	&XF86Dists,	DIST_XF86_CSRC,		NULL		},
{ "Xbin",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_BIN,		NULL		},
{ "Xcfg",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_CFG,		NULL		},
{ "Xdoc",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_DOC,		NULL		},
{ "Xhtml",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_HTML,		NULL		},
{ "Xlib",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_LIB,		NULL		},
{ "Xlk98",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_LKIT98,	NULL		},
{ "Xlkit",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_LKIT,		NULL		},
{ "Xman",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_MAN,		NULL		},
{ "Xprog",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_PROG,		NULL		},
{ "Xps",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_PS,		NULL		},
{ "Xset",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_SET,		NULL		},
{ "PC98-Servers/X9set",	"/usr/X11R6",		&XF86Dists,	DIST_XF86_9SET,		NULL		},
{ NULL },
};

/* The XFree86 server distribution */
static Distribution XF86ServerDistTable[] = {
#ifdef __i386__
{ "PC98-Servers/X9480",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9480,	NULL		},
{ "PC98-Servers/X9EGC",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9EGC,	NULL		},
{ "PC98-Servers/X9GA9",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9GA9,	NULL		},
{ "PC98-Servers/X9GAN",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9GAN,	NULL		},
{ "PC98-Servers/X9LPW",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9LPW,	NULL		},
{ "PC98-Servers/X9MGA",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9MGA,	NULL		},
{ "PC98-Servers/X9NKV",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9NKV,	NULL		},
{ "PC98-Servers/X9NS3",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9NS3,	NULL		},
{ "PC98-Servers/X9SPW",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9SPW,	NULL		},
{ "PC98-Servers/X9SVG",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9SVG,	NULL		},
{ "PC98-Servers/X9TGU",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9TGU,	NULL		},
{ "PC98-Servers/X9WEP",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9WEP,	NULL		},
{ "PC98-Servers/X9WS",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9WS,	NULL		},
{ "PC98-Servers/X9WSN",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_9WSN,	NULL		},
#endif
{ "Servers/X3DL",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_3DL,	NULL		},
{ "Servers/X8514",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_8514,	NULL		},
{ "Servers/XAGX",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_AGX,	NULL		},
{ "Servers/XI128",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_I128,	NULL		},
{ "Servers/XMa8",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_MACH8,	NULL		},
{ "Servers/XMa32",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_MACH32,NULL		},
{ "Servers/XMa64",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_MACH64,NULL		},
{ "Servers/XMono",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_MONO,	NULL		},
{ "Servers/XP9K",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_P9000,	NULL		},
{ "Servers/XS3",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_S3,	NULL		},
{ "Servers/XS3V",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_S3V,	NULL		},
{ "Servers/XSVGA",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_SVGA,	NULL		},
{ "Servers/XVG16",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_VGA16,	NULL		},
{ "Servers/XW32",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_W32,	NULL		},
#ifdef __alpha__
{ "Servers/XTGA",	"/usr/X11R6",		&XF86ServerDists,	DIST_XF86_SERVER_TGA,	NULL		},
#endif
{ NULL },
};

/* The XFree86 font distribution */
static Distribution XF86FontDistTable[] = {
{ "Xfnts",	"/usr/X11R6",		&XF86FontDists,		DIST_XF86_FONTS_MISC,	NULL		},
{ "Xf100",	"/usr/X11R6",		&XF86FontDists,		DIST_XF86_FONTS_100,	NULL		},
{ "Xfcyr",	"/usr/X11R6",		&XF86FontDists,		DIST_XF86_FONTS_CYR,	NULL		},
{ "Xfscl",	"/usr/X11R6",		&XF86FontDists,		DIST_XF86_FONTS_SCALE,	NULL		},
{ "Xfnon",	"/usr/X11R6",		&XF86FontDists,		DIST_XF86_FONTS_NON,	NULL		},
{ "Xfsrv",	"/usr/X11R6",		&XF86FontDists,		DIST_XF86_FONTS_SERVER,	NULL		},
{ NULL },
};

static int	distMaybeSetDES(dialogMenuItem *self);
static int	distMaybeSetPorts(dialogMenuItem *self);


static void
distVerifyFlags(void)
{
    if (SrcDists)
	Dists |= DIST_SRC;
#if defined(PC98) && defined(PC98SRC)
    if (Src98Dists)
	Dists |= DIST_98SRC;
#endif /* defined(PC98) && defined(PC98SRC) */
    if (DESDists) {
	if (DESDists & DIST_DES_KERBEROS)
	    DESDists |= DIST_DES_DES;
	Dists |= DIST_DES;
    }
    if (XF86Dists & DIST_XF86_SET)
	XF86ServerDists |= DIST_XF86_SERVER_VGA16;
    if (XF86ServerDists)
	XF86Dists |= DIST_XF86_SERVER;
    if (XF86FontDists)
	XF86Dists |= DIST_XF86_FONTS;
    if (XF86Dists || XF86ServerDists || XF86FontDists) {
	Dists |= DIST_XF86;
#ifdef __i386__
	Dists |= DIST_COMPAT22;	/* For certain old X applications */
#if __FreeBSD__ > 3
	Dists |= DIST_COMPAT3X;
#endif
#endif
    }
    if (isDebug())
#if defined(PC98) && defined(PC98SRC)
	msgDebug("Dist Masks: Dists: %0x, DES: %0x, Srcs: %0x, 98Srcs: %0x\nXServer: %0x, XFonts: %0x, XDists: %0x\n",
		 Dists, DESDists, SrcDists, Src98Dists, XF86ServerDists, XF86FontDists, XF86Dists);
#else /* defined(PC98) && defined(PC98SRC) */
	msgDebug("Dist Masks: Dists: %0x, DES: %0x, Srcs: %0x\nXServer: %0x, XFonts: %0x, XDists: %0x\n",
		 Dists, DESDists, SrcDists, XF86ServerDists, XF86FontDists, XF86Dists);
#endif /* defined(PC98) && defined(PC98SRC) */
}

int
distReset(dialogMenuItem *self)
{
    Dists = 0;
    DESDists = 0;
    SrcDists = 0;
#if defined(PC98) && defined(PC98SRC)
    Src98Dists = 0;
#endif /* defined(PC98) && defined(PC98SRC) */
    XF86Dists = 0;
    XF86ServerDists = 0;
    XF86FontDists = 0;
    return DITEM_SUCCESS | DITEM_REDRAW;
}

int
distConfig(dialogMenuItem *self)
{
    char *cp;

    distReset(NULL);

    if ((cp = variable_get(VAR_DIST_MAIN)) != NULL)
	Dists = atoi(cp);

    if ((cp = variable_get(VAR_DIST_DES)) != NULL)
	DESDists = atoi(cp);

    if ((cp = variable_get(VAR_DIST_SRC)) != NULL)
	SrcDists = atoi(cp);

    if ((cp = variable_get(VAR_DIST_X11)) != NULL)
	XF86Dists = atoi(cp);

    if ((cp = variable_get(VAR_DIST_XSERVER)) != NULL)
	XF86ServerDists = atoi(cp);

    if ((cp = variable_get(VAR_DIST_XFONTS)) != NULL)
	XF86FontDists = atoi(cp);
    distVerifyFlags();
    return DITEM_SUCCESS | DITEM_REDRAW;
}

static int
distSetX(void)
{
    Dists |= DIST_XF86;
    XF86Dists = DIST_XF86_BIN | DIST_XF86_SET | DIST_XF86_CFG | DIST_XF86_LIB | DIST_XF86_PROG | DIST_XF86_MAN | DIST_XF86_SERVER | DIST_XF86_FONTS;
#ifdef PC98
    XF86ServerDists = DIST_XF86_SERVER_9480 | DIST_XF86_SERVER_9EGC;
    XF86FontDists = DIST_XF86_FONTS_MISC | DIST_XF86_FONTS_NON;
#else
    XF86ServerDists = DIST_XF86_SERVER_SVGA | DIST_XF86_SERVER_VGA16;
    XF86FontDists = DIST_XF86_FONTS_MISC;
#endif
    return distSetXF86(NULL);
}

int
distSetDeveloper(dialogMenuItem *self)
{
    int i;

    distReset(NULL);
    Dists = _DIST_DEVELOPER;
    SrcDists = DIST_SRC_ALL;
#if defined(PC98) && defined(PC98SRC)
    Src98Dists = DIST_SRC_ALL;
#endif /* defined(PC98) && defined(PC98SRC) */
    i = distMaybeSetDES(self) | distMaybeSetPorts(self);
    distVerifyFlags();
    return i;
}

int
distSetXDeveloper(dialogMenuItem *self)
{
    int i;

    i = distSetDeveloper(self);
    i |= distSetX();
    distVerifyFlags();
    return i;
}

int
distSetKernDeveloper(dialogMenuItem *self)
{
    int i;

    distReset(NULL);
    Dists = _DIST_DEVELOPER;
    SrcDists = DIST_SRC_SYS;
#if defined(PC98) && defined(PC98SRC)
    Src98Dists = DIST_SRC_SYS;
#endif /* defined(PC98) && defined(PC98SRC) */
    i = distMaybeSetDES(self) | distMaybeSetPorts(self);
    distVerifyFlags();
    return i;
}

int
distSetXKernDeveloper(dialogMenuItem *self)
{
    int i;

    i = distSetKernDeveloper(self);
    i |= distSetX();
    distVerifyFlags();
    return i;
}

int
distSetUser(dialogMenuItem *self)
{
    int i;

    distReset(NULL);
    Dists = _DIST_USER;
#ifdef PCCARD
    if (pccard_mode) {
	Dists |= DIST_SRC;
	SrcDists = DIST_SRC_SYS;
#if defined(PC98) && defined(PC98SRC)
	Dists |= DIST_98SRC;
	Src98Dists = DIST_SRC_SYS;
#endif /* defined(PC98) && defined(PC98SRC) */
    }
#endif
    i = distMaybeSetDES(self) | distMaybeSetPorts(self);
    distVerifyFlags();
    return i;
}

int
distSetXUser(dialogMenuItem *self)
{
    int i;

    i = distSetUser(self);
    i |= distSetX();
    distVerifyFlags();
    return i;
}

int
distSetMinimum(dialogMenuItem *self)
{
    distReset(NULL);
#ifdef PC98
    Dists = DIST_BIN | DIST_98BIN;
#else
    Dists = DIST_BIN;
#endif
    return DITEM_SUCCESS | DITEM_REDRAW;
}

int
distSetEverything(dialogMenuItem *self)
{
    int i;

    Dists = DIST_ALL | DIST_XF86;
    SrcDists = DIST_SRC_ALL;
#if defined(PC98) && defined(PC98SRC)
    Dists |= DIST_98SRC;
    Src98Dists = DIST_SRC_ALL;
#endif /* defined(PC98) && defined(PC98SRC) */
    XF86Dists = DIST_XF86_ALL;
    XF86ServerDists = DIST_XF86_SERVER_ALL;
    XF86FontDists = DIST_XF86_FONTS_ALL;
    i = distMaybeSetDES(self) | distMaybeSetPorts(self);
    distVerifyFlags();
    return i;
}

int
distSetDES(dialogMenuItem *self)
{
    int i;
 
    dialog_clear_norefresh();
    if (!dmenuOpenSimple(&MenuDESDistributions, FALSE))
	i = DITEM_FAILURE;
    else
	i = DITEM_SUCCESS;
    distVerifyFlags();
    return i | DITEM_REDRAW | DITEM_RESTORE;
}

static int
distMaybeSetDES(dialogMenuItem *self)
{
    int i = DITEM_SUCCESS | DITEM_REDRAW;

    dialog_clear_norefresh();
    KANJI_MESSAGE(
    "DES 暗号化ソフトウェアをインストールしたいのですか?\n\n"
    "もしここで No を選択すれば, FreeBSD は MD5 ベースのパスワード方式\n"
    "を使用します. これは今まで以上に安全ですが, 古典的な UNIX の DES \n"
    "によるパスワードや他の FreeBSD 以外のシステムとは互換性を持ちませ\n"
    "ん.\n"
    "もしあなたが住んでいるのがアメリカ合衆国でもカナダでもない場合で,\n"
    "かつアメリカ合衆国の FTP サーバからインストールしている場合は, こ\n"
    "の質問に Yes と「答えないで下さい」. これは合衆国の輸出制限に抵触\n"
    "し, サーバサイトをトラブルに巻き込むかも知れません. このような場合\n"
    "は, 合衆国のサーバから DES 以外の配布ファイルを入手し, カスタムイ\n"
    "ンストールを用いてメディアタイプを変更し, インターナショナルな FTP \n"
    "サーバに切替えて, 二度目のパスで DES 配布ファイルを入手して下さい.");
    if (!msgYesNo(KM("Do you wish to install DES cryptographic software?\n\n"
		  "If you choose No, FreeBSD will use an MD5 based password scheme which,\n"
		  "while perhaps more secure, is not interoperable with the traditional\n"
		  "UNIX DES passwords on other non-FreeBSD systems.\n\n"
		  "Please do NOT choose Yes at this point if you are outside the\n"
		  "United States and Canada yet are installing from a U.S. FTP server.\n"
		  "This will violate U.S. export restrictions and possibly get the\n"
		  "server site into trouble!  In such cases, install everything but the\n"
		  "DES distribution from the U.S. server then switch your media type to\n"
		  "point to an international FTP server, using the Custom installation\n"
		  "option to select and extract the DES distribution in a second pass."))) {
	if (!dmenuOpenSimple(&MenuDESDistributions, FALSE))
	    i = DITEM_FAILURE;
    }
    distVerifyFlags();
    return i | DITEM_REDRAW | DITEM_RESTORE;
}

static int
distMaybeSetPorts(dialogMenuItem *self)
{
    dialog_clear_norefresh();
    KANJI_MESSAGE("FreeBSD の portsコレクションをインストールしますか?\n\n"
		  "これによって 2000 以上の移植されたソフトウェアが使えるようになりますが\n"
		  "\"clean\" な場合でも 90MB 程度, たくさんの配布物の tarball がロード\n"
		  "されているなら もっとたくさんのディスク・スペースが必要です. (FreeBSD\n"
		  "の CDROM の特別な CD をもっておらず /cdrom にマウントできない場合です,\n"
		  "それが可能なら問題はずっと小さくなります).\n\n"
		  "ports コレクションはとても価値のあるものであり, /usr パーティションに\n"
		  "最低で 100MB のスペースがあるなら, 置いておく価値があります.\n\n"
		  "ports コレクションと最新の ports に関する情報は以下を参照して下さい:\n"
		  "    http://www.freebsd.org/ports\n");
    if (!msgYesNo(KM("Would you like to install the FreeBSD ports collection?\n\n"
		  "This will give you ready access to over 2000 ported software packages,\n"
		  "though at a cost of around 90MB of disk space when \"clean\" and possibly\n"
		  "much more than that if a lot of the distribution tarballs are loaded\n"
		  "(unless you have the extra CDs available from a FreeBSD CDROM distribution\n"
		  "and can mount them on /cdrom, in which case this is far less of a problem).\n\n"
		  "The ports collection is a very valuable resource and, if you have at least\n"
		  "100MB to spare in your /usr partition, well worth having around.\n\n"
		  "For more information on the ports collection & the latest ports, visit:\n"
		  "    http://www.freebsd.org/ports\n")))
	Dists |= DIST_PORTS;
    else
	Dists &= ~DIST_PORTS;
    return DITEM_SUCCESS | DITEM_RESTORE;
}

static Boolean
distSetByName(Distribution *dist, char *name)
{
    int i, status = FALSE;
    
    /* Loop through current set */
    for (i = 0; dist[i].my_name; i++) {
	/* This is shorthand for "dist currently disabled" */
	if (!dist[i].my_dir)
	    continue;
	if (!strcmp(dist[i].my_name, name)) {
	    *(dist[i].my_mask) |= dist[i].my_bit;
	    status = TRUE;
	}
	if (dist[i].my_dist) {
	    if (distSetByName(dist[i].my_dist, name)) {
		status = TRUE;
	    }
	}
    }
    distVerifyFlags();
    return status;
}

static Boolean
distUnsetByName(Distribution *dist, char *name)
{
    int i, status = FALSE;
    
    /* Loop through current set */
    for (i = 0; dist[i].my_name; i++) {
	/* This is shorthand for "dist currently disabled" */
	if (!dist[i].my_dir)
	    continue;
	if (!strcmp(dist[i].my_name, name)) {
	    *(dist[i].my_mask) &= ~(dist[i].my_bit);
	    status = TRUE;
	}
	if (dist[i].my_dist) {
	    if (distUnsetByName(dist[i].my_dist, name)) {
		status = TRUE;
	    }
	}
    }
    return status;
}

/* Just for the dispatch stuff */
int
distSetCustom(dialogMenuItem *self)
{
    char *cp, *cp2, *tmp;

    if (!(tmp = variable_get(VAR_DISTS))) {
	msgDebug("distSetCustom() called without %s variable set.\n", VAR_DISTS);
	return DITEM_FAILURE;
    }

    cp = alloca(strlen(tmp) + 1);
    if (!cp)
	msgFatal("Couldn't alloca() %d bytes!\n", strlen(tmp) + 1);
    strcpy(cp, tmp);
    while (cp) {
	if ((cp2 = index(cp, ' ')) != NULL)
	    *(cp2++) = '\0';
	if (!distSetByName(DistTable, cp))
	    msgDebug("distSetCustom: Warning, no such release \"%s\"\n", cp);
	cp = cp2;
    }
    distVerifyFlags();
    return DITEM_SUCCESS;
}

/* Just for the dispatch stuff */
int
distUnsetCustom(dialogMenuItem *self)
{
    char *cp, *cp2, *tmp;

    if (!(tmp = variable_get(VAR_DISTS))) {
	msgDebug("distUnsetCustom() called without %s variable set.\n", VAR_DISTS);
	return DITEM_FAILURE;
    }

    cp = alloca(strlen(tmp) + 1);
    if (!cp)
	msgFatal("Couldn't alloca() %d bytes!\n", strlen(tmp) + 1);
    strcpy(cp, tmp);
    while (cp) {
	if ((cp2 = index(cp, ' ')) != NULL)
	    *(cp2++) = '\0';
	if (!distUnsetByName(DistTable, cp))
	    msgDebug("distUnsetCustom: Warning, no such release \"%s\"\n", cp);
	cp = cp2;
    }
    return DITEM_SUCCESS;
}
    
int
distSetSrc(dialogMenuItem *self)
{
    int i;

    dialog_clear_norefresh();
    if (!dmenuOpenSimple(&MenuSrcDistributions, FALSE))
	i = DITEM_FAILURE;
    else
	i = DITEM_SUCCESS;
    distVerifyFlags();
    return i | DITEM_RESTORE;
}

#if defined(PC98) && defined(PC98SRC)
int
distSet98Src(dialogMenuItem *self)
{
    int i = DITEM_SUCCESS;
    int oldSrc98Dists = Src98Dists;

    dialog_clear_norefresh();
    if (dmenuOpenSimple(&Menu98SrcDistributions, FALSE)) {
	if (Src98Dists) {
	    Dists |= DIST_98SRC;
	    /* 変化したビットをクリアする (share を除いて) */
	    SrcDists &= ~((oldSrc98Dists ^ Src98Dists) & ~DIST_SRC_SHARE);
	    SrcDists |= Src98Dists & ~DIST_SRC_SHARE;
	    msgDebug("SetSrc Masks: 98Srcs: %0x, Srcs: %0x, Dists: %0x\n", Src98Dists, SrcDists, Dists);
	}
	if (SrcDists)
	    Dists |= DIST_SRC;
    }
    else
	i = DITEM_FAILURE;
    return i | DITEM_RECREATE;
}
#endif /* defined(PC98) && defined(PC98SRC) */

int
distSetXF86(dialogMenuItem *self)
{
    int i = DITEM_SUCCESS;

    dialog_clear_norefresh();
    if (!dmenuOpenSimple(&MenuXF86Select, FALSE))
	i = DITEM_FAILURE;
    distVerifyFlags();
    return i | DITEM_RESTORE;
}

static Boolean got_intr = FALSE;

/* timeout handler */
static void
handle_intr(int sig)
{
    msgDebug("User generated interrupt.\n");
    got_intr = TRUE;
}

static int
check_for_interrupt(void)
{
    if (got_intr) {
	got_intr = FALSE;
	return TRUE;
    }
    return FALSE;
}

static Boolean
distExtract(char *parent, Distribution *me)
{
    int i, status, total, intr;
#ifdef KURA_IMPL
    int j;
#endif /* KURA_IMPL */
    int cpid, zpid, fd2, chunk, numchunks;
    char *path, *dist, buf[BUFSIZ];
    const char *tmp;
    FILE *fp;
    WINDOW *w = savescr();
    struct timeval start, stop;
    struct sigaction old, new;
#ifdef KURA_IMPL
    Distribution *subdist;
#endif /* KURA_IMPL */

    status = TRUE;
    if (isDebug())
	msgDebug("distExtract: parent: %s, me: %s\n", parent ? parent : "(none)", me->my_name);

    /* Make ^C fake a sudden timeout */
    new.sa_handler = handle_intr;
    new.sa_flags = 0;
    (void)sigemptyset(&new.sa_mask);
    dialog_clear_norefresh();
    dialog_msgbox("Please Wait", "Extracting all requested distributions...", -1, -1, 0);
    sigaction(SIGINT, &new, &old);

    /* Loop through to see if we're in our parent's plans */
    for (i = 0; me[i].my_name; i++) {
	dist = me[i].my_name;
	path = parent ? parent : dist;

	/* If our bit isn't set, go to the next */
	if (!(me[i].my_bit & *(me[i].my_mask)))
	    continue;

	/* This is shorthand for "dist currently disabled" */
	if (!me[i].my_dir) {
	    *(me[i].my_mask) &= ~(me[i].my_bit);
	    continue;
	}

	/* Recurse if we actually have a sub-distribution */
	if (me[i].my_dist) {
#ifdef KURA_IMPL
	    status = distExtract(dist, me[i].my_dist);
	    subdist = me[i].my_dist; 
	    for(j = 0; subdist[j].my_name && (*(subdist[j].my_mask) == 0); j++)
		;
	    if(subdist[j].my_name) {
		/* not all subdists has been extracted */
		status = FALSE;
	    }
#else
	    if ((status = distExtract(dist, me[i].my_dist)) == TRUE)
		*(me[i].my_mask) &= ~(me[i].my_bit);
#endif /* KURA_IMPL */
	    goto done;
	}

	/*
	 * Try to get distribution as multiple pieces, locating and parsing an
	 * info file which tells us how many we need for this distribution.
	 */
	numchunks = 0;

	snprintf(buf, sizeof buf, "%s/%s.inf", path, dist);

    getinfo:
	fp = mediaDevice->get(mediaDevice, buf, TRUE);
	intr = check_for_interrupt();
	if (fp == (FILE *)IO_ERROR || intr) {	/* Hard error, can't continue */
	    KANJI_MESSAGE("%s をオープンできません: %s.\nメディアを再初期化しますか?");
	    if (!msgYesNo(KM("Unable to open %s: %s.\nReinitialize media?"),
			  buf, !intr ? "I/O error." : "User interrupt.")) {
		mediaDevice->shutdown(mediaDevice);
		if (!mediaDevice->init(mediaDevice)) {
		    status = FALSE;
		    goto done;
		}
		else
		    goto getinfo;
	    }
	    else {
		status = FALSE;
		goto done;
	    }
	}
	else if (fp > 0) {
	    properties dist_attr;

	    if (isDebug())
		msgDebug("Parsing attributes file for distribution %s\n", dist);

	    dist_attr = properties_read(fileno(fp));
	    intr = check_for_interrupt();
	    if (intr || !dist_attr) {
		KANJI_MESSAGE("%s 配布ファイルに関する情報ファイルを読み込めません: %s\n"
			   "メディアが正常であるかどうか確認して再度お試し下さい.");
		msgConfirm(KM("Cannot parse information file for the %s distribution: %s\n"
			   "Please verify that your media is valid and try again."),
			   dist, !intr ? "I/O error" : "User interrupt");
	    }
	    else {
		tmp = property_find(dist_attr, "Pieces");
		if (tmp)
		    numchunks = strtol(tmp, 0, 0);
	    }
	    fclose(fp);
	    properties_free(dist_attr);
	    if (!numchunks)
		continue;
	}
	else {
	    /* Try to get the distribution as a single file */
	    snprintf(buf, sizeof buf, "%s/%s.tgz", path, dist);
	    /*
	     * Passing TRUE as 3rd parm to get routine makes this a "probing" get, for which errors
	     * are not considered too significant.
	     */
	getsingle:
	    fp = mediaDevice->get(mediaDevice, buf, TRUE);
	    intr = check_for_interrupt();
	    if (fp == (FILE *)IO_ERROR || intr) {	/* Hard error, can't continue */
		if (intr) {	/* result of an interrupt */
		    KANJI_MESSAGE("%s をオープンできません: ユーザによる中断");
		    msgConfirm(KM("Unable to open %s: User interrupt"), buf);
		} else {
		    KANJI_MESSAGE("%s をオープンできません: I/Oエラー");
		    msgConfirm(KM("Unable to open %s: I/O error"), buf);
		}
		mediaDevice->shutdown(mediaDevice);
		if (!mediaDevice->init(mediaDevice)) {
		    status = FALSE;
		    goto done;
		}
		else
		    goto getsingle;
	    }
	    else if (fp > 0) {
		char *dir = root_bias(me[i].my_dir);

		dialog_clear_norefresh();
#ifdef KURA_IMPL
		KANJI_MESSAGE("%s を %s に展開しています…");
#else
		KANJI_MESSAGE("%s をディレクトリ %s に展開しています…");
#endif /* KURA_IMPL */
		msgNotify(KM("Extracting %s into %s directory..."), dist, dir);
		status = mediaExtractDist(dir, dist, fp);
		fclose(fp);
		goto done;
	    }
	    else
		numchunks = 0;
	}

	/* Fall through from "we got the attribute file, now get the pieces" step */
	if (!numchunks)
	    continue;

	if (isDebug())
	    msgDebug("Attempting to extract distribution from %u chunks.\n", numchunks);

	total = 0;
	(void)gettimeofday(&start, (struct timezone *)0);

	/* We have one or more chunks, initialize unpackers... */
	mediaExtractDistBegin(root_bias(me[i].my_dir), &fd2, &zpid, &cpid);

	/* And go for all the chunks */
	dialog_clear_norefresh();
	for (chunk = 0; chunk < numchunks; chunk++) {
	    int n, retval, last_msg;
	    char prompt[80];

	    last_msg = 0;

	getchunk:
	    snprintf(buf, sizeof buf, "%s/%s.%c%c", path, dist, (chunk / 26) + 'a', (chunk % 26) + 'a');
	    if (isDebug())
		msgDebug("trying for piece %d of %d: %s\n", chunk + 1, numchunks, buf);
	    fp = mediaDevice->get(mediaDevice, buf, FALSE);
	    intr = check_for_interrupt();
	    if (fp <= (FILE *)0 || intr) {
		if (fp == (FILE *)0) {
		    KANJI_MESSAGE("%s がこのメディアには見つかりません. メディアを再初期化しています.");
		    msgConfirm(KM("Failed to find %s on this media.  Reinitializing media."), buf);
		} else {
		    KANJI_MESSAGE("ファイル %s を読み込めません\n"
				  "%s: メディアを再初期化しています.");
		    msgConfirm(KM("failed to retreive piece file %s.\n"
			       "%s: Reinitializing media."), buf, !intr ? "I/O error" : "User interrupt");
		}
		mediaDevice->shutdown(mediaDevice);
		if (!mediaDevice->init(mediaDevice))
		    goto punt;
		else
		    goto getchunk;
 	    }

#ifdef KURA_IMPL
	    KANJI_MESSAGE("%s を %s に転送しています…");
#else
	    KANJI_MESSAGE("%s を %s ディレクトリに転送しています…");
#endif /* KURA_IMPL */
	    snprintf(prompt, sizeof prompt, KM("Extracting %s into %s directory..."), dist, root_bias(me[i].my_dir));
	    KANJI_MESSAGE("進行状況");
	    dialog_gauge(KM("Progress"), prompt, 8, 15, 6, 50, (int)((float)(chunk + 1) / numchunks * 100));

	    while (1) {
		int seconds;

		n = fread(buf, 1, BUFSIZ, fp);
		if (check_for_interrupt()) {
		    KANJI_MESSAGE("メディア読みだしエラー: ユーザによる中断.\n");
		    msgConfirm(KM("Media read error:  User interrupt."));
		    fclose(fp);
		    goto punt;
		}
		else if (n <= 0)
		    break;
		total += n;

		/* Print statistics about how we're doing */
		(void) gettimeofday(&stop, (struct timezone *)0);
		stop.tv_sec = stop.tv_sec - start.tv_sec;
		stop.tv_usec = stop.tv_usec - start.tv_usec;
		if (stop.tv_usec < 0)
		    stop.tv_sec--, stop.tv_usec += 1000000;
		seconds = stop.tv_sec + (stop.tv_usec / 1000000.0);
		if (!seconds)
		    seconds = 1;

		if (seconds != last_msg) {
		    last_msg = seconds;
#ifdef KURA_IMPL
		    KANJI_MESSAGE(
		    "%10d バイト %s を読み込みました "
		    "(チャンク %d/%d, %.1f KB/秒)");
#else
		    KANJI_MESSAGE(
		    "%10d バイト %s を読み込みました, "
		    "チャンク %2d / %2d @ %.1f KB/秒");
#endif /* KURA_IMPL */
		    msgInfo(KM("%10d bytes read from %s dist, chunk %2d of %2d @ %.1f KB/sec."),
			    total, dist, chunk + 1, numchunks, (total / seconds) / 1024.0);
		}
		retval = write(fd2, buf, n);
		if (retval != n) {
		    fclose(fp);
		    dialog_clear_norefresh();
#ifdef KURA_IMPL
		    KANJI_MESSAGE("転送中に書き込みエラーが発生しました!(%dバイト/%dバイト書き込み済み)");
#else
		    KANJI_MESSAGE("転送中に書き込みエラーが発生しました! (%d バイト / %d バイト 書き込み済み)");
#endif /* KURA_IMPL */
		    msgConfirm(KM("Write failure on transfer! (wrote %d bytes of %d bytes)"), retval, n);
		    goto punt;
		}
	    }
	    fclose(fp);
	}
	close(fd2);
	status = mediaExtractDistEnd(zpid, cpid);
        goto done;

    punt:
	close(fd2);
	mediaExtractDistEnd(zpid, cpid);
	status = FALSE;

    done:
#ifdef PC98
	/* unlink X --> XF86_SVGA */
	if (strcmp(me[i].my_name, "X312bin") == 0)
	    if (access("/usr/X11R6/bin/X", F_OK)==0)
		if (vsystem("rm -f /usr/X11R6/bin/X")) {
		    KANJI_MESSAGE("/usr/X11R6/bin/X を削除できません!");
		    msgConfirm(KM("Unable to unlink /usr/X11R6/bin/X!"));
		}
#endif
	if (!status) {
	    dialog_clear_norefresh();
	    if (me[i].my_dist) {
		    KANJI_MESSAGE(
		    "配布ファイル %s のすべてのコンポーネントを転送することができません.\n"
		    "もし CDROM インストールであるならば, DES コードのアメリカ合衆国から\n"
		    "の輸出制限によるものでしょう. ローカルな FTP サイトからこれらを入手\n"
		    "して下さい!");
		msgConfirm(KM("Unable to transfer all components of the %s distribution.\n"
			   "If this is a CDROM install, it may be because export restrictions prohibit\n"
			   "DES code from being shipped from the U.S.  Try to get this code from a\n"
			   "local FTP site instead!"), me[i].my_name);
	    }
	    else {
		    KANJI_MESSAGE(
		    "配布ファイル %s を\n"
		    "%s から転送できません.\n\n"
		    "もう一度試してみますか?");
		status = msgYesNo(KM("Unable to transfer the %s distribution from\n%s.\n\n"
				  "Do you want to try to retrieve it again?"),
				  me[i].my_name, mediaDevice->name);
		if (!status)
		    --i;
	    }
	}
	/* Extract was successful, remove ourselves from further consideration */
	if (status)
	    *(me[i].my_mask) &= ~(me[i].my_bit);
	else
	    continue;
    }
    sigaction(SIGINT, &old, NULL);	/* Restore signal handler */
    restorescr(w);
    return status;
}

static void
printSelected(char *buf, int selected, Distribution *me, int *col)
{
    int i;

    /* Loop through to see if we're in our parent's plans */
    for (i = 0; me[i].my_name; i++) {

	/* If our bit isn't set, go to the next */
	if (!(me[i].my_bit & selected))
	    continue;

	/* This is shorthand for "dist currently disabled" */
	if (!me[i].my_dir)
	    continue;

#if 1	/* add at PCCARD */
	/* Do not display the redundant items */
	if (strstr(buf, me[i].my_name) != NULL)
	    continue;
#endif
	*col += strlen(me[i].my_name);
	if (*col > 50) {
	    *col = 0;
	    strcat(buf, "\n");
	}
	sprintf(&buf[strlen(buf)], " %s", me[i].my_name);
	/* Recurse if have a sub-distribution */
	if (me[i].my_dist)
	    printSelected(buf, *(me[i].my_mask), me[i].my_dist, col);
    }
}

int
distExtractAll(dialogMenuItem *self)
{
    int old_dists, retries = 0, status = DITEM_SUCCESS;
    char buf[512];
    WINDOW *w;

    /* paranoia */
    if (!Dists) {
	if (!dmenuOpenSimple(&MenuSubDistributions, FALSE) || !Dists)
	    return DITEM_FAILURE;
    }

    if (!mediaVerify() || !mediaDevice->init(mediaDevice))
	return DITEM_FAILURE;

#ifdef PC98
    /* IDE カーネルの設定 DIST_98BIN の設定に合わせてフラグを設定する */
    if (Dists & DIST_98BIN) {			/* 98bin の指定がある */
	if (DistsIdeFlg & DIST_98IDE2) {	/* boot.flp に /IDE2 があれば */
	    Dists98 |= DIST_98BIN;
	    DistsIde |= DIST_98IDE2;
	}
	else if(DistsIdeFlg & DIST_98IDE4) {	/* boot.flp に /IDE4 があれば */
	    Dists98 |= DIST_98BIN;
	    DistsIde |= DIST_98IDE4;
	}
	else if(DistsIdeFlg & DIST_98UIDE) {	/* boot.flp に /UIDE があれば */
	    Dists98 |= DIST_98BIN;
	    DistsIde |= DIST_98UIDE;
	}
    }
#endif

    old_dists = Dists;
    distVerifyFlags();

    dialog_clear_norefresh();
    w = savescr();
    KANJI_MESSAGE("指定された全ての配布ファイルを展開します…");
    msgNotify(KM("Attempting to install all selected distributions.."));

    /* Try for 3 times around the loop, then give up. */
    while (Dists && ++retries < 3)
	distExtract(NULL, DistTable);
#ifdef KURA_IMPL
    distVerifyFlags();
#endif /* KURA_IMPL */

    dialog_clear_norefresh();
    /* Only do bin fixup if bin dist was successfully extracted */
#ifdef PC98
    if ((old_dists & DIST_98BIN) && !(Dists & DIST_98BIN))
#else
    if ((old_dists & DIST_BIN) && !(Dists & DIST_BIN))
#endif
	status |= installFixupBin(self);
    if (old_dists & DIST_XF86)
	status |= installFixupXFree(self);

    /* Clear any local dist flags now */
    Dists &= ~DIST_LOCAL;

    if (Dists) {
	int col = 0;

	buf[0] = '\0';
	dialog_clear_norefresh();
	printSelected(buf, Dists, DistTable, &col);
	dialog_clear_norefresh();
#if defined(PC98) && defined(KURA_IMPL) && defined(PCCARD)
	KANJI_MESSAGE(
	"以下の配布ファイルを展開できませんでした. これはおそらく, 選択した\n"
	"インストールメディアにこれらが存在しないためでしょう.\n"
	"展開できなかった配布ファイルが別のメディア上にあるのならば, カスタ\n"
	"ムインストールメニュー中の「インストールメディアの選択」からを再度\n"
	"行って下さい. \n\n\t%s");
	msgConfirm(KM("Couldn't extract the following distributions.  This may\n"
		   "be because they were not available on the installation\n"
		   "media you've chosen.\n"
		   "If the distributions failed to be extracted are on any\n"
		   "other media, try again from \"the selection of the install\n"
		   "media\" in the custom installation menu.\n\n\t%s"), buf);
#else /* PC98 && KURA_IMPL */
	KANJI_MESSAGE(
	"以下の配布ファイルを展開できませんでした. これはおそらく, 選択した\n"
	"インストールメディアにこれらが存在しないためでしょう.\n\n\t%s"); 
	msgConfirm(KM("Couldn't extract the following distributions.  This may\n"
		   "be because they were not available on the installation\n"
		   "media you've chosen:\n\n\t%s"), buf);
#endif /* PC98 && KURA_IMPL */
    }
    restorescr(w);
    return status;
}
