/*
 *
 * 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 1997 The Ohio State University
 *	GDB/RBD
 *
 *	$Id: di_bootcmd.c,v 6.7 1999/08/14 22:57:17 lamteam Exp $
 *
 *	Function:	- obtains link information from command line
 *	Accepts:	- link array (value returned)
 *			- link array size (value returned)
 *			- argument vector length
 *			- argument vector
 */

#include <lam_config.h>
#include <sfh.h>

#include <netdb.h>			/* Solaris MAXHOSTNAMELEN */
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/socket.h>

#include <args.h>
#include <dl_inet.h>
#include <laminternal.h>
#include <terror.h>
#include <typical.h>


/*
 * local variables
 */
static char		my_hname[MAXHOSTNAMELEN + 1];

int
di_bootcmd(pdilinks, pndil, argc, argv)

struct dilink		**pdilinks;
int4			*pndil;
int			argc;
char			**argv;

{
	int		dli_port;	/* datalink input port */
	int		dli_sd;		/* datalink input socket */
	int4		i;
	int4		my_link;	/* my datalink # */
	int4		ngbr_link;	/* neighbour link # */
	unsigned char	ngbr_haddr[4];	/* neighbour host address */
	unsigned char	my_haddr[4];	/* my host address */

	if ((argc % 2) != 0) {
		errno = EUSAGE;
		lampanic("dli_inet: <host>, <link> go in pairs");
	}
/*
 * Get my dli port number.
 */
	if (opt_taken('p')) {
		intparam('p', &dli_port);
	} else {
		dli_port = DLDEFPORT;
	}
/*
 * Create the inter-node communication socket.
 */
	if ((dli_sd = sfh_sock_open_srv_inet_dgm(&dli_port)) < 0) {
		lampanic("dli_inet (sfh_sock_open_srv_inet_dgm)");
	}

	if (sfh_sock_set_buf_size(dli_sd, SFH_INET, SO_RCVBUF, 
	    		sizeof(struct dlframe) * DOMAXPENDING)) {
		lampanic("dli_inet (sfh_sock_set_buf_size)");
	}
/*
 * Get my link #.
 */
	if (opt_taken('n')) {
		intparam('n', &my_link);
	} else {
		my_link = 0;
	}
/*
 * Get my host network address.
 */
	if (gethostname(my_hname, MAXHOSTNAMELEN + 1)) {
		lampanic("dli_inet (gethostname)");
	}

	if (getinetaddr(my_hname, my_haddr)) {
		lampanic("dli_inet (getinetaddr)");
	}

	*pndil = 0;

	for (i = 1; i < argc; i += 2) {
		*pndil = LAM_max(atoi(argv[i]), *pndil);
	}

	*pndil = LAM_max(my_link, *pndil);
	(*pndil)++;
/*
 * Create the links array.
 */
	*pdilinks = (struct dilink *) malloc((unsigned) *pndil *
			sizeof(struct dilink));
	if (*pdilinks == 0) lampanic("dli_inet (malloc)");
/*
 * Init all entries to invalid link.
 */
	for (i = 0; i < *pndil; ++i) {
		(*pdilinks)[i].dil_link = NOTLINKID;
		(*pdilinks)[i].dil_seqrecv = 0;
	}
/*
 * Parse active link information off the command line.
 */
	for (i = 0; i < (argc / 2); ++i) {
		if (getinetaddr(*argv++, ngbr_haddr))
				lampanic("dli_inet (getinetaddr)");
		ngbr_link = atoi(*argv++);

		if ((ngbr_link < 0) || (ngbr_link >= *pndil)) {
			errno = EBADLINK;
			lampanic("dli_inet");
		}

		(*pdilinks)[ngbr_link].dil_link = ngbr_link;
		sfh_sock_fill_inet_addr(ngbr_haddr, (int) dli_port,
				&((*pdilinks)[ngbr_link].dil_addr));
	}
/*
 * Set my link.
 */
	(*pdilinks)[my_link].dil_link = my_link;
	sfh_sock_fill_inet_addr(my_haddr, (int) dli_port,
			&((*pdilinks)[my_link].dil_addr));

	return(dli_sd);
}
