|
Packit |
0848f5 |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* (C) 2001 by Argonne National Laboratory.
|
|
Packit |
0848f5 |
* See COPYRIGHT in top-level directory.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Allow fprintf to logfile */
|
|
Packit |
0848f5 |
/* style: allow:fprintf:1 sig:0 */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Utility functions associated with PMI implementation, but not part of
|
|
Packit |
0848f5 |
the PMI interface itself. Reading and writing on pipes, signals, and parsing
|
|
Packit |
0848f5 |
key=value messages
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
#include "mpichconf.h"
|
|
Packit |
0848f5 |
#include "pmutil.h"
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#include <stdio.h>
|
|
Packit |
0848f5 |
#ifdef HAVE_STDLIB_H
|
|
Packit |
0848f5 |
#include <stdlib.h>
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
#include <stdarg.h>
|
|
Packit |
0848f5 |
#ifdef HAVE_STRING_H
|
|
Packit |
0848f5 |
#include <string.h>
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
#ifdef HAVE_UNISTD_H
|
|
Packit |
0848f5 |
#include <unistd.h>
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
#include <errno.h>
|
|
Packit |
0848f5 |
#include "simple_pmiutil2.h"
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#include "mpl.h"
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MAXVALLEN 1024
|
|
Packit |
0848f5 |
#define MAXKEYLEN 32
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* These are not the keyvals in the keyval space that is part of the
|
|
Packit |
0848f5 |
PMI specification.
|
|
Packit |
0848f5 |
They are just part of this implementation's internal utilities.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
struct PMIU_keyval_pairs {
|
|
Packit |
0848f5 |
char key[MAXKEYLEN];
|
|
Packit |
0848f5 |
char value[MAXVALLEN];
|
|
Packit |
0848f5 |
};
|
|
Packit |
0848f5 |
static struct PMIU_keyval_pairs PMIU_keyval_tab[64] = { { {0}, {0} } };
|
|
Packit |
0848f5 |
static int PMIU_keyval_tab_idx = 0;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* This is used to prepend printed output. Set the initial value to
|
|
Packit |
0848f5 |
"unset" */
|
|
Packit |
0848f5 |
static char PMIU_print_id[PMIU_IDSIZE] = "unset";
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
void PMIU_Set_rank( int PMI_rank )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
MPL_snprintf( PMIU_print_id, PMIU_IDSIZE, "cli_%d", PMI_rank );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
void PMIU_SetServer( void )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
MPIU_Strncpy( PMIU_print_id, "server", PMIU_IDSIZE );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Note that vfprintf is part of C89 */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* style: allow:fprintf:1 sig:0 */
|
|
Packit |
0848f5 |
/* style: allow:vfprintf:1 sig:0 */
|
|
Packit |
0848f5 |
/* This should be combined with the message routines */
|
|
Packit |
0848f5 |
void PMIU_printf( int print_flag, const char *fmt, ... )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
va_list ap;
|
|
Packit |
0848f5 |
static FILE *logfile= 0;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* In some cases when we are debugging, the handling of stdout or
|
|
Packit |
0848f5 |
stderr may be unreliable. In that case, we make it possible to
|
|
Packit |
0848f5 |
select an output file. */
|
|
Packit |
0848f5 |
if (!logfile) {
|
|
Packit |
0848f5 |
char *p;
|
|
Packit |
0848f5 |
p = getenv("PMI_USE_LOGFILE");
|
|
Packit |
0848f5 |
if (p) {
|
|
Packit |
0848f5 |
char filename[1024];
|
|
Packit |
0848f5 |
p = getenv("PMI_ID");
|
|
Packit |
0848f5 |
if (p) {
|
|
Packit |
0848f5 |
MPL_snprintf( filename, sizeof(filename),
|
|
Packit |
0848f5 |
"testclient-%s.out", p );
|
|
Packit |
0848f5 |
logfile = fopen( filename, "w" );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
logfile = fopen( "testserver.out", "w" );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else
|
|
Packit |
0848f5 |
logfile = stderr;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if ( print_flag ) {
|
|
Packit |
0848f5 |
/* MPL_error_printf( "[%s]: ", PMIU_print_id ); */
|
|
Packit |
0848f5 |
/* FIXME: Decide what role PMIU_printf should have (if any) and
|
|
Packit |
0848f5 |
select the appropriate MPIU routine */
|
|
Packit |
0848f5 |
fprintf( logfile, "[%s]: ", PMIU_print_id );
|
|
Packit |
0848f5 |
va_start( ap, fmt );
|
|
Packit |
0848f5 |
vfprintf( logfile, fmt, ap );
|
|
Packit |
0848f5 |
va_end( ap );
|
|
Packit |
0848f5 |
fflush( logfile );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#define MAX_READLINE 1024
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Return the next newline-terminated string of maximum length maxlen.
|
|
Packit |
0848f5 |
* This is a buffered version, and reads from fd as necessary. A
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
int PMIU_readline( int fd, char *buf, int maxlen )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
static char readbuf[MAX_READLINE];
|
|
Packit |
0848f5 |
static char *nextChar = 0, *lastChar = 0; /* lastChar is really one past
|
|
Packit |
0848f5 |
last char */
|
|
Packit |
0848f5 |
static int lastErrno = 0;
|
|
Packit |
0848f5 |
static int lastfd = -1;
|
|
Packit |
0848f5 |
int curlen, n;
|
|
Packit |
0848f5 |
char *p, ch;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Note: On the client side, only one thread at a time should
|
|
Packit |
0848f5 |
be calling this, and there should only be a single fd.
|
|
Packit |
0848f5 |
Server side code should not use this routine (see the
|
|
Packit |
0848f5 |
replacement version in src/pm/util/pmiserv.c) */
|
|
Packit |
0848f5 |
if (nextChar != lastChar && fd != lastfd) {
|
|
Packit |
0848f5 |
MPL_internal_error_printf( "Panic - buffer inconsistent\n" );
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
p = buf;
|
|
Packit |
0848f5 |
curlen = 1; /* Make room for the null */
|
|
Packit |
0848f5 |
while (curlen < maxlen) {
|
|
Packit |
0848f5 |
if (nextChar == lastChar) {
|
|
Packit |
0848f5 |
lastfd = fd;
|
|
Packit |
0848f5 |
do {
|
|
Packit |
0848f5 |
/* The size of the read buffer will always fit within
|
|
Packit |
0848f5 |
an int. */
|
|
Packit |
0848f5 |
/* FIXME: the read length should be the size of the buffer,
|
|
Packit |
0848f5 |
not the size of the pointer to buffer */
|
|
Packit |
0848f5 |
n = (int)read( fd, readbuf, sizeof(readbuf)-1 );
|
|
Packit |
0848f5 |
} while (n == -1 && errno == EINTR);
|
|
Packit |
0848f5 |
if (n == 0) {
|
|
Packit |
0848f5 |
/* EOF */
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else if (n < 0) {
|
|
Packit |
0848f5 |
/* Error. Return a negative value if there is no
|
|
Packit |
0848f5 |
data. Save the errno in case we need to return it
|
|
Packit |
0848f5 |
later. */
|
|
Packit |
0848f5 |
lastErrno = errno;
|
|
Packit |
0848f5 |
if (curlen == 1) {
|
|
Packit |
0848f5 |
curlen = 0;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
nextChar = readbuf;
|
|
Packit |
0848f5 |
lastChar = readbuf + n;
|
|
Packit |
0848f5 |
/* Add a null at the end just to make it easier to print
|
|
Packit |
0848f5 |
the read buffer */
|
|
Packit |
0848f5 |
readbuf[n] = 0;
|
|
Packit |
0848f5 |
/* FIXME: Make this an optional output */
|
|
Packit |
0848f5 |
/* printf( "Readline %s\n", readbuf ); */
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
ch = *nextChar++;
|
|
Packit |
0848f5 |
*p++ = ch;
|
|
Packit |
0848f5 |
curlen++;
|
|
Packit |
0848f5 |
if (ch == '\n') break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* We null terminate the string for convenience in printing */
|
|
Packit |
0848f5 |
*p = 0;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Return the number of characters, not counting the null */
|
|
Packit |
0848f5 |
return curlen-1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
int PMIU_writeline( int fd, char *buf )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int n;
|
|
Packit |
0848f5 |
size_t size;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
size = strlen( buf );
|
|
Packit |
0848f5 |
if ( size > PMIU_MAXLINE ) {
|
|
Packit |
0848f5 |
buf[PMIU_MAXLINE-1] = '\0';
|
|
Packit |
0848f5 |
PMIU_printf( 1, "write_line: message string too big: :%s:\n", buf );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else if ( buf[strlen( buf ) - 1] != '\n' ) /* error: no newline at end */
|
|
Packit |
0848f5 |
PMIU_printf( 1, "write_line: message string doesn't end in newline: :%s:\n",
|
|
Packit |
0848f5 |
buf );
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
do {
|
|
Packit |
0848f5 |
/* We assume that the size of any buf to be written fits
|
|
Packit |
0848f5 |
in an int. For the PMI interface, this should always
|
|
Packit |
0848f5 |
be true */
|
|
Packit |
0848f5 |
n = (int)write( fd, buf, size );
|
|
Packit |
0848f5 |
} while (n == -1 && errno == EINTR);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if ( n < 0 ) {
|
|
Packit |
0848f5 |
PMIU_printf( 1, "write_line error; fd=%d buf=:%s:\n", fd, buf );
|
|
Packit |
0848f5 |
perror("system msg for write_line failure ");
|
|
Packit |
0848f5 |
return(-1);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if ( n < size)
|
|
Packit |
0848f5 |
PMIU_printf( 1, "write_line failed to write entire message\n" );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
return 0;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Given an input string st, parse it into internal storage that can be
|
|
Packit |
0848f5 |
* queried by routines such as PMIU_getval.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
int PMIU_parse_keyvals( char *st )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
char *p, *keystart, *valstart;
|
|
Packit |
0848f5 |
size_t offset;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if ( !st )
|
|
Packit |
0848f5 |
return( -1 );
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
PMIU_keyval_tab_idx = 0;
|
|
Packit |
0848f5 |
p = st;
|
|
Packit |
0848f5 |
while ( 1 ) {
|
|
Packit |
0848f5 |
while ( *p == ' ' )
|
|
Packit |
0848f5 |
p++;
|
|
Packit |
0848f5 |
/* got non-blank */
|
|
Packit |
0848f5 |
if ( *p == '=' ) {
|
|
Packit |
0848f5 |
PMIU_printf( 1, "PMIU_parse_keyvals: unexpected = at character %d in %s\n",
|
|
Packit |
0848f5 |
p - st, st );
|
|
Packit |
0848f5 |
return( -1 );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if ( *p == '\n' || *p == '\0' )
|
|
Packit |
0848f5 |
return( 0 ); /* normal exit */
|
|
Packit |
0848f5 |
/* got normal character */
|
|
Packit |
0848f5 |
keystart = p; /* remember where key started */
|
|
Packit |
0848f5 |
while ( *p != ' ' && *p != '=' && *p != '\n' && *p != '\0' )
|
|
Packit |
0848f5 |
p++;
|
|
Packit |
0848f5 |
if ( *p == ' ' || *p == '\n' || *p == '\0' ) {
|
|
Packit |
0848f5 |
PMIU_printf( 1,
|
|
Packit |
0848f5 |
"PMIU_parse_keyvals: unexpected key delimiter at character %d in %s\n",
|
|
Packit |
0848f5 |
p - st, st );
|
|
Packit |
0848f5 |
return( -1 );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
/* Null terminate the key */
|
|
Packit |
0848f5 |
*p = 0;
|
|
Packit |
0848f5 |
/* store key */
|
|
Packit |
0848f5 |
MPIU_Strncpy( PMIU_keyval_tab[PMIU_keyval_tab_idx].key, keystart,
|
|
Packit |
0848f5 |
MAXKEYLEN );
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
valstart = ++p; /* start of value */
|
|
Packit |
0848f5 |
while ( *p != ' ' && *p != '\n' && *p != '\0' )
|
|
Packit |
0848f5 |
p++;
|
|
Packit |
0848f5 |
/* store value */
|
|
Packit |
0848f5 |
MPIU_Strncpy( PMIU_keyval_tab[PMIU_keyval_tab_idx].value, valstart,
|
|
Packit |
0848f5 |
MAXVALLEN );
|
|
Packit |
0848f5 |
offset = p - valstart;
|
|
Packit |
0848f5 |
/* When compiled with -fPIC, the pgcc compiler generates incorrect
|
|
Packit |
0848f5 |
code if "p - valstart" is used instead of using the
|
|
Packit |
0848f5 |
intermediate offset */
|
|
Packit |
0848f5 |
PMIU_keyval_tab[PMIU_keyval_tab_idx].value[offset] = '\0';
|
|
Packit |
0848f5 |
PMIU_keyval_tab_idx++;
|
|
Packit |
0848f5 |
if ( *p == ' ' )
|
|
Packit |
0848f5 |
continue;
|
|
Packit |
0848f5 |
if ( *p == '\n' || *p == '\0' )
|
|
Packit |
0848f5 |
return( 0 ); /* value has been set to empty */
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
void PMIU_dump_keyvals( void )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int i;
|
|
Packit |
0848f5 |
for (i=0; i < PMIU_keyval_tab_idx; i++)
|
|
Packit |
0848f5 |
PMIU_printf(1, " %s=%s\n",PMIU_keyval_tab[i].key, PMIU_keyval_tab[i].value);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
char *PMIU_getval( const char *keystr, char *valstr, int vallen )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int i, rc;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
for (i = 0; i < PMIU_keyval_tab_idx; i++) {
|
|
Packit |
0848f5 |
if ( strcmp( keystr, PMIU_keyval_tab[i].key ) == 0 ) {
|
|
Packit |
0848f5 |
rc = MPIU_Strncpy( valstr, PMIU_keyval_tab[i].value, vallen );
|
|
Packit |
0848f5 |
if (rc != 0) {
|
|
Packit |
0848f5 |
PMIU_printf( 1, "MPIU_Strncpy failed in PMIU_getval\n" );
|
|
Packit |
0848f5 |
return NULL;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
return valstr;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
valstr[0] = '\0';
|
|
Packit |
0848f5 |
return NULL;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
void PMIU_chgval( const char *keystr, char *valstr )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int i;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
for ( i = 0; i < PMIU_keyval_tab_idx; i++ ) {
|
|
Packit |
0848f5 |
if ( strcmp( keystr, PMIU_keyval_tab[i].key ) == 0 ) {
|
|
Packit |
0848f5 |
MPIU_Strncpy( PMIU_keyval_tab[i].value, valstr, MAXVALLEN - 1 );
|
|
Packit |
0848f5 |
PMIU_keyval_tab[i].value[MAXVALLEN - 1] = '\0';
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|