/*
 *   Copyright (c) 1999 David Parsons. 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.
 *  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.
 *  3. All advertising materials mentioning features or use of this
 *     software must display the following acknowledgement:
 *     
 *   This product includes software developed by David Parsons
 *   (orc@pell.chi.il.us)
 *
 *  4. My name may not be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *     
 *  THIS SOFTWARE IS PROVIDED BY DAVID PARSONS ``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 DAVID
 *  PARSONS 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, 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.
 */
/*
 * packages:  code that deals with installation packages
 */
#include "pathnames.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "packages.h"
#include "media.h"

struct pkg *packages = 0;	/* goodies to install */
int NRpkg = 0;			/* number of goodies to install */


/*
 * free_package_list() -- free the old package list, if any.
 */
static void
free_package_list()
{
    int cnt;

    for (cnt=0; cnt<NRpkg; cnt++) {
	free(packages[cnt].name);
	free(packages[cnt].desc);
    }
    if (packages)
	free(packages);
    NRpkg = 0;
    packages = 0;
} /* free_package_list */


/*
 * readpackagelist() reads the PACKAGES file and fills the packages[] array
 */
int
readpackagelist(void *this, int fd)
{
    FILE *input = fdopen(fd, "r");
    int cnt;
    char line[200], name[80], desc[80], flags[80], size[20];
    char **dep;
    int required;
    int finished = 0;

    free_package_list();
    packages = malloc(0);
    dep = malloc(0);

    fprintf(stderr, "Loading package TOC from %s (%s)\n", mName(this), mDev(this));
    while (fgets(line, sizeof line, input)) {
	if (line[0] == '#')
	    continue;
	if (strcmp(line, "$EOF\n") == 0) {
	    finished=1;
	    break;
	}
	memset(flags, 0, sizeof flags);
	if (sscanf(line, "%[^:]:%[^:]:%[^:]:%[^\n]",
				name,flags,size,desc) == 4) {

	    required = (strcasecmp(flags, "required-package") == 0);

	    packages = realloc(packages, (2+NRpkg)*sizeof packages[0]);
	    dep = realloc(dep, (2+NRpkg) * sizeof dep[0]);
	    dep[NRpkg] = 0;
	    packages[NRpkg].flags = 0;
	    packages[NRpkg].name = strdup(name);
	    packages[NRpkg].size = atoi(size);
	    packages[NRpkg].desc = strdup(desc);

	    if (required)
		packages[NRpkg].flags |= PKG_REQUIRED;
	    else if (strcasecmp(flags, "none") != 0)
		dep[NRpkg] = strdup(flags);
	    fprintf(stderr, "%s: depends=[%s], %ld bytes, `%s'\n",
			    name, flags, packages[NRpkg].size, desc);
	    NRpkg++;
	}
    }

    /* walk the dependency list to build dependencies for each package
     */
    for (cnt=0; cnt < NRpkg; cnt++) {
	char *p;

	FD_ZERO(&packages[cnt].depends);

	if (dep[cnt] == 0)
	    continue;

	for (p = strtok(dep[cnt], ","); p; p = strtok(0, ",")) {
	    int i;

	    for (i=0; i < NRpkg; i++)
		if (i != cnt && strcmp(p, packages[i].name) == 0) {
		    FD_SET(i, &packages[cnt].depends);
		    break;
		}
	}
	free(dep[cnt]);
    }
    free(dep);
    fclose(input);

    if (finished) {
	fprintf(stderr, "Read %d package%s from %s (%s)\n",
			    NRpkg, (NRpkg != 1) ? "s":"",
			    mName(this), mDev(this));
	return 0;
    }
    Error("Incomplete package list; EOF after reading %d package%s\n",
			NRpkg, (NRpkg==1)?"":"s");
    free_package_list();
    return 1;
} /* readpackagelist */
