mpiexec::main()
{
    MPI_Init();

    BNR_Convert_args_to_info(argc, argv, infos);
    
    /* generate command lines */

    /* pack job configuration information into MPI info structures */

    /* use info parameter to tell spawn process group to notify mpiexec when
    spawn group has reached MPI_Finalize().  this can be accomplished by
    sending a message from one of the spawned processes to the mpiexec process
    over the intercomm created during the spawn.  without this info parameter
    mpiexec will return "immediately". */
    
    MPI_Comm_spawn_multiple(count, cmds, argvs, maxprocs, infos, 0,
			    MPI_COMM_WORLD, &intercomm, errors);

    /* communicate some things here */

    /* wait for spawned job to finish ??? */

    MPI_Finalize();
}


int MPI_Init()
{
    BNR_Init();

    /* initialize methods, device, etc. */
    
    BNR_Get_my_DB_name(my_dbname);
    BNR_Put(my_dbname, ..., ...);
    BNR_Commit(my_dbname);

    BNR_Barrier();
    
    /* Various initializations like datatypes, COMM_WORLD, etc. */

    /* get parent_port_name from environment */
    if (parent_port_name is defined)
    {
	MPI_Comm_connect(parent_port_name, info, 0, MPI_COMM_WORLD,
			 &intercomm);
    }
    else
    {
	intercomm = MPI_COMM_NULL;
    }
}

int MPI_Comm_Spawn_multiple(count, cmds, argvs, maxprocs, infos, root, comm,
                            intercomm, errors)
{
    if (root)
    {
	port_info = NULL; /* ??? */
	MPI_Open_port(port_info, port_name);

	/* add port_name to all infos */

	BNR_Spawn_multiple(count, cmds, argvs, maxprocs, infos, errors,
			   &bnr_same_domain, &pg);
	if (bnr_same_domain)
	{
	    MPI_Info_set(accept_info, "BNR_SAME_DOMAIN", "");
	}
    }

    MPI_Comm_accept(port_name, accept_info, root, comm, intercomm);
    
}

int MPI_Open_port(info, port_name)
{
    port_name = MM_get_port_name();  /* query_descriptor() ??? */
}

int MPI_Comm_accept(port_name, info, root, comm, intercomm)
{
    if (root)
    {
	conn = MM_accept(port_name);

	MPI_Info_get(info, "BNR_SAME_DOMAIN", 0, NULL, &bnr_same_domain);

	MM_send(conn, bnr_same_domain);
	MM_send(conn, comm->size);
	MM_recv(conn, remote_size);
	
	MPID_Intercomm_alloc(INTER, intercomm, comm->size, remote_size);
	intercomm->local_VCTable = comm->VCTable;
	intercomm->local_size = comm->size;
	
	SendCommVCTable(conn, comm->VCTable, comm->size);
	if (!bnr_same_domain)
	{
	    SendDatabases(conn, comm);
	}
	
	RecvCommVCTable(conn, intercomm->remote_VCTable,
			intercomm->remote_size);
	if (!bnr_same_domain)
	{
	    RecvDatabases(conn, dbmap);
	    FixVCTable(dbmap, intercomm->remote_VCTable);
	}

	MPI_Bcast(remote_size, root, comm);
	MPI_Bcast(intercomm->remote_VCTable, root, comm)
    }
    else
    {
        MPI_Bcast(remote_size, root, comm);
	
	MPID_Intercomm_alloc(INTER, intercomm, comm->size, remote_size);
	intercomm->local_VCTable = comm->VCTable;
	intercomm->local_size = comm->size;
	
	MPI_Bcast(intercomm->remote_VCTable, root, comm)
    }
}

int MPI_Comm_connect(port_name, info, root, comm, intercomm)
{
    if (root)
    {
	conn = MM_connect(port_name);
	
	MM_recv(conn, bnr_same_domain);
	MM_recv(conn, remote_size);
	MM_send(conn, comm->size);

	MPID_Intercomm_alloc(INTER, intercomm, comm->size, remote_size);
	intercomm->local_VCTable = comm->VCTable;
	intercomm->local_size = comm->size;
	
	RecvCommVCTable(conn, intercomm->remote_VCTable,
			intercomm->remote_size);
	if (!bnr_same_domain)
	{
	    RecvDatabases(conn, dbmap);
	    FixVCTable(dbmap, intercomm->remote_VCTable);
	}
	
	SendCommVCTable(conn, comm->VCTable, comm->size);
	if (!bnr_same_domain)
	{
	    SendDatabases(conn, comm);
	}
	
        MPI_Bcast(remote_size, root, comm);
	MPI_Bcast(intercomm->remote_VCTable, root, comm)
    }
    else
    {
        MPI_Bcast(remote_size, root, comm);
	
	MPID_Intercomm_alloc(INTER, intercomm, comm->size, remote_size);
	intercomm->local_VCTable = comm->VCTable;
	intercomm->local_size = comm->size;
	
	MPI_Bcast(intercomm->remote_VCTable, root, comm)
    }
}

SendDatabases([IN] conn, [IN] comm)
{
    MM_send(conn, Ndb)
    foreach dbname (used in a vc in comm)
    {
        MM_send(conn, dbname);
        done = BNR_Key_iter_first(dbname, key, val);
        while (!done)
        {
            MM_send(conn, (key,val));
            done = BNR_Key_iter_next(dbname, key, val);
        }
        MM_Send(conn, (dbdone));
    }
}

RecvDatabases([IN] conn, [OUT] dbmap)
{
    MM_recv(conn, Ndb);
    dbmap = malloc(Ndb * sizeof(int));
    
    for (i = 0; i < Ndb; i++)
    {
	MM_recv(conn, (remote_dbname));

	BNR_Create_DB(dbname);
	strcpy(dbmap[i], dbname);
	
	while(1)
	{
	    MM_recv(conn, (key, val));
	    if (key == (dbdone)) break;
	    BNR_Put(dbname, key, val);
	}

	BNR_Commit(dbname);
    }
}
