-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/pmi/simple/simple_pmi.c
        -:    0:Graph:simple_pmi.gcno
        -:    0:Data:simple_pmi.gcda
        -:    0:Runs:4381
        -:    0:Programs:1376
        -:    1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
        -:    2:/*  
        -:    3: *  (C) 2001 by Argonne National Laboratory.
        -:    4: *      See COPYRIGHT in top-level directory.
        -:    5: */
        -:    6:
        -:    7:/*********************** PMI implementation ********************************/
        -:    8:/*
        -:    9: * This file implements the client-side of the PMI interface.
        -:   10: *
        -:   11: * Note that the PMI client code must not print error messages (except 
        -:   12: * when an abort is required) because MPI error handling is based on
        -:   13: * reporting error codes to which messages are attached.  
        -:   14: *
        -:   15: * In v2, we should require a PMI client interface to use MPI error codes
        -:   16: * to provide better integration with MPICH2.  
        -:   17: */
        -:   18:/***************************************************************************/
        -:   19:
        -:   20:#include "pmiconf.h" 
        -:   21:
        -:   22:#define PMI_VERSION    1
        -:   23:#define PMI_SUBVERSION 1
        -:   24:
        -:   25:#include <stdio.h>
        -:   26:#ifdef HAVE_UNISTD_H
        -:   27:#include <unistd.h>
        -:   28:#endif
        -:   29:#ifdef HAVE_STDLIB_H
        -:   30:#include <stdlib.h>
        -:   31:#endif
        -:   32:#ifdef HAVE_STRING_H
        -:   33:#include <string.h>
        -:   34:#endif
        -:   35:#ifdef HAVE_STRINGS_H
        -:   36:#include <strings.h>
        -:   37:#endif
        -:   38:#ifdef USE_PMI_PORT
        -:   39:#ifndef MAXHOSTNAME
        -:   40:#define MAXHOSTNAME 256
        -:   41:#endif
        -:   42:#endif
        -:   43:/* This should be moved to pmiu for shutdown */
        -:   44:#if defined(HAVE_SYS_SOCKET_H)
        -:   45:#include <sys/socket.h>
        -:   46:#endif
        -:   47:
        -:   48:#include "mpibase.h"            /* Get ATTRIBUTE, some base functions */
        -:   49:/* mpimem includes the definitions for MPIU_Snprintf, MPIU_Malloc, and 
        -:   50:   MPIU_Free */
        -:   51:#include "mpimem.h"
        -:   52:
        -:   53:/* Temporary debug definitions */
        -:   54:#if 0
        -:   55:#define DBG_PRINTF(args) printf args ; fflush(stdout)
        -:   56:#else
        -:   57:#define DBG_PRINTF(args)
        -:   58:#endif
        -:   59:
        -:   60:#include "pmi.h"
        -:   61:#include "simple_pmiutil.h"
        -:   62:#include "mpi.h"		/* to get MPI_MAX_PORT_NAME */
        -:   63:
        -:   64:/* 
        -:   65:   These are global variable used *ONLY* in this file, and are hence
        -:   66:   declared static.
        -:   67: */
        -:   68:
        -:   69:
        -:   70:static int PMI_fd = -1;
        -:   71:static int PMI_size = 1;
        -:   72:static int PMI_rank = 0;
        -:   73:
        -:   74:/* Set PMI_initialized to 1 for singleton init but no process manager
        -:   75:   to help.  Initialized to 2 for normal initialization.  Initialized
        -:   76:   to values higher than 2 when singleton_init by a process manager.
        -:   77:   All values higher than 1 invlove a PM in some way.
        -:   78:*/
        -:   79:typedef enum { PMI_UNINITIALIZED = 0, 
        -:   80:               SINGLETON_INIT_BUT_NO_PM = 1,
        -:   81:	       NORMAL_INIT_WITH_PM,
        -:   82:	       SINGLETON_INIT_WITH_PM } PMIState;
        -:   83:static PMIState PMI_initialized = PMI_UNINITIALIZED;
        -:   84:
        -:   85:/* ALL GLOBAL VARIABLES MUST BE INITIALIZED TO AVOID POLLUTING THE 
        -:   86:   LIBRARY WITH COMMON SYMBOLS */
        -:   87:static int PMI_kvsname_max = 0;
        -:   88:static int PMI_keylen_max = 0;
        -:   89:static int PMI_vallen_max = 0;
        -:   90:
        -:   91:static int PMI_iter_next_idx = 0;
        -:   92:static int PMI_debug = 0;
        -:   93:static int PMI_debug_init = 0;    /* Set this to true to debug the init
        -:   94:				     handshakes */
        -:   95:static int PMI_spawned = 0;
        -:   96:
        -:   97:/* Function prototypes for internal routines */
        -:   98:static int PMII_getmaxes( int *kvsname_max, int *keylen_max, int *vallen_max );
        -:   99:static int PMII_iter( const char *kvsname, const int idx, int *nextidx, 
        -:  100:		      char *key, int key_len, char *val, int val_len );
        -:  101:static int PMII_Set_from_port( int, int );
        -:  102:static int PMII_Connect_to_pm( char *, int );
        -:  103:
        -:  104:static int GetResponse( const char [], const char [], int );
        -:  105:static int getPMIFD( int * );
        -:  106:
        -:  107:#ifdef USE_PMI_PORT
        -:  108:static int PMII_singinit(void);
        -:  109:static int PMI_totalview = 0;
        -:  110:#endif
        -:  111:static int PMIi_InitIfSingleton(void);
        -:  112:static int accept_one_connection(int);
        -:  113:static char cached_singinit_key[PMIU_MAXLINE];
        -:  114:static char cached_singinit_val[PMIU_MAXLINE];
        -:  115:static char singinit_kvsname[256];
        -:  116:
        -:  117:/******************************** Group functions *************************/
        -:  118:
        -:  119:int PMI_Init( int *spawned )
     4381:  120:{
        -:  121:    char *p;
     4381:  122:    int notset = 1;
        -:  123:    int rc;
        -:  124:
        -:  125:    /* FIXME: Why is setvbuf commented out? */
        -:  126:    /* FIXME: What if the output should be fully buffered (directed to file)?
        -:  127:       unbuffered (user explicitly set?) */
        -:  128:    /* setvbuf(stdout,0,_IONBF,0); */
     4381:  129:    setbuf(stdout,NULL);
        -:  130:    /* PMIU_printf( 1, "PMI_INIT\n" ); */
        -:  131:
        -:  132:    /* Get the value of PMI_DEBUG from the environment if possible, since
        -:  133:       we may have set it to help debug the setup process */
     4381:  134:    p = getenv( "PMI_DEBUG" );
     4381:  135:    if (p) PMI_debug = atoi( p );
        -:  136:
        -:  137:    /* Get the fd for PMI commands; if none, we're a singleton */
     4381:  138:    rc = getPMIFD(&notset);
     4381:  139:    if (rc) {
    #####:  140:	return rc;
        -:  141:    }
        -:  142:
     4381:  143:    if ( PMI_fd == -1 ) {
        -:  144:	/* Singleton init: Process not started with mpiexec, 
        -:  145:	   so set size to 1, rank to 0 */
    #####:  146:	PMI_size = 1;
    #####:  147:	PMI_rank = 0;
    #####:  148:	*spawned = 0;
        -:  149:	
    #####:  150:	PMI_initialized = SINGLETON_INIT_BUT_NO_PM;
        -:  151:	/* 256 is picked as the minimum allowed length by the PMI servers */
    #####:  152:	PMI_kvsname_max = 256;
    #####:  153:	PMI_keylen_max  = 256;
    #####:  154:	PMI_vallen_max  = 256;
        -:  155:	
    #####:  156:	return( 0 );
        -:  157:    }
        -:  158:
        -:  159:    /* If size, rank, and debug are not set from a communication port,
        -:  160:       use the environment */
     4381:  161:    if (notset) {
     4381:  162:	if ( ( p = getenv( "PMI_SIZE" ) ) )
     4381:  163:	    PMI_size = atoi( p );
        -:  164:	else 
    #####:  165:	    PMI_size = 1;
        -:  166:	
     4381:  167:	if ( ( p = getenv( "PMI_RANK" ) ) ) {
     4381:  168:	    PMI_rank = atoi( p );
        -:  169:	    /* Let the util routine know the rank of this process for 
        -:  170:	       any messages (usually debugging or error) */
     4381:  171:	    PMIU_Set_rank( PMI_rank );
        -:  172:	}
        -:  173:	else 
    #####:  174:	    PMI_rank = 0;
        -:  175:	
     4381:  176:	if ( ( p = getenv( "PMI_DEBUG" ) ) )
     4381:  177:	    PMI_debug = atoi( p );
        -:  178:	else 
    #####:  179:	    PMI_debug = 0;
        -:  180:
        -:  181:	/* Leave unchanged otherwise, which indicates that no value
        -:  182:	   was set */
        -:  183:    }
        -:  184:
        -:  185:/* FIXME: Why does this depend on their being a port??? */
        -:  186:/* FIXME: What is this for? */
        -:  187:#ifdef USE_PMI_PORT
     4381:  188:    if ( ( p = getenv( "PMI_TOTALVIEW" ) ) )
     4381:  189:	PMI_totalview = atoi( p );
     4381:  190:    if ( PMI_totalview ) {
        -:  191:	char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
        -:  192:	/* FIXME: This should use a cmd/response rather than a expecting the
        -:  193:	   server to set a value in this and only this case */
        -:  194:	/* FIXME: And it most ceratainly should not happen *before* the
        -:  195:	   initialization handshake */
    #####:  196:	PMIU_readline( PMI_fd, buf, PMIU_MAXLINE );
    #####:  197:	PMIU_parse_keyvals( buf );
    #####:  198:	PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
    #####:  199:	if ( strncmp( cmd, "tv_ready", PMIU_MAXLINE ) != 0 ) {
    #####:  200:	    PMIU_printf( 1, "expecting cmd=tv_ready, got %s\n", buf );
    #####:  201:	    return( PMI_FAIL );
        -:  202:	}
        -:  203:    }
        -:  204:#endif
        -:  205:
     4381:  206:    PMII_getmaxes( &PMI_kvsname_max, &PMI_keylen_max, &PMI_vallen_max );
        -:  207:
        -:  208:    /* FIXME: This is something that the PM should tell the process,
        -:  209:       rather than deliver it through the environment */
     4381:  210:    if ( ( p = getenv( "PMI_SPAWNED" ) ) )
     4381:  211:	PMI_spawned = atoi( p );
        -:  212:    else
    #####:  213:	PMI_spawned = 0;
     4381:  214:    if (PMI_spawned)
      406:  215:	*spawned = 1;
        -:  216:    else
     3975:  217:	*spawned = 0;
        -:  218:
     4381:  219:    if ( ! PMI_initialized )
     4381:  220:	PMI_initialized = NORMAL_INIT_WITH_PM;
        -:  221:
     4381:  222:    return( 0 );
        -:  223:}
        -:  224:
        -:  225:int PMI_Initialized( PMI_BOOL *initialized )
    #####:  226:{
        -:  227:    /* Turn this into a logical value (1 or 0) .  This allows us
        -:  228:       to use PMI_initialized to distinguish between initialized with
        -:  229:       an PMI service (e.g., via mpiexec) and the singleton init, 
        -:  230:       which has no PMI service */
    #####:  231:    *initialized = PMI_initialized != 0 ? PMI_TRUE : PMI_FALSE;
    #####:  232:    return PMI_SUCCESS;
        -:  233:}
        -:  234:
        -:  235:int PMI_Get_size( int *size )
     4381:  236:{
     4381:  237:    if ( PMI_initialized )
     4381:  238:	*size = PMI_size;
        -:  239:    else
    #####:  240:	*size = 1;
     4381:  241:    return( 0 );
        -:  242:}
        -:  243:
        -:  244:int PMI_Get_rank( int *rank )
     4381:  245:{
     4381:  246:    if ( PMI_initialized )
     4381:  247:	*rank = PMI_rank;
        -:  248:    else
    #####:  249:	*rank = 0;
     4381:  250:    return( 0 );
        -:  251:}
        -:  252:
        -:  253:/* 
        -:  254: * Get_universe_size is one of the routines that needs to communicate
        -:  255: * with the process manager.  If we started as a singleton init, then
        -:  256: * we first need to connect to the process manager and acquire the 
        -:  257: * needed information.
        -:  258: */
        -:  259:int PMI_Get_universe_size( int *size)
        5:  260:{
        -:  261:    int  err;
        -:  262:    char size_c[PMIU_MAXLINE];
        -:  263:
        -:  264:    /* Connect to the PM if we haven't already */
        5:  265:    if (PMIi_InitIfSingleton() != 0) return -1;
        -:  266:
        5:  267:    if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM)  {
        5:  268:	err = GetResponse( "cmd=get_universe_size\n", "universe_size", 0 );
        5:  269:	if (err == PMI_SUCCESS) {
        5:  270:	    PMIU_getval( "size", size_c, PMIU_MAXLINE );
        5:  271:	    *size = atoi(size_c);
        5:  272:	    return( PMI_SUCCESS );
        -:  273:	}
    #####:  274:	else return err;
        -:  275:    }
        -:  276:    else
    #####:  277:	*size = 1;
    #####:  278:    return( PMI_SUCCESS );
        -:  279:}
        -:  280:
        -:  281:int PMI_Get_appnum( int *appnum )
     4381:  282:{
        -:  283:    int  err;
        -:  284:    char appnum_c[PMIU_MAXLINE];
        -:  285:
     4381:  286:    if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
     4381:  287:	err = GetResponse( "cmd=get_appnum\n", "appnum", 0 );
     4381:  288:	if (err == PMI_SUCCESS) {
     4381:  289:	    PMIU_getval( "appnum", appnum_c, PMIU_MAXLINE );
     4381:  290:	    *appnum = atoi(appnum_c);
     4381:  291:	    return( PMI_SUCCESS );
        -:  292:	}
    #####:  293:	else return err;
        -:  294:	
        -:  295:    }
        -:  296:    else
    #####:  297:	*appnum = -1;
        -:  298:
    #####:  299:    return( PMI_SUCCESS );
        -:  300:}
        -:  301:
        -:  302:int PMI_Barrier( void )
     4463:  303:{
     4463:  304:    int err = PMI_SUCCESS;
        -:  305:
     4463:  306:    if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
     4463:  307:	err = GetResponse( "cmd=barrier_in\n", "barrier_out", 0 );
        -:  308:    }
        -:  309:
     4463:  310:    return err;
        -:  311:}
        -:  312:
        -:  313:/* */
        -:  314:static int clique_size=-2, *clique_ranks =0;
        -:  315:
        -:  316:/* pmiPrivateLocalRanks_<r> gets the local ranks for this process */
        -:  317:int PMI_Get_clique_size( int *size )
    #####:  318:{
        -:  319:#if 1
        -:  320:    char buf[PMIU_MAXLINE];
        -:  321:    char pmi_kvsname[1024];
        -:  322:    int i, rc, err;
        -:  323:
        -:  324:    /* As the server for the information on the */
    #####:  325:    if (clique_size == -2 && PMI_initialized > SINGLETON_INIT_BUT_NO_PM)  {
    #####:  326:	PMI_KVS_Get_my_name( pmi_kvsname, sizeof(pmi_kvsname) );
    #####:  327:	rc = MPIU_Snprintf( buf, PMIU_MAXLINE, 
        -:  328:			    "cmd=get kvsname=%s key=pmiPrivateLocalRanks_%d\n", 
        -:  329:			    pmi_kvsname, PMI_rank );
    #####:  330:	if (rc < 0) return PMI_FAIL;
        -:  331:
    #####:  332:	err = GetResponse( buf, "get_result", 0 );
    #####:  333:	if (err == PMI_SUCCESS) {
    #####:  334:	    PMIU_getval( "rc", buf, PMIU_MAXLINE );
    #####:  335:	    rc = atoi( buf );
    #####:  336:	    if ( rc == 0 ) {
    #####:  337:		char *p = buf, *p0;
        -:  338:		/* Allocate clique_ranks and fill it in */
    #####:  339:		PMIU_getval( "value", buf, PMIU_MAXLINE );
        -:  340:		/* Count the number of ranks and allocate the space for them */
    #####:  341:		clique_size = 1;
    #####:  342:		while (*p) {
    #####:  343:		    if (*p++ == ',') clique_size++;
        -:  344:		}
    #####:  345:		clique_ranks = (int *)MPIU_Malloc( clique_size * sizeof(int) );
        -:  346:		DBG_PRINTF( ("Clique_size = %d\n", clique_size) );
    #####:  347:		p0 = p = buf;
    #####:  348:		i  = 0;
    #####:  349:		while (*p) {
    #####:  350:		    while (*p && *p != ',') p++;
    #####:  351:		    if (*p == ',') *p++ = 0;
    #####:  352:		    clique_ranks[i++] = atoi(p0);
    #####:  353:		    p0 = p;
        -:  354:		}
        -:  355:	    }
        -:  356:	    else {
        -:  357:		/* Default case (PM did not understand request) */
    #####:  358:		clique_size = 1;
        -:  359:	    }
        -:  360:	}
        -:  361:    }
    #####:  362:    if (clique_size < 0) *size = 1;
    #####:  363:    else                 *size = clique_size;
        -:  364:#else
        -:  365:    *size = 1;
        -:  366:#endif
    #####:  367:    return PMI_SUCCESS;
        -:  368:}
        -:  369:
        -:  370:int PMI_Get_clique_ranks( int ranks[], int length )
    #####:  371:{
        -:  372:#if 1
        -:  373:    int i;
    #####:  374:    if (length < 1) 
    #####:  375:	return PMI_ERR_INVALID_ARG;
        -:  376:
    #####:  377:    if (clique_size > 0 && clique_ranks) {
    #####:  378:	for (i=0; i<length && i<clique_size; i++) 
    #####:  379:	    ranks[i] = clique_ranks[i];
        -:  380:    }
        -:  381:    else 
    #####:  382:	ranks[0] = PMI_rank;
    #####:  383:    return PMI_SUCCESS;
        -:  384:#else
        -:  385:    if ( length < 1 )
        -:  386:	return PMI_ERR_INVALID_ARG;
        -:  387:    else
        -:  388:	return PMI_Get_rank( &ranks[0] );
        -:  389:#endif
        -:  390:}
        -:  391:
        -:  392:/* Inform the process manager that we're in finalize */
        -:  393:int PMI_Finalize( void )
     4374:  394:{
     4374:  395:    int err = PMI_SUCCESS;
        -:  396:
     4374:  397:    if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
     4374:  398:	err = GetResponse( "cmd=finalize\n", "finalize_ack", 0 );
     4374:  399:	shutdown( PMI_fd, SHUT_RDWR );
     4374:  400:	close( PMI_fd );
        -:  401:    }
        -:  402:    /* Free any memory that we've allocated */
     4374:  403:    if (clique_ranks) MPIU_Free( clique_ranks );
        -:  404:
     4374:  405:    return err;
        -:  406:}
        -:  407:
        -:  408:int PMI_Abort(int exit_code, const char error_msg[])
        7:  409:{
        7:  410:    PMIU_printf(1, "aborting job:\n%s\n", error_msg);
        7:  411:    MPIU_Exit(exit_code);
    #####:  412:    return -1;
        -:  413:}
        -:  414:
        -:  415:/************************************* Keymap functions **********************/
        -:  416:
        -:  417:/*FIXME: need to return an error if the value of the kvs name returned is 
        -:  418:  truncated because it is larger than length */
        -:  419:/* FIXME: My name should be cached rather than re-acquired, as it is
        -:  420:   unchanging (after singleton init) */
        -:  421:int PMI_KVS_Get_my_name( char kvsname[], int length )
     8762:  422:{
        -:  423:    int err;
        -:  424:
     8762:  425:    if (PMI_initialized == SINGLETON_INIT_BUT_NO_PM) {
        -:  426:	/* Return a dummy name */
        -:  427:	/* FIXME: We need to support a distinct kvsname for each 
        -:  428:	   process group */
    #####:  429:	MPIU_Snprintf( kvsname, length, "singinit_kvs_%d_0", (int)getpid() );
    #####:  430:	return 0;
        -:  431:    }
     8762:  432:    err = GetResponse( "cmd=get_my_kvsname\n", "my_kvsname", 0 );
     8762:  433:    if (err == PMI_SUCCESS) {
     8762:  434:	PMIU_getval( "kvsname", kvsname, length );
        -:  435:    }
     8762:  436:    return err;
        -:  437:}
        -:  438:
        -:  439:int PMI_KVS_Get_name_length_max( int *maxlen )
     4381:  440:{
     4381:  441:    if (maxlen == NULL)
    #####:  442:	return PMI_ERR_INVALID_ARG;
     4381:  443:    *maxlen = PMI_kvsname_max;
     4381:  444:    return PMI_SUCCESS;
        -:  445:}
        -:  446:
        -:  447:int PMI_KVS_Get_key_length_max( int *maxlen )
     3939:  448:{
     3939:  449:    if (maxlen == NULL)
    #####:  450:	return PMI_ERR_INVALID_ARG;
     3939:  451:    *maxlen = PMI_keylen_max;
     3939:  452:    return PMI_SUCCESS;
        -:  453:}
        -:  454:
        -:  455:int PMI_KVS_Get_value_length_max( int *maxlen )
     8238:  456:{
     8238:  457:    if (maxlen == NULL)
    #####:  458:	return PMI_ERR_INVALID_ARG;
     8238:  459:    *maxlen = PMI_vallen_max;
     8238:  460:    return PMI_SUCCESS;
        -:  461:}
        -:  462:
        -:  463:/* We will use the default kvsname for both the kvs_domain_id and for the id */
        -:  464:/* Hence the implementation of the following three functions */
        -:  465:
        -:  466:int PMI_Get_id_length_max( int *length )
    24840:  467:{
    24840:  468:    if (length == NULL)
    #####:  469:	return PMI_ERR_INVALID_ARG;
    24840:  470:    *length = PMI_kvsname_max;
    24840:  471:    return PMI_SUCCESS;
        -:  472:}
        -:  473:
        -:  474:int PMI_Get_id( char id_str[], int length )
     4381:  475:{
     4381:  476:    int rc = PMI_KVS_Get_my_name( id_str, length );
     4381:  477:    return rc;
        -:  478:}
        -:  479:
        -:  480:/* FIXME: What is this function?  How is it defined and used? */
        -:  481:int PMI_Get_kvs_domain_id( char id_str[], int length )
    #####:  482:{
    #####:  483:    return PMI_KVS_Get_my_name( id_str, length );
        -:  484:}
        -:  485:
        -:  486:/*FIXME: need to return an error if the value of the kvs name returned is 
        -:  487:  truncated  because it is larger than length */
        -:  488:int PMI_KVS_Create( char kvsname[], int length )
    #####:  489:{
    #####:  490:    int err = PMI_SUCCESS;
        -:  491:    
    #####:  492:    if (PMI_initialized == SINGLETON_INIT_BUT_NO_PM) {
        -:  493:	/* It is ok to pretend to *create* a kvs space */
    #####:  494:	return 0;
        -:  495:    }
        -:  496:
    #####:  497:    err = GetResponse( "cmd=create_kvs\n", "newkvs", 0 );
    #####:  498:    if (err == PMI_SUCCESS) {
    #####:  499:	PMIU_getval( "kvsname", kvsname, length );
        -:  500:    }
    #####:  501:    return err;
        -:  502:}
        -:  503:
        -:  504:int PMI_KVS_Destroy( const char kvsname[] )
    #####:  505:{
        -:  506:    char buf[PMIU_MAXLINE];
    #####:  507:    int  err = PMI_SUCCESS;
        -:  508:
    #####:  509:    if (PMI_initialized == SINGLETON_INIT_BUT_NO_PM) {
    #####:  510:	return 0;
        -:  511:    }
        -:  512:
        -:  513:    /* FIXME: Check for tempbuf too short */
    #####:  514:    MPIU_Snprintf( buf, PMIU_MAXLINE, "cmd=destroy_kvs kvsname=%s\n", 
        -:  515:		   kvsname );
    #####:  516:    err = GetResponse( buf, "kvs_destroyed", 1 );
    #####:  517:    return err;
        -:  518:
        -:  519:}
        -:  520:
        -:  521:int PMI_KVS_Put( const char kvsname[], const char key[], const char value[] )
     4463:  522:{
        -:  523:    char buf[PMIU_MAXLINE];
     4463:  524:    int  err = PMI_SUCCESS;
        -:  525:    int  rc;
        -:  526:
        -:  527:    /* This is a special hack to support singleton initialization */
     4463:  528:    if (PMI_initialized == SINGLETON_INIT_BUT_NO_PM) {
    #####:  529:	rc = MPIU_Strncpy(cached_singinit_key,key,PMI_keylen_max);
    #####:  530:	if (rc != 0) return PMI_FAIL;
    #####:  531:	rc = MPIU_Strncpy(cached_singinit_val,value,PMI_vallen_max);
    #####:  532:	if (rc != 0) return PMI_FAIL;
    #####:  533:	return 0;
        -:  534:    }
        -:  535:    
     4463:  536:    rc = MPIU_Snprintf( buf, PMIU_MAXLINE, 
        -:  537:			"cmd=put kvsname=%s key=%s value=%s\n",
        -:  538:			kvsname, key, value);
     4463:  539:    if (rc < 0) return PMI_FAIL;
     4463:  540:    err = GetResponse( buf, "put_result", 1 );
     4463:  541:    return err;
        -:  542:}
        -:  543:
        -:  544:int PMI_KVS_Commit( const char kvsname[] ATTRIBUTE((unused)))
     4463:  545:{
        -:  546:    /* no-op in this implementation */
     4463:  547:    return( 0 );
        -:  548:}
        -:  549:
        -:  550:/*FIXME: need to return an error if the value returned is truncated
        -:  551:  because it is larger than length */
        -:  552:int PMI_KVS_Get( const char kvsname[], const char key[], char value[], 
        -:  553:		 int length)
    13414:  554:{
        -:  555:    char buf[PMIU_MAXLINE];
    13414:  556:    int err = PMI_SUCCESS;
        -:  557:    int  rc;
        -:  558:
        -:  559:    /* Connect to the PM if we haven't already.  This is needed in case
        -:  560:       we're doing an MPI_Comm_join or MPI_Comm_connect/accept from
        -:  561:       the singleton init case.  This test is here because, in the way in 
        -:  562:       which MPICH2 uses PMI, this is where the test needs to be. */
    13414:  563:    if (PMIi_InitIfSingleton() != 0) return -1;
        -:  564:
    13414:  565:    rc = MPIU_Snprintf( buf, PMIU_MAXLINE, "cmd=get kvsname=%s key=%s\n", 
        -:  566:			kvsname, key );
    13414:  567:    if (rc < 0) return PMI_FAIL;
        -:  568:
    13414:  569:    err = GetResponse( buf, "get_result", 0 );
    13414:  570:    if (err == PMI_SUCCESS) {
    13414:  571:	PMIU_getval( "rc", buf, PMIU_MAXLINE );
    13414:  572:	rc = atoi( buf );
    13414:  573:	if ( rc == 0 ) {
    13332:  574:	    PMIU_getval( "value", value, length );
    13332:  575:	    return( 0 );
        -:  576:	}
        -:  577:	else {
       82:  578:	    return( -1 );
        -:  579:	}
        -:  580:    }
        -:  581:
    #####:  582:    return err;
        -:  583:}
        -:  584:
        -:  585:int PMI_KVS_Iter_first(const char kvsname[], char key[], int key_len, 
        -:  586:		       char val[], int val_len)
    #####:  587:{
        -:  588:    int rc;
        -:  589:
    #####:  590:    rc = PMII_iter( kvsname, 0, &PMI_iter_next_idx, key, key_len, val, val_len );
    #####:  591:    return( rc );
        -:  592:}
        -:  593:
        -:  594:int PMI_KVS_Iter_next(const char kvsname[], char key[], int key_len, 
        -:  595:		      char val[], int val_len)
    #####:  596:{
        -:  597:    int rc;
        -:  598:
    #####:  599:    rc = PMII_iter( kvsname, PMI_iter_next_idx, &PMI_iter_next_idx, 
        -:  600:		    key, key_len, val, val_len );
    #####:  601:    if ( rc == -2 )
    #####:  602:	PMI_iter_next_idx = 0;
    #####:  603:    return( rc );
        -:  604:}
        -:  605:
        -:  606:/*************************** Name Publishing functions **********************/
        -:  607:
        -:  608:int PMI_Publish_name( const char service_name[], const char port[] )
        4:  609:{
        -:  610:    char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
        -:  611:    int err;
        -:  612:
        4:  613:    if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
        4:  614:        MPIU_Snprintf( cmd, PMIU_MAXLINE, 
        -:  615:		       "cmd=publish_name service=%s port=%s\n",
        -:  616:		       service_name, port );
        4:  617:	err = GetResponse( cmd, "publish_result", 0 );
        -:  618:	/* FIXME: This should have used rc and msg */
        4:  619:	if (err == PMI_SUCCESS) {
        4:  620:	    PMIU_getval( "info", buf, PMIU_MAXLINE );
        4:  621:	    if ( strcmp(buf,"ok") != 0 ) {
    #####:  622:	        PMIU_printf( 1, "publish failed; reason = %s\n", buf );
    #####:  623:	        return( PMI_FAIL );
        -:  624:	    }
        -:  625:	}
        -:  626:    }
        -:  627:    else
        -:  628:    {
    #####:  629:	PMIU_printf( 1, "PMI_Publish_name called before init\n" );
    #####:  630:	return( PMI_FAIL );
        -:  631:    }
        -:  632:
        4:  633:    return( PMI_SUCCESS );
        -:  634:}
        -:  635:
        -:  636:int PMI_Unpublish_name( const char service_name[] )
        4:  637:{
        -:  638:    char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
        4:  639:    int err = PMI_SUCCESS;
        -:  640:
        4:  641:    if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
        4:  642:        MPIU_Snprintf( cmd, PMIU_MAXLINE, "cmd=unpublish_name service=%s\n", 
        -:  643:		       service_name );
        4:  644:	err = GetResponse( cmd, "unpublish_result", 0 );
        4:  645:	if (err == PMI_SUCCESS) {
        4:  646:	    PMIU_getval( "info", buf, PMIU_MAXLINE );
        4:  647:	    if ( strcmp(buf,"ok") != 0 ) {
        -:  648:		/* FIXME: Do correct error reporting */
        -:  649:		/*
        -:  650:	        PMIU_printf( 1, "unpublish failed; reason = %s\n", buf );
        -:  651:		*/
        1:  652:	        return( PMI_FAIL );
        -:  653:	    }
        -:  654:	}
        -:  655:    }
        -:  656:    else
        -:  657:    {
    #####:  658:	PMIU_printf( 1, "PMI_Unpublish_name called before init\n" );
    #####:  659:	return( PMI_FAIL );
        -:  660:    }
        -:  661:
        3:  662:    return( PMI_SUCCESS );
        -:  663:}
        -:  664:
        -:  665:int PMI_Lookup_name( const char service_name[], char port[] )
       31:  666:{
        -:  667:    char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
        -:  668:    int err;
        -:  669:
       31:  670:    if ( PMI_initialized > SINGLETON_INIT_BUT_NO_PM) {
       31:  671:        MPIU_Snprintf( cmd, PMIU_MAXLINE, "cmd=lookup_name service=%s\n", 
        -:  672:		       service_name );
       31:  673:	err = GetResponse( cmd, "lookup_result", 0 );
       31:  674:	if (err == PMI_SUCCESS) {
       31:  675:	    PMIU_getval( "info", buf, PMIU_MAXLINE );
       31:  676:	    if ( strcmp(buf,"ok") != 0 ) {
        -:  677:		/* FIXME: Do correct error reporting */
        -:  678:		/****
        -:  679:	        PMIU_printf( 1, "lookup failed; reason = %s\n", buf );
        -:  680:		****/
       27:  681:	        return( PMI_FAIL );
        -:  682:	    }
        4:  683:	    PMIU_getval( "port", port, MPI_MAX_PORT_NAME );
        -:  684:	}
        -:  685:    }
        -:  686:    else
        -:  687:    {
    #####:  688:	PMIU_printf( 1, "PMI_Lookup_name called before init\n" );
    #####:  689:	return( PMI_FAIL );
        -:  690:    }
        -:  691:
        4:  692:    return( PMI_SUCCESS );
        -:  693:}
        -:  694:
        -:  695:
        -:  696:/************************** Process Creation functions **********************/
        -:  697:
        -:  698:int PMI_Spawn_multiple(int count,
        -:  699:                       const char * cmds[],
        -:  700:                       const char ** argvs[],
        -:  701:                       const int maxprocs[],
        -:  702:                       const int info_keyval_sizes[],
        -:  703:                       const PMI_keyval_t * info_keyval_vectors[],
        -:  704:                       int preput_keyval_size,
        -:  705:                       const PMI_keyval_t preput_keyval_vector[],
        -:  706:                       int errors[])
      357:  707:{
        -:  708:    int  i,rc,argcnt,spawncnt,total_num_processes,num_errcodes_found;
        -:  709:    char buf[PMIU_MAXLINE], tempbuf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
        -:  710:    char *lead, *lag;
        -:  711:
        -:  712:    /* Connect to the PM if we haven't already */
      357:  713:    if (PMIi_InitIfSingleton() != 0) return -1;
        -:  714:
      357:  715:    total_num_processes = 0;
        -:  716:
      718:  717:    for (spawncnt=0; spawncnt < count; spawncnt++)
        -:  718:    {
      361:  719:        total_num_processes += maxprocs[spawncnt];
        -:  720:
      361:  721:        rc = MPIU_Snprintf(buf, PMIU_MAXLINE, 
        -:  722:			   "mcmd=spawn\nnprocs=%d\nexecname=%s\n",
        -:  723:			   maxprocs[spawncnt], cmds[spawncnt] );
      361:  724:	if (rc < 0) {
    #####:  725:	    return PMI_FAIL;
        -:  726:	}
        -:  727:
      361:  728:	rc = MPIU_Snprintf(tempbuf, PMIU_MAXLINE,
        -:  729:			   "totspawns=%d\nspawnssofar=%d\n",
        -:  730:			   count, spawncnt+1);
        -:  731:
      361:  732:	if (rc < 0) { 
    #####:  733:	    return PMI_FAIL;
        -:  734:	}
      361:  735:	rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
      361:  736:	if (rc != 0) {
    #####:  737:	    return PMI_FAIL;
        -:  738:	}
        -:  739:
      361:  740:        argcnt = 0;
      361:  741:        if ((argvs != NULL) && (argvs[spawncnt] != NULL)) {
      736:  742:            for (i=0; argvs[spawncnt][i] != NULL; i++)
        -:  743:            {
        -:  744:		/* FIXME (protocol design flaw): command line arguments
        -:  745:		   may contain both = and <space> (and even tab!).
        -:  746:		*/
        -:  747:		/* Note that part of this fixme was really a design error -
        -:  748:		   because this uses the mcmd form, the data can be
        -:  749:		   sent in multiple writelines.  This code now takes 
        -:  750:		   advantage of that.  Note also that a correct parser 
        -:  751:		   of the commands will permit any character other than a 
        -:  752:		   new line in the argument, since the form is 
        -:  753:		   argn=<any nonnewline><newline> */
      653:  754:                rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"arg%d=%s\n",
        -:  755:				   i+1,argvs[spawncnt][i]);
      653:  756:		if (rc < 0) {
    #####:  757:		    return PMI_FAIL;
        -:  758:		}
      653:  759:                rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
      653:  760:		if (rc != 0) {
    #####:  761:		    return PMI_FAIL;
        -:  762:		}
      653:  763:                argcnt++;
      653:  764:		rc = PMIU_writeline( PMI_fd, buf );
      653:  765:		buf[0] = 0;
        -:  766:
        -:  767:            }
        -:  768:        }
      361:  769:        rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"argcnt=%d\n",argcnt);
      361:  770:	if (rc < 0) {
    #####:  771:	    return PMI_FAIL;
        -:  772:	}
      361:  773:        rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
      361:  774:	if (rc != 0) {
    #####:  775:	    return PMI_FAIL;
        -:  776:	}
        -:  777:    
      361:  778:        rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"preput_num=%d\n", 
        -:  779:			   preput_keyval_size);
      361:  780:	if (rc < 0) {
    #####:  781:	    return PMI_FAIL;
        -:  782:	}
        -:  783:
      361:  784:        rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
      361:  785:	if (rc != 0) {
    #####:  786:	    return PMI_FAIL;
        -:  787:	}
      722:  788:        for (i=0; i < preput_keyval_size; i++) {
      361:  789:	    rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"preput_key_%d=%s\n",
        -:  790:			       i,preput_keyval_vector[i].key);
      361:  791:	    if (rc < 0) {
    #####:  792:		return PMI_FAIL;
        -:  793:	    }
      361:  794:	    rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE); 
      361:  795:	    if (rc != 0) {
    #####:  796:		return PMI_FAIL;
        -:  797:	    }
      361:  798:	    rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"preput_val_%d=%s\n",
        -:  799:			       i,preput_keyval_vector[i].val);
      361:  800:	    if (rc < 0) {
    #####:  801:		return PMI_FAIL;
        -:  802:	    }
      361:  803:	    rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE); 
      361:  804:	    if (rc != 0) {
    #####:  805:		return PMI_FAIL;
        -:  806:	    }
        -:  807:        } 
      361:  808:        rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"info_num=%d\n", 
        -:  809:			   info_keyval_sizes[spawncnt]);
      361:  810:	if (rc < 0) {
    #####:  811:	    return PMI_FAIL;
        -:  812:	}
      361:  813:        rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE);
      361:  814:	if (rc != 0) {
    #####:  815:	    return PMI_FAIL;
        -:  816:	}
      373:  817:	for (i=0; i < info_keyval_sizes[spawncnt]; i++)
        -:  818:	{
       12:  819:	    rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"info_key_%d=%s\n",
        -:  820:			       i,info_keyval_vectors[spawncnt][i].key);
       12:  821:	    if (rc < 0) {
    #####:  822:		return PMI_FAIL;
        -:  823:	    }
       12:  824:	    rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE); 
       12:  825:	    if (rc != 0) {
    #####:  826:		return PMI_FAIL;
        -:  827:	    }
       12:  828:	    rc = MPIU_Snprintf(tempbuf,PMIU_MAXLINE,"info_val_%d=%s\n",
        -:  829:			       i,info_keyval_vectors[spawncnt][i].val);
       12:  830:	    if (rc < 0) {
    #####:  831:		return PMI_FAIL;
        -:  832:	    }
       12:  833:	    rc = MPIU_Strnapp(buf,tempbuf,PMIU_MAXLINE); 
       12:  834:	    if (rc != 0) {
    #####:  835:		return PMI_FAIL;
        -:  836:	    }
        -:  837:	}
        -:  838:
      361:  839:        rc = MPIU_Strnapp(buf, "endcmd\n", PMIU_MAXLINE);
      361:  840:	if (rc != 0) {
    #####:  841:	    return PMI_FAIL;
        -:  842:	}
      361:  843:        PMIU_writeline( PMI_fd, buf );
        -:  844:    }
        -:  845:
      357:  846:    PMIU_readline( PMI_fd, buf, PMIU_MAXLINE );
      357:  847:    PMIU_parse_keyvals( buf ); 
      357:  848:    PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
      357:  849:    if ( strncmp( cmd, "spawn_result", PMIU_MAXLINE ) != 0 ) {
    #####:  850:	PMIU_printf( 1, "got unexpected response to spawn :%s:\n", buf );
    #####:  851:	return( -1 );
        -:  852:    }
        -:  853:    else {
      357:  854:	PMIU_getval( "rc", buf, PMIU_MAXLINE );
      357:  855:	rc = atoi( buf );
      357:  856:	if ( rc != 0 ) {
        -:  857:	    /****
        -:  858:	    PMIU_getval( "status", tempbuf, PMIU_MAXLINE );
        -:  859:	    PMIU_printf( 1, "pmi_spawn_mult failed; status: %s\n",tempbuf);
        -:  860:	    ****/
    #####:  861:	    return( -1 );
        -:  862:	}
        -:  863:    }
        -:  864:    
      357:  865:    PMIU_Assert(errors != NULL);
      357:  866:    if (PMIU_getval( "errcodes", tempbuf, PMIU_MAXLINE )) {
      357:  867:        num_errcodes_found = 0;
      357:  868:        lag = &tempbuf[0];
        -:  869:        do {
      406:  870:            lead = strchr(lag, ',');
      406:  871:            if (lead) *lead = '\0';
      406:  872:            errors[num_errcodes_found++] = atoi(lag);
      406:  873:            lag = lead + 1; /* move past the null char */
      406:  874:            PMIU_Assert(num_errcodes_found <= total_num_processes);
      406:  875:        } while (lead != NULL);
      357:  876:        PMIU_Assert(num_errcodes_found == total_num_processes);
        -:  877:    }
        -:  878:    else {
        -:  879:        /* gforker doesn't return errcodes, so we'll just pretend that means
        -:  880:           that it was going to send all `0's. */
    #####:  881:        for (i = 0; i < total_num_processes; ++i) {
    #####:  882:            errors[i] = 0;
        -:  883:        }
        -:  884:    }
        -:  885:
      357:  886:    return( 0 );
        -:  887:}
        -:  888:
        -:  889:/***************** Internal routines not part of PMI interface ***************/
        -:  890:
        -:  891:/* get a keyval pair by specific index */
        -:  892:
        -:  893:static int PMII_iter( const char *kvsname, const int idx, int *next_idx, 
        -:  894:		      char *key, int key_len, char *val, int val_len)
    #####:  895:{
        -:  896:    char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
        -:  897:    int  rc, err;
        -:  898:
        -:  899:    /* FIXME: Check for tempbuf too short */
    #####:  900:    rc = MPIU_Snprintf( buf, PMIU_MAXLINE, "cmd=getbyidx kvsname=%s idx=%d\n", 
        -:  901:			kvsname, idx  );
    #####:  902:    if (rc < 0) {
    #####:  903:	return PMI_FAIL;
        -:  904:    }
    #####:  905:    err = GetResponse( cmd, "getbyidx_results", 0 );
    #####:  906:    if (err == PMI_SUCCESS) {
    #####:  907:	PMIU_getval( "rc", buf, PMIU_MAXLINE );
        -:  908:	rc = atoi( buf );
    #####:  909:	if ( rc == 0 ) {
    #####:  910:	    PMIU_getval( "nextidx", buf, PMIU_MAXLINE );
    #####:  911:	    *next_idx = atoi( buf );
    #####:  912:	    PMIU_getval( "key", key, key_len );
    #####:  913:	    PMIU_getval( "val", val, val_len );
    #####:  914:	    return( PMI_SUCCESS );
        -:  915:	}
        -:  916:	else {
    #####:  917:	    PMIU_getval( "reason", buf, PMIU_MAXLINE );
    #####:  918:	    if ( strncmp( buf, "no_more_keyvals", PMIU_MAXLINE ) == 0 ) {
    #####:  919:		key[0] = '\0';
    #####:  920:		return( PMI_SUCCESS );
        -:  921:	    }
        -:  922:	    else {
    #####:  923:		PMIU_printf( 1, "iter failed; reason = %s\n", buf );
    #####:  924:		return( PMI_FAIL );
        -:  925:	    }
        -:  926:	}
        -:  927:    }
    #####:  928:    return err;
        -:  929:}
        -:  930:
        -:  931:/* to get all maxes in one message */
        -:  932:/* FIXME: This mixes init with get maxes */
        -:  933:static int PMII_getmaxes( int *kvsname_max, int *keylen_max, int *vallen_max )
     4381:  934:{
        -:  935:    char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE], errmsg[PMIU_MAXLINE];
        -:  936:    int err, rc;
        -:  937:
     4381:  938:    rc = MPIU_Snprintf( buf, PMIU_MAXLINE, 
        -:  939:			"cmd=init pmi_version=%d pmi_subversion=%d\n",
        -:  940:			PMI_VERSION, PMI_SUBVERSION );
     4381:  941:    if (rc < 0) {
    #####:  942:	return PMI_FAIL;
        -:  943:    }
        -:  944:
     4381:  945:    rc = PMIU_writeline( PMI_fd, buf );
     4381:  946:    if (rc != 0) {
    #####:  947:	PMIU_printf( 1, "Unable to write to PMI_fd\n" );
    #####:  948:	return PMI_FAIL;
        -:  949:    }
     4381:  950:    buf[0] = 0;   /* Ensure buffer is empty if read fails */
     4381:  951:    err = PMIU_readline( PMI_fd, buf, PMIU_MAXLINE );
     4381:  952:    if (err < 0) {
    #####:  953:	PMIU_printf( 1, "Error reading initack on %d\n", PMI_fd );
    #####:  954:	perror( "Error on readline:" );
    #####:  955:	PMI_Abort(-1, "Above error when reading after init" );
        -:  956:    }
     4381:  957:    PMIU_parse_keyvals( buf );
     4381:  958:    cmd[0] = 0;
     4381:  959:    PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
     4381:  960:    if ( strncmp( cmd, "response_to_init", PMIU_MAXLINE ) != 0 ) {
    #####:  961:	MPIU_Snprintf(errmsg, PMIU_MAXLINE, 
        -:  962:		      "got unexpected response to init :%s: (full line = %s)",
        -:  963:		      cmd, buf  );
    #####:  964:	PMI_Abort( -1, errmsg );
        -:  965:    }
        -:  966:    else {
        -:  967:	char buf1[PMIU_MAXLINE];
     4381:  968:        PMIU_getval( "rc", buf, PMIU_MAXLINE );
     4381:  969:        if ( strncmp( buf, "0", PMIU_MAXLINE ) != 0 ) {
    #####:  970:            PMIU_getval( "pmi_version", buf, PMIU_MAXLINE );
    #####:  971:            PMIU_getval( "pmi_subversion", buf1, PMIU_MAXLINE );
    #####:  972:	    MPIU_Snprintf(errmsg, PMIU_MAXLINE, 
        -:  973:			  "pmi_version mismatch; client=%d.%d mgr=%s.%s",
        -:  974:			  PMI_VERSION, PMI_SUBVERSION, buf, buf1 );
    #####:  975:	    PMI_Abort( -1, errmsg );
        -:  976:        }
        -:  977:    }
     4381:  978:    err = GetResponse( "cmd=get_maxes\n", "maxes", 0 );
     4381:  979:    if (err == PMI_SUCCESS) {
     4381:  980:	PMIU_getval( "kvsname_max", buf, PMIU_MAXLINE );
     4381:  981:	*kvsname_max = atoi( buf );
     4381:  982:	PMIU_getval( "keylen_max", buf, PMIU_MAXLINE );
     4381:  983:	*keylen_max = atoi( buf );
     4381:  984:	PMIU_getval( "vallen_max", buf, PMIU_MAXLINE );
     4381:  985:	*vallen_max = atoi( buf );
        -:  986:    }
     4381:  987:    return err;
        -:  988:}
        -:  989:
        -:  990:/* ----------------------------------------------------------------------- */
        -:  991:/* 
        -:  992: * This function is used to request information from the server and check
        -:  993: * that the response uses the expected command name.  On a successful
        -:  994: * return from this routine, additional PMIU_getval calls may be used
        -:  995: * to access information about the returned value.
        -:  996: *
        -:  997: * If checkRc is true, this routine also checks that the rc value returned
        -:  998: * was 0.  If not, it uses the "msg" value to report on the reason for
        -:  999: * the failure.
        -: 1000: */
        -: 1001:static int GetResponse( const char request[], const char expectedCmd[],
        -: 1002:			int checkRc )
    44282: 1003:{
        -: 1004:    int err, n;
        -: 1005:    char *p;
        -: 1006:    char recvbuf[PMIU_MAXLINE];
        -: 1007:    char cmdName[PMIU_MAXLINE];
        -: 1008:
        -: 1009:    /* FIXME: This is an example of an incorrect fix - writeline can change
        -: 1010:       the second argument in some cases, and that will break the const'ness
        -: 1011:       of request.  Instead, writeline should take a const item and return
        -: 1012:       an error in the case in which it currently truncates the data. */
    44282: 1013:    err = PMIU_writeline( PMI_fd, (char *)request );
    44282: 1014:    if (err) {
    #####: 1015:	return err;
        -: 1016:    }
    44282: 1017:    n = PMIU_readline( PMI_fd, recvbuf, sizeof(recvbuf) );
    44282: 1018:    if (n <= 0) {
    #####: 1019:	PMIU_printf( 1, "readline failed\n" );
    #####: 1020:	return PMI_FAIL;
        -: 1021:    }
    44282: 1022:    err = PMIU_parse_keyvals( recvbuf );
    44282: 1023:    if (err) {
    #####: 1024:	PMIU_printf( 1, "parse_kevals failed %d\n", err );
    #####: 1025:	return err;
        -: 1026:    }
    44282: 1027:    p = PMIU_getval( "cmd", cmdName, sizeof(cmdName) );
    44282: 1028:    if (!p) {
    #####: 1029:	PMIU_printf( 1, "getval cmd failed\n" );
    #####: 1030:	return PMI_FAIL;
        -: 1031:    }
    44282: 1032:    if (strcmp( expectedCmd, cmdName ) != 0) {
    #####: 1033:	PMIU_printf( 1, "expecting cmd=%s, got %s\n", expectedCmd, cmdName );
    #####: 1034:	return PMI_FAIL;
        -: 1035:    }
    44282: 1036:    if (checkRc) {
     4463: 1037:	p = PMIU_getval( "rc", cmdName, PMIU_MAXLINE );
     4463: 1038:	if ( p && strcmp(cmdName,"0") != 0 ) {
    #####: 1039:	    PMIU_getval( "msg", cmdName, PMIU_MAXLINE );
    #####: 1040:	    PMIU_printf( 1, "Command %s failed, reason='%s'\n", 
        -: 1041:			 request, cmdName );
    #####: 1042:	    return PMI_FAIL;
        -: 1043:	}
        -: 1044:    }
        -: 1045:
    44282: 1046:    return err;
        -: 1047:}
        -: 1048:/* ----------------------------------------------------------------------- */
        -: 1049:
        -: 1050:
        -: 1051:#ifdef USE_PMI_PORT
        -: 1052:/*
        -: 1053: * This code allows a program to contact a host/port for the PMI socket.
        -: 1054: */
        -: 1055:#include <errno.h>
        -: 1056:#if defined(HAVE_SYS_TYPES_H)
        -: 1057:#include <sys/types.h>
        -: 1058:#endif
        -: 1059:#include <sys/param.h>
        -: 1060:#include <sys/socket.h>
        -: 1061:
        -: 1062:/* sockaddr_in (Internet) */
        -: 1063:#include <netinet/in.h>
        -: 1064:/* TCP_NODELAY */
        -: 1065:#include <netinet/tcp.h>
        -: 1066:
        -: 1067:/* sockaddr_un (Unix) */
        -: 1068:#include <sys/un.h>
        -: 1069:
        -: 1070:/* defs of gethostbyname */
        -: 1071:#include <netdb.h>
        -: 1072:
        -: 1073:/* fcntl, F_GET/SETFL */
        -: 1074:#include <fcntl.h>
        -: 1075:
        -: 1076:/* This is really IP!? */
        -: 1077:#ifndef TCP
        -: 1078:#define TCP 0
        -: 1079:#endif
        -: 1080:
        -: 1081:/* stub for connecting to a specified host/port instead of using a 
        -: 1082:   specified fd inherited from a parent process */
        -: 1083:static int PMII_Connect_to_pm( char *hostname, int portnum )
     4381: 1084:{
        -: 1085:    struct hostent     *hp;
        -: 1086:    struct sockaddr_in sa;
        -: 1087:    int                fd;
     4381: 1088:    int                optval = 1;
     4381: 1089:    int                q_wait = 1;
        -: 1090:    
     4381: 1091:    hp = gethostbyname( hostname );
     4381: 1092:    if (!hp) {
    #####: 1093:	PMIU_printf( 1, "Unable to get host entry for %s\n", hostname );
    #####: 1094:	return -1;
        -: 1095:    }
        -: 1096:    
     4381: 1097:    memset( (void *)&sa, 0, sizeof(sa) );
        -: 1098:    /* POSIX might define h_addr_list only and node define h_addr */
        -: 1099:#ifdef HAVE_H_ADDR_LIST
     4381: 1100:    memcpy( (void *)&sa.sin_addr, (void *)hp->h_addr_list[0], hp->h_length);
        -: 1101:#else
        -: 1102:    memcpy( (void *)&sa.sin_addr, (void *)hp->h_addr, hp->h_length);
        -: 1103:#endif
     4381: 1104:    sa.sin_family = hp->h_addrtype;
     4381: 1105:    sa.sin_port   = htons( (unsigned short) portnum );
        -: 1106:    
     4381: 1107:    fd = socket( AF_INET, SOCK_STREAM, TCP );
     4381: 1108:    if (fd < 0) {
    #####: 1109:	PMIU_printf( 1, "Unable to get AF_INET socket\n" );
    #####: 1110:	return -1;
        -: 1111:    }
        -: 1112:    
     4381: 1113:    if (setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, 
        -: 1114:		    (char *)&optval, sizeof(optval) )) {
    #####: 1115:	perror( "Error calling setsockopt:" );
        -: 1116:    }
        -: 1117:
        -: 1118:    /* We wait here for the connection to succeed */
     4381: 1119:    if (connect( fd, (struct sockaddr *)&sa, sizeof(sa) ) < 0) {
    #####: 1120:	switch (errno) {
        -: 1121:	case ECONNREFUSED:
    #####: 1122:	    PMIU_printf( 1, "connect failed with connection refused\n" );
        -: 1123:	    /* (close socket, get new socket, try again) */
    #####: 1124:	    if (q_wait)
    #####: 1125:		close(fd);
    #####: 1126:	    return -1;
        -: 1127:	    
        -: 1128:	case EINPROGRESS: /*  (nonblocking) - select for writing. */
        -: 1129:	    break;
        -: 1130:	    
        -: 1131:	case EISCONN: /*  (already connected) */
        -: 1132:	    break;
        -: 1133:	    
        -: 1134:	case ETIMEDOUT: /* timed out */
    #####: 1135:	    PMIU_printf( 1, "connect failed with timeout\n" );
    #####: 1136:	    return -1;
        -: 1137:
        -: 1138:	default:
    #####: 1139:	    PMIU_printf( 1, "connect failed with errno %d\n", errno );
    #####: 1140:	    return -1;
        -: 1141:	}
        -: 1142:    }
        -: 1143:
     4381: 1144:    return fd;
        -: 1145:}
        -: 1146:
        -: 1147:static int PMII_Set_from_port( int fd, int id )
    #####: 1148:{
        -: 1149:    char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
        -: 1150:    int err, rc;
        -: 1151:
        -: 1152:    /* We start by sending a startup message to the server */
        -: 1153:
    #####: 1154:    if (PMI_debug) {
    #####: 1155:	PMIU_printf( 1, "Writing initack to destination fd %d\n", fd );
        -: 1156:    }
        -: 1157:    /* Handshake and initialize from a port */
        -: 1158:
    #####: 1159:    rc = MPIU_Snprintf( buf, PMIU_MAXLINE, "cmd=initack pmiid=%d\n", id );
    #####: 1160:    if (rc < 0) {
    #####: 1161:	return PMI_FAIL;
        -: 1162:    }
    #####: 1163:    PMIU_printf( PMI_debug, "writing on fd %d line :%s:\n", fd, buf );
    #####: 1164:    err = PMIU_writeline( fd, buf );
    #####: 1165:    if (err) {
    #####: 1166:	PMIU_printf( 1, "Error in writeline initack\n" );
    #####: 1167:	return -1;
        -: 1168:    }
        -: 1169:
        -: 1170:    /* cmd=initack */
    #####: 1171:    buf[0] = 0;
    #####: 1172:    PMIU_printf( PMI_debug, "reading initack\n" );
    #####: 1173:    err = PMIU_readline( fd, buf, PMIU_MAXLINE );
    #####: 1174:    if (err < 0) {
    #####: 1175:	PMIU_printf( 1, "Error reading initack on %d\n", fd );
    #####: 1176:	perror( "Error on readline:" );
    #####: 1177:	return -1;
        -: 1178:    }
    #####: 1179:    PMIU_parse_keyvals( buf );
    #####: 1180:    PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
    #####: 1181:    if ( strcmp( cmd, "initack" ) ) {
    #####: 1182:	PMIU_printf( 1, "got unexpected input %s\n", buf );
    #####: 1183:	return -1;
        -: 1184:    }
        -: 1185:    
        -: 1186:    /* Read, in order, size, rank, and debug.  Eventually, we'll want 
        -: 1187:       the handshake to include a version number */
        -: 1188:
        -: 1189:    /* size */
    #####: 1190:    PMIU_printf( PMI_debug, "reading size\n" );
    #####: 1191:    err = PMIU_readline( fd, buf, PMIU_MAXLINE );
    #####: 1192:    if (err < 0) {
    #####: 1193:	PMIU_printf( 1, "Error reading size on %d\n", fd );
    #####: 1194:	perror( "Error on readline:" );
    #####: 1195:	return -1;
        -: 1196:    }
    #####: 1197:    PMIU_parse_keyvals( buf );
    #####: 1198:    PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
    #####: 1199:    if ( strcmp(cmd,"set")) {
    #####: 1200:	PMIU_printf( 1, "got unexpected command %s in %s\n", cmd, buf );
    #####: 1201:	return -1;
        -: 1202:    }
        -: 1203:    /* cmd=set size=n */
    #####: 1204:    PMIU_getval( "size", cmd, PMIU_MAXLINE );
    #####: 1205:    PMI_size = atoi(cmd);
        -: 1206:
        -: 1207:    /* rank */
    #####: 1208:    PMIU_printf( PMI_debug, "reading rank\n" );
    #####: 1209:    err = PMIU_readline( fd, buf, PMIU_MAXLINE );
    #####: 1210:    if (err < 0) {
    #####: 1211:	PMIU_printf( 1, "Error reading rank on %d\n", fd );
    #####: 1212:	perror( "Error on readline:" );
    #####: 1213:	return -1;
        -: 1214:    }
    #####: 1215:    PMIU_parse_keyvals( buf );
    #####: 1216:    PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
    #####: 1217:    if ( strcmp(cmd,"set")) {
    #####: 1218:	PMIU_printf( 1, "got unexpected command %s in %s\n", cmd, buf );
    #####: 1219:	return -1;
        -: 1220:    }
        -: 1221:    /* cmd=set rank=n */
    #####: 1222:    PMIU_getval( "rank", cmd, PMIU_MAXLINE );
    #####: 1223:    PMI_rank = atoi(cmd);
    #####: 1224:    PMIU_Set_rank( PMI_rank );
        -: 1225:
        -: 1226:    /* debug flag */
    #####: 1227:    err = PMIU_readline( fd, buf, PMIU_MAXLINE );
    #####: 1228:    if (err < 0) {
    #####: 1229:	PMIU_printf( 1, "Error reading debug on %d\n", fd );
    #####: 1230:	return -1;
        -: 1231:    }
    #####: 1232:    PMIU_parse_keyvals( buf );
    #####: 1233:    PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
    #####: 1234:    if ( strcmp(cmd,"set")) {
    #####: 1235:	PMIU_printf( 1, "got unexpected command %s in %s\n", cmd, buf );
    #####: 1236:	return -1;
        -: 1237:    }
        -: 1238:    /* cmd=set debug=n */
    #####: 1239:    PMIU_getval( "debug", cmd, PMIU_MAXLINE );
    #####: 1240:    PMI_debug = atoi(cmd);
        -: 1241:
    #####: 1242:    if (PMI_debug) {
        -: 1243:	DBG_PRINTF( ("end of handshake, rank = %d, size = %d\n", 
        -: 1244:		    PMI_rank, PMI_size )); 
        -: 1245:	DBG_PRINTF( ("Completed init\n" ) );
        -: 1246:    }
        -: 1247:
    #####: 1248:    return 0;
        -: 1249:}
        -: 1250:
        -: 1251:/* ------------------------------------------------------------------------- */
        -: 1252:/* 
        -: 1253: * Singleton Init.
        -: 1254: * 
        -: 1255: * MPI-2 allows processes to become MPI processes and then make MPI calls,
        -: 1256: * such as MPI_Comm_spawn, that require a process manager (this is different 
        -: 1257: * than the much simpler case of allowing MPI programs to run with an 
        -: 1258: * MPI_COMM_WORLD of size 1 without an mpiexec or process manager).
        -: 1259: *
        -: 1260: * The process starts when either the client or the process manager contacts
        -: 1261: * the other.  If the client starts, it sends a singinit command and
        -: 1262: * waits for the server to respond with its own singinit command.
        -: 1263: * If the server start, it send a singinit command and waits for the 
        -: 1264: * client to respond with its own singinit command
        -: 1265: *
        -: 1266: * client sends singinit with these required values
        -: 1267: *   pmi_version=<value of PMI_VERSION>
        -: 1268: *   pmi_subversion=<value of PMI_SUBVERSION>
        -: 1269: *
        -: 1270: * and these optional values
        -: 1271: *   stdio=[yes|no]
        -: 1272: *   authtype=[none|shared|<other-to-be-defined>]
        -: 1273: *   authstring=<string>
        -: 1274: *
        -: 1275: * server sends singinit with the same required and optional values as
        -: 1276: * above.
        -: 1277: *
        -: 1278: * At this point, the protocol is now the same in both cases, and has the
        -: 1279: * following components:
        -: 1280: *
        -: 1281: * server sends singinit_info with these required fields
        -: 1282: *   versionok=[yes|no]
        -: 1283: *   stdio=[yes|no]
        -: 1284: *   kvsname=<string>
        -: 1285: *
        -: 1286: * The client then issues the init command (see PMII_getmaxes)
        -: 1287: *
        -: 1288: * cmd=init pmi_version=<val> pmi_subversion=<val>
        -: 1289: *
        -: 1290: * and expects to receive a 
        -: 1291: *
        -: 1292: * cmd=response_to_init rc=0 pmi_version=<val> pmi_subversion=<val> 
        -: 1293: *
        -: 1294: * (This is the usual init sequence).
        -: 1295: *
        -: 1296: */
        -: 1297:/* ------------------------------------------------------------------------- */
        -: 1298:/* This is a special routine used to re-initialize PMI when it is in 
        -: 1299:   the singleton init case.  That is, the executable was started without 
        -: 1300:   mpiexec, and PMI_Init returned as if there was only one process.
        -: 1301:
        -: 1302:   Note that PMI routines should not call PMII_singinit; they should
        -: 1303:   call PMIi_InitIfSingleton(), which both connects to the process mangager
        -: 1304:   and sets up the initial KVS connection entry.
        -: 1305:*/
        -: 1306:
        -: 1307:static int PMII_singinit(void)
    #####: 1308:{
        -: 1309:    int pid, rc;
        -: 1310:    int singinit_listen_sock, stdin_sock, stdout_sock, stderr_sock;
        -: 1311:    const char *newargv[8];
        -: 1312:    char charpid[8], port_c[8];
        -: 1313:    struct sockaddr_in sin;
        -: 1314:    socklen_t len;
        -: 1315:
        -: 1316:    /* Create a socket on which to allow an mpiexec to connect back to
        -: 1317:       us */
    #####: 1318:    sin.sin_family	= AF_INET;
    #####: 1319:    sin.sin_addr.s_addr	= INADDR_ANY;
    #####: 1320:    sin.sin_port	= htons(0);    /* anonymous port */
    #####: 1321:    singinit_listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    #####: 1322:    rc = bind(singinit_listen_sock, (struct sockaddr *)&sin ,sizeof(sin));
    #####: 1323:    len = sizeof(struct sockaddr_in);
    #####: 1324:    rc = getsockname( singinit_listen_sock, (struct sockaddr *) &sin, &len ); 
    #####: 1325:    MPIU_Snprintf(port_c, sizeof(port_c), "%d",ntohs(sin.sin_port));
    #####: 1326:    rc = listen(singinit_listen_sock, 5);
        -: 1327:
    #####: 1328:    PMIU_printf( PMI_debug_init, "Starting mpiexec with %s\n", port_c );
        -: 1329:
        -: 1330:    /* Launch the mpiexec process with the name of this port */
    #####: 1331:    pid = fork();
    #####: 1332:    if (pid < 0) {
    #####: 1333:	perror("PMII_singinit: fork failed");
    #####: 1334:	exit(-1);
        -: 1335:    }
    #####: 1336:    else if (pid == 0) {
    #####: 1337:	newargv[0] = "mpiexec";
    #####: 1338:	newargv[1] = "-pmi_args";
    #####: 1339:	newargv[2] = port_c;
        -: 1340:	/* FIXME: Use a valid hostname */
    #####: 1341:	newargv[3] = "default_interface";  /* default interface name, for now */
    #####: 1342:	newargv[4] = "default_key";   /* default authentication key, for now */
    #####: 1343:	MPIU_Snprintf(charpid, sizeof(charpid), "%d",getpid());
    #####: 1344:	newargv[5] = charpid;
    #####: 1345:	newargv[6] = NULL;
    #####: 1346:	rc = execvp(newargv[0], (char **)newargv);
    #####: 1347:	perror("PMII_singinit: execv failed");
    #####: 1348:	PMIU_printf(1, "  This singleton init program attempted to access some feature\n");
    #####: 1349:	PMIU_printf(1, "  for which process manager support was required, e.g. spawn or universe_size.\n");
    #####: 1350:	PMIU_printf(1, "  But the necessary mpiexec is not in your path.\n");
    #####: 1351:	return(-1);
        -: 1352:    }
        -: 1353:    else
        -: 1354:    {
        -: 1355:	char buf[PMIU_MAXLINE], cmd[PMIU_MAXLINE];
        -: 1356:	char *p;
    #####: 1357:	int connectStdio = 0;
        -: 1358:
        -: 1359:	/* Allow one connection back from the created mpiexec program */
    #####: 1360:	PMI_fd =  accept_one_connection(singinit_listen_sock);
    #####: 1361:	if (PMI_fd < 0) {
    #####: 1362:	    PMIU_printf( 1, "Failed to establish singleton init connection\n" );
    #####: 1363:	    return PMI_FAIL;
        -: 1364:	}
        -: 1365:	/* Execute the singleton init protocol */
    #####: 1366:	rc = PMIU_readline( PMI_fd, buf, PMIU_MAXLINE );
    #####: 1367:	PMIU_printf( PMI_debug_init, "Singinit: read %s\n", buf );
        -: 1368:
    #####: 1369:	PMIU_parse_keyvals( buf );
    #####: 1370:	PMIU_getval( "cmd", cmd, PMIU_MAXLINE );
    #####: 1371:	if (strcmp( cmd, "singinit" ) != 0) {
    #####: 1372:	    PMIU_printf( 1, "unexpected command from PM: %s\n", cmd );
    #####: 1373:	    return PMI_FAIL;
        -: 1374:	}
    #####: 1375:	p = PMIU_getval( "authtype", cmd, PMIU_MAXLINE );
    #####: 1376:	if (p && strcmp( cmd, "none" ) != 0) {
    #####: 1377:	    PMIU_printf( 1, "unsupported authentication method %s\n", cmd );
    #####: 1378:	    return PMI_FAIL;
        -: 1379:	}
        -: 1380:	/* p = PMIU_getval( "authstring", cmd, PMIU_MAXLINE ); */
        -: 1381:	
        -: 1382:	/* If we're successful, send back our own singinit */
    #####: 1383:	rc = MPIU_Snprintf( buf, PMIU_MAXLINE, 
        -: 1384:     "cmd=singinit pmi_version=%d pmi_subversion=%d stdio=yes authtype=none\n",
        -: 1385:			PMI_VERSION, PMI_SUBVERSION );
    #####: 1386:	if (rc < 0) {
    #####: 1387:	    return PMI_FAIL;
        -: 1388:	}
    #####: 1389:	PMIU_printf( PMI_debug_init, "GetResponse with %s\n", buf );
        -: 1390:
    #####: 1391:	rc = GetResponse( buf, "singinit_info", 0 );
    #####: 1392:	if (rc != 0) {
    #####: 1393:	    PMIU_printf( 1, "GetResponse failed\n" );
    #####: 1394:	    return PMI_FAIL;
        -: 1395:	}
    #####: 1396:	p = PMIU_getval( "versionok", cmd, PMIU_MAXLINE );
    #####: 1397:	if (p && strcmp( cmd, "yes" ) != 0) {
    #####: 1398:	    PMIU_printf( 1, "Process manager needs a different PMI version\n" );
    #####: 1399:	    return PMI_FAIL;
        -: 1400:	}
    #####: 1401:	p = PMIU_getval( "stdio", cmd, PMIU_MAXLINE );
    #####: 1402:	if (p && strcmp( cmd, "yes" ) == 0) {
    #####: 1403:	    PMIU_printf( PMI_debug_init, "PM agreed to connect stdio\n" );
    #####: 1404:	    connectStdio = 1;
        -: 1405:	}
    #####: 1406:	p = PMIU_getval( "kvsname", singinit_kvsname, sizeof(singinit_kvsname) );
    #####: 1407:	PMIU_printf( PMI_debug_init, "kvsname to use is %s\n", 
        -: 1408:		     singinit_kvsname );
        -: 1409:	
    #####: 1410:	if (connectStdio) {
    #####: 1411:	    PMIU_printf( PMI_debug_init, 
        -: 1412:			 "Accepting three connections for stdin, out, err\n" );
    #####: 1413:	    stdin_sock  = accept_one_connection(singinit_listen_sock);
    #####: 1414:	    dup2(stdin_sock, 0);
    #####: 1415:	    stdout_sock = accept_one_connection(singinit_listen_sock);
    #####: 1416:	    dup2(stdout_sock,1);
    #####: 1417:	    stderr_sock = accept_one_connection(singinit_listen_sock);
    #####: 1418:	    dup2(stderr_sock,2);
        -: 1419:	}
    #####: 1420:	PMIU_printf( PMI_debug_init, "Done with singinit handshake\n" );
        -: 1421:    }
    #####: 1422:    return 0;
        -: 1423:}
        -: 1424:
        -: 1425:/* Promote PMI to a fully initialized version if it was started as
        -: 1426:   a singleton init */
        -: 1427:static int PMIi_InitIfSingleton(void)
    13776: 1428:{
        -: 1429:    int rc;
        -: 1430:    static int firstcall = 1;
        -: 1431:
    13776: 1432:    if (PMI_initialized != SINGLETON_INIT_BUT_NO_PM || !firstcall) return 0;
        -: 1433:
        -: 1434:    /* We only try to init as a singleton the first time */
    #####: 1435:    firstcall = 0;
        -: 1436:
        -: 1437:    /* First, start (if necessary) an mpiexec, connect to it, 
        -: 1438:       and start the singleton init handshake */
    #####: 1439:    rc = PMII_singinit();
        -: 1440:
    #####: 1441:    if (rc < 0)
    #####: 1442:	return(-1);
    #####: 1443:    PMI_initialized = SINGLETON_INIT_WITH_PM;    /* do this right away */
    #####: 1444:    PMI_size	    = 1;
    #####: 1445:    PMI_rank	    = 0;
    #####: 1446:    PMI_debug	    = 0;
    #####: 1447:    PMI_spawned	    = 0;
        -: 1448:
    #####: 1449:    PMII_getmaxes( &PMI_kvsname_max, &PMI_keylen_max, &PMI_vallen_max );
        -: 1450:
        -: 1451:    /* FIXME: We need to support a distinct kvsname for each 
        -: 1452:       process group */
    #####: 1453:    PMI_KVS_Put( singinit_kvsname, cached_singinit_key, cached_singinit_val );
        -: 1454:
    #####: 1455:    return 0;
        -: 1456:}
        -: 1457:
        -: 1458:static int accept_one_connection(int list_sock)
    #####: 1459:{
        -: 1460:    int gotit, new_sock;
        -: 1461:    struct sockaddr_in from;
        -: 1462:    socklen_t len;
        -: 1463:
    #####: 1464:    len = sizeof(from);
    #####: 1465:    gotit = 0;
    #####: 1466:    while ( ! gotit )
        -: 1467:    {
    #####: 1468:	new_sock = accept(list_sock, (struct sockaddr *)&from, &len);
    #####: 1469:	if (new_sock == -1)
        -: 1470:	{
    #####: 1471:	    if (errno == EINTR)    /* interrupted? If so, try again */
    #####: 1472:		continue;
        -: 1473:	    else
        -: 1474:	    {
    #####: 1475:		PMIU_printf(1, "accept failed in accept_one_connection\n");
    #####: 1476:		exit(-1);
        -: 1477:	    }
        -: 1478:	}
        -: 1479:	else
    #####: 1480:	    gotit = 1;
        -: 1481:    }
    #####: 1482:    return(new_sock);
        -: 1483:}
        -: 1484:
        -: 1485:#endif
        -: 1486:/* end USE_PMI_PORT */
        -: 1487:
        -: 1488:/* Get the FD to use for PMI operations.  If a port is used, rather than 
        -: 1489:   a pre-established FD (i.e., via pipe), this routine will handle the 
        -: 1490:   initial handshake.  
        -: 1491:*/
        -: 1492:static int getPMIFD( int *notset )
     4381: 1493:{
        -: 1494:    char *p;
        -: 1495:
        -: 1496:    /* Set the default */
     4381: 1497:    PMI_fd = -1;
        -: 1498:    
     4381: 1499:    p = getenv( "PMI_FD" );
        -: 1500:
     4381: 1501:    if (p) {
    #####: 1502:	PMI_fd = atoi( p );
    #####: 1503:	return 0;
        -: 1504:    }
        -: 1505:
        -: 1506:#ifdef USE_PMI_PORT
     4381: 1507:    p = getenv( "PMI_PORT" );
     4381: 1508:    if (p) {
        -: 1509:	int portnum;
        -: 1510:	char hostname[MAXHOSTNAME+1];
        -: 1511:	char *pn, *ph;
     4381: 1512:	int id = 0;
        -: 1513:
        -: 1514:	/* Connect to the indicated port (in format hostname:portnumber) 
        -: 1515:	   and get the fd for the socket */
        -: 1516:	
        -: 1517:	/* Split p into host and port */
     4381: 1518:	pn = p;
     4381: 1519:	ph = hostname;
    61334: 1520:	while (*pn && *pn != ':' && (ph - hostname) < MAXHOSTNAME) {
    52572: 1521:	    *ph++ = *pn++;
        -: 1522:	}
     4381: 1523:	*ph = 0;
        -: 1524:
     4381: 1525:	if (PMI_debug) {
        -: 1526:	    DBG_PRINTF( ("Connecting to %s\n", p) );
        -: 1527:	}
     4381: 1528:	if (*pn == ':') {
     4381: 1529:	    portnum = atoi( pn+1 );
        -: 1530:	    /* FIXME: Check for valid integer after : */
        -: 1531:	    /* This routine only gets the fd to use to talk to 
        -: 1532:	       the process manager. The handshake below is used
        -: 1533:	       to setup the initial values */
     4381: 1534:	    PMI_fd = PMII_Connect_to_pm( hostname, portnum );
     4381: 1535:	    if (PMI_fd < 0) {
    #####: 1536:		PMIU_printf( 1, "Unable to connect to %s on %d\n", 
        -: 1537:			     hostname, portnum );
    #####: 1538:		return -1;
        -: 1539:	    }
        -: 1540:	}
        -: 1541:	else {
    #####: 1542:	    PMIU_printf( 1, "unable to decode hostport from %s\n", p );
    #####: 1543:	    return PMI_FAIL;
        -: 1544:	}
        -: 1545:
        -: 1546:	/* We should first handshake to get size, rank, debug. */
     4381: 1547:	p = getenv( "PMI_ID" );
     4381: 1548:	if (p) {
        -: 1549:	    id = atoi( p );
        -: 1550:	    /* PMII_Set_from_port sets up the values that are delivered
        -: 1551:	       by enviroment variables when a separate port is not used */
    #####: 1552: 	    PMII_Set_from_port( PMI_fd, id );
    #####: 1553:	    *notset = 0;
        -: 1554:	}
     4381: 1555:	return 0;
        -: 1556:    }
        -: 1557:#endif
        -: 1558:
        -: 1559:    /* Singleton init case - its ok to return success with no fd set */
    #####: 1560:    return 0;
        -: 1561:}