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