commit:     8f1127807f68bbb9c3c85622808677f8c7b60b5b
Author:     Christoph Junghans <ottxor <AT> gentoo <DOT> org>
AuthorDate: Fri Aug 29 19:27:46 2014 +0000
Commit:     Christoph Junghans <ottxor <AT> gentoo <DOT> org>
CommitDate: Fri Aug 29 19:27:46 2014 +0000
URL:        http://sources.gentoo.org/gitweb/?p=proj/sci.git;a=commit;h=8f112780

initial commit

Package-Manager: portage-2.2.8-r1

---
 app-shells/mpibash/ChangeLog                       |   11 +
 .../files/bash-4.3-append-process-segfault.patch   |   18 +
 app-shells/mpibash/files/bash-4.3-compat-lvl.patch |   13 +
 .../files/bash-4.3-parse-time-keyword.patch        |   30 +
 app-shells/mpibash/files/mpibash-4.3.patch         | 1565 ++++++++++++++++++++
 app-shells/mpibash/metadata.xml                    |   16 +
 app-shells/mpibash/mpibash-4.3_p24.ebuild          |  259 ++++
 7 files changed, 1912 insertions(+)

diff --git a/app-shells/mpibash/ChangeLog b/app-shells/mpibash/ChangeLog
new file mode 100644
index 0000000..58fda67
--- /dev/null
+++ b/app-shells/mpibash/ChangeLog
@@ -0,0 +1,11 @@
+# ChangeLog for app-shells/mpibash
+# Copyright 1999-2014 Gentoo Foundation; Distributed under the GPL v2
+# $Header: $
+
+*mpibash-4.3_p24 (29 Aug 2014)
+
+  29 Aug 2014; Christoph Junghans <[email protected]>
+  +files/bash-4.3-append-process-segfault.patch,
+  +files/bash-4.3-compat-lvl.patch, +files/bash-4.3-parse-time-keyword.patch,
+  +files/mpibash-4.3.patch, +metadata.xml, +mpibash-4.3_p24.ebuild:
+  initial commit

