Gentoo Archives: gentoo-commits

From: Christoph Junghans <ottxor@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/sci:master commit in: app-shells/mpibash/files/, app-shells/mpibash/
Date: Fri, 29 Aug 2014 19:28:16
Message-Id: 1409340466.8f1127807f68bbb9c3c85622808677f8c7b60b5b.ottxor@gentoo
1 commit: 8f1127807f68bbb9c3c85622808677f8c7b60b5b
2 Author: Christoph Junghans <ottxor <AT> gentoo <DOT> org>
3 AuthorDate: Fri Aug 29 19:27:46 2014 +0000
4 Commit: Christoph Junghans <ottxor <AT> gentoo <DOT> org>
5 CommitDate: Fri Aug 29 19:27:46 2014 +0000
6 URL: http://sources.gentoo.org/gitweb/?p=proj/sci.git;a=commit;h=8f112780
7
8 initial commit
9
10 Package-Manager: portage-2.2.8-r1
11
12 ---
13 app-shells/mpibash/ChangeLog | 11 +
14 .../files/bash-4.3-append-process-segfault.patch | 18 +
15 app-shells/mpibash/files/bash-4.3-compat-lvl.patch | 13 +
16 .../files/bash-4.3-parse-time-keyword.patch | 30 +
17 app-shells/mpibash/files/mpibash-4.3.patch | 1565 ++++++++++++++++++++
18 app-shells/mpibash/metadata.xml | 16 +
19 app-shells/mpibash/mpibash-4.3_p24.ebuild | 259 ++++
20 7 files changed, 1912 insertions(+)
21
22 diff --git a/app-shells/mpibash/ChangeLog b/app-shells/mpibash/ChangeLog
23 new file mode 100644
24 index 0000000..58fda67
25 --- /dev/null
26 +++ b/app-shells/mpibash/ChangeLog
27 @@ -0,0 +1,11 @@
28 +# ChangeLog for app-shells/mpibash
29 +# Copyright 1999-2014 Gentoo Foundation; Distributed under the GPL v2
30 +# $Header: $
31 +
32 +*mpibash-4.3_p24 (29 Aug 2014)
33 +
34 + 29 Aug 2014; Christoph Junghans <ottxor@g.o>
35 + +files/bash-4.3-append-process-segfault.patch,
36 + +files/bash-4.3-compat-lvl.patch, +files/bash-4.3-parse-time-keyword.patch,
37 + +files/mpibash-4.3.patch, +metadata.xml, +mpibash-4.3_p24.ebuild:
38 + initial commit
39
40 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
41 new file mode 100644
42 index 0000000..6c9b2e8
43 --- /dev/null
44 +++ b/app-shells/mpibash/files/bash-4.3-append-process-segfault.patch
45 @@ -0,0 +1,18 @@
46 +https://lists.gnu.org/archive/html/bug-bash/2014-08/msg00048.html
47 +
48 +*** ../bash-4.3-patched/execute_cmd.c 2014-07-30 10:26:52.000000000 -0400
49 +--- execute_cmd.c 2014-08-11 16:55:57.000000000 -0400
50 +***************
51 +*** 2406,2410 ****
52 + {
53 + #if defined (JOB_CONTROL)
54 +! append_process (savestring (the_printed_command), dollar_dollar_pid, exec_result, lastpipe_jid);
55 + #endif
56 + lstdin = wait_for (lastpid);
57 +--- 2433,2438 ----
58 + {
59 + #if defined (JOB_CONTROL)
60 +! if (INVALID_JOB (lastpipe_jid) == 0)
61 +! append_process (savestring (the_printed_command_except_trap), dollar_dollar_pid, exec_result, lastpipe_jid);
62 + #endif
63 + lstdin = wait_for (lastpid);
64
65 diff --git a/app-shells/mpibash/files/bash-4.3-compat-lvl.patch b/app-shells/mpibash/files/bash-4.3-compat-lvl.patch
66 new file mode 100644
67 index 0000000..5734687
68 --- /dev/null
69 +++ b/app-shells/mpibash/files/bash-4.3-compat-lvl.patch
70 @@ -0,0 +1,13 @@
71 +https://lists.gnu.org/archive/html/bug-bash/2014-06/msg00046.html
72 +
73 +--- a/builtins/shopt.def
74 ++++ b/builtins/shopt.def
75 +@@ -160,7 +160,7 @@ static struct {
76 + { "compat32", &shopt_compat32, set_compatibility_level },
77 + { "compat40", &shopt_compat40, set_compatibility_level },
78 + { "compat41", &shopt_compat41, set_compatibility_level },
79 +- { "compat42", &shopt_compat41, set_compatibility_level },
80 ++ { "compat42", &shopt_compat42, set_compatibility_level },
81 + #if defined (READLINE)
82 + { "complete_fullquote", &complete_fullquote, (shopt_set_func_t *)NULL},
83 + { "direxpand", &dircomplete_expand, shopt_set_complete_direxpand },
84
85 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
86 new file mode 100644
87 index 0000000..cd516e5
88 --- /dev/null
89 +++ b/app-shells/mpibash/files/bash-4.3-parse-time-keyword.patch
90 @@ -0,0 +1,30 @@
91 +https://lists.gnu.org/archive/html/bug-bash/2014-06/msg00034.html
92 +
93 +*** ../bash-4.3-patched/parse.y 2014-04-07 11:56:12.000000000 -0400
94 +--- parse.y 2014-06-11 10:25:53.000000000 -0400
95 +***************
96 +*** 2789,2797 ****
97 + case OR_OR:
98 + case '&':
99 + case DO:
100 + case THEN:
101 + case ELSE:
102 + case '{': /* } */
103 +! case '(': /* ) */
104 + case BANG: /* ! time pipeline */
105 + case TIME: /* time time pipeline */
106 +--- 2789,2802 ----
107 + case OR_OR:
108 + case '&':
109 ++ case WHILE:
110 + case DO:
111 ++ case UNTIL:
112 ++ case IF:
113 + case THEN:
114 ++ case ELIF:
115 + case ELSE:
116 + case '{': /* } */
117 +! case '(': /* )( */
118 +! case ')': /* only valid in case statement */
119 + case BANG: /* ! time pipeline */
120 + case TIME: /* time time pipeline */
121
122 diff --git a/app-shells/mpibash/files/mpibash-4.3.patch b/app-shells/mpibash/files/mpibash-4.3.patch
123 new file mode 100644
124 index 0000000..20d4787
125 --- /dev/null
126 +++ b/app-shells/mpibash/files/mpibash-4.3.patch
127 @@ -0,0 +1,1565 @@
128 +diff -Naur bash-4.3/builtins/circle.def mpibash-4.3/builtins/circle.def
129 +--- bash-4.3/builtins/circle.def 1969-12-31 17:00:00.000000000 -0700
130 ++++ mpibash-4.3/builtins/circle.def 2014-05-13 11:27:37.314100671 -0600
131 +@@ -0,0 +1,620 @@
132 ++This file is circle.def, from which is created circle.c.
133 ++It implements all of the "circle_*" builtins in Bash.
134 ++
135 ++$PRODUCES circle.c
136 ++
137 ++#include <config.h>
138 ++
139 ++#include <stdio.h>
140 ++#if defined (HAVE_UNISTD_H)
141 ++# ifdef _MINIX
142 ++# include <sys/types.h>
143 ++# endif
144 ++# include <unistd.h>
145 ++#endif
146 ++
147 ++#include "../bashintl.h"
148 ++#include "../shell.h"
149 ++#include "common.h"
150 ++#include "bashgetopt.h"
151 ++#include <libcircle.h>
152 ++
153 ++extern int running_trap, trap_saved_exit_value;
154 ++
155 ++static int circle_rank; /* Rank in the Libcircle job */
156 ++static SHELL_VAR *create_func = NULL; /* User-defined callback function for CIRCLE_cb_create. */
157 ++static SHELL_VAR *process_func = NULL; /* User-defined callback function for CIRCLE_cb_process. */
158 ++static SHELL_VAR *reduce_init_func = NULL; /* User-defined callback function for CIRCLE_cb_reduce_init. */
159 ++static SHELL_VAR *reduce_fini_func = NULL; /* User-defined callback function for CIRCLE_cb_reduce_fini. */
160 ++static SHELL_VAR *reduce_op_func = NULL; /* User-defined callback function for CIRCLE_cb_reduce_op. */
161 ++static CIRCLE_handle *current_handle = NULL; /* Active handle within a callback or NULL if not within a callback */
162 ++static int within_reduction = 0; /* 1=within a reduction callback; 0=not */
163 ++
164 ++/* Return with a usage message if no arguments remain. */
165 ++#define YES_ARGS(LIST) \
166 ++ if ((LIST) == 0) \
167 ++ { \
168 ++ builtin_usage (); \
169 ++ return (EX_USAGE); \
170 ++ }
171 ++
172 ++/* Perform the same operation as bind_variable, but with VALUE being a
173 ++ * number, not a string. */
174 ++static SHELL_VAR *
175 ++bind_variable_number (name, value, flags)
176 ++ const char *name;
177 ++ long value;
178 ++ int flags;
179 ++{
180 ++ char numstr[25]; /* String version of VALUE */
181 ++
182 ++ sprintf (numstr, "%ld", value);
183 ++ return bind_variable (name, numstr, flags);
184 ++}
185 ++
186 ++/* Invoke the user-defined creation-callback function (create_func). */
187 ++static void
188 ++internal_create_func (handle)
189 ++ CIRCLE_handle *handle;
190 ++{
191 ++ WORD_LIST *funcargs;
192 ++
193 ++ if (create_func == NULL)
194 ++ return;
195 ++ current_handle = handle;
196 ++ funcargs = make_word_list (make_word ("cb_create"), NULL);
197 ++ execute_shell_function (create_func, funcargs);
198 ++ dispose_words (funcargs);
199 ++ current_handle = NULL;
200 ++}
201 ++
202 ++/* Invoke the user-defined process-callback function (process_func). */
203 ++static void
204 ++internal_process_func (handle)
205 ++ CIRCLE_handle *handle;
206 ++{
207 ++ WORD_LIST *funcargs;
208 ++
209 ++ if (process_func == NULL)
210 ++ return;
211 ++ current_handle = handle;
212 ++ funcargs = make_word_list (make_word ("cb_process"), NULL);
213 ++ execute_shell_function (process_func, funcargs);
214 ++ dispose_words (funcargs);
215 ++ current_handle = NULL;
216 ++}
217 ++
218 ++/* Invoke the user-defined reduction-initiation callback function
219 ++ * (reduce_init_func). */
220 ++static void
221 ++internal_reduce_init_func (void)
222 ++{
223 ++ WORD_LIST *funcargs;
224 ++
225 ++ if (reduce_init_func == NULL)
226 ++ return;
227 ++ within_reduction = 1;
228 ++ funcargs = make_word_list (make_word ("cb_reduce_init"), NULL);
229 ++ execute_shell_function (reduce_init_func, funcargs);
230 ++ dispose_words (funcargs);
231 ++ within_reduction = 0;
232 ++}
233 ++
234 ++/* Invoke the user-defined reduction callback function
235 ++ * (reduce_op_func). */
236 ++static void
237 ++internal_reduce_op_func (buf1, size1, buf2, size2)
238 ++ const void* buf1;
239 ++ size_t size1;
240 ++ const void* buf2;
241 ++ size_t size2;
242 ++{
243 ++ WORD_LIST *funcargs;
244 ++
245 ++ if (reduce_op_func == NULL)
246 ++ return;
247 ++ within_reduction = 1;
248 ++ funcargs = make_word_list (make_word (buf2), NULL);
249 ++ funcargs = make_word_list (make_word (buf1), funcargs);
250 ++ funcargs = make_word_list (make_word ("cb_reduce_op"), funcargs);
251 ++ execute_shell_function (reduce_op_func, funcargs);
252 ++ dispose_words (funcargs);
253 ++ within_reduction = 0;
254 ++}
255 ++
256 ++/* Invoke the user-defined reduction-finalization callback function
257 ++ * (reduce_fini_func). */
258 ++static void
259 ++internal_reduce_fini_func (buf, size)
260 ++ const void* buf;
261 ++ size_t size;
262 ++{
263 ++ WORD_LIST *funcargs;
264 ++
265 ++ if (reduce_fini_func == NULL)
266 ++ return;
267 ++ funcargs = make_word_list (make_word (buf), NULL);
268 ++ funcargs = make_word_list (make_word ("cb_reduce_fini"), funcargs);
269 ++ execute_shell_function (reduce_fini_func, funcargs);
270 ++ dispose_words (funcargs);
271 ++}
272 ++
273 ++/* Look up a user-provided callback function. */
274 ++static int
275 ++find_callback_function (list, user_func)
276 ++ WORD_LIST *list;
277 ++ SHELL_VAR **user_func;
278 ++{
279 ++ char *funcname; /* Name of the user-defined function. */
280 ++
281 ++ /* If no argument was provided, nullify the callback function. */
282 ++ if (list == NULL)
283 ++ {
284 ++ *user_func = NULL;
285 ++ return EXECUTION_SUCCESS;
286 ++ }
287 ++
288 ++ /* Get the callback function. */
289 ++ funcname = list->word->word;
290 ++ list = list->next;
291 ++ no_args (list);
292 ++ *user_func = find_function (funcname);
293 ++ if (*user_func == NULL)
294 ++ {
295 ++ builtin_error (_("function %s not found"), funcname);
296 ++ return EXECUTION_FAILURE;
297 ++ }
298 ++ return EXECUTION_SUCCESS;
299 ++}
300 ++
301 ++/* Initialize Libcircle. */
302 ++void
303 ++initialize_libcircle (argc, argv)
304 ++ int argc;
305 ++ char **argv;
306 ++{
307 ++ circle_rank = CIRCLE_init (argc, argv, CIRCLE_DEFAULT_FLAGS);
308 ++ bind_variable_number ("circle_rank", circle_rank, 0);
309 ++ CIRCLE_enable_logging (CIRCLE_LOG_WARN);
310 ++ CIRCLE_cb_create (internal_create_func);
311 ++ CIRCLE_cb_process (internal_process_func);
312 ++ CIRCLE_cb_reduce_init (internal_reduce_init_func);
313 ++ CIRCLE_cb_reduce_op (internal_reduce_op_func);
314 ++ CIRCLE_cb_reduce_fini (internal_reduce_fini_func);
315 ++}
316 ++
317 ++/* Finalize Libcircle. */
318 ++void
319 ++finalize_libcircle (void)
320 ++{
321 ++ CIRCLE_finalize ();
322 ++}
323 ++
324 ++/* ---------------------------------------------------------------------- */
325 ++
326 ++$BUILTIN circle_set_options
327 ++$FUNCTION circle_set_options_builtin
328 ++$SHORT_DOC circle_set_options [flag]...
329 ++Change Libcircle's run-time behavior.
330 ++
331 ++Arguments:
332 ++ FLAG "split_random", "split_equal", or "create_global"
333 ++
334 ++Multiple flags can be provided. If no flags are provided, Libcircle
335 ++reverts to its default options.
336 ++
337 ++Exit Status:
338 ++Returns 0 unless an invalid option is given.
339 ++$END
340 ++/*'*/
341 ++
342 ++/* Here is the circle_set_options builtin. */
343 ++int
344 ++circle_set_options_builtin (list)
345 ++ WORD_LIST *list;
346 ++{
347 ++ char *word; /* One argument */
348 ++ int flags = 0; /* Flags to pass to CIRCLE_set_options */
349 ++
350 ++ if (list == NULL)
351 ++ flags = CIRCLE_DEFAULT_FLAGS;
352 ++ else
353 ++ while (list != NULL)
354 ++ {
355 ++ word = list->word->word;
356 ++ if (!strcmp (word, "split_random"))
357 ++ flags |= CIRCLE_SPLIT_RANDOM;
358 ++ else if (!strcmp (word, "split_equal"))
359 ++ flags |= CIRCLE_SPLIT_EQUAL;
360 ++ else if (!strcmp (word, "create_global"))
361 ++ flags |= CIRCLE_CREATE_GLOBAL;
362 ++ else
363 ++ {
364 ++ builtin_error (_("invalid flag \"%s\""), word);
365 ++ return (EXECUTION_FAILURE);
366 ++ }
367 ++ list = list->next;
368 ++ }
369 ++ CIRCLE_set_options (flags);
370 ++ return EXECUTION_SUCCESS;
371 ++}
372 ++
373 ++$BUILTIN circle_cb_create
374 ++$FUNCTION circle_cb_create_builtin
375 ++$SHORT_DOC circle_cb_create [func]
376 ++Register a function that will create work when asked.
377 ++
378 ++Arguments:
379 ++ FUNC User-defined callback function that will invoke
380 ++ circle_enqueue when called
381 ++
382 ++If FUNC is omitted, no function will be associated with work creation.
383 ++This can be used to nullify a previous circle_cb_create invocation.
384 ++
385 ++Exit Status:
386 ++Returns 0 unless an invalid function is given or an error occurs.
387 ++$END
388 ++
389 ++/* Here is the circle_cb_create builtin. */
390 ++int
391 ++circle_cb_create_builtin (list)
392 ++ WORD_LIST *list;
393 ++{
394 ++ return find_callback_function (list, &create_func);
395 ++}
396 ++
397 ++$BUILTIN circle_cb_process
398 ++$FUNCTION circle_cb_process_builtin
399 ++$SHORT_DOC circle_cb_process [func]
400 ++Register a function that will process work when asked.
401 ++
402 ++Arguments:
403 ++ FUNC User-defined callback function that will invoke
404 ++ circle_enqueue when called
405 ++
406 ++If FUNC is omitted, no function will be associated with work processing.
407 ++This can be used to nullify a previous circle_cb_process invocation.
408 ++
409 ++Exit Status:
410 ++Returns 0 unless an invalid function is given or an error occurs.
411 ++$END
412 ++
413 ++/* Here is the circle_cb_process builtin. */
414 ++int
415 ++circle_cb_process_builtin (list)
416 ++ WORD_LIST *list;
417 ++{
418 ++ return find_callback_function (list, &process_func);
419 ++}
420 ++
421 ++$BUILTIN circle_begin
422 ++$FUNCTION circle_begin_builtin
423 ++$SHORT_DOC circle_begin
424 ++Begin creation and processing of the distributed work queue.
425 ++
426 ++Exit Status:
427 ++Returns 0 unless an error occurs.
428 ++$END
429 ++
430 ++/* Here is the circle_begin builtin. */
431 ++int
432 ++circle_begin_builtin (list)
433 ++ WORD_LIST *list;
434 ++{
435 ++ no_args (list);
436 ++ CIRCLE_begin ();
437 ++ return EXECUTION_SUCCESS;
438 ++}
439 ++
440 ++$BUILTIN circle_enqueue
441 ++$FUNCTION circle_enqueue_builtin
442 ++$SHORT_DOC circle_enqueue work
443 ++Enqueue work onto the distributed queue.
444 ++
445 ++Arguments:
446 ++ WORK "Work" as represented by an arbitrary string of limited
447 ++ size (generally around 4KB)
448 ++
449 ++Exit Status:
450 ++Returns 0 unless an error occurs.
451 ++$END
452 ++
453 ++/* Here is the circle_enqueue builtin. */
454 ++int
455 ++circle_enqueue_builtin (list)
456 ++ WORD_LIST *list;
457 ++{
458 ++ char *work; /* Work to perform */
459 ++
460 ++ /* Extract the work argument. */
461 ++ YES_ARGS (list);
462 ++ work = list->word->word;
463 ++ list = list->next;
464 ++ no_args (list);
465 ++
466 ++ /* Complain if we're not within a proper callback function. */
467 ++ if (current_handle == NULL)
468 ++ {
469 ++ builtin_error (_("not within a Libcircle \"create\" or \"process\" callback function"));
470 ++ return EXECUTION_FAILURE;
471 ++ }
472 ++
473 ++ /* Enqueue the work. */
474 ++ if (current_handle->enqueue (work) == -1)
475 ++ return EXECUTION_FAILURE;
476 ++ return EXECUTION_SUCCESS;
477 ++}
478 ++
479 ++$BUILTIN circle_dequeue
480 ++$FUNCTION circle_dequeue_builtin
481 ++$SHORT_DOC circle_dequeue var
482 ++Dequeue work from the distributed queue into a variable.
483 ++
484 ++Arguments:
485 ++ VAR Variable in which to receive previously enqueued "work"
486 ++
487 ++Exit Status:
488 ++Returns 0 unless an error occurs.
489 ++$END
490 ++
491 ++/* Here is the circle_dequeue builtin. */
492 ++int
493 ++circle_dequeue_builtin (list)
494 ++ WORD_LIST *list;
495 ++{
496 ++ char *varname; /* Variable in which to store the work string */
497 ++ char work[CIRCLE_MAX_STRING_LEN+1]; /* Work to perform */
498 ++
499 ++ /* Extract the variable-name argument. */
500 ++ YES_ARGS (list);
501 ++ varname = list->word->word;
502 ++ list = list->next;
503 ++ no_args (list);
504 ++
505 ++ /* Complain if we're not within a callback function. */
506 ++ if (current_handle == NULL)
507 ++ {
508 ++ builtin_error (_("not within a Libcircle callback function"));
509 ++ return EXECUTION_FAILURE;
510 ++ }
511 ++
512 ++ /* Dequeue the work and bind it to the given variable. */
513 ++ if (current_handle->dequeue (work) == -1)
514 ++ return EXECUTION_FAILURE;
515 ++ bind_variable (varname, work, 0);
516 ++ return EXECUTION_SUCCESS;
517 ++}
518 ++
519 ++$BUILTIN circle_enable_logging
520 ++$FUNCTION circle_enable_logging_builtin
521 ++$SHORT_DOC circle_enable_logging log_level
522 ++Change Libcircle's logging verbosity
523 ++
524 ++Arguments:
525 ++ LOG_LEVEL "fatal", "error", "warning", "info", or "debug"
526 ++
527 ++Exit Status:
528 ++Returns 0 unless an invalid option is given.
529 ++$END
530 ++/*'*/
531 ++
532 ++/* Here is the circle_enable_logging builtin. */
533 ++int
534 ++circle_enable_logging_builtin (list)
535 ++ WORD_LIST *list;
536 ++{
537 ++ char *word; /* One argument */
538 ++ CIRCLE_loglevel loglevel; /* Level to set */
539 ++
540 ++ /* Parse the log level. */
541 ++ YES_ARGS (list);
542 ++ word = list->word->word;
543 ++ if (!strcmp (word, "fatal"))
544 ++ loglevel = CIRCLE_LOG_FATAL;
545 ++ else if (!strcmp (word, "error"))
546 ++ loglevel = CIRCLE_LOG_ERR;
547 ++ else if (!strcmp (word, "warning"))
548 ++ loglevel = CIRCLE_LOG_WARN;
549 ++ else if (!strcmp (word, "info"))
550 ++ loglevel = CIRCLE_LOG_INFO;
551 ++ else if (!strcmp (word, "debug"))
552 ++ loglevel = CIRCLE_LOG_DBG;
553 ++ else
554 ++ {
555 ++ builtin_error (_("invalid log level \"%s\""), word);
556 ++ return (EXECUTION_FAILURE);
557 ++ }
558 ++
559 ++ /* Set the log level. */
560 ++ CIRCLE_enable_logging (loglevel);
561 ++ return EXECUTION_SUCCESS;
562 ++}
563 ++
564 ++$BUILTIN circle_abort
565 ++$FUNCTION circle_abort_builtin
566 ++$SHORT_DOC circle_abort
567 ++Terminate queue processing.
568 ++
569 ++Exit Status:
570 ++Returns 0 unless an error occurs.
571 ++$END
572 ++
573 ++/* Here is the circle_abort builtin. */
574 ++int
575 ++circle_abort_builtin (list)
576 ++ WORD_LIST *list;
577 ++{
578 ++ no_args (list);
579 ++ CIRCLE_abort ();
580 ++ return EXECUTION_SUCCESS;
581 ++}
582 ++
583 ++$BUILTIN circle_checkpoint
584 ++$FUNCTION circle_checkpoint_builtin
585 ++$SHORT_DOC circle_checkpoint
586 ++Checkpoint a work queue to disk.
587 ++
588 ++Write a file called circle${circle_rank}.txt containing the current
589 ++queue state of rank ${circle_rank}. On a later run, a worker can
590 ++invoke circle_read_restarts to repopulate its queue from such a
591 ++checkpoint file.
592 ++
593 ++Exit Status:
594 ++Returns 0 unless an error occurs.
595 ++$END
596 ++/*'*/
597 ++
598 ++/* Here is the circle_checkpoint builtin. */
599 ++int
600 ++circle_checkpoint_builtin (list)
601 ++ WORD_LIST *list;
602 ++{
603 ++ no_args (list);
604 ++ CIRCLE_checkpoint ();
605 ++ return EXECUTION_SUCCESS;
606 ++}
607 ++
608 ++$BUILTIN circle_read_restarts
609 ++$FUNCTION circle_read_restarts_builtin
610 ++$SHORT_DOC circle_read_restarts
611 ++Repopulate a work queue from a disk checkpoint.
612 ++
613 ++Read queue contents from a file called circle${circle_rank}.txt, which
614 ++was previously produced by circle_checkpoint.
615 ++
616 ++Exit Status:
617 ++Returns 0 unless an error occurs.
618 ++$END
619 ++/*'*/
620 ++
621 ++/* Here is the circle_read_restarts builtin. */
622 ++int
623 ++circle_read_restarts_builtin (list)
624 ++ WORD_LIST *list;
625 ++{
626 ++ no_args (list);
627 ++ CIRCLE_read_restarts ();
628 ++ return EXECUTION_SUCCESS;
629 ++}
630 ++
631 ++$BUILTIN circle_cb_reduce_init
632 ++$FUNCTION circle_cb_reduce_init_builtin
633 ++$SHORT_DOC circle_cb_reduce_init [func]
634 ++Register a function that will initiate a reduction operation.
635 ++
636 ++Arguments:
637 ++ FUNC User-defined callback function that will invoke
638 ++ circle_reduce when called
639 ++
640 ++FUNC will be invoked on all ranks.
641 ++
642 ++If FUNC is omitted, no function will be associated with reduction
643 ++initialization. This can be used to nullify a previous
644 ++circle_cb_reduce_init invocation.
645 ++
646 ++Exit Status:
647 ++Returns 0 unless an invalid function is given or an error occurs.
648 ++$END
649 ++
650 ++/* Here is the circle_cb_reduce_init builtin. */
651 ++int
652 ++circle_cb_reduce_init_builtin (list)
653 ++ WORD_LIST *list;
654 ++{
655 ++ return find_callback_function (list, &reduce_init_func);
656 ++}
657 ++
658 ++$BUILTIN circle_cb_reduce_op
659 ++$FUNCTION circle_cb_reduce_op_builtin
660 ++$SHORT_DOC circle_cb_reduce_op [func]
661 ++Register a function that will complete a reduction operation.
662 ++
663 ++Arguments:
664 ++ FUNC User-defined callback function that will receive
665 ++ two items to reduce and invoke circle_reduce on
666 ++ the reduced value
667 ++
668 ++If FUNC is omitted, no function will be associated with reduction
669 ++execution. This can be used to nullify a previous circle_cb_reduce_op
670 ++invocation.
671 ++
672 ++Exit Status:
673 ++Returns 0 unless an invalid function is given or an error occurs.
674 ++$END
675 ++
676 ++/* Here is the circle_cb_reduce_op builtin. */
677 ++int
678 ++circle_cb_reduce_op_builtin (list)
679 ++ WORD_LIST *list;
680 ++{
681 ++ return find_callback_function (list, &reduce_op_func);
682 ++}
683 ++
684 ++$BUILTIN circle_cb_reduce_fini
685 ++$FUNCTION circle_cb_reduce_fini_builtin
686 ++$SHORT_DOC circle_cb_reduce_fini [func]
687 ++Register a function that will complete a reduction operation.
688 ++
689 ++Arguments:
690 ++ FUNC User-defined callback function that will receive
691 ++ the final reduced data
692 ++
693 ++If FUNC is omitted, no function will be associated with reduction
694 ++completion. This can be used to nullify a previous
695 ++circle_cb_reduce_fini invocation.
696 ++
697 ++Libcircle guarantees that FUNC will be invoked only on rank 0.
698 ++
699 ++Exit Status:
700 ++Returns 0 unless an invalid function is given or an error occurs.
701 ++$END
702 ++
703 ++/* Here is the circle_cb_reduce_fini builtin. */
704 ++int
705 ++circle_cb_reduce_fini_builtin (list)
706 ++ WORD_LIST *list;
707 ++{
708 ++ return find_callback_function (list, &reduce_fini_func);
709 ++}
710 ++
711 ++$BUILTIN circle_reduce
712 ++$FUNCTION circle_reduce_builtin
713 ++$SHORT_DOC circle_reduce work
714 ++Seed the next phase of a reduction operation
715 ++
716 ++Arguments:
717 ++ WORK "Work" as represented by an arbitrary string of limited
718 ++ size (generally around 4KB)
719 ++
720 ++This function should be called both by the callback function
721 ++registered with circle_reduce_init and the callback function
722 ++registered with circle_reduce_op.
723 ++
724 ++Exit Status:
725 ++Returns 0 unless an error occurs.
726 ++$END
727 ++
728 ++/* Here is the circle_reduce builtin. */
729 ++int
730 ++circle_reduce_builtin (list)
731 ++ WORD_LIST *list;
732 ++{
733 ++ char *work; /* Work to perform */
734 ++
735 ++ /* Extract the work argument. */
736 ++ YES_ARGS (list);
737 ++ work = list->word->word;
738 ++ list = list->next;
739 ++ no_args (list);
740 ++
741 ++ /* Complain if we're not within a proper callback function. */
742 ++ if (!within_reduction)
743 ++ {
744 ++ builtin_error (_("not within a Libcircle \"reduce_init\" or \"reduce_op\" callback function"));
745 ++ return EXECUTION_FAILURE;
746 ++ }
747 ++
748 ++ /* Reduce the work. */
749 ++ CIRCLE_reduce (work, strlen (work));
750 ++ return EXECUTION_SUCCESS;
751 ++}
752 +diff -Naur bash-4.3/builtins/Makefile.in mpibash-4.3/builtins/Makefile.in
753 +--- bash-4.3/builtins/Makefile.in 2012-05-25 07:29:19.000000000 -0600
754 ++++ mpibash-4.3/builtins/Makefile.in 2014-05-13 11:27:37.314100671 -0600
755 +@@ -141,7 +141,9 @@
756 + $(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \
757 + $(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \
758 + $(srcdir)/reserved.def $(srcdir)/pushd.def $(srcdir)/shopt.def \
759 +- $(srcdir)/printf.def $(srcdir)/complete.def $(srcdir)/mapfile.def
760 ++ $(srcdir)/printf.def $(srcdir)/complete.def $(srcdir)/mapfile.def \
761 ++ $(srcdir)/mpi.def \
762 ++@CIRCLE@ $(srcdir)/circle.def
763 +
764 + STATIC_SOURCE = common.c evalstring.c evalfile.c getopt.c bashgetopt.c \
765 + getopt.h
766 +@@ -153,7 +155,9 @@
767 + jobs.o kill.o let.o mapfile.o \
768 + pushd.o read.o return.o set.o setattr.o shift.o source.o \
769 + suspend.o test.o times.o trap.o type.o ulimit.o umask.o \
770 +- wait.o getopts.o shopt.o printf.o getopt.o bashgetopt.o complete.o
771 ++ wait.o getopts.o shopt.o printf.o getopt.o bashgetopt.o complete.o \
772 ++ mpi.o \
773 ++@CIRCLE@ circle.o
774 +
775 + CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h tmpbuiltins.c \
776 + tmpbuiltins.h
777 +@@ -317,6 +321,8 @@
778 + getopts.o: getopts.def
779 + reserved.o: reserved.def
780 + complete.o: complete.def
781 ++@CIRCLE@ circle.o: circle.def
782 ++mpi.o: mpi.def
783 +
784 + # C files
785 + bashgetopt.o: ../config.h $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
786 +@@ -644,6 +650,19 @@
787 + mapfile.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
788 + mapfile.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/variables.h $(topdir)/conftypes.h
789 + mapfile.o: $(topdir)/arrayfunc.h ../pathnames.h
790 ++@CIRCLE@ circle.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
791 ++@CIRCLE@ circle.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/subst.h $(topdir)/externs.h
792 ++@CIRCLE@ circle.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
793 ++@CIRCLE@ circle.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
794 ++@CIRCLE@ circle.o: $(BASHINCDIR)/maxpath.h ../pathnames.h
795 ++mpi.o: ../config.h ../config-top.h ../config-bot.h ../bashintl.h
796 ++mpi.o: ../include/gettext.h ../shell.h ../config.h ../bashjmp.h
797 ++mpi.o: ../include/posixjmp.h ../command.h ../syntax.h ../general.h
798 ++mpi.o: ../bashtypes.h ../include/chartypes.h ../xmalloc.h ../bashansi.h
799 ++mpi.o: ../error.h ../variables.h ../array.h ../assoc.h ../hashlib.h
800 ++mpi.o: ../conftypes.h ../arrayfunc.h ../quit.h ../sig.h ../include/maxpath.h
801 ++mpi.o: ../unwind_prot.h ../dispose_cmd.h ../make_cmd.h ../include/ocache.h
802 ++mpi.o: ../subst.h ../pathnames.h ../externs.h common.h bashgetopt.h
803 +
804 + #bind.o: $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)readline.h $(RL_LIBSRC)keymaps.h
805 +
806 +diff -Naur bash-4.3/builtins/mpi.def mpibash-4.3/builtins/mpi.def
807 +--- bash-4.3/builtins/mpi.def 1969-12-31 17:00:00.000000000 -0700
808 ++++ mpibash-4.3/builtins/mpi.def 2014-05-13 11:27:37.314100671 -0600
809 +@@ -0,0 +1,744 @@
810 ++This file is mpi.def, from which is created mpi.c.
811 ++It implements all of the "mpi_*" builtins in Bash.
812 ++
813 ++$PRODUCES mpi.c
814 ++
815 ++#include <config.h>
816 ++
817 ++#include <stdio.h>
818 ++#if defined (HAVE_UNISTD_H)
819 ++# ifdef _MINIX
820 ++# include <sys/types.h>
821 ++# endif
822 ++# include <unistd.h>
823 ++#endif
824 ++
825 ++#include "../bashintl.h"
826 ++#include "../shell.h"
827 ++#include "common.h"
828 ++#include "bashgetopt.h"
829 ++#include <mpi.h>
830 ++
831 ++extern int running_trap, trap_saved_exit_value;
832 ++
833 ++/* Keep track of who we are within MPI_COMM_WORLD. */
834 ++static int mpi_rank;
835 ++static int mpi_num_ranks;
836 ++
837 ++/* Try an MPI operation. Return with an error message on failure. */
838 ++#define MPI_TRY(STMT) \
839 ++ do \
840 ++ { \
841 ++ int mpierr; \
842 ++ mpierr = STMT; \
843 ++ if (mpierr != MPI_SUCCESS) \
844 ++ return report_mpi_error (mpierr); \
845 ++ } \
846 ++ while (0)
847 ++
848 ++/* Return with a usage message if no arguments remain. */
849 ++#define YES_ARGS(LIST) \
850 ++ if ((LIST) == 0) \
851 ++ { \
852 ++ builtin_usage (); \
853 ++ return (EX_USAGE); \
854 ++ }
855 ++
856 ++/* Return with an error message if a given variable is read-only or if
857 ++ * we can't write to it for any other reason (e.g., it's defined as a
858 ++ * function). */
859 ++#define REQUIRE_WRITABLE(NAME) \
860 ++ do \
861 ++ { \
862 ++ SHELL_VAR *bindvar = find_shell_variable (NAME); \
863 ++ if (bindvar) \
864 ++ { \
865 ++ if (readonly_p (bindvar)) \
866 ++ { \
867 ++ err_readonly (NAME); \
868 ++ return (EXECUTION_FAILURE); \
869 ++ } \
870 ++ if (unbind_variable (NAME) == -1) \
871 ++ { \
872 ++ builtin_error ("Failed to write to variable %s", NAME); \
873 ++ return (EXECUTION_FAILURE); \
874 ++ } \
875 ++ } \
876 ++ } \
877 ++ while (0)
878 ++
879 ++/* Initialize MPI. */
880 ++void
881 ++initialize_mpi (argc, argv)
882 ++ int argc;
883 ++ char **argv;
884 ++{
885 ++ int init_done;
886 ++
887 ++ MPI_Initialized (&init_done);
888 ++ if (!init_done)
889 ++ MPI_Init (&argc, &argv);
890 ++ MPI_Errhandler_set (MPI_COMM_WORLD, MPI_ERRORS_RETURN);
891 ++ MPI_Comm_rank (MPI_COMM_WORLD, &mpi_rank);
892 ++ MPI_Comm_size (MPI_COMM_WORLD, &mpi_num_ranks);
893 ++}
894 ++
895 ++/* Finalize MPI. */
896 ++void
897 ++finalize_mpi ()
898 ++{
899 ++ MPI_Finalize ();
900 ++}
901 ++
902 ++/* Parse an operation name into an MPI_Op. Return 1 on success, 0 on
903 ++ * failure. */
904 ++static int
905 ++parse_operation (char *name, MPI_Op *op)
906 ++{
907 ++ /* Define a mapping from operator names to MPI_Op values. */
908 ++ typedef struct {
909 ++ char *name; /* Operation name (e.g., "sum") */
910 ++ MPI_Op value; /* Operation value (e.g., MPI_SUM) */
911 ++ } opname2value_t;
912 ++ static opname2value_t oplist[] = {
913 ++ {"max", MPI_MAX},
914 ++ {"min", MPI_MIN},
915 ++ {"sum", MPI_SUM},
916 ++ {"prod", MPI_PROD},
917 ++ {"land", MPI_LAND},
918 ++ {"band", MPI_BAND},
919 ++ {"lor", MPI_LOR},
920 ++ {"bor", MPI_BOR},
921 ++ {"lxor", MPI_LXOR},
922 ++ {"bxor", MPI_BXOR},
923 ++ {"maxloc", MPI_MAXLOC},
924 ++ {"minloc", MPI_MINLOC}
925 ++ };
926 ++ size_t i;
927 ++
928 ++ for (i = 0; i < sizeof(oplist)/sizeof(opname2value_t); i++)
929 ++ if (!strcmp(name, oplist[i].name))
930 ++ {
931 ++ *op = oplist[i].value;
932 ++ if (i > 0)
933 ++ {
934 ++ /* As a performance optimization, bubble up the value we
935 ++ * just found. */
936 ++ opname2value_t prev = oplist[i - 1];
937 ++ oplist[i - 1] = oplist[i];
938 ++ oplist[i] = prev;
939 ++ }
940 ++ return 1;
941 ++ }
942 ++ return 0;
943 ++}
944 ++
945 ++/* Report an error to the user and return EXECUTION_FAILURE. */
946 ++static int
947 ++report_mpi_error (mpierr)
948 ++ int mpierr;
949 ++{
950 ++ char errstr[MPI_MAX_ERROR_STRING];
951 ++ int errstrlen;
952 ++
953 ++ MPI_Error_string (mpierr, errstr, &errstrlen);
954 ++ builtin_error ("%s", errstr);
955 ++ return EXECUTION_FAILURE;
956 ++}
957 ++
958 ++/* Perform the same operation as bind_variable, but with VALUE being a
959 ++ * number, not a string. */
960 ++static SHELL_VAR *
961 ++bind_variable_number (name, value, flags)
962 ++ const char *name;
963 ++ long value;
964 ++ int flags;
965 ++{
966 ++ char numstr[25]; /* String version of VALUE */
967 ++
968 ++ sprintf (numstr, "%ld", value);
969 ++ return bind_variable (name, numstr, flags);
970 ++}
971 ++
972 ++/* Perform the same operation as bind_array_variable, but with VALUE
973 ++ * being a number, not a string. */
974 ++static SHELL_VAR *
975 ++bind_array_variable_number (name, ind, value, flags)
976 ++ char *name;
977 ++ arrayind_t ind;
978 ++ long value;
979 ++ int flags;
980 ++{
981 ++ char numstr[25]; /* String version of VALUE */
982 ++
983 ++ sprintf (numstr, "%ld", value);
984 ++ return bind_array_variable (name, ind, numstr, flags);
985 ++}
986 ++
987 ++/* Define a reduction-type function (allreduce, scan, exscan, etc.). */
988 ++typedef int (*reduction_func_t)(void *, void *, int, MPI_Datatype, MPI_Op, MPI_Comm);
989 ++
990 ++/* Perform any reduction-type operation (allreduce, scan, exscan, etc.). */
991 ++static int
992 ++reduction_like (list, funcname, func)
993 ++ WORD_LIST *list;
994 ++ char *funcname;
995 ++ reduction_func_t func;
996 ++{
997 ++ char *word; /* One argument */
998 ++ struct {
999 ++ long int value; /* Reduced value */
1000 ++ int rank; /* Rank associated with the above */
1001 ++ } number, result;
1002 ++ MPI_Op operation = MPI_SUM; /* Operation to perform */
1003 ++ char *varname; /* Name of the variable to bind the results to */
1004 ++ intmax_t n;
1005 ++ int i;
1006 ++
1007 ++ /* Parse "-O OPERATION" (optional), where OPERATION is a reduction
1008 ++ * operation. */
1009 ++ YES_ARGS (list);
1010 ++ word = list->word->word;
1011 ++ if (ISOPTION (word, 'O'))
1012 ++ {
1013 ++ list = list->next;
1014 ++ if (list == 0)
1015 ++ {
1016 ++ sh_needarg (funcname);
1017 ++ return (EX_USAGE);
1018 ++ }
1019 ++ word = list->word->word;
1020 ++ if (!parse_operation (word, &operation))
1021 ++ {
1022 ++ sh_invalidopt ("-O");
1023 ++ return (EX_USAGE);
1024 ++ }
1025 ++ list = list->next;
1026 ++ }
1027 ++
1028 ++ /* Parse the argument, which must be a number. */
1029 ++ YES_ARGS (list);
1030 ++ word = list->word->word;
1031 ++ if (!legal_number (word, &n))
1032 ++ {
1033 ++ sh_neednumarg (funcname);
1034 ++ return (EX_USAGE);
1035 ++ }
1036 ++ number.value = (long int) n;
1037 ++ number.rank = mpi_rank;
1038 ++ list = list->next;
1039 ++
1040 ++ /* Parse the target variable, which must not be read-only. */
1041 ++ YES_ARGS (list);
1042 ++ varname = list->word->word;
1043 ++ if (mpi_rank != 0 || func != MPI_Exscan)
1044 ++ REQUIRE_WRITABLE (varname);
1045 ++ list = list->next;
1046 ++ no_args (list);
1047 ++
1048 ++ /* Perform the reduction operation. Bind the given array variable
1049 ++ * to the result and, for minloc/maxloc, the associated rank. */
1050 ++ if (mpi_rank != 0 || func != MPI_Exscan) {
1051 ++ bind_array_variable (varname, 0, "", 0);
1052 ++ bind_array_variable (varname, 1, "", 0);
1053 ++ }
1054 ++ if (operation == MPI_MINLOC || operation == MPI_MAXLOC)
1055 ++ {
1056 ++ MPI_TRY (func (&number, &result, 1, MPI_LONG_INT, operation, MPI_COMM_WORLD));
1057 ++ if (mpi_rank != 0 || func != MPI_Exscan)
1058 ++ bind_array_variable_number (varname, 1, result.rank, 0);
1059 ++ }
1060 ++ else
1061 ++ MPI_TRY (func (&number.value, &result.value, 1, MPI_LONG, operation, MPI_COMM_WORLD));
1062 ++ if (mpi_rank != 0 || func != MPI_Exscan)
1063 ++ bind_array_variable_number (varname, 0, result.value, 0);
1064 ++ return EXECUTION_SUCCESS;
1065 ++}
1066 ++
1067 ++$BUILTIN mpi_comm_rank
1068 ++$FUNCTION mpi_comm_rank_builtin
1069 ++$SHORT_DOC mpi_comm_rank name
1070 ++Return the process's rank in the MPI job.
1071 ++
1072 ++Arguments:
1073 ++ NAME Scalar variable in which to receive the rank
1074 ++
1075 ++Exit Status:
1076 ++Returns 0 unless an invalid option is given.
1077 ++$END
1078 ++/*'*/
1079 ++
1080 ++/* Here is the mpi_comm_rank builtin. */
1081 ++int
1082 ++mpi_comm_rank_builtin (list)
1083 ++ WORD_LIST *list;
1084 ++{
1085 ++ char *varname; /* Name of the variable to bind the results to */
1086 ++
1087 ++ YES_ARGS (list);
1088 ++ varname = list->word->word;
1089 ++ REQUIRE_WRITABLE (varname);
1090 ++ list = list->next;
1091 ++ no_args (list);
1092 ++ bind_variable_number (varname, mpi_rank, 0);
1093 ++ return EXECUTION_SUCCESS;
1094 ++}
1095 ++
1096 ++$BUILTIN mpi_comm_size
1097 ++$FUNCTION mpi_comm_size_builtin
1098 ++$SHORT_DOC mpi_comm_size name
1099 ++Return the total number of ranks in the MPI job.
1100 ++
1101 ++Arguments:
1102 ++ NAME Scalar variable in which to receive the number of ranks
1103 ++
1104 ++Exit Status:
1105 ++Returns 0 unless an invalid option is given.
1106 ++$END
1107 ++
1108 ++/* Here is the mpi_comm_size builtin. */
1109 ++int
1110 ++mpi_comm_size_builtin (list)
1111 ++ WORD_LIST *list;
1112 ++{
1113 ++ char *varname; /* Name of the variable to bind the results to */
1114 ++
1115 ++ YES_ARGS (list);
1116 ++ varname = list->word->word;
1117 ++ REQUIRE_WRITABLE (varname);
1118 ++ list = list->next;
1119 ++ no_args (list);
1120 ++ bind_variable_number (varname, mpi_num_ranks, 0);
1121 ++ return EXECUTION_SUCCESS;
1122 ++}
1123 ++
1124 ++$BUILTIN mpi_abort
1125 ++$FUNCTION mpi_abort_builtin
1126 ++$SHORT_DOC mpi_abort [n]
1127 ++Abort all processes in the MPI job and exit the shell.
1128 ++
1129 ++Exits not only the caller's shell (with a status of N) but also all
1130 ++remote shells that are part of the same MPI job. If N is omitted, the
1131 ++exit status is that of the last command executed.
1132 ++
1133 ++This command should be used only in extreme circumstances. It is
1134 ++better for each process to exit normally on its own.
1135 ++$END
1136 ++/*'*/
1137 ++
1138 ++/* Here is the mpi_abort builtin. */
1139 ++int
1140 ++mpi_abort_builtin (list)
1141 ++ WORD_LIST *list;
1142 ++{
1143 ++ int exit_value;
1144 ++
1145 ++ exit_value = (running_trap == 1 && list == 0) ? trap_saved_exit_value : get_exitstat (list); /* Copied from exit.def */
1146 ++ MPI_TRY (MPI_Abort (MPI_COMM_WORLD, exit_value));
1147 ++ return EXECUTION_FAILURE;
1148 ++}
1149 ++
1150 ++$BUILTIN mpi_send
1151 ++$FUNCTION mpi_send_builtin
1152 ++$SHORT_DOC mpi_send [-t tag] rank message
1153 ++Send a message to a remote process in the same MPI job.
1154 ++
1155 ++Options:
1156 ++ -t TAG Send the message using tag TAG (default: 0). TAG must
1157 ++ be a nonnegative integer.
1158 ++
1159 ++Arguments:
1160 ++ RANK Whom to send the message to. RANK must be an integer in
1161 ++ the range [0, $(mpi_comm_size)-1].
1162 ++
1163 ++ MESSAGE String to send to rank RANK.
1164 ++
1165 ++Exit Status:
1166 ++Returns 0 unless an invalid option is given or an error occurs.
1167 ++$END
1168 ++
1169 ++/* Here is the mpi_send builtin. */
1170 ++int
1171 ++mpi_send_builtin (list)
1172 ++ WORD_LIST *list;
1173 ++{
1174 ++ char *word; /* One argument */
1175 ++ intmax_t target_rank; /* MPI target rank */
1176 ++ char *message; /* Message to send to rank target_rank */
1177 ++ intmax_t tag = 0; /* Message tag to use */
1178 ++
1179 ++ /* Parse "-t TAG" (optional), where TAG is a number or "any". */
1180 ++ YES_ARGS (list);
1181 ++ word = list->word->word;
1182 ++ if (ISOPTION (word, 't'))
1183 ++ {
1184 ++ list = list->next;
1185 ++ if (list == 0)
1186 ++ {
1187 ++ sh_needarg ("mpi_recv");
1188 ++ return (EX_USAGE);
1189 ++ }
1190 ++ word = list->word->word;
1191 ++ if (!legal_number (word, &tag))
1192 ++ {
1193 ++ sh_neednumarg ("-t");
1194 ++ return (EX_USAGE);
1195 ++ }
1196 ++ list = list->next;
1197 ++ }
1198 ++ else if (*word == '-')
1199 ++ {
1200 ++ sh_invalidopt (word);
1201 ++ builtin_usage ();
1202 ++ return (EX_USAGE);
1203 ++ }
1204 ++
1205 ++ /* Parse the target rank, which must be a number. */
1206 ++ YES_ARGS (list);
1207 ++ word = list->word->word;
1208 ++ if (!legal_number (word, &target_rank))
1209 ++ {
1210 ++ builtin_error (_("mpi_send: numeric rank required"));
1211 ++ return (EX_USAGE);
1212 ++ }
1213 ++ list = list->next;
1214 ++
1215 ++ /* Parse the message to send. */
1216 ++ YES_ARGS (list);
1217 ++ message = list->word->word;
1218 ++ list = list->next;
1219 ++ no_args (list);
1220 ++
1221 ++ /* Send the message. */
1222 ++ MPI_TRY (MPI_Send (message, strlen(message)+1, MPI_BYTE, (int)target_rank, (int)tag, MPI_COMM_WORLD));
1223 ++ return EXECUTION_SUCCESS;
1224 ++}
1225 ++
1226 ++
1227 ++$BUILTIN mpi_recv
1228 ++$FUNCTION mpi_recv_builtin
1229 ++$SHORT_DOC mpi_recv [-t tag] rank name
1230 ++Receive a message from a remote process in the same MPI job.
1231 ++
1232 ++Options:
1233 ++ -t TAG Receive only messages sent using tag TAG (default: 0).
1234 ++ TAG must be either a nonnegative integer or the string
1235 ++ "any" to receive messages sent using any tag.
1236 ++
1237 ++Arguments:
1238 ++ RANK Receive only messages sent from sender RANK. RANK
1239 ++ must either be in the range [0, $(mpi_comm_size)-1] or
1240 ++ be the string "any" to receive messages from any sender.
1241 ++
1242 ++ NAME Array variable in which to receive the message, sender
1243 ++ rank, and tag.
1244 ++
1245 ++Exit Status:
1246 ++Returns 0 unless an invalid option is given or an error occurs.
1247 ++$END
1248 ++
1249 ++/* Here is the mpi_recv builtin. */
1250 ++int
1251 ++mpi_recv_builtin (list)
1252 ++ WORD_LIST *list;
1253 ++{
1254 ++ char *word; /* One argument */
1255 ++ intmax_t source_rank; /* MPI source rank */
1256 ++ char *endptr; /* Used for parsing strings into numbers */
1257 ++ MPI_Status status; /* Status of an MPI operation */
1258 ++ int count; /* Message length in bytes */
1259 ++ intmax_t tag = 0; /* Message tag to use */
1260 ++ char *varname; /* Name of the variable to bind the results to */
1261 ++ static char *message = NULL; /* Message received from MPI */
1262 ++ static size_t alloced = 0; /* Number of bytes allocated for the above */
1263 ++ int opt; /* Parsed option */
1264 ++
1265 ++ /* Parse any options provided. */
1266 ++ reset_internal_getopt ();
1267 ++ while ((opt = internal_getopt (list, "t:")) != -1)
1268 ++ {
1269 ++ switch (opt)
1270 ++ {
1271 ++ case 't':
1272 ++ if (!strcmp (list_optarg, "any"))
1273 ++ tag = MPI_ANY_TAG;
1274 ++ else if (!legal_number (list_optarg, &tag))
1275 ++ {
1276 ++ builtin_error (_("-t: numeric argument or \"any\" required"));
1277 ++ return (EX_USAGE);
1278 ++ }
1279 ++ break;
1280 ++
1281 ++ default:
1282 ++ sh_invalidopt (word);
1283 ++ builtin_usage ();
1284 ++ return (EX_USAGE);
1285 ++ }
1286 ++ }
1287 ++ list = loptend;
1288 ++
1289 ++ /* Parse the source rank, which must be a number or "any". */
1290 ++ YES_ARGS (list);
1291 ++ word = list->word->word;
1292 ++ if (!legal_number (word, &source_rank))
1293 ++ {
1294 ++ if (!strcmp (word, "any"))
1295 ++ source_rank = MPI_ANY_SOURCE;
1296 ++ else
1297 ++ {
1298 ++ builtin_error (_("mpi_recv: numeric rank or \"any\" required"));
1299 ++ return (EX_USAGE);
1300 ++ }
1301 ++ }
1302 ++ list = list->next;
1303 ++
1304 ++ /* Parse the target variable, which must not be read-only. */
1305 ++ YES_ARGS (list);
1306 ++ varname = list->word->word;
1307 ++ REQUIRE_WRITABLE (varname);
1308 ++ list = list->next;
1309 ++ no_args (list);
1310 ++
1311 ++ /* Receive a message. Because we don't know long the message will
1312 ++ * be, we first probe to get the length. */
1313 ++ MPI_TRY (MPI_Probe ((int)source_rank, (int)tag, MPI_COMM_WORLD, &status));
1314 ++ MPI_TRY (MPI_Get_count (&status, MPI_BYTE, &count));
1315 ++ if (alloced < count)
1316 ++ {
1317 ++ message = xrealloc (message, count);
1318 ++ alloced = count;
1319 ++ }
1320 ++ MPI_TRY (MPI_Recv (message, count, MPI_BYTE, status.MPI_SOURCE, status.MPI_TAG, MPI_COMM_WORLD, &status));
1321 ++ bind_array_variable (varname, 0, message, 0);
1322 ++ bind_array_variable_number (varname, 1, status.MPI_SOURCE, 0);
1323 ++ bind_array_variable_number (varname, 2, status.MPI_TAG, 0);
1324 ++ return EXECUTION_SUCCESS;
1325 ++}
1326 ++
1327 ++$BUILTIN mpi_barrier
1328 ++$FUNCTION mpi_barrier_builtin
1329 ++$SHORT_DOC mpi_barrier
1330 ++Synchronizes all of the processes in the MPI job.
1331 ++
1332 ++No process will return from mpi_barrier until all processes have
1333 ++called mpi_barrier.
1334 ++
1335 ++Exit Status:
1336 ++Returns 0 unless an invalid option is given or an error occurs.
1337 ++$END
1338 ++
1339 ++/* Here is the mpi_barrier builtin. */
1340 ++int
1341 ++mpi_barrier_builtin (list)
1342 ++ WORD_LIST *list;
1343 ++{
1344 ++ no_args (list);
1345 ++ MPI_TRY (MPI_Barrier (MPI_COMM_WORLD));
1346 ++ return EXECUTION_SUCCESS;
1347 ++}
1348 ++
1349 ++$BUILTIN mpi_bcast
1350 ++$FUNCTION mpi_bcast_builtin
1351 ++$SHORT_DOC mpi_bcast [message] name
1352 ++Broadcast a message to all processes in the same MPI job.
1353 ++
1354 ++Arguments:
1355 ++ MESSAGE String to broadcast from one process to all the others.
1356 ++
1357 ++ NAME Scalar variable in which to receive the broadcast message.
1358 ++
1359 ++Exactly one process in the MPI job must specify a message to
1360 ++broadcast. No process will return from mpi_bcast until all processes
1361 ++have called mpi_bcast.
1362 ++
1363 ++Exit Status:
1364 ++Returns 0 unless an invalid option is given or an error occurs.
1365 ++$END
1366 ++
1367 ++/* Here is the mpi_bcast builtin. */
1368 ++int
1369 ++mpi_bcast_builtin (list)
1370 ++ WORD_LIST *list;
1371 ++{
1372 ++ char *word; /* One argument */
1373 ++ int root; /* MPI root rank */
1374 ++ char *root_message; /* Message to broadcast */
1375 ++ int msglen; /* Length in bytes of the above (including the NULL byte) */
1376 ++ char *varname; /* Name of the variable to bind the results to */
1377 ++ static int *all_lengths = NULL; /* List of every rank's msglen */
1378 ++ static char *message = NULL; /* Message received from the root */
1379 ++ static int alloced = 0; /* Bytes allocated for the above */
1380 ++ int i;
1381 ++
1382 ++ /* Parse the optional message and target variable, which must not be
1383 ++ * read-only. */
1384 ++ YES_ARGS (list);
1385 ++ if (list->next == NULL)
1386 ++ {
1387 ++ /* Non-root */
1388 ++ root_message = NULL;
1389 ++ msglen = -1;
1390 ++ }
1391 ++ else
1392 ++ {
1393 ++ /* Root */
1394 ++ root_message = list->word->word;
1395 ++ msglen = (int) strlen(root_message) + 1;
1396 ++ list = list->next;
1397 ++ }
1398 ++ varname = list->word->word;
1399 ++ REQUIRE_WRITABLE (varname);
1400 ++ list = list->next;
1401 ++ no_args (list);
1402 ++
1403 ++ /* Acquire global agreement on the root and the message size. */
1404 ++ if (all_lengths == NULL)
1405 ++ all_lengths = xmalloc (mpi_num_ranks*sizeof(int));
1406 ++ MPI_TRY (MPI_Allgather (&msglen, 1, MPI_INT, all_lengths, 1, MPI_INT, MPI_COMM_WORLD));
1407 ++ root = -1;
1408 ++ for (i = 0; i < mpi_num_ranks; i++)
1409 ++ {
1410 ++ if (all_lengths[i] == -1)
1411 ++ continue;
1412 ++ if (root != -1)
1413 ++ {
1414 ++ builtin_error (_("mpi_bcast: more than one process specified a message"));
1415 ++ return (EXECUTION_FAILURE);
1416 ++ }
1417 ++ root = i;
1418 ++ msglen = all_lengths[i];
1419 ++ }
1420 ++ if (root == -1)
1421 ++ {
1422 ++ builtin_error (_("mpi_bcast: no process specified a message"));
1423 ++ return (EXECUTION_FAILURE);
1424 ++ }
1425 ++
1426 ++ /* Broadcast the message. */
1427 ++ if (mpi_rank == root)
1428 ++ {
1429 ++ MPI_TRY (MPI_Bcast (root_message, msglen, MPI_BYTE, root, MPI_COMM_WORLD));
1430 ++ bind_variable (varname, root_message, 0);
1431 ++ }
1432 ++ else
1433 ++ {
1434 ++ if (alloced < msglen)
1435 ++ {
1436 ++ message = xrealloc (message, msglen);
1437 ++ alloced = msglen;
1438 ++ }
1439 ++ MPI_TRY (MPI_Bcast (message, msglen, MPI_BYTE, root, MPI_COMM_WORLD));
1440 ++ bind_variable (varname, message, 0);
1441 ++ }
1442 ++ return EXECUTION_SUCCESS;
1443 ++}
1444 ++
1445 ++$BUILTIN mpi_scan
1446 ++$FUNCTION mpi_scan_builtin
1447 ++$SHORT_DOC mpi_scan number name
1448 ++Perform an inclusive scan across all processes in the same MPI job.
1449 ++
1450 ++ -O OPERATION Operation to perform. Must be one of "max", "min",
1451 ++ "sum", "prod", "land", "band", "lor", "bor", "lxor",
1452 ++ "bxor", "maxloc", or "minloc" (default: "sum").
1453 ++
1454 ++Arguments:
1455 ++ NUMBER Integer to use in the scan operation.
1456 ++
1457 ++ NAME Array variable in which to receive the result and, in
1458 ++ the case of maxloc and minloc, the associated rank.
1459 ++
1460 ++In an inclusive-scan operation, each process i presents a number,
1461 ++a[i]. Once all processes in the MPI job have presented their number,
1462 ++the command returns a[0] to rank 0, a[0]+a[1] to rank 1,
1463 ++a[0]+a[1]+a[2] to rank 2, and so forth. The -O option enables "+" to
1464 ++be replaced with other operations.
1465 ++
1466 ++Inclusive scans can be useful for assigning a unique index to each
1467 ++process in the MPI job.
1468 ++
1469 ++Exit Status:
1470 ++Returns 0 unless an invalid option is given or an error occurs.
1471 ++$END
1472 ++
1473 ++/* Here is the mpi_scan builtin. */
1474 ++int
1475 ++mpi_scan_builtin (list)
1476 ++ WORD_LIST *list;
1477 ++{
1478 ++ return reduction_like (list, "mpi_scan", MPI_Scan);
1479 ++}
1480 ++
1481 ++$BUILTIN mpi_exscan
1482 ++$FUNCTION mpi_exscan_builtin
1483 ++$SHORT_DOC mpi_exscan number name
1484 ++Perform an exclusive scan across all processes in the same MPI job.
1485 ++
1486 ++ -O OPERATION Operation to perform. Must be one of "max", "min",
1487 ++ "sum", "prod", "land", "band", "lor", "bor", "lxor",
1488 ++ "bxor", "maxloc", or "minloc" (default: "sum").
1489 ++
1490 ++Arguments:
1491 ++ NUMBER Integer to use in the scan operation.
1492 ++
1493 ++ NAME Array variable in which to receive the result and, in
1494 ++ the case of maxloc and minloc, the associated rank.
1495 ++
1496 ++In a exclusive-scan operation, each process i presents a number, a[i].
1497 ++Once all processes in the MPI job have presented their number, the
1498 ++command assigns a[0] to NAME on rank 1, a[0]+a[1] to NAME on rank 2,
1499 ++a[0]+a[1]+a[2] to NAME on rank 3, and so forth. No assignment is
1500 ++performed on rank 0. The -O option enables "+" to be replaced with
1501 ++other operations.
1502 ++
1503 ++Exclusive scans can be useful for assigning a unique index to each
1504 ++process in the MPI job.
1505 ++
1506 ++Exit Status:
1507 ++Returns 0 unless an invalid option is given or an error occurs.
1508 ++$END
1509 ++
1510 ++/* Here is the mpi_exscan builtin. */
1511 ++int
1512 ++mpi_exscan_builtin (list)
1513 ++ WORD_LIST *list;
1514 ++{
1515 ++ return reduction_like (list, "mpi_exscan", MPI_Exscan);
1516 ++}
1517 ++
1518 ++$BUILTIN mpi_allreduce
1519 ++$FUNCTION mpi_allreduce_builtin
1520 ++$SHORT_DOC mpi_allreduce number name
1521 ++Reduce numbers from all processes in an MPI job to a single number.
1522 ++
1523 ++Options:
1524 ++
1525 ++ -O OPERATION Operation to perform. Must be one of "max", "min",
1526 ++ "sum", "prod", "land", "band", "lor", "bor", "lxor",
1527 ++ "bxor", "maxloc", or "minloc" (default: "sum").
1528 ++
1529 ++Arguments:
1530 ++ NUMBER Integer to use in the allreduce operation.
1531 ++
1532 ++ NAME Array variable in which to receive the result and, in
1533 ++ the case of maxloc and minloc, the associated rank.
1534 ++
1535 ++In an all-reduce operation, each process i presents a number, a[i].
1536 ++Once all processes in the MPI job have presented their number, the
1537 ++command returns a[0]+a[1]+...+a[n-1] to all ranks. The -O option
1538 ++enables "+" to be replaced with other operations.
1539 ++
1540 ++All-reduces can be useful for reaching global agreement (e.g., of a
1541 ++termination condition).
1542 ++
1543 ++Exit Status:
1544 ++Returns 0 unless an invalid option is given or an error occurs.
1545 ++$END
1546 ++
1547 ++/* Here is the mpi_allreduce builtin. */
1548 ++int
1549 ++mpi_allreduce_builtin (list)
1550 ++ WORD_LIST *list;
1551 ++{
1552 ++ return reduction_like (list, "mpi_allreduce", MPI_Allreduce);
1553 ++}
1554 +diff -Naur bash-4.3/config.h.in mpibash-4.3/config.h.in
1555 +--- bash-4.3/config.h.in 2013-06-29 15:35:33.000000000 -0600
1556 ++++ mpibash-4.3/config.h.in 2014-05-13 11:27:37.314100671 -0600
1557 +@@ -1147,6 +1147,12 @@
1558 + /* Define if you have the `__argz_stringify' function. */
1559 + #undef HAVE___ARGZ_STRINGIFY
1560 +
1561 ++/* Define if you have both the <libcircle.h> header file and the libcircle library. */
1562 ++#undef HAVE_LIBCIRCLE
1563 ++
1564 ++/* Define if you have the `CIRCLE_cb_reduce_op' function. */
1565 ++#undef HAVE_CIRCLE_CB_REDUCE_OP
1566 ++
1567 + /* End additions for lib/intl */
1568 +
1569 + #include "config-bot.h"
1570 +diff -Naur bash-4.3/configure.ac mpibash-4.3/configure.ac
1571 +--- bash-4.3/configure.ac 2014-02-11 08:37:53.000000000 -0700
1572 ++++ mpibash-4.3/configure.ac 2014-05-13 11:27:37.302100179 -0600
1573 +@@ -24,7 +24,7 @@
1574 + AC_REVISION([for Bash 4.3, version 4.063])dnl
1575 +
1576 + define(bashvers, 4.3)
1577 +-define(relstatus, release)
1578 ++define(relstatus, MPI)
1579 +
1580 + AC_INIT([bash], bashvers-relstatus, [bug-bash@×××.org])
1581 +
1582 +@@ -813,6 +813,21 @@
1583 + fi
1584 + ])
1585 +
1586 ++dnl Ensure that we can find an MPI library.
1587 ++AC_CHECK_FUNCS([MPI_Init], [], [
1588 ++ AC_MSG_ERROR([Cannot continue without MPI. Consider specifying CC=mpicc.])])
1589 ++
1590 ++dnl If we have Libcircle, use it, too.
1591 ++AC_SEARCH_LIBS([CIRCLE_cb_create], [circle], [AC_CHECK_HEADERS([libcircle.h])])
1592 ++if test "x$ac_cv_header_libcircle_h" = xyes; then
1593 ++ libcircle_make_prefix=""
1594 ++ AC_DEFINE([HAVE_LIBCIRCLE], [1], [Define if you have the Libcircle header and library.])
1595 ++ AC_CHECK_FUNCS([CIRCLE_cb_reduce_op])
1596 ++else
1597 ++ libcircle_make_prefix="#"
1598 ++fi
1599 ++AC_SUBST([CIRCLE], [$libcircle_make_prefix])
1600 ++
1601 + BASH_CHECK_DECL(strtoimax)
1602 + BASH_CHECK_DECL(strtol)
1603 + BASH_CHECK_DECL(strtoll)
1604 +diff -Naur bash-4.3/Makefile.in mpibash-4.3/Makefile.in
1605 +--- bash-4.3/Makefile.in 2014-01-25 14:27:30.000000000 -0700
1606 ++++ mpibash-4.3/Makefile.in 2014-05-13 11:27:37.314100671 -0600
1607 +@@ -104,7 +104,7 @@
1608 + VERSPROG = bashversion$(EXEEXT)
1609 + VERSOBJ = bashversion.$(OBJEXT)
1610 +
1611 +-Program = bash$(EXEEXT)
1612 ++Program = mpibash$(EXEEXT)
1613 + Version = @BASHVERS@
1614 + PatchLevel = `$(BUILD_DIR)/$(VERSPROG) -p`
1615 + RELSTATUS = @RELSTATUS@
1616 +diff -Naur bash-4.3/shell.c mpibash-4.3/shell.c
1617 +--- bash-4.3/shell.c 2014-01-14 06:04:32.000000000 -0700
1618 ++++ mpibash-4.3/shell.c 2014-05-13 11:27:37.314100671 -0600
1619 +@@ -107,6 +107,13 @@
1620 + extern char *primary_prompt, *secondary_prompt;
1621 + extern char *this_command_name;
1622 +
1623 ++extern void initialize_mpi __P((int, char **));
1624 ++extern void finalize_mpi __P((void));
1625 ++#ifdef HAVE_LIBCIRCLE
1626 ++extern void initialize_libcircle __P((int, char **));
1627 ++extern void finalize_libcircle __P((void));
1628 ++#endif
1629 ++
1630 + /* Non-zero means that this shell has already been run; i.e. you should
1631 + call shell_reinitialize () if you need to start afresh. */
1632 + int shell_initialized = 0;
1633 +@@ -324,7 +331,7 @@
1634 + static void init_interactive_script __P((void));
1635 +
1636 + static void set_shell_name __P((char *));
1637 +-static void shell_initialize __P((void));
1638 ++static void shell_initialize __P((int, char **));
1639 + static void shell_reinitialize __P((void));
1640 +
1641 + static void show_shell_usage __P((FILE *, int));
1642 +@@ -561,7 +568,7 @@
1643 +
1644 + /* From here on in, the shell must be a normal functioning shell.
1645 + Variables from the environment are expected to be set, etc. */
1646 +- shell_initialize ();
1647 ++ shell_initialize (argc, argv);
1648 +
1649 + set_default_lang ();
1650 + set_default_locale_vars ();
1651 +@@ -941,6 +948,12 @@
1652 + end_job_control ();
1653 + #endif /* JOB_CONTROL */
1654 +
1655 ++#ifdef HAVE_LIBCIRCLE
1656 ++ finalize_libcircle ();
1657 ++#else
1658 ++ finalize_mpi ();
1659 ++#endif
1660 ++
1661 + /* Always return the exit status of the last command to our parent. */
1662 + sh_exit (s);
1663 + }
1664 +@@ -1691,7 +1704,9 @@
1665 + /* Do whatever is necessary to initialize the shell.
1666 + Put new initializations in here. */
1667 + static void
1668 +-shell_initialize ()
1669 ++shell_initialize (argc, argv)
1670 ++ int argc;
1671 ++ char **argv;
1672 + {
1673 + char hostname[256];
1674 +
1675 +@@ -1760,6 +1775,17 @@
1676 + initialize_shell_options (privileged_mode||running_setuid);
1677 + initialize_bashopts (privileged_mode||running_setuid);
1678 + #endif
1679 ++
1680 ++ /* Initialize Libcircle and MPI. */
1681 ++#ifdef HAVE_LIBCIRCLE
1682 ++ initialize_libcircle (argc, argv);
1683 ++ initialize_mpi (argc, argv);
1684 ++ bind_variable ("libcircle", "yes", 0);
1685 ++#else
1686 ++ initialize_mpi (argc, argv);
1687 ++ bind_variable ("libcircle", "no", 0);
1688 ++#endif
1689 ++ bind_variable ("mpibash", "yes", 0);
1690 + }
1691 +
1692 + /* Function called by main () when it appears that the shell has already
1693
1694 diff --git a/app-shells/mpibash/metadata.xml b/app-shells/mpibash/metadata.xml
1695 new file mode 100644
1696 index 0000000..8598dc9
1697 --- /dev/null
1698 +++ b/app-shells/mpibash/metadata.xml
1699 @@ -0,0 +1,16 @@
1700 +<?xml version="1.0" encoding="UTF-8"?>
1701 +<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
1702 +<pkgmetadata>
1703 +<herd>base-system</herd>
1704 +<use>
1705 + <flag name='bashlogger'>Log ALL commands typed into bash; should ONLY be
1706 + used in restricted environments such as honeypots</flag>
1707 + <flag name='mem-scramble'>Build with custom malloc/free overwriting allocated/freed memory</flag>
1708 + <flag name='net'>Enable /dev/tcp/host/port redirection</flag>
1709 + <flag name='plugins'>Add support for loading builtins at runtime via
1710 + 'enable'</flag>
1711 +</use>
1712 +<upstream>
1713 + <remote-id type="cpe">cpe:/a:gnu:bash</remote-id>
1714 +</upstream>
1715 +</pkgmetadata>
1716
1717 diff --git a/app-shells/mpibash/mpibash-4.3_p24.ebuild b/app-shells/mpibash/mpibash-4.3_p24.ebuild
1718 new file mode 100644
1719 index 0000000..cf8e545
1720 --- /dev/null
1721 +++ b/app-shells/mpibash/mpibash-4.3_p24.ebuild
1722 @@ -0,0 +1,259 @@
1723 +# Copyright 1999-2014 Gentoo Foundation
1724 +# Distributed under the terms of the GNU General Public License v2
1725 +# $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 $
1726 +
1727 +EAPI="4"
1728 +
1729 +inherit autotools eutils flag-o-matic toolchain-funcs multilib
1730 +
1731 +# Official patchlevel
1732 +# See ftp://ftp.cwru.edu/pub/bash/bash-4.3-patches/
1733 +PLEVEL=${PV##*_p}
1734 +MY_PV=${PV/_p*}
1735 +MY_PV=${MY_PV/_/-}
1736 +MY_P=${PN#mpi}-${MY_PV}
1737 +[[ ${PV} != *_p* ]] && PLEVEL=0
1738 +patches() {
1739 + local opt=$1 plevel=${2:-${PLEVEL}} pn=${3:-${PN#mpi}} pv=${4:-${MY_PV}}
1740 + [[ ${plevel} -eq 0 ]] && return 1
1741 + eval set -- {1..${plevel}}
1742 + set -- $(printf "${pn}${pv/\.}-%03d " "$@")
1743 + if [[ ${opt} == -s ]] ; then
1744 + echo "${@/#/${DISTDIR}/}"
1745 + else
1746 + local u
1747 + for u in ftp://ftp.cwru.edu/pub/bash mirror://gnu/${pn} ; do
1748 + printf "${u}/${pn}-${pv}-patches/%s " "$@"
1749 + done
1750 + fi
1751 +}
1752 +
1753 +# The version of readline this bash normally ships with.
1754 +READLINE_VER="6.3"
1755 +
1756 +DESCRIPTION="Parallel scripting right from the Bourne-Again Shell (Bash)"
1757 +HOMEPAGE="http://www.ccs3.lanl.gov/~pakin/software/mpibash-4.3.html"
1758 +SRC_URI="mirror://gnu/bash/${MY_P}.tar.gz $(patches)"
1759 +[[ ${PV} == *_rc* ]] && SRC_URI+=" ftp://ftp.cwru.edu/pub/bash/${MY_P}.tar.gz"
1760 +
1761 +LICENSE="GPL-3"
1762 +SLOT="0"
1763 +#KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~amd64-fbsd ~sparc-fbsd ~x86-fbsd"
1764 +IUSE="afs bashlogger examples mem-scramble +net nls plugins +readline vanilla"
1765 +
1766 +DEPEND=">=sys-libs/ncurses-5.2-r2
1767 + readline? ( >=sys-libs/readline-${READLINE_VER} )
1768 + nls? ( virtual/libintl )"
1769 +RDEPEND="${DEPEND}
1770 + virtual/mpi
1771 + sys-cluster/libcircle
1772 + !<sys-apps/portage-2.1.6.7_p1
1773 + !<sys-apps/paludis-0.26.0_alpha5"
1774 +# we only need yacc when the .y files get patched (bash42-005)
1775 +DEPEND+=" virtual/yacc"
1776 +
1777 +S=${WORKDIR}/${MY_P}
1778 +
1779 +pkg_setup() {
1780 + if is-flag -malign-double ; then #7332
1781 + eerror "Detected bad CFLAGS '-malign-double'. Do not use this"
1782 + eerror "as it breaks LFS (struct stat64) on x86."
1783 + die "remove -malign-double from your CFLAGS mr ricer"
1784 + fi
1785 + if use bashlogger ; then
1786 + ewarn "The logging patch should ONLY be used in restricted (i.e. honeypot) envs."
1787 + ewarn "This will log ALL output you enter into the shell, you have been warned."
1788 + fi
1789 +}
1790 +
1791 +src_unpack() {
1792 + unpack ${MY_P}.tar.gz
1793 +}
1794 +
1795 +src_prepare() {
1796 + # Include official patches
1797 + [[ ${PLEVEL} -gt 0 ]] && epatch $(patches -s)
1798 +
1799 + # Clean out local libs so we know we use system ones w/releases.
1800 + if [[ ${PV} != *_rc* ]] ; then
1801 + rm -rf lib/{readline,termcap}/*
1802 + touch lib/{readline,termcap}/Makefile.in # for config.status
1803 + sed -ri -e 's:\$[(](RL|HIST)_LIBSRC[)]/[[:alpha:]]*.h::g' Makefile.in || die
1804 + fi
1805 +
1806 + # Avoid regenerating docs after patches #407985
1807 + sed -i -r '/^(HS|RL)USER/s:=.*:=:' doc/Makefile.in || die
1808 + touch -r . doc/*
1809 +
1810 + epatch "${FILESDIR}"/${PN#mpi}-4.3-compat-lvl.patch
1811 + epatch "${FILESDIR}"/${PN#mpi}-4.3-parse-time-keyword.patch
1812 + epatch "${FILESDIR}"/${PN#mpi}-4.3-append-process-segfault.patch
1813 + epatch "${FILESDIR}"/${PN}-4.3.patch
1814 +
1815 + epatch_user
1816 +
1817 + eautoconf
1818 +}
1819 +
1820 +src_configure() {
1821 + local myconf=()
1822 +
1823 + # For descriptions of these, see config-top.h
1824 + # bashrc/#26952 bash_logout/#90488 ssh/#24762
1825 + append-cppflags \
1826 + -DDEFAULT_PATH_VALUE=\'\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"\' \
1827 + -DSTANDARD_UTILS_PATH=\'\"/bin:/usr/bin:/sbin:/usr/sbin\"\' \
1828 + -DSYS_BASHRC=\'\"/etc/bash/bashrc\"\' \
1829 + -DSYS_BASH_LOGOUT=\'\"/etc/bash/bash_logout\"\' \
1830 + -DNON_INTERACTIVE_LOGIN_SHELLS \
1831 + -DSSH_SOURCE_BASHRC \
1832 + $($(tc-getPKG_CONFIG) --cflags libcircle) \
1833 + $(use bashlogger && echo -DSYSLOG_HISTORY)
1834 +
1835 + # Don't even think about building this statically without
1836 + # reading Bug 7714 first. If you still build it statically,
1837 + # don't come crying to us with bugs ;).
1838 + #use static && export LDFLAGS="${LDFLAGS} -static"
1839 + use nls || myconf+=( --disable-nls )
1840 +
1841 + # Historically, we always used the builtin readline, but since
1842 + # our handling of SONAME upgrades has gotten much more stable
1843 + # in the PM (and the readline ebuild itself preserves the old
1844 + # libs during upgrades), linking against the system copy should
1845 + # be safe.
1846 + # Exact cached version here doesn't really matter as long as it
1847 + # is at least what's in the DEPEND up above.
1848 + export ac_cv_rl_version=${READLINE_VER}
1849 +
1850 + # Force linking with system curses ... the bundled termcap lib
1851 + # sucks bad compared to ncurses. For the most part, ncurses
1852 + # is here because readline needs it. But bash itself calls
1853 + # ncurses in one or two small places :(.
1854 +
1855 + if [[ ${PV} != *_rc* ]] ; then
1856 + # Use system readline only with released versions.
1857 + myconf+=( --with-installed-readline=. )
1858 + fi
1859 +
1860 + if use plugins; then
1861 + append-ldflags -Wl,-rpath,/usr/$(get_libdir)/bash
1862 + else
1863 + # Disable the plugins logic by hand since bash doesn't
1864 + # provide a way of doing it.
1865 + export ac_cv_func_dl{close,open,sym}=no \
1866 + ac_cv_lib_dl_dlopen=no ac_cv_header_dlfcn_h=no
1867 + sed -i \
1868 + -e '/LOCAL_LDFLAGS=/s:-rdynamic::' \
1869 + configure || die
1870 + fi
1871 + tc-export AR #444070
1872 + LIBS="-lcircle" CC=mpicc \
1873 + econf \
1874 + --docdir='$(datarootdir)'/doc/${PF} \
1875 + --htmldir='$(docdir)/html' \
1876 + --with-curses \
1877 + $(use_with afs) \
1878 + $(use_enable net net-redirections) \
1879 + --disable-profiling \
1880 + $(use_enable mem-scramble) \
1881 + $(use_with mem-scramble bash-malloc) \
1882 + $(use_enable readline) \
1883 + $(use_enable readline history) \
1884 + $(use_enable readline bang-history) \
1885 + "${myconf[@]}"
1886 +}
1887 +
1888 +src_compile() {
1889 + emake
1890 +
1891 + if use plugins ; then
1892 + emake -C examples/loadables all others
1893 + fi
1894 +}
1895 +
1896 +src_install() {
1897 + local d f
1898 +
1899 + default
1900 +
1901 + find "${ED}" -name "bashbug*" -delete
1902 + mv "${ED}"/usr/share/man/man1/{,mpi}bash.1 || die
1903 + mv "${ED}"/usr/share/info/{,mpi}bash.info || die
1904 + return 0
1905 +
1906 + dodir /bin
1907 + mv "${ED}"/usr/bin/bash "${ED}"/bin/ || die
1908 + dosym bash /bin/rbash
1909 +
1910 + insinto /etc/bash
1911 + doins "${FILESDIR}"/{bashrc,bash_logout}
1912 + insinto /etc/skel
1913 + for f in bash{_logout,_profile,rc} ; do
1914 + newins "${FILESDIR}"/dot-${f} .${f}
1915 + done
1916 +
1917 + local sed_args=(
1918 + -e "s:#${USERLAND}#@::"
1919 + -e '/#@/d'
1920 + )
1921 + if ! use readline ; then
1922 + sed_args+=( #432338
1923 + -e '/^shopt -s histappend/s:^:#:'
1924 + -e 's:use_color=true:use_color=false:'
1925 + )
1926 + fi
1927 + sed -i \
1928 + "${sed_args[@]}" \
1929 + "${ED}"/etc/skel/.bashrc \
1930 + "${ED}"/etc/bash/bashrc || die
1931 +
1932 + if use plugins ; then
1933 + exeinto /usr/$(get_libdir)/bash
1934 + doexe $(echo examples/loadables/*.o | sed 's:\.o::g')
1935 + insinto /usr/include/bash-plugins
1936 + doins *.h builtins/*.h include/*.h lib/{glob/glob.h,tilde/tilde.h}
1937 + fi
1938 +
1939 + if use examples ; then
1940 + for d in examples/{functions,misc,scripts,scripts.noah,scripts.v2} ; do
1941 + exeinto /usr/share/doc/${PF}/${d}
1942 + insinto /usr/share/doc/${PF}/${d}
1943 + for f in ${d}/* ; do
1944 + if [[ ${f##*/} != PERMISSION ]] && [[ ${f##*/} != *README ]] ; then
1945 + doexe ${f}
1946 + else
1947 + doins ${f}
1948 + fi
1949 + done
1950 + done
1951 + fi
1952 +
1953 + doman doc/*.1
1954 + newdoc CWRU/changelog ChangeLog
1955 + dosym bash.info /usr/share/info/bashref.info
1956 +}
1957 +
1958 +pkg_preinst() {
1959 + return 0
1960 + if [[ -e ${EROOT}/etc/bashrc ]] && [[ ! -d ${EROOT}/etc/bash ]] ; then
1961 + mkdir -p "${EROOT}"/etc/bash
1962 + mv -f "${EROOT}"/etc/bashrc "${EROOT}"/etc/bash/
1963 + fi
1964 +
1965 + if [[ -L ${EROOT}/bin/sh ]] ; then
1966 + # rewrite the symlink to ensure that its mtime changes. having /bin/sh
1967 + # missing even temporarily causes a fatal error with paludis.
1968 + local target=$(readlink "${EROOT}"/bin/sh)
1969 + local tmp=$(emktemp "${EROOT}"/bin)
1970 + ln -sf "${target}" "${tmp}"
1971 + mv -f "${tmp}" "${EROOT}"/bin/sh
1972 + fi
1973 +}
1974 +
1975 +pkg_postinst() {
1976 + return 0
1977 + # If /bin/sh does not exist, provide it
1978 + if [[ ! -e ${EROOT}/bin/sh ]] ; then
1979 + ln -sf bash "${EROOT}"/bin/sh
1980 + fi
1981 +}