/*
 *
 * Copyright 1998-1999, University of Notre Dame.
 * Authors: Jeffrey M. Squyres, Kinis L. Meyer with M. D. McNally 
 *          and Andrew Lumsdaine
 *
 * This file is part of the Notre Dame LAM implementation of MPI.
 *
 * You should have received a copy of the License Agreement for the
 * Notre Dame LAM implementation of MPI along with the software; see
 * the file LICENSE.  If not, contact Office of Research, University
 * of Notre Dame, Notre Dame, IN 46556.
 *
 * Permission to modify the code and to distribute modified code is
 * granted, provided the text of this NOTICE is retained, a notice that
 * the code was modified is included with the above COPYRIGHT NOTICE and
 * with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
 * file is distributed with the modified code.
 *
 * LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
 * By way of example, but not limitation, Licensor MAKES NO
 * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
 * PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
 * OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
 * OR OTHER RIGHTS.  
 *
 * Additional copyrights may follow.
 *
 *	Ohio Trollius
 *	Copyright 1995 The Ohio State University
 *	GDB
 *
 *	$Log: proc_schema.c,v $
 *	Revision 6.2  1999/05/23 19:28:25  kmeyer1
 *	added copyrights
 *	
 *	Revision 6.1  1996/11/24 00:44:58  nevin
 *	Ohio Release
 *	
 * Revision 6.0  96/02/29  13:41:26  gdburns
 * Ohio Release
 * 
 *	Function:	- process schema operations
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <all_list.h>
#include <args.h>
#include <proc_schema.h>
#include <typical.h>

/*
 * public functions
 */
int			psc_parse();
struct psc		*psc_find();
int			cnfexec();

/*
 * external functions
 */
extern char		*_path_env_find();
extern int		_lam_few();

/*
 * private functions
 */
static void		var_substitute();

/*
 * private variables
 */
static char		line[PSC_MAXLINE];
static char		*seps = " 	,=\n";

/*
 *	psc_parse
 *
 *	Function:	- parses process schema
 *	Accepts:	- open file stream
 *			- process schema list (out)
 *			- substitution variables
 */
int
psc_parse(fp, list_psc, argv_var)

FILE			*fp;
LIST			**list_psc;
char			**argv_var;

{
	char		*r;
	char		*token;
	struct psc	psc_new;

	*list_psc = al_init(sizeof(struct psc), (int (*)()) 0);
	if (*list_psc == 0) return(LAMERROR);

	r = fgets(line, PSC_MAXLINE, fp);

	while (r) {

		if (*line == '#') {
			r = fgets(line, PSC_MAXLINE, fp);
			continue;
		}

		token = strtok(line, seps);

		if (token == 0) {
			r = fgets(line, PSC_MAXLINE, fp);
			continue;
		}

		psc_new.psc_argc = 0;
		psc_new.psc_argv = 0;
		psc_new.psc_delay = 0;
		psc_new.psc_flags = 0;

		while (token) {

			if (! strcmp(token, "$delay")) {
				psc_new.psc_delay = PSC_DELAY;
			} else if (*token == '$') {
				var_substitute(&psc_new, token, argv_var);
			} else {
				argvadd(&psc_new.psc_argc, &psc_new.psc_argv,
						token);
			}

			token = strtok((char *) 0, seps);
		}

		if (psc_new.psc_argc != 0) {
			al_append(*list_psc, &psc_new);
		}

		r = fgets(line, PSC_MAXLINE, fp);
	}

	return(0);
}

/*
 *	psc_find
 *
 *	Function:	- expands each argv[0] to full pathname
 *	Accepts:	- process schema list
 *	Returns:	- 0 or ptr to program that can't be located
 */
struct psc *
psc_find(list_psc)

LIST			*list_psc;

{
	char		*full;		/* full pathname */
	struct psc	*p;

	if (list_psc == 0) return(0);
/*
 * Loop through all the programs in the parsed process schema.
 */
	for (p = al_top(list_psc); p; p = al_next(list_psc, p)) {

		if (p->psc_argv == 0) continue;

		full = _path_env_find(p->psc_argv[0], R_OK | X_OK);

		if (! full) {
			return(p);
		} else {
			p->psc_argv[0] = full;
		}
	}

	return(0);
}

/*
 *	cnfexec
 *
 *	Function:	- forks, execs and waits for a subordinate program
 *	Accepts:	- argument vector, argv[0] is program
 *	Returns:	- status code or ERROR
 */
int
cnfexec(argv)

char			*argv[];

{
	return(_lam_few(argv));
}

/*
 *	var_substitute
 *
 *	Function:	- searches a variable in the substitution vector
 *			- if found, inserts its contents into process schema
 *	Accepts:	- process schema list entry
 *			- substitution variable
 *			- substitution variable vector
 */
static void
var_substitute(ppsc, var, argv_var)

struct psc		*ppsc;
char			*var;
char			**argv_var;

{
	char		**p;
	char		*token;

	if (argv_var == 0) return;

	for (p = argv_var; *p; p++) {

		if (! strncmp(*p, var, strlen(var))) break;
	}

	if (*p) {
		token = strtok(*p, seps);
		token = strtok((char *) 0, seps);

		while (token) {
			argvadd(&ppsc->psc_argc, &ppsc->psc_argv, token);
			token = strtok((char *) 0, seps);
		}
	}
}