diff --git a/app-shells/mpibash/files/bash-4.3-append-process-segfault.patch 
b/app-shells/mpibash/files/bash-4.3-append-process-segfault.patch
new file mode 100644
index 0000000..6c9b2e8
--- /dev/null
+++ b/app-shells/mpibash/files/bash-4.3-append-process-segfault.patch
@@ -0,0 +1,18 @@
+https://lists.gnu.org/archive/html/bug-bash/2014-08/msg00048.html
+
+*** ../bash-4.3-patched/execute_cmd.c  2014-07-30 10:26:52.000000000 -0400
+--- execute_cmd.c      2014-08-11 16:55:57.000000000 -0400
+***************
+*** 2406,2410 ****
+      {
+  #if defined (JOB_CONTROL)
+!       append_process (savestring (the_printed_command), dollar_dollar_pid, 
exec_result, lastpipe_jid);
+  #endif
+        lstdin = wait_for (lastpid);
+--- 2433,2438 ----
+      {
+  #if defined (JOB_CONTROL)
+!       if (INVALID_JOB (lastpipe_jid) == 0)
+!      append_process (savestring (the_printed_command_except_trap), 
dollar_dollar_pid, exec_result, lastpipe_jid);
+  #endif
+        lstdin = wait_for (lastpid);

diff --git a/app-shells/mpibash/files/bash-4.3-compat-lvl.patch 
b/app-shells/mpibash/files/bash-4.3-compat-lvl.patch
new file mode 100644
index 0000000..5734687
--- /dev/null
+++ b/app-shells/mpibash/files/bash-4.3-compat-lvl.patch
@@ -0,0 +1,13 @@
+https://lists.gnu.org/archive/html/bug-bash/2014-06/msg00046.html
+
+--- a/builtins/shopt.def
++++ b/builtins/shopt.def
+@@ -160,7 +160,7 @@ static struct {
+   { "compat32", &shopt_compat32, set_compatibility_level },
+   { "compat40", &shopt_compat40, set_compatibility_level },
+   { "compat41", &shopt_compat41, set_compatibility_level },
+-  { "compat42", &shopt_compat41, set_compatibility_level },
++  { "compat42", &shopt_compat42, set_compatibility_level },
+ #if defined (READLINE)
+   { "complete_fullquote", &complete_fullquote, (shopt_set_func_t *)NULL},
+   { "direxpand", &dircomplete_expand, shopt_set_complete_direxpand },

diff --git a/app-shells/mpibash/files/bash-4.3-parse-time-keyword.patch 
b/app-shells/mpibash/files/bash-4.3-parse-time-keyword.patch
new file mode 100644
index 0000000..cd516e5
--- /dev/null
+++ b/app-shells/mpibash/files/bash-4.3-parse-time-keyword.patch
@@ -0,0 +1,30 @@
+https://lists.gnu.org/archive/html/bug-bash/2014-06/msg00034.html
+
+*** ../bash-4.3-patched/parse.y        2014-04-07 11:56:12.000000000 -0400
+--- parse.y    2014-06-11 10:25:53.000000000 -0400
+***************
+*** 2789,2797 ****
+      case OR_OR:
+      case '&':
+      case DO:
+      case THEN:
+      case ELSE:
+      case '{':                /* } */
+!     case '(':                /* ) */
+      case BANG:               /* ! time pipeline */
+      case TIME:               /* time time pipeline */
+--- 2789,2802 ----
+      case OR_OR:
+      case '&':
++     case WHILE:
+      case DO:
++     case UNTIL:
++     case IF:
+      case THEN:
++     case ELIF:
+      case ELSE:
+      case '{':                /* } */
+!     case '(':                /* )( */
+!     case ')':                /* only valid in case statement */
+      case BANG:               /* ! time pipeline */
+      case TIME:               /* time time pipeline */

diff --git a/app-shells/mpibash/files/mpibash-4.3.patch 
b/app-shells/mpibash/files/mpibash-4.3.patch
new file mode 100644
index 0000000..20d4787
--- /dev/null
+++ b/app-shells/mpibash/files/mpibash-4.3.patch
@@ -0,0 +1,1565 @@
+diff -Naur bash-4.3/builtins/circle.def mpibash-4.3/builtins/circle.def
+--- bash-4.3/builtins/circle.def       1969-12-31 17:00:00.000000000 -0700
++++ mpibash-4.3/builtins/circle.def    2014-05-13 11:27:37.314100671 -0600
+@@ -0,0 +1,620 @@
++This file is circle.def, from which is created circle.c.
++It implements all of the "circle_*" builtins in Bash.
++
++$PRODUCES circle.c
++
++#include <config.h>
++
++#include <stdio.h>
++#if defined (HAVE_UNISTD_H)
++#  ifdef _MINIX
++#    include <sys/types.h>
++#  endif
++#  include <unistd.h>
++#endif
++
++#include "../bashintl.h"
++#include "../shell.h"
++#include "common.h"
++#include "bashgetopt.h"
++#include <libcircle.h>
++
++extern int running_trap, trap_saved_exit_value;
++
++static int circle_rank;          /* Rank in the Libcircle job */
++static SHELL_VAR *create_func = NULL;   /* User-defined callback function for 
CIRCLE_cb_create. */
++static SHELL_VAR *process_func = NULL;  /* User-defined callback function for 
CIRCLE_cb_process. */
++static SHELL_VAR *reduce_init_func = NULL;  /* User-defined callback function 
for CIRCLE_cb_reduce_init. */
++static SHELL_VAR *reduce_fini_func = NULL;  /* User-defined callback function 
for CIRCLE_cb_reduce_fini. */
++static SHELL_VAR *reduce_op_func = NULL;   /* User-defined callback function 
for CIRCLE_cb_reduce_op. */
++static CIRCLE_handle *current_handle = NULL;   /* Active handle within a 
callback or NULL if not within a callback */
++static int within_reduction = 0;           /* 1=within a reduction callback; 
0=not */
++
++/* Return with a usage message if no arguments remain. */
++#define YES_ARGS(LIST)                          \
++  if ((LIST) == 0)                              \
++    {                                           \
++      builtin_usage ();                         \
++      return (EX_USAGE);                        \
++    }
++
++/* Perform the same operation as bind_variable, but with VALUE being a
++ * number, not a string. */
++static SHELL_VAR *
++bind_variable_number (name, value, flags)
++     const char *name;
++     long value;
++     int flags;
++{
++  char numstr[25];    /* String version of VALUE */
++
++  sprintf (numstr, "%ld", value);
++  return bind_variable (name, numstr, flags);
++}
++
++/* Invoke the user-defined creation-callback function (create_func). */
++static void
++internal_create_func (handle)
++     CIRCLE_handle *handle;
++{
++  WORD_LIST *funcargs;
++
++  if (create_func == NULL)
++    return;
++  current_handle = handle;
++  funcargs = make_word_list (make_word ("cb_create"), NULL);
++  execute_shell_function (create_func, funcargs);
++  dispose_words (funcargs);
++  current_handle = NULL;
++}
++
++/* Invoke the user-defined process-callback function (process_func). */
++static void
++internal_process_func (handle)
++     CIRCLE_handle *handle;
++{
++  WORD_LIST *funcargs;
++
++  if (process_func == NULL)
++    return;
++  current_handle = handle;
++  funcargs = make_word_list (make_word ("cb_process"), NULL);
++  execute_shell_function (process_func, funcargs);
++  dispose_words (funcargs);
++  current_handle = NULL;
++}
++
++/* Invoke the user-defined reduction-initiation callback function
++ * (reduce_init_func). */
++static void
++internal_reduce_init_func (void)
++{
++  WORD_LIST *funcargs;
++
++  if (reduce_init_func == NULL)
++    return;
++  within_reduction = 1;
++  funcargs = make_word_list (make_word ("cb_reduce_init"), NULL);
++  execute_shell_function (reduce_init_func, funcargs);
++  dispose_words (funcargs);
++  within_reduction = 0;
++}
++
++/* Invoke the user-defined reduction callback function
++ * (reduce_op_func). */
++static void
++internal_reduce_op_func (buf1, size1, buf2, size2)
++     const void* buf1;
++     size_t size1;
++     const void* buf2;
++     size_t size2;
++{
++  WORD_LIST *funcargs;
++
++  if (reduce_op_func == NULL)
++    return;
++  within_reduction = 1;
++  funcargs = make_word_list (make_word (buf2), NULL);
++  funcargs = make_word_list (make_word (buf1), funcargs);
++  funcargs = make_word_list (make_word ("cb_reduce_op"), funcargs);
++  execute_shell_function (reduce_op_func, funcargs);
++  dispose_words (funcargs);
++  within_reduction = 0;
++}
++
++/* Invoke the user-defined reduction-finalization callback function
++ * (reduce_fini_func). */
++static void
++internal_reduce_fini_func (buf, size)
++     const void* buf;
++     size_t size;
++{
++  WORD_LIST *funcargs;
++
++  if (reduce_fini_func == NULL)
++    return;
++  funcargs = make_word_list (make_word (buf), NULL);
++  funcargs = make_word_list (make_word ("cb_reduce_fini"), funcargs);
++  execute_shell_function (reduce_fini_func, funcargs);
++  dispose_words (funcargs);
++}
++
++/* Look up a user-provided callback function. */
++static int
++find_callback_function (list, user_func)
++     WORD_LIST *list;
++     SHELL_VAR **user_func;
++{
++  char *funcname;   /* Name of the user-defined function. */
++
++  /* If no argument was provided, nullify the callback function. */
++  if (list == NULL)
++    {
++      *user_func = NULL;
++      return EXECUTION_SUCCESS;
++    }
++
++  /* Get the callback function. */
++  funcname = list->word->word;
++  list = list->next;
++  no_args (list);
++  *user_func = find_function (funcname);
++  if (*user_func == NULL)
++    {
++      builtin_error (_("function %s not found"), funcname);
++      return EXECUTION_FAILURE;
++    }
++  return EXECUTION_SUCCESS;
++}
++
++/* Initialize Libcircle. */
++void
++initialize_libcircle (argc, argv)
++     int argc;
++     char **argv;
++{
++  circle_rank = CIRCLE_init (argc, argv, CIRCLE_DEFAULT_FLAGS);
++  bind_variable_number ("circle_rank", circle_rank, 0);
++  CIRCLE_enable_logging (CIRCLE_LOG_WARN);
++  CIRCLE_cb_create (internal_create_func);
++  CIRCLE_cb_process (internal_process_func);
++  CIRCLE_cb_reduce_init (internal_reduce_init_func);
++  CIRCLE_cb_reduce_op (internal_reduce_op_func);
++  CIRCLE_cb_reduce_fini (internal_reduce_fini_func);
++}
++
++/* Finalize Libcircle. */
++void
++finalize_libcircle (void)
++{
++  CIRCLE_finalize ();
++}
++
++/* ---------------------------------------------------------------------- */
++
++$BUILTIN circle_set_options
++$FUNCTION circle_set_options_builtin
++$SHORT_DOC circle_set_options [flag]...
++Change Libcircle's run-time behavior.
++
++Arguments:
++  FLAG          "split_random", "split_equal", or "create_global"
++
++Multiple flags can be provided.  If no flags are provided, Libcircle
++reverts to its default options.
++
++Exit Status:
++Returns 0 unless an invalid option is given.
++$END
++/*'*/
++
++/* Here is the circle_set_options builtin. */
++int
++circle_set_options_builtin (list)
++     WORD_LIST *list;
++{
++  char *word;          /* One argument */
++  int flags = 0;       /* Flags to pass to CIRCLE_set_options */
++
++  if (list == NULL)
++    flags = CIRCLE_DEFAULT_FLAGS;
++  else
++    while (list != NULL)
++      {
++        word = list->word->word;
++        if (!strcmp (word, "split_random"))
++          flags |= CIRCLE_SPLIT_RANDOM;
++        else if (!strcmp (word, "split_equal"))
++          flags |= CIRCLE_SPLIT_EQUAL;
++        else if (!strcmp (word, "create_global"))
++          flags |= CIRCLE_CREATE_GLOBAL;
++        else
++          {
++            builtin_error (_("invalid flag \"%s\""), word);
++            return (EXECUTION_FAILURE);
++          }
++        list = list->next;
++      }
++  CIRCLE_set_options (flags);
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN circle_cb_create
++$FUNCTION circle_cb_create_builtin
++$SHORT_DOC circle_cb_create [func]
++Register a function that will create work when asked.
++
++Arguments:
++  FUNC          User-defined callback function that will invoke
++                circle_enqueue when called
++
++If FUNC is omitted, no function will be associated with work creation.
++This can be used to nullify a previous circle_cb_create invocation.
++
++Exit Status:
++Returns 0 unless an invalid function is given or an error occurs.
++$END
++
++/* Here is the circle_cb_create builtin. */
++int
++circle_cb_create_builtin (list)
++     WORD_LIST *list;
++{
++  return find_callback_function (list, &create_func);
++}
++
++$BUILTIN circle_cb_process
++$FUNCTION circle_cb_process_builtin
++$SHORT_DOC circle_cb_process [func]
++Register a function that will process work when asked.
++
++Arguments:
++  FUNC          User-defined callback function that will invoke
++                circle_enqueue when called
++
++If FUNC is omitted, no function will be associated with work processing.
++This can be used to nullify a previous circle_cb_process invocation.
++
++Exit Status:
++Returns 0 unless an invalid function is given or an error occurs.
++$END
++
++/* Here is the circle_cb_process builtin. */
++int
++circle_cb_process_builtin (list)
++     WORD_LIST *list;
++{
++  return find_callback_function (list, &process_func);
++}
++
++$BUILTIN circle_begin
++$FUNCTION circle_begin_builtin
++$SHORT_DOC circle_begin
++Begin creation and processing of the distributed work queue.
++
++Exit Status:
++Returns 0 unless an error occurs.
++$END
++
++/* Here is the circle_begin builtin. */
++int
++circle_begin_builtin (list)
++     WORD_LIST *list;
++{
++  no_args (list);
++  CIRCLE_begin ();
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN circle_enqueue
++$FUNCTION circle_enqueue_builtin
++$SHORT_DOC circle_enqueue work
++Enqueue work onto the distributed queue.
++
++Arguments:
++  WORK          "Work" as represented by an arbitrary string of limited
++                size (generally around 4KB)
++
++Exit Status:
++Returns 0 unless an error occurs.
++$END
++
++/* Here is the circle_enqueue builtin. */
++int
++circle_enqueue_builtin (list)
++     WORD_LIST *list;
++{
++  char *work;          /* Work to perform */
++
++  /* Extract the work argument. */
++  YES_ARGS (list);
++  work = list->word->word;
++  list = list->next;
++  no_args (list);
++
++  /* Complain if we're not within a proper callback function. */
++  if (current_handle == NULL)
++    {
++      builtin_error (_("not within a Libcircle \"create\" or \"process\" 
callback function"));
++      return EXECUTION_FAILURE;
++    }
++
++  /* Enqueue the work. */
++  if (current_handle->enqueue (work) == -1)
++    return EXECUTION_FAILURE;
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN circle_dequeue
++$FUNCTION circle_dequeue_builtin
++$SHORT_DOC circle_dequeue var
++Dequeue work from the distributed queue into a variable.
++
++Arguments:
++  VAR           Variable in which to receive previously enqueued "work"
++
++Exit Status:
++Returns 0 unless an error occurs.
++$END
++
++/* Here is the circle_dequeue builtin. */
++int
++circle_dequeue_builtin (list)
++     WORD_LIST *list;
++{
++  char *varname;       /* Variable in which to store the work string */
++  char work[CIRCLE_MAX_STRING_LEN+1];  /* Work to perform */
++
++  /* Extract the variable-name argument. */
++  YES_ARGS (list);
++  varname = list->word->word;
++  list = list->next;
++  no_args (list);
++
++  /* Complain if we're not within a callback function. */
++  if (current_handle == NULL)
++    {
++      builtin_error (_("not within a Libcircle callback function"));
++      return EXECUTION_FAILURE;
++    }
++
++  /* Dequeue the work and bind it to the given variable. */
++  if (current_handle->dequeue (work) == -1)
++    return EXECUTION_FAILURE;
++  bind_variable (varname, work, 0);
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN circle_enable_logging
++$FUNCTION circle_enable_logging_builtin
++$SHORT_DOC circle_enable_logging log_level
++Change Libcircle's logging verbosity
++
++Arguments:
++  LOG_LEVEL     "fatal", "error", "warning", "info", or "debug"
++
++Exit Status:
++Returns 0 unless an invalid option is given.
++$END
++/*'*/
++
++/* Here is the circle_enable_logging builtin. */
++int
++circle_enable_logging_builtin (list)
++     WORD_LIST *list;
++{
++  char *word;                   /* One argument */
++  CIRCLE_loglevel loglevel;     /* Level to set */
++
++  /* Parse the log level. */
++  YES_ARGS (list);
++  word = list->word->word;
++  if (!strcmp (word, "fatal"))
++    loglevel = CIRCLE_LOG_FATAL;
++  else if (!strcmp (word, "error"))
++    loglevel = CIRCLE_LOG_ERR;
++  else if (!strcmp (word, "warning"))
++    loglevel = CIRCLE_LOG_WARN;
++  else if (!strcmp (word, "info"))
++    loglevel = CIRCLE_LOG_INFO;
++  else if (!strcmp (word, "debug"))
++    loglevel = CIRCLE_LOG_DBG;
++  else
++    {
++      builtin_error (_("invalid log level \"%s\""), word);
++      return (EXECUTION_FAILURE);
++    }
++
++  /* Set the log level. */
++  CIRCLE_enable_logging (loglevel);
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN circle_abort
++$FUNCTION circle_abort_builtin
++$SHORT_DOC circle_abort
++Terminate queue processing.
++
++Exit Status:
++Returns 0 unless an error occurs.
++$END
++
++/* Here is the circle_abort builtin. */
++int
++circle_abort_builtin (list)
++     WORD_LIST *list;
++{
++  no_args (list);
++  CIRCLE_abort ();
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN circle_checkpoint
++$FUNCTION circle_checkpoint_builtin
++$SHORT_DOC circle_checkpoint
++Checkpoint a work queue to disk.
++
++Write a file called circle${circle_rank}.txt containing the current
++queue state of rank ${circle_rank}.  On a later run, a worker can
++invoke circle_read_restarts to repopulate its queue from such a
++checkpoint file.
++
++Exit Status:
++Returns 0 unless an error occurs.
++$END
++/*'*/
++
++/* Here is the circle_checkpoint builtin. */
++int
++circle_checkpoint_builtin (list)
++     WORD_LIST *list;
++{
++  no_args (list);
++  CIRCLE_checkpoint ();
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN circle_read_restarts
++$FUNCTION circle_read_restarts_builtin
++$SHORT_DOC circle_read_restarts
++Repopulate a work queue from a disk checkpoint.
++
++Read queue contents from a file called circle${circle_rank}.txt, which
++was previously produced by circle_checkpoint.
++
++Exit Status:
++Returns 0 unless an error occurs.
++$END
++/*'*/
++
++/* Here is the circle_read_restarts builtin. */
++int
++circle_read_restarts_builtin (list)
++     WORD_LIST *list;
++{
++  no_args (list);
++  CIRCLE_read_restarts ();
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN circle_cb_reduce_init
++$FUNCTION circle_cb_reduce_init_builtin
++$SHORT_DOC circle_cb_reduce_init [func]
++Register a function that will initiate a reduction operation.
++
++Arguments:
++  FUNC          User-defined callback function that will invoke
++                circle_reduce when called
++
++FUNC will be invoked on all ranks.
++
++If FUNC is omitted, no function will be associated with reduction
++initialization.  This can be used to nullify a previous
++circle_cb_reduce_init invocation.
++
++Exit Status:
++Returns 0 unless an invalid function is given or an error occurs.
++$END
++
++/* Here is the circle_cb_reduce_init builtin. */
++int
++circle_cb_reduce_init_builtin (list)
++     WORD_LIST *list;
++{
++  return find_callback_function (list, &reduce_init_func);
++}
++
++$BUILTIN circle_cb_reduce_op
++$FUNCTION circle_cb_reduce_op_builtin
++$SHORT_DOC circle_cb_reduce_op [func]
++Register a function that will complete a reduction operation.
++
++Arguments:
++  FUNC          User-defined callback function that will receive
++                two items to reduce and invoke circle_reduce on
++                the reduced value
++
++If FUNC is omitted, no function will be associated with reduction
++execution.  This can be used to nullify a previous circle_cb_reduce_op
++invocation.
++
++Exit Status:
++Returns 0 unless an invalid function is given or an error occurs.
++$END
++
++/* Here is the circle_cb_reduce_op builtin. */
++int
++circle_cb_reduce_op_builtin (list)
++     WORD_LIST *list;
++{
++  return find_callback_function (list, &reduce_op_func);
++}
++
++$BUILTIN circle_cb_reduce_fini
++$FUNCTION circle_cb_reduce_fini_builtin
++$SHORT_DOC circle_cb_reduce_fini [func]
++Register a function that will complete a reduction operation.
++
++Arguments:
++  FUNC          User-defined callback function that will receive
++                the final reduced data
++
++If FUNC is omitted, no function will be associated with reduction
++completion.  This can be used to nullify a previous
++circle_cb_reduce_fini invocation.
++
++Libcircle guarantees that FUNC will be invoked only on rank 0.
++
++Exit Status:
++Returns 0 unless an invalid function is given or an error occurs.
++$END
++
++/* Here is the circle_cb_reduce_fini builtin. */
++int
++circle_cb_reduce_fini_builtin (list)
++     WORD_LIST *list;
++{
++  return find_callback_function (list, &reduce_fini_func);
++}
++
++$BUILTIN circle_reduce
++$FUNCTION circle_reduce_builtin
++$SHORT_DOC circle_reduce work
++Seed the next phase of a reduction operation
++
++Arguments:
++  WORK          "Work" as represented by an arbitrary string of limited
++                size (generally around 4KB)
++
++This function should be called both by the callback function
++registered with circle_reduce_init and the callback function
++registered with circle_reduce_op.
++
++Exit Status:
++Returns 0 unless an error occurs.
++$END
++
++/* Here is the circle_reduce builtin. */
++int
++circle_reduce_builtin (list)
++     WORD_LIST *list;
++{
++  char *work;          /* Work to perform */
++
++  /* Extract the work argument. */
++  YES_ARGS (list);
++  work = list->word->word;
++  list = list->next;
++  no_args (list);
++
++  /* Complain if we're not within a proper callback function. */
++  if (!within_reduction)
++    {
++      builtin_error (_("not within a Libcircle \"reduce_init\" or 
\"reduce_op\" callback function"));
++      return EXECUTION_FAILURE;
++    }
++
++  /* Reduce the work. */
++  CIRCLE_reduce (work, strlen (work));
++  return EXECUTION_SUCCESS;
++}
+diff -Naur bash-4.3/builtins/Makefile.in mpibash-4.3/builtins/Makefile.in
+--- bash-4.3/builtins/Makefile.in      2012-05-25 07:29:19.000000000 -0600
++++ mpibash-4.3/builtins/Makefile.in   2014-05-13 11:27:37.314100671 -0600
+@@ -141,7 +141,9 @@
+         $(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \
+         $(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \
+         $(srcdir)/reserved.def $(srcdir)/pushd.def $(srcdir)/shopt.def \
+-        $(srcdir)/printf.def $(srcdir)/complete.def $(srcdir)/mapfile.def
++        $(srcdir)/printf.def $(srcdir)/complete.def $(srcdir)/mapfile.def \
++        $(srcdir)/mpi.def \
++@CIRCLE@        $(srcdir)/circle.def
+ 
+ STATIC_SOURCE = common.c evalstring.c evalfile.c getopt.c bashgetopt.c \
+               getopt.h 
+@@ -153,7 +155,9 @@
+       jobs.o kill.o let.o mapfile.o \
+       pushd.o read.o return.o set.o setattr.o shift.o source.o \
+       suspend.o test.o times.o trap.o type.o ulimit.o umask.o \
+-      wait.o getopts.o shopt.o printf.o getopt.o bashgetopt.o complete.o
++      wait.o getopts.o shopt.o printf.o getopt.o bashgetopt.o complete.o \
++      mpi.o \
++@CIRCLE@      circle.o
+ 
+ CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h tmpbuiltins.c \
+       tmpbuiltins.h
+@@ -317,6 +321,8 @@
+ getopts.o: getopts.def
+ reserved.o: reserved.def
+ complete.o: complete.def
++@CIRCLE@ circle.o: circle.def
++mpi.o: mpi.def
+ 
+ # C files
+ bashgetopt.o: ../config.h $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
+@@ -644,6 +650,19 @@
+ mapfile.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
+ mapfile.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/variables.h 
$(topdir)/conftypes.h
+ mapfile.o: $(topdir)/arrayfunc.h ../pathnames.h
++@CIRCLE@ circle.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h 
$(topdir)/error.h
++@CIRCLE@ circle.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/subst.h 
$(topdir)/externs.h
++@CIRCLE@ circle.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h 
$(topdir)/make_cmd.h
++@CIRCLE@ circle.o: $(topdir)/shell.h $(topdir)/syntax.h 
$(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
++@CIRCLE@ circle.o: $(BASHINCDIR)/maxpath.h ../pathnames.h
++mpi.o: ../config.h ../config-top.h ../config-bot.h ../bashintl.h
++mpi.o: ../include/gettext.h ../shell.h ../config.h ../bashjmp.h
++mpi.o: ../include/posixjmp.h ../command.h ../syntax.h ../general.h
++mpi.o: ../bashtypes.h ../include/chartypes.h ../xmalloc.h ../bashansi.h
++mpi.o: ../error.h ../variables.h ../array.h ../assoc.h ../hashlib.h
++mpi.o: ../conftypes.h ../arrayfunc.h ../quit.h ../sig.h ../include/maxpath.h
++mpi.o: ../unwind_prot.h ../dispose_cmd.h ../make_cmd.h ../include/ocache.h
++mpi.o: ../subst.h ../pathnames.h ../externs.h common.h bashgetopt.h
+ 
+ #bind.o: $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)readline.h $(RL_LIBSRC)keymaps.h
+ 
+diff -Naur bash-4.3/builtins/mpi.def mpibash-4.3/builtins/mpi.def
+--- bash-4.3/builtins/mpi.def  1969-12-31 17:00:00.000000000 -0700
++++ mpibash-4.3/builtins/mpi.def       2014-05-13 11:27:37.314100671 -0600
+@@ -0,0 +1,744 @@
++This file is mpi.def, from which is created mpi.c.
++It implements all of the "mpi_*" builtins in Bash.
++
++$PRODUCES mpi.c
++
++#include <config.h>
++
++#include <stdio.h>
++#if defined (HAVE_UNISTD_H)
++#  ifdef _MINIX
++#    include <sys/types.h>
++#  endif
++#  include <unistd.h>
++#endif
++
++#include "../bashintl.h"
++#include "../shell.h"
++#include "common.h"
++#include "bashgetopt.h"
++#include <mpi.h>
++
++extern int running_trap, trap_saved_exit_value;
++
++/* Keep track of who we are within MPI_COMM_WORLD. */
++static int mpi_rank;
++static int mpi_num_ranks;
++
++/* Try an MPI operation.  Return with an error message on failure. */
++#define MPI_TRY(STMT)                           \
++  do                                            \
++    {                                           \
++      int mpierr;                               \
++      mpierr = STMT;                            \
++      if (mpierr != MPI_SUCCESS)                \
++        return report_mpi_error (mpierr);       \
++    }                                           \
++  while (0)
++
++/* Return with a usage message if no arguments remain. */
++#define YES_ARGS(LIST)                          \
++  if ((LIST) == 0)                              \
++    {                                           \
++      builtin_usage ();                         \
++      return (EX_USAGE);                        \
++    }
++
++/* Return with an error message if a given variable is read-only or if
++ * we can't write to it for any other reason (e.g., it's defined as a
++ * function). */
++#define REQUIRE_WRITABLE(NAME)                                          \
++  do                                                                    \
++    {                                                                   \
++      SHELL_VAR *bindvar = find_shell_variable (NAME);                  \
++      if (bindvar)                                                      \
++        {                                                               \
++          if (readonly_p (bindvar))                                     \
++            {                                                           \
++              err_readonly (NAME);                                      \
++              return (EXECUTION_FAILURE);                               \
++            }                                                           \
++          if (unbind_variable (NAME) == -1)                             \
++            {                                                           \
++              builtin_error ("Failed to write to variable %s", NAME);   \
++              return (EXECUTION_FAILURE);                               \
++            }                                                           \
++        }                                                               \
++    }                                                                   \
++  while (0)
++
++/* Initialize MPI. */
++void
++initialize_mpi (argc, argv)
++     int argc;
++     char **argv;
++{
++  int init_done;
++
++  MPI_Initialized (&init_done);
++  if (!init_done)
++    MPI_Init (&argc, &argv);
++  MPI_Errhandler_set (MPI_COMM_WORLD, MPI_ERRORS_RETURN);
++  MPI_Comm_rank (MPI_COMM_WORLD, &mpi_rank);
++  MPI_Comm_size (MPI_COMM_WORLD, &mpi_num_ranks);
++}
++
++/* Finalize MPI. */
++void
++finalize_mpi ()
++{
++  MPI_Finalize ();
++}
++
++/* Parse an operation name into an MPI_Op.  Return 1 on success, 0 on
++ * failure. */
++static int
++parse_operation (char *name, MPI_Op *op)
++{
++  /* Define a mapping from operator names to MPI_Op values. */
++  typedef struct {
++    char *name;        /* Operation name (e.g., "sum") */
++    MPI_Op value;      /* Operation value (e.g., MPI_SUM) */
++  } opname2value_t;
++  static opname2value_t oplist[] = {
++    {"max",    MPI_MAX},
++    {"min",    MPI_MIN},
++    {"sum",    MPI_SUM},
++    {"prod",   MPI_PROD},
++    {"land",   MPI_LAND},
++    {"band",   MPI_BAND},
++    {"lor",    MPI_LOR},
++    {"bor",    MPI_BOR},
++    {"lxor",   MPI_LXOR},
++    {"bxor",   MPI_BXOR},
++    {"maxloc", MPI_MAXLOC},
++    {"minloc", MPI_MINLOC}
++  };
++  size_t i;
++
++  for (i = 0; i < sizeof(oplist)/sizeof(opname2value_t); i++)
++    if (!strcmp(name, oplist[i].name))
++      {
++        *op = oplist[i].value;
++        if (i > 0)
++          {
++            /* As a performance optimization, bubble up the value we
++             * just found. */
++            opname2value_t prev = oplist[i - 1];
++            oplist[i - 1] = oplist[i];
++            oplist[i] = prev;
++          }
++        return 1;
++      }
++  return 0;
++}
++
++/* Report an error to the user and return EXECUTION_FAILURE. */
++static int
++report_mpi_error (mpierr)
++     int mpierr;
++{
++  char errstr[MPI_MAX_ERROR_STRING];
++  int errstrlen;
++
++  MPI_Error_string (mpierr, errstr, &errstrlen);
++  builtin_error ("%s", errstr);
++  return EXECUTION_FAILURE;
++}
++
++/* Perform the same operation as bind_variable, but with VALUE being a
++ * number, not a string. */
++static SHELL_VAR *
++bind_variable_number (name, value, flags)
++     const char *name;
++     long value;
++     int flags;
++{
++  char numstr[25];    /* String version of VALUE */
++
++  sprintf (numstr, "%ld", value);
++  return bind_variable (name, numstr, flags);
++}
++
++/* Perform the same operation as bind_array_variable, but with VALUE
++ * being a number, not a string. */
++static SHELL_VAR *
++bind_array_variable_number (name, ind, value, flags)
++     char *name;
++     arrayind_t ind;
++     long value;
++     int flags;
++{
++  char numstr[25];    /* String version of VALUE */
++
++  sprintf (numstr, "%ld", value);
++  return bind_array_variable (name, ind, numstr, flags);
++}
++
++/* Define a reduction-type function (allreduce, scan, exscan, etc.). */
++typedef int (*reduction_func_t)(void *, void *, int, MPI_Datatype, MPI_Op, 
MPI_Comm);
++
++/* Perform any reduction-type operation (allreduce, scan, exscan, etc.). */
++static int
++reduction_like (list, funcname, func)
++     WORD_LIST *list;
++     char *funcname;
++     reduction_func_t func;
++{
++  char *word;                   /* One argument */
++  struct {
++    long int value;             /* Reduced value */
++    int rank;                   /* Rank associated with the above */
++  } number, result;
++  MPI_Op operation = MPI_SUM;   /* Operation to perform */
++  char *varname;                /* Name of the variable to bind the results 
to */
++  intmax_t n;
++  int i;
++
++  /* Parse "-O OPERATION" (optional), where OPERATION is a reduction
++   * operation. */
++  YES_ARGS (list);
++  word = list->word->word;
++  if (ISOPTION (word, 'O'))
++    {
++      list = list->next;
++      if (list == 0)
++        {
++          sh_needarg (funcname);
++          return (EX_USAGE);
++        }
++      word = list->word->word;
++      if (!parse_operation (word, &operation))
++        {
++          sh_invalidopt ("-O");
++          return (EX_USAGE);
++        }
++      list = list->next;
++    }
++
++  /* Parse the argument, which must be a number. */
++  YES_ARGS (list);
++  word = list->word->word;
++  if (!legal_number (word, &n))
++    {
++      sh_neednumarg (funcname);
++      return (EX_USAGE);
++    }
++  number.value = (long int) n;
++  number.rank = mpi_rank;
++  list = list->next;
++
++  /* Parse the target variable, which must not be read-only. */
++  YES_ARGS (list);
++  varname = list->word->word;
++  if (mpi_rank != 0 || func != MPI_Exscan)
++    REQUIRE_WRITABLE (varname);
++  list = list->next;
++  no_args (list);
++
++  /* Perform the reduction operation.  Bind the given array variable
++   * to the result and, for minloc/maxloc, the associated rank. */
++  if (mpi_rank != 0 || func != MPI_Exscan) {
++    bind_array_variable (varname, 0, "", 0);
++    bind_array_variable (varname, 1, "", 0);
++  }
++  if (operation == MPI_MINLOC || operation == MPI_MAXLOC)
++    {
++      MPI_TRY (func (&number, &result, 1, MPI_LONG_INT, operation, 
MPI_COMM_WORLD));
++      if (mpi_rank != 0 || func != MPI_Exscan)
++      bind_array_variable_number (varname, 1, result.rank, 0);
++    }
++  else
++    MPI_TRY (func (&number.value, &result.value, 1, MPI_LONG, operation, 
MPI_COMM_WORLD));
++  if (mpi_rank != 0 || func != MPI_Exscan)
++    bind_array_variable_number (varname, 0, result.value, 0);
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN mpi_comm_rank
++$FUNCTION mpi_comm_rank_builtin
++$SHORT_DOC mpi_comm_rank name
++Return the process's rank in the MPI job.
++
++Arguments:
++  NAME          Scalar variable in which to receive the rank
++
++Exit Status:
++Returns 0 unless an invalid option is given.
++$END
++/*'*/
++
++/* Here is the mpi_comm_rank builtin. */
++int
++mpi_comm_rank_builtin (list)
++     WORD_LIST *list;
++{
++  char *varname;         /* Name of the variable to bind the results to */
++
++  YES_ARGS (list);
++  varname = list->word->word;
++  REQUIRE_WRITABLE (varname);
++  list = list->next;
++  no_args (list);
++  bind_variable_number (varname, mpi_rank, 0);
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN mpi_comm_size
++$FUNCTION mpi_comm_size_builtin
++$SHORT_DOC mpi_comm_size name
++Return the total number of ranks in the MPI job.
++
++Arguments:
++  NAME          Scalar variable in which to receive the number of ranks
++
++Exit Status:
++Returns 0 unless an invalid option is given.
++$END
++
++/* Here is the mpi_comm_size builtin. */
++int
++mpi_comm_size_builtin (list)
++     WORD_LIST *list;
++{
++  char *varname;         /* Name of the variable to bind the results to */
++
++  YES_ARGS (list);
++  varname = list->word->word;
++  REQUIRE_WRITABLE (varname);
++  list = list->next;
++  no_args (list);
++  bind_variable_number (varname, mpi_num_ranks, 0);
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN mpi_abort
++$FUNCTION mpi_abort_builtin
++$SHORT_DOC mpi_abort [n]
++Abort all processes in the MPI job and exit the shell.
++
++Exits not only the caller's shell (with a status of N) but also all
++remote shells that are part of the same MPI job.  If N is omitted, the
++exit status is that of the last command executed.
++
++This command should be used only in extreme circumstances.  It is
++better for each process to exit normally on its own.
++$END
++/*'*/
++
++/* Here is the mpi_abort builtin. */
++int
++mpi_abort_builtin (list)
++     WORD_LIST *list;
++{
++  int exit_value;
++
++  exit_value = (running_trap == 1 && list == 0) ? trap_saved_exit_value : 
get_exitstat (list);  /* Copied from exit.def */
++  MPI_TRY (MPI_Abort (MPI_COMM_WORLD, exit_value));
++  return EXECUTION_FAILURE;
++}
++
++$BUILTIN mpi_send
++$FUNCTION mpi_send_builtin
++$SHORT_DOC mpi_send [-t tag] rank message
++Send a message to a remote process in the same MPI job.
++
++Options:
++  -t TAG        Send the message using tag TAG (default: 0).  TAG must
++                be a nonnegative integer.
++
++Arguments:
++  RANK          Whom to send the message to.  RANK must be an integer in
++                the range [0, $(mpi_comm_size)-1].
++
++  MESSAGE       String to send to rank RANK.
++
++Exit Status:
++Returns 0 unless an invalid option is given or an error occurs.
++$END
++
++/* Here is the mpi_send builtin. */
++int
++mpi_send_builtin (list)
++     WORD_LIST *list;
++{
++  char *word;              /* One argument */
++  intmax_t target_rank;    /* MPI target rank */
++  char *message;           /* Message to send to rank target_rank */
++  intmax_t tag = 0;        /* Message tag to use */
++
++  /* Parse "-t TAG" (optional), where TAG is a number or "any". */
++  YES_ARGS (list);
++  word = list->word->word;
++  if (ISOPTION (word, 't'))
++    {
++      list = list->next;
++      if (list == 0)
++        {
++          sh_needarg ("mpi_recv");
++          return (EX_USAGE);
++        }
++      word = list->word->word;
++      if (!legal_number (word, &tag))
++        {
++          sh_neednumarg ("-t");
++          return (EX_USAGE);
++        }
++      list = list->next;
++    }
++  else if (*word == '-')
++    {
++      sh_invalidopt (word);
++      builtin_usage ();
++      return (EX_USAGE);
++    }
++
++  /* Parse the target rank, which must be a number. */
++  YES_ARGS (list);
++  word = list->word->word;
++  if (!legal_number (word, &target_rank))
++    {
++      builtin_error (_("mpi_send: numeric rank required"));
++      return (EX_USAGE);
++    }
++  list = list->next;
++
++  /* Parse the message to send. */
++  YES_ARGS (list);
++  message = list->word->word;
++  list = list->next;
++  no_args (list);
++
++  /* Send the message. */
++  MPI_TRY (MPI_Send (message, strlen(message)+1, MPI_BYTE, (int)target_rank, 
(int)tag, MPI_COMM_WORLD));
++  return EXECUTION_SUCCESS;
++}
++
++
++$BUILTIN mpi_recv
++$FUNCTION mpi_recv_builtin
++$SHORT_DOC mpi_recv [-t tag] rank name
++Receive a message from a remote process in the same MPI job.
++
++Options:
++  -t TAG        Receive only messages sent using tag TAG (default: 0).
++                TAG must be either a nonnegative integer or the string
++                "any" to receive messages sent using any tag.
++
++Arguments:
++  RANK          Receive only messages sent from sender RANK.  RANK
++                must either be in the range [0, $(mpi_comm_size)-1] or
++                be the string "any" to receive messages from any sender.
++
++  NAME          Array variable in which to receive the message, sender
++                rank, and tag.
++
++Exit Status:
++Returns 0 unless an invalid option is given or an error occurs.
++$END
++
++/* Here is the mpi_recv builtin. */
++int
++mpi_recv_builtin (list)
++     WORD_LIST *list;
++{
++  char *word;            /* One argument */
++  intmax_t source_rank;  /* MPI source rank */
++  char *endptr;          /* Used for parsing strings into numbers */
++  MPI_Status status;     /* Status of an MPI operation */
++  int count;             /* Message length in bytes */
++  intmax_t tag = 0;      /* Message tag to use */
++  char *varname;         /* Name of the variable to bind the results to */
++  static char *message = NULL;  /* Message received from MPI */
++  static size_t alloced = 0;    /* Number of bytes allocated for the above */
++  int opt;               /* Parsed option */
++
++  /* Parse any options provided. */
++  reset_internal_getopt ();
++  while ((opt = internal_getopt (list, "t:")) != -1)
++    {
++      switch (opt)
++        {
++          case 't':
++            if (!strcmp (list_optarg, "any"))
++              tag = MPI_ANY_TAG;
++            else if (!legal_number (list_optarg, &tag))
++              {
++                builtin_error (_("-t: numeric argument or \"any\" required"));
++                return (EX_USAGE);
++              }
++            break;
++
++          default:
++            sh_invalidopt (word);
++            builtin_usage ();
++            return (EX_USAGE);
++        }
++    }
++  list = loptend;
++
++  /* Parse the source rank, which must be a number or "any". */
++  YES_ARGS (list);
++  word = list->word->word;
++  if (!legal_number (word, &source_rank))
++    {
++      if (!strcmp (word, "any"))
++        source_rank = MPI_ANY_SOURCE;
++      else
++        {
++          builtin_error (_("mpi_recv: numeric rank or \"any\" required"));
++          return (EX_USAGE);
++        }
++    }
++  list = list->next;
++
++  /* Parse the target variable, which must not be read-only. */
++  YES_ARGS (list);
++  varname = list->word->word;
++  REQUIRE_WRITABLE (varname);
++  list = list->next;
++  no_args (list);
++
++  /* Receive a message.  Because we don't know long the message will
++   * be, we first probe to get the length. */
++  MPI_TRY (MPI_Probe ((int)source_rank, (int)tag, MPI_COMM_WORLD, &status));
++  MPI_TRY (MPI_Get_count (&status, MPI_BYTE, &count));
++  if (alloced < count)
++    {
++      message = xrealloc (message, count);
++      alloced = count;
++    }
++  MPI_TRY (MPI_Recv (message, count, MPI_BYTE, status.MPI_SOURCE, 
status.MPI_TAG, MPI_COMM_WORLD, &status));
++  bind_array_variable (varname, 0, message, 0);
++  bind_array_variable_number (varname, 1, status.MPI_SOURCE, 0);
++  bind_array_variable_number (varname, 2, status.MPI_TAG, 0);
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN mpi_barrier
++$FUNCTION mpi_barrier_builtin
++$SHORT_DOC mpi_barrier
++Synchronizes all of the processes in the MPI job.
++
++No process will return from mpi_barrier until all processes have
++called mpi_barrier.
++
++Exit Status:
++Returns 0 unless an invalid option is given or an error occurs.
++$END
++
++/* Here is the mpi_barrier builtin. */
++int
++mpi_barrier_builtin (list)
++     WORD_LIST *list;
++{
++  no_args (list);
++  MPI_TRY (MPI_Barrier (MPI_COMM_WORLD));
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN mpi_bcast
++$FUNCTION mpi_bcast_builtin
++$SHORT_DOC mpi_bcast [message] name
++Broadcast a message to all processes in the same MPI job.
++
++Arguments:
++  MESSAGE       String to broadcast from one process to all the others.
++
++  NAME          Scalar variable in which to receive the broadcast message.
++
++Exactly one process in the MPI job must specify a message to
++broadcast.  No process will return from mpi_bcast until all processes
++have called mpi_bcast.
++
++Exit Status:
++Returns 0 unless an invalid option is given or an error occurs.
++$END
++
++/* Here is the mpi_bcast builtin. */
++int
++mpi_bcast_builtin (list)
++     WORD_LIST *list;
++{
++  char *word;            /* One argument */
++  int root;              /* MPI root rank */
++  char *root_message;    /* Message to broadcast */
++  int msglen;            /* Length in bytes of the above (including the NULL 
byte) */
++  char *varname;         /* Name of the variable to bind the results to */
++  static int *all_lengths = NULL;   /* List of every rank's msglen */
++  static char *message = NULL;      /* Message received from the root */
++  static int alloced = 0;           /* Bytes allocated for the above */
++  int i;
++
++  /* Parse the optional message and target variable, which must not be
++   * read-only. */
++  YES_ARGS (list);
++  if (list->next == NULL)
++    {
++      /* Non-root */
++      root_message = NULL;
++      msglen = -1;
++    }
++  else
++    {
++      /* Root */
++      root_message = list->word->word;
++      msglen = (int) strlen(root_message) + 1;
++      list = list->next;
++    }
++  varname = list->word->word;
++  REQUIRE_WRITABLE (varname);
++  list = list->next;
++  no_args (list);
++
++  /* Acquire global agreement on the root and the message size. */
++  if (all_lengths == NULL)
++    all_lengths = xmalloc (mpi_num_ranks*sizeof(int));
++  MPI_TRY (MPI_Allgather (&msglen, 1, MPI_INT, all_lengths, 1, MPI_INT, 
MPI_COMM_WORLD));
++  root = -1;
++  for (i = 0; i < mpi_num_ranks; i++)
++    {
++      if (all_lengths[i] == -1)
++        continue;
++      if (root != -1)
++        {
++          builtin_error (_("mpi_bcast: more than one process specified a 
message"));
++          return (EXECUTION_FAILURE);
++        }
++      root = i;
++      msglen = all_lengths[i];
++    }
++  if (root == -1)
++    {
++      builtin_error (_("mpi_bcast: no process specified a message"));
++      return (EXECUTION_FAILURE);
++    }
++
++  /* Broadcast the message. */
++  if (mpi_rank == root)
++    {
++      MPI_TRY (MPI_Bcast (root_message, msglen, MPI_BYTE, root, 
MPI_COMM_WORLD));
++      bind_variable (varname, root_message, 0);
++    }
++  else
++    {
++      if (alloced < msglen)
++        {
++          message = xrealloc (message, msglen);
++          alloced = msglen;
++        }
++      MPI_TRY (MPI_Bcast (message, msglen, MPI_BYTE, root, MPI_COMM_WORLD));
++      bind_variable (varname, message, 0);
++    }
++  return EXECUTION_SUCCESS;
++}
++
++$BUILTIN mpi_scan
++$FUNCTION mpi_scan_builtin
++$SHORT_DOC mpi_scan number name
++Perform an inclusive scan across all processes in the same MPI job.
++
++ -O OPERATION   Operation to perform.  Must be one of "max", "min",
++                "sum", "prod", "land", "band", "lor", "bor", "lxor",
++                "bxor", "maxloc", or "minloc" (default: "sum").
++
++Arguments:
++  NUMBER        Integer to use in the scan operation.
++
++  NAME          Array variable in which to receive the result and, in
++                the case of maxloc and minloc, the associated rank.
++
++In an inclusive-scan operation, each process i presents a number,
++a[i].  Once all processes in the MPI job have presented their number,
++the command returns a[0] to rank 0, a[0]+a[1] to rank 1,
++a[0]+a[1]+a[2] to rank 2, and so forth.  The -O option enables "+" to
++be replaced with other operations.
++
++Inclusive scans can be useful for assigning a unique index to each
++process in the MPI job.
++
++Exit Status:
++Returns 0 unless an invalid option is given or an error occurs.
++$END
++
++/* Here is the mpi_scan builtin. */
++int
++mpi_scan_builtin (list)
++     WORD_LIST *list;
++{
++  return reduction_like (list, "mpi_scan", MPI_Scan);
++}
++
++$BUILTIN mpi_exscan
++$FUNCTION mpi_exscan_builtin
++$SHORT_DOC mpi_exscan number name
++Perform an exclusive scan across all processes in the same MPI job.
++
++ -O OPERATION   Operation to perform.  Must be one of "max", "min",
++                "sum", "prod", "land", "band", "lor", "bor", "lxor",
++                "bxor", "maxloc", or "minloc" (default: "sum").
++
++Arguments:
++  NUMBER        Integer to use in the scan operation.
++
++  NAME          Array variable in which to receive the result and, in
++                the case of maxloc and minloc, the associated rank.
++
++In a exclusive-scan operation, each process i presents a number, a[i].
++Once all processes in the MPI job have presented their number, the
++command assigns a[0] to NAME on rank 1, a[0]+a[1] to NAME on rank 2,
++a[0]+a[1]+a[2] to NAME on rank 3, and so forth.  No assignment is
++performed on rank 0.  The -O option enables "+" to be replaced with
++other operations.
++
++Exclusive scans can be useful for assigning a unique index to each
++process in the MPI job.
++
++Exit Status:
++Returns 0 unless an invalid option is given or an error occurs.
++$END
++
++/* Here is the mpi_exscan builtin. */
++int
++mpi_exscan_builtin (list)
++     WORD_LIST *list;
++{
++  return reduction_like (list, "mpi_exscan", MPI_Exscan);
++}
++
++$BUILTIN mpi_allreduce
++$FUNCTION mpi_allreduce_builtin
++$SHORT_DOC mpi_allreduce number name
++Reduce numbers from all processes in an MPI job to a single number.
++
++Options:
++
++ -O OPERATION   Operation to perform.  Must be one of "max", "min",
++                "sum", "prod", "land", "band", "lor", "bor", "lxor",
++                "bxor", "maxloc", or "minloc" (default: "sum").
++
++Arguments:
++  NUMBER        Integer to use in the allreduce operation.
++
++  NAME          Array variable in which to receive the result and, in
++                the case of maxloc and minloc, the associated rank.
++
++In an all-reduce operation, each process i presents a number, a[i].
++Once all processes in the MPI job have presented their number, the
++command returns a[0]+a[1]+...+a[n-1] to all ranks.  The -O option
++enables "+" to be replaced with other operations.
++
++All-reduces can be useful for reaching global agreement (e.g., of a
++termination condition).
++
++Exit Status:
++Returns 0 unless an invalid option is given or an error occurs.
++$END
++
++/* Here is the mpi_allreduce builtin. */
++int
++mpi_allreduce_builtin (list)
++     WORD_LIST *list;
++{
++  return reduction_like (list, "mpi_allreduce", MPI_Allreduce);
++}
+diff -Naur bash-4.3/config.h.in mpibash-4.3/config.h.in
+--- bash-4.3/config.h.in       2013-06-29 15:35:33.000000000 -0600
++++ mpibash-4.3/config.h.in    2014-05-13 11:27:37.314100671 -0600
+@@ -1147,6 +1147,12 @@
+ /* Define if you have the `__argz_stringify' function. */
+ #undef HAVE___ARGZ_STRINGIFY
+ 
++/* Define if you have both the <libcircle.h> header file and the libcircle 
library. */
++#undef HAVE_LIBCIRCLE
++
++/* Define if you have the `CIRCLE_cb_reduce_op' function. */
++#undef HAVE_CIRCLE_CB_REDUCE_OP
++
+ /* End additions for lib/intl */
+ 
+ #include "config-bot.h"
+diff -Naur bash-4.3/configure.ac mpibash-4.3/configure.ac
+--- bash-4.3/configure.ac      2014-02-11 08:37:53.000000000 -0700
++++ mpibash-4.3/configure.ac   2014-05-13 11:27:37.302100179 -0600
+@@ -24,7 +24,7 @@
+ AC_REVISION([for Bash 4.3, version 4.063])dnl
+ 
+ define(bashvers, 4.3)
+-define(relstatus, release)
++define(relstatus, MPI)
+ 
+ AC_INIT([bash], bashvers-relstatus, [[email protected]])
+ 
+@@ -813,6 +813,21 @@
+     fi
+ ])
+ 
++dnl Ensure that we can find an MPI library.
++AC_CHECK_FUNCS([MPI_Init], [], [
++  AC_MSG_ERROR([Cannot continue without MPI.  Consider specifying 
CC=mpicc.])])
++
++dnl If we have Libcircle, use it, too.
++AC_SEARCH_LIBS([CIRCLE_cb_create], [circle], 
[AC_CHECK_HEADERS([libcircle.h])])
++if test "x$ac_cv_header_libcircle_h" = xyes; then
++  libcircle_make_prefix=""
++  AC_DEFINE([HAVE_LIBCIRCLE], [1], [Define if you have the Libcircle header 
and library.])
++  AC_CHECK_FUNCS([CIRCLE_cb_reduce_op])
++else
++  libcircle_make_prefix="#"
++fi
++AC_SUBST([CIRCLE], [$libcircle_make_prefix])
++
+ BASH_CHECK_DECL(strtoimax)
+ BASH_CHECK_DECL(strtol)
+ BASH_CHECK_DECL(strtoll)
+diff -Naur bash-4.3/Makefile.in mpibash-4.3/Makefile.in
+--- bash-4.3/Makefile.in       2014-01-25 14:27:30.000000000 -0700
++++ mpibash-4.3/Makefile.in    2014-05-13 11:27:37.314100671 -0600
+@@ -104,7 +104,7 @@
+ VERSPROG = bashversion$(EXEEXT)
+ VERSOBJ = bashversion.$(OBJEXT)
+ 
+-Program = bash$(EXEEXT)
++Program = mpibash$(EXEEXT)
+ Version = @BASHVERS@
+ PatchLevel = `$(BUILD_DIR)/$(VERSPROG) -p`
+ RELSTATUS = @RELSTATUS@
+diff -Naur bash-4.3/shell.c mpibash-4.3/shell.c
+--- bash-4.3/shell.c   2014-01-14 06:04:32.000000000 -0700
++++ mpibash-4.3/shell.c        2014-05-13 11:27:37.314100671 -0600
+@@ -107,6 +107,13 @@
+ extern char *primary_prompt, *secondary_prompt;
+ extern char *this_command_name;
+ 
++extern void initialize_mpi __P((int, char **));
++extern void finalize_mpi __P((void));
++#ifdef HAVE_LIBCIRCLE
++extern void initialize_libcircle __P((int, char **));
++extern void finalize_libcircle __P((void));
++#endif
++
+ /* Non-zero means that this shell has already been run; i.e. you should
+    call shell_reinitialize () if you need to start afresh. */
+ int shell_initialized = 0;
+@@ -324,7 +331,7 @@
+ static void init_interactive_script __P((void));
+ 
+ static void set_shell_name __P((char *));
+-static void shell_initialize __P((void));
++static void shell_initialize __P((int, char **));
+ static void shell_reinitialize __P((void));
+ 
+ static void show_shell_usage __P((FILE *, int));
+@@ -561,7 +568,7 @@
+ 
+   /* From here on in, the shell must be a normal functioning shell.
+      Variables from the environment are expected to be set, etc. */
+-  shell_initialize ();
++  shell_initialize (argc, argv);
+ 
+   set_default_lang ();
+   set_default_locale_vars ();
+@@ -941,6 +948,12 @@
+     end_job_control ();
+ #endif /* JOB_CONTROL */
+ 
++#ifdef HAVE_LIBCIRCLE
++  finalize_libcircle ();
++#else
++  finalize_mpi ();
++#endif
++
+   /* Always return the exit status of the last command to our parent. */
+   sh_exit (s);
+ }
+@@ -1691,7 +1704,9 @@
+ /* Do whatever is necessary to initialize the shell.
+    Put new initializations in here. */
+ static void
+-shell_initialize ()
++shell_initialize (argc, argv)
++     int argc;
++     char **argv;
+ {
+   char hostname[256];
+ 
+@@ -1760,6 +1775,17 @@
+   initialize_shell_options (privileged_mode||running_setuid);
+   initialize_bashopts (privileged_mode||running_setuid);
+ #endif
++
++  /* Initialize Libcircle and MPI. */
++#ifdef HAVE_LIBCIRCLE
++  initialize_libcircle (argc, argv);
++  initialize_mpi (argc, argv);
++  bind_variable ("libcircle", "yes", 0);
++#else
++  initialize_mpi (argc, argv);
++  bind_variable ("libcircle", "no", 0);
++#endif
++  bind_variable ("mpibash", "yes", 0);
+ }
+ 
+ /* Function called by main () when it appears that the shell has already

diff --git a/app-shells/mpibash/metadata.xml b/app-shells/mpibash/metadata.xml
new file mode 100644
index 0000000..8598dc9
--- /dev/null
+++ b/app-shells/mpibash/metadata.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd";>
+<pkgmetadata>
+<herd>base-system</herd>
+<use>
+  <flag name='bashlogger'>Log ALL commands typed into bash; should ONLY be
+    used in restricted environments such as honeypots</flag>
+  <flag name='mem-scramble'>Build with custom malloc/free overwriting 
allocated/freed memory</flag>
+  <flag name='net'>Enable /dev/tcp/host/port redirection</flag>
+  <flag name='plugins'>Add support for loading builtins at runtime via
+    'enable'</flag>
+</use>
+<upstream>
+  <remote-id type="cpe">cpe:/a:gnu:bash</remote-id>
+</upstream>
+</pkgmetadata>

diff --git a/app-shells/mpibash/mpibash-4.3_p24.ebuild 
b/app-shells/mpibash/mpibash-4.3_p24.ebuild
new file mode 100644
index 0000000..cf8e545
--- /dev/null
+++ b/app-shells/mpibash/mpibash-4.3_p24.ebuild
@@ -0,0 +1,259 @@
+# Copyright 1999-2014 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/app-shells/bash/bash-4.3_p24.ebuild,v 1.1 
2014/08/24 17:53:01 polynomial-c Exp $
+
+EAPI="4"
+
+inherit autotools eutils flag-o-matic toolchain-funcs multilib
+
+# Official patchlevel
+# See ftp://ftp.cwru.edu/pub/bash/bash-4.3-patches/
+PLEVEL=${PV##*_p}
+MY_PV=${PV/_p*}
+MY_PV=${MY_PV/_/-}
+MY_P=${PN#mpi}-${MY_PV}
+[[ ${PV} != *_p* ]] && PLEVEL=0
+patches() {
+       local opt=$1 plevel=${2:-${PLEVEL}} pn=${3:-${PN#mpi}} pv=${4:-${MY_PV}}
+       [[ ${plevel} -eq 0 ]] && return 1
+       eval set -- {1..${plevel}}
+       set -- $(printf "${pn}${pv/\.}-%03d " "$@")
+       if [[ ${opt} == -s ]] ; then
+               echo "${@/#/${DISTDIR}/}"
+       else
+               local u
+               for u in ftp://ftp.cwru.edu/pub/bash mirror://gnu/${pn} ; do
+                       printf "${u}/${pn}-${pv}-patches/%s " "$@"
+               done
+       fi
+}
+
+# The version of readline this bash normally ships with.
+READLINE_VER="6.3"
+
+DESCRIPTION="Parallel scripting right from the Bourne-Again Shell (Bash)"
+HOMEPAGE="http://www.ccs3.lanl.gov/~pakin/software/mpibash-4.3.html";
+SRC_URI="mirror://gnu/bash/${MY_P}.tar.gz $(patches)"
+[[ ${PV} == *_rc* ]] && SRC_URI+=" ftp://ftp.cwru.edu/pub/bash/${MY_P}.tar.gz";
+
+LICENSE="GPL-3"
+SLOT="0"
+#KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 
~sh ~sparc ~x86 ~amd64-fbsd ~sparc-fbsd ~x86-fbsd"
+IUSE="afs bashlogger examples mem-scramble +net nls plugins +readline vanilla"
+
+DEPEND=">=sys-libs/ncurses-5.2-r2
+       readline? ( >=sys-libs/readline-${READLINE_VER} )
+       nls? ( virtual/libintl )"
+RDEPEND="${DEPEND}
+       virtual/mpi
+       sys-cluster/libcircle
+       !<sys-apps/portage-2.1.6.7_p1
+       !<sys-apps/paludis-0.26.0_alpha5"
+# we only need yacc when the .y files get patched (bash42-005)
+DEPEND+=" virtual/yacc"
+
+S=${WORKDIR}/${MY_P}
+
+pkg_setup() {
+       if is-flag -malign-double ; then #7332
+               eerror "Detected bad CFLAGS '-malign-double'.  Do not use this"
+               eerror "as it breaks LFS (struct stat64) on x86."
+               die "remove -malign-double from your CFLAGS mr ricer"
+       fi
+       if use bashlogger ; then
+               ewarn "The logging patch should ONLY be used in restricted 
(i.e. honeypot) envs."
+               ewarn "This will log ALL output you enter into the shell, you 
have been warned."
+       fi
+}
+
+src_unpack() {
+       unpack ${MY_P}.tar.gz
+}
+
+src_prepare() {
+       # Include official patches
+       [[ ${PLEVEL} -gt 0 ]] && epatch $(patches -s)
+
+       # Clean out local libs so we know we use system ones w/releases.
+       if [[ ${PV} != *_rc* ]] ; then
+               rm -rf lib/{readline,termcap}/*
+               touch lib/{readline,termcap}/Makefile.in # for config.status
+               sed -ri -e 's:\$[(](RL|HIST)_LIBSRC[)]/[[:alpha:]]*.h::g' 
Makefile.in || die
+       fi
+
+       # Avoid regenerating docs after patches #407985
+       sed -i -r '/^(HS|RL)USER/s:=.*:=:' doc/Makefile.in || die
+       touch -r . doc/*
+
+       epatch "${FILESDIR}"/${PN#mpi}-4.3-compat-lvl.patch
+       epatch "${FILESDIR}"/${PN#mpi}-4.3-parse-time-keyword.patch
+       epatch "${FILESDIR}"/${PN#mpi}-4.3-append-process-segfault.patch
+       epatch "${FILESDIR}"/${PN}-4.3.patch
+
+       epatch_user
+
+       eautoconf
+}
+
+src_configure() {
+       local myconf=()
+
+       # For descriptions of these, see config-top.h
+       # bashrc/#26952 bash_logout/#90488 ssh/#24762
+       append-cppflags \
+               
-DDEFAULT_PATH_VALUE=\'\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"\'
 \
+               -DSTANDARD_UTILS_PATH=\'\"/bin:/usr/bin:/sbin:/usr/sbin\"\' \
+               -DSYS_BASHRC=\'\"/etc/bash/bashrc\"\' \
+               -DSYS_BASH_LOGOUT=\'\"/etc/bash/bash_logout\"\' \
+               -DNON_INTERACTIVE_LOGIN_SHELLS \
+               -DSSH_SOURCE_BASHRC \
+               $($(tc-getPKG_CONFIG) --cflags libcircle) \
+               $(use bashlogger && echo -DSYSLOG_HISTORY)
+
+       # Don't even think about building this statically without
+       # reading Bug 7714 first.  If you still build it statically,
+       # don't come crying to us with bugs ;).
+       #use static && export LDFLAGS="${LDFLAGS} -static"
+       use nls || myconf+=( --disable-nls )
+
+       # Historically, we always used the builtin readline, but since
+       # our handling of SONAME upgrades has gotten much more stable
+       # in the PM (and the readline ebuild itself preserves the old
+       # libs during upgrades), linking against the system copy should
+       # be safe.
+       # Exact cached version here doesn't really matter as long as it
+       # is at least what's in the DEPEND up above.
+       export ac_cv_rl_version=${READLINE_VER}
+
+       # Force linking with system curses ... the bundled termcap lib
+       # sucks bad compared to ncurses.  For the most part, ncurses
+       # is here because readline needs it.  But bash itself calls
+       # ncurses in one or two small places :(.
+
+       if [[ ${PV} != *_rc* ]] ; then
+               # Use system readline only with released versions.
+               myconf+=( --with-installed-readline=. )
+       fi
+
+       if use plugins; then
+               append-ldflags -Wl,-rpath,/usr/$(get_libdir)/bash
+       else
+               # Disable the plugins logic by hand since bash doesn't
+               # provide a way of doing it.
+               export ac_cv_func_dl{close,open,sym}=no \
+                       ac_cv_lib_dl_dlopen=no ac_cv_header_dlfcn_h=no
+               sed -i \
+                       -e '/LOCAL_LDFLAGS=/s:-rdynamic::' \
+                       configure || die
+       fi
+       tc-export AR #444070
+       LIBS="-lcircle" CC=mpicc \
+       econf \
+               --docdir='$(datarootdir)'/doc/${PF} \
+               --htmldir='$(docdir)/html' \
+               --with-curses \
+               $(use_with afs) \
+               $(use_enable net net-redirections) \
+               --disable-profiling \
+               $(use_enable mem-scramble) \
+               $(use_with mem-scramble bash-malloc) \
+               $(use_enable readline) \
+               $(use_enable readline history) \
+               $(use_enable readline bang-history) \
+               "${myconf[@]}"
+}
+
+src_compile() {
+       emake
+
+       if use plugins ; then
+               emake -C examples/loadables all others
+       fi
+}
+
+src_install() {
+       local d f
+
+       default
+
+       find "${ED}" -name "bashbug*" -delete
+       mv "${ED}"/usr/share/man/man1/{,mpi}bash.1 || die
+       mv "${ED}"/usr/share/info/{,mpi}bash.info || die
+       return 0
+
+       dodir /bin
+       mv "${ED}"/usr/bin/bash "${ED}"/bin/ || die
+       dosym bash /bin/rbash
+
+       insinto /etc/bash
+       doins "${FILESDIR}"/{bashrc,bash_logout}
+       insinto /etc/skel
+       for f in bash{_logout,_profile,rc} ; do
+               newins "${FILESDIR}"/dot-${f} .${f}
+       done
+
+       local sed_args=(
+               -e "s:#${USERLAND}#@::"
+               -e '/#@/d'
+       )
+       if ! use readline ; then
+               sed_args+=( #432338
+                       -e '/^shopt -s histappend/s:^:#:'
+                       -e 's:use_color=true:use_color=false:'
+               )
+       fi
+       sed -i \
+               "${sed_args[@]}" \
+               "${ED}"/etc/skel/.bashrc \
+               "${ED}"/etc/bash/bashrc || die
+
+       if use plugins ; then
+               exeinto /usr/$(get_libdir)/bash
+               doexe $(echo examples/loadables/*.o | sed 's:\.o::g')
+               insinto /usr/include/bash-plugins
+               doins *.h builtins/*.h include/*.h 
lib/{glob/glob.h,tilde/tilde.h}
+       fi
+
+       if use examples ; then
+               for d in 
examples/{functions,misc,scripts,scripts.noah,scripts.v2} ; do
+                       exeinto /usr/share/doc/${PF}/${d}
+                       insinto /usr/share/doc/${PF}/${d}
+                       for f in ${d}/* ; do
+                               if [[ ${f##*/} != PERMISSION ]] && [[ ${f##*/} 
!= *README ]] ; then
+                                       doexe ${f}
+                               else
+                                       doins ${f}
+                               fi
+                       done
+               done
+       fi
+
+       doman doc/*.1
+       newdoc CWRU/changelog ChangeLog
+       dosym bash.info /usr/share/info/bashref.info
+}
+
+pkg_preinst() {
+       return 0
+       if [[ -e ${EROOT}/etc/bashrc ]] && [[ ! -d ${EROOT}/etc/bash ]] ; then
+               mkdir -p "${EROOT}"/etc/bash
+               mv -f "${EROOT}"/etc/bashrc "${EROOT}"/etc/bash/
+       fi
+
+       if [[ -L ${EROOT}/bin/sh ]] ; then
+               # rewrite the symlink to ensure that its mtime changes. having 
/bin/sh
+               # missing even temporarily causes a fatal error with paludis.
+               local target=$(readlink "${EROOT}"/bin/sh)
+               local tmp=$(emktemp "${EROOT}"/bin)
+               ln -sf "${target}" "${tmp}"
+               mv -f "${tmp}" "${EROOT}"/bin/sh
+       fi
+}
+
+pkg_postinst() {
+       return 0
+       # If /bin/sh does not exist, provide it
+       if [[ ! -e ${EROOT}/bin/sh ]] ; then
+               ln -sf bash "${EROOT}"/bin/sh
+       fi
+}

Reply via email to