summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastien Fabbro <bicatali@gentoo.org>2008-11-05 22:13:59 +0000
committerSebastien Fabbro <bicatali@gentoo.org>2008-11-05 22:13:59 +0000
commitceed812a7c9f5e4e6ebd9d09ab0c8c1c574dad75 (patch)
treebcb0d4f33daf65fb8902c54d792fd7b2ead4753f /sci-astronomy
parentInitial import (diff)
downloadgentoo-2-ceed812a7c9f5e4e6ebd9d09ab0c8c1c574dad75.tar.gz
gentoo-2-ceed812a7c9f5e4e6ebd9d09ab0c8c1c574dad75.tar.bz2
gentoo-2-ceed812a7c9f5e4e6ebd9d09ab0c8c1c574dad75.zip
Initial import
(Portage version: 2.2_rc11/cvs/Linux 2.6.25-gentoo-r7 x86_64)
Diffstat (limited to 'sci-astronomy')
-rw-r--r--sci-astronomy/funtools/ChangeLog12
-rw-r--r--sci-astronomy/funtools/Manifest6
-rw-r--r--sci-astronomy/funtools/files/funtools-1.4.0-ds9-5.4.patch2475
-rw-r--r--sci-astronomy/funtools/files/funtools-1.4.0-makefiles.patch368
-rw-r--r--sci-astronomy/funtools/funtools-1.4.0.ebuild55
-rw-r--r--sci-astronomy/funtools/metadata.xml12
6 files changed, 2928 insertions, 0 deletions
diff --git a/sci-astronomy/funtools/ChangeLog b/sci-astronomy/funtools/ChangeLog
new file mode 100644
index 000000000000..674c84bf8d85
--- /dev/null
+++ b/sci-astronomy/funtools/ChangeLog
@@ -0,0 +1,12 @@
+# ChangeLog for sci-astronomy/funtools
+# Copyright 1999-2008 Gentoo Foundation; Distributed under the GPL v2
+# $Header: /var/cvsroot/gentoo-x86/sci-astronomy/funtools/ChangeLog,v 1.1 2008/11/05 22:13:59 bicatali Exp $
+
+*funtools-1.4.0 (05 Nov 2008)
+
+ 05 Nov 2008; Sébastien Fabbro <bicatali@gentoo.org>
+ +files/funtools-1.4.0-ds9-5.4.patch,
+ +files/funtools-1.4.0-makefiles.patch, +metadata.xml,
+ +funtools-1.4.0.ebuild:
+ Initial import
+
diff --git a/sci-astronomy/funtools/Manifest b/sci-astronomy/funtools/Manifest
new file mode 100644
index 000000000000..f037f5fd811e
--- /dev/null
+++ b/sci-astronomy/funtools/Manifest
@@ -0,0 +1,6 @@
+AUX funtools-1.4.0-ds9-5.4.patch 61571 RMD160 0bf225a206ec2f3f1a4529229c1cc9a6eeca5b96 SHA1 43476971dba93e3d6b1b38ceccb1c8670b6353ef SHA256 96ba34ad5af4e35ffbb2775609da87378c5291b0a4f89a82d24bbaf3e1a15d95
+AUX funtools-1.4.0-makefiles.patch 10907 RMD160 1e1e955960fe288fea053712155d23d86587cbea SHA1 12fd50b394239633a664b15a91311f36b54f4aaa SHA256 a6964c87c2272eef85ab6167e89016ad05cec25c1a3854e5a9def86387f52914
+DIST funtools-1.4.0.tar.gz 3253384 RMD160 f566ac1dfd5724171f46507ccbdec6f80a168f5b SHA1 cf24c89acd4a4e6815336e0cbc4d445998d89db3 SHA256 9a7cb60dcec93879d75cc682b11abc05b04e0ed64d11f56dedbd05eca316a1d7
+EBUILD funtools-1.4.0.ebuild 1259 RMD160 06bbfa50b4b07e82931940bec853a82ef8eb004c SHA1 97f3284fe9e99d27434458f5621eb14de1699879 SHA256 ddae219eb2bd68909661786760ee09babfa69a395c8ac0a3fa6f1716b584edbe
+MISC ChangeLog 348 RMD160 f90b0eebfa8b39d5ea116c15d436f0619e126cc4 SHA1 d38a32cb126748c4de91fd8dbb7dfbea03cd4f69 SHA256 be3bd4ce1595bc5e03b5a94cc1e51217fbe602174f19c0a7972c9a6ef72440de
+MISC metadata.xml 510 RMD160 57f4fbe12f07386a337460992c906fc598035562 SHA1 d4e3e4e617f36b00158e4f7aa38f5b924023c712 SHA256 bb4351e9a8a65b4d087a015350702c5da7d3d47a83bb5a4e2a763be302f0ce9d
diff --git a/sci-astronomy/funtools/files/funtools-1.4.0-ds9-5.4.patch b/sci-astronomy/funtools/files/funtools-1.4.0-ds9-5.4.patch
new file mode 100644
index 000000000000..da7f5e48c9c6
--- /dev/null
+++ b/sci-astronomy/funtools/files/funtools-1.4.0-ds9-5.4.patch
@@ -0,0 +1,2475 @@
+--- filter/evfilter.c.orig 2005-12-07 21:29:34.000000000 +0000
++++ filter/evfilter.c 2007-12-18 20:10:26.000000000 +0000
+@@ -65,6 +65,9 @@
+ g->masks = _masks;
+ }
+ /* initialize shapes -- but check to make sure eptr is OK */
++#if DO_FILTER_SWAP
++ memset(_swf, 0, EVSIZE);
++#endif
+ if( eptr ) FINIT;
+ /* these also must be defined if EVSECT is being used */
+ g->tlminx = TLMINX;
+@@ -115,6 +118,9 @@
+ /* do the filtering on each event */
+ for(rptr=rbuf, eptr=ebuf; ne--; rptr++, eptr += esize){
+ g->rid = 0;
++#if DO_FILTER_SWAP
++ memset(_swf, 0, EVSIZE);
++#endif
+ *rptr = ((FILTER) ? (g->rid ? g->rid : -1) : 0);
+ }
+ return (void *)g;
+@@ -123,14 +129,48 @@
+
+ int main(int argc, char **argv)
+ {
+- char *ebuf, *etop;
+- int *rbuf;
++ int i;
++ int pipes[4];
+ int get, got;
++#if DO_FILTER_SWAP
++ int sgot;
++#endif
+ int n;
++ int *rbuf;
++ char *ebuf, *etop;
++ char *s=NULL, *t=NULL, *u=NULL;
+ void *g=NULL;
+
++ /* Launch() sometimes rearranges passed pipes to be stdin/stdout */
++ if( (s=getenv("LAUNCH_PIPES")) ){
++ t = (char *)strdup(s);
++ for(i=0, u=(char *)strtok(t, ","); i<4 && u;
++ i++, u=(char *)strtok(NULL,",")){
++ pipes[i] = atoi(u);
++ }
++ if( t ) free(t);
++ if( i < 4 ) return(1);
++ close(pipes[0]);
++ close(pipes[3]);
++ dup2(pipes[2], 0); close(pipes[2]);
++ dup2(pipes[1], 1); close(pipes[1]);
++ }
++
+ /* read and filter events */
+ while( read(0, &get, sizeof(int)) >0 ){
++#if DO_FILTER_SWAP
++ switch(sizeof(int)){
++ case 2:
++ _sw2((char *)&get,2,NULL,0);
++ break;
++ case 4:
++ _sw4((char *)&get,4,NULL,0);
++ break;
++ case 8:
++ _sw8((char *)&get,8,NULL,0);
++ break;
++ }
++#endif
+ ebuf = (char *)calloc(get, sizeof(char));
+ for(n=0, etop=ebuf; get>0; etop += got, get -= got){
+ if( (got=read(0, etop, get)) <=0 )
+@@ -144,7 +184,36 @@
+ g = EVFILTRTN(g, ebuf, n, EVSIZE, rbuf);
+ /* write results */
+ got = n*sizeof(int);
++#if DO_FILTER_SWAP
++ sgot = got;
++ switch(sizeof(int)){
++ case 2:
++ _sw2((char *)&sgot,2,NULL,0);
++ break;
++ case 4:
++ _sw4((char *)&sgot,4,NULL,0);
++ break;
++ case 8:
++ _sw8((char *)&sgot,8,NULL,0);
++ break;
++ }
++ write(1, &sgot, sizeof(int));
++#else
+ write(1, &got, sizeof(int));
++#endif
++#if DO_FILTER_SWAP
++ switch(sizeof(int)){
++ case 2:
++ _sw2((char *)rbuf,got,NULL,0);
++ break;
++ case 4:
++ _sw4((char *)rbuf,got,NULL,0);
++ break;
++ case 8:
++ _sw8((char *)rbuf,got,NULL,0);
++ break;
++ }
++#endif
+ write(1, rbuf, got);
+ if( ebuf) free(ebuf);
+ if( rbuf ) free(rbuf);
+--- filter/filter.c.orig 2007-04-13 18:18:34.000000000 +0100
++++ filter/filter.c 2007-12-18 20:10:26.000000000 +0000
+@@ -215,7 +215,6 @@
+ int got=0;
+ char *s, *t;
+ char tbuf[SZ_LINE];
+- char *argv[3];
+ Filter filter;
+ char *filtstr;
+
+@@ -471,11 +470,7 @@
+ switch(filter->ptype){
+ case PTYPE_PROCESS:
+ case PTYPE_CONTAINED:
+- /* now start the filter process we just readied */
+- argv[0] = filter->prog;
+- argv[1] = filter->args;
+- argv[2] = NULL;
+- if( !ProcessOpen(filter->prog, argv,
++ if( !ProcessOpen(filter->prog,
+ &(filter->ichan), &(filter->ochan), &(filter->pid)) )
+ goto error;
+ break;
+@@ -785,7 +780,6 @@
+ if( filter->shflags ) xfree(filter->shflags);
+ if( filter->code ) xfree(filter->code);
+ if( filter->prog ) xfree(filter->prog);
+- if( filter->args ) xfree(filter->args);
+ if( filter->string ) xfree(filter->string);
+ if( filter->xbin ) xfree(filter->xbin);
+ if( filter->ybin ) xfree(filter->ybin);
+--- filter/filtprog_c.c.orig 2006-12-12 21:39:07.000000000 +0000
++++ filter/filtprog_c.c 2007-12-18 20:10:26.000000000 +0000
+@@ -16,6 +16,7 @@
+ #include <evregions_c.h>
+ #include <imregions_c.h>
+ #include <xalloc_c.h>
++#include <swap_c.h>
+
+ /*
+ *
+@@ -316,6 +317,14 @@
+ break;
+ }
+
++ /* we want the byte order up at the top */
++ if( is_bigendian() ){
++ fprintf(fd, "#define MYBYTE_ORDER 4321\n");
++ }
++ else{
++ fprintf(fd, "#define MYBYTE_ORDER 1234\n");
++ }
++
+ /* prepend the filter header */
+ contents = REGIONS_H;
+ if( (contents != NULL) && (*contents != '\0') ){
+@@ -418,6 +427,7 @@
+ if( (contents != NULL) && (*contents != '\0') ){
+ fprintf(fd, "%s\n", contents);
+ }
++ /* region routines if not linking against previously compiled code */
+ switch( filter->type ){
+ case TYPE_EVENTS:
+ /* normally, we filter events analytically using evregions.o */
+@@ -446,6 +456,12 @@
+ break;
+ }
+
++ /* always need the swap routines (they're part of the filter) */
++ contents = SWAP_C;
++ if( (contents != NULL) && (*contents != '\0') ){
++ fprintf(fd, "%s\n", contents);
++ }
++
+ /* output counts of shapes */
+ fprintf(fd, "#define NSHAPE %d\n",
+ FilterShapeCount());
+@@ -533,10 +549,13 @@
+ t = "";
+ }
+ if( fhd->table->col[sp->idx].n == 1 ){
+- fprintf(fd, "#define %s %s*((%s *)(eptr+%d))%s\n",
++ fprintf(fd, "#define %s %s*((%s *)(SW%d(eptr+%d,%d,_swf,%d)))%s\n",
+ sp->name,
+ s,
+ GetType((int)fhd->table->col[sp->idx].type),
++ dsize,
++ offset,
++ dsize,
+ offset,
+ t);
+ }
+@@ -548,18 +567,21 @@
+ sp->name, s, "unsigned char", offset, t);
+ break;
+ case 16:
+- fprintf(fd, "#define %s %s*((%s *)(eptr+%d))%s\n",
+- sp->name, s, "unsigned short", offset, t);
++ fprintf(fd, "#define %s %s*((%s *)(SW2(eptr+%d,%d,_swf,%d)))%s\n",
++ sp->name, s, "unsigned short", offset, 2, offset, t);
+ break;
+ case 32:
+- fprintf(fd, "#define %s %s*((%s *)(eptr+%d))%s\n",
+- sp->name, s, "unsigned int", offset, t);
++ fprintf(fd, "#define %s %s*((%s *)(SW4(eptr+%d,%d,_swf,%d)))%s\n",
++ sp->name, s, "unsigned int", offset, 4, offset, t);
+ break;
+ default:
+- fprintf(fd, "#define %s %s((%s *)(eptr+%d))%s\n",
++ fprintf(fd, "#define %s %s((%s *)(SW%d(eptr+%d,%d,_swf,%d)))%s\n",
+ sp->name,
+ s,
+ GetType((int)fhd->table->col[sp->idx].type),
++ dsize,
++ offset,
++ dsize,
+ offset,
+ t);
+ }
+@@ -571,10 +593,13 @@
+ fhd->table->col[sp->idx].n);
+ }
+ else{
+- fprintf(fd, "#define %s %s((%s *)(eptr+%d))%s\n",
++ fprintf(fd, "#define %s %s((%s *)(SW%d(eptr+%d,%d,_swf,%d)))%s\n",
+ sp->name,
+ s,
+ GetType((int)fhd->table->col[sp->idx].type),
++ dsize,
++ offset,
++ dsize,
+ offset,
+ t);
+ }
+@@ -628,6 +653,7 @@
+ if( evsize <=0 ) evsize = 1;
+ /* output the size of the filter record */
+ fprintf(fd, "#define EVSIZE %d\n", evsize);
++ fprintf(fd, "static char _swf[%d];\n", evsize);
+ /* save for later use */
+ filter->evsize = evsize;
+ break;
+@@ -829,7 +855,7 @@
+ stdfiles[0] = NULL;
+ stdfiles[1] = "/dev/null";
+ stdfiles[2] = log;
+- got = launch(tbuf, 1, stdfiles);
++ got = Launch(tbuf, 1, stdfiles, NULL);
+ #else
+ got = system(tbuf);
+ #endif
+@@ -860,7 +886,7 @@
+ }
+ else{
+ s = FileContents(log, 0, &len);
+- if( *s && len ){
++ if( s && *s && len ){
+ fprintf(stderr, "Compilation error message:\n%s\n", s);
+ }
+ if( !keep ){
+--- filter/idxacts.c.orig 2007-01-05 17:35:25.000000000 +0000
++++ filter/idxacts.c 2007-12-18 20:10:26.000000000 +0000
+@@ -179,9 +179,8 @@
+ int *pid;
+ #endif
+ {
+- int i=0;
+ char *s;
+- char *pargs[SZ_LINE];
++ char cmd[SZ_LINE];
+
+ if( !idxsort ){
+ if( idxpath ) return 0;
+@@ -190,28 +189,27 @@
+ }
+ if( !(idxsort=Find(IDX_SORTPROG, "x", NULL, idxpath)) &&
+ !(idxsort=Find(IDX_SORTPROG, "x", NULL, ".")) ){
++ idxerror("index sort program cannot be found");
+ return 0;
+ }
+ }
+- /* construct argument list for sort program */
+- pargs[i++] = (char *)idxsort;
+- pargs[i++] = "-B4";
+- pargs[i++] = "+i0";
++ /* construct command line for sort program */
+ switch(type){
+ case IDX_SORT:
++ snprintf(cmd, SZ_LINE-1, "%s -B4 +i0", idxsort);
+ break;
+ case IDX_OR_SORT:
+- pargs[i++] = "-u";
++ snprintf(cmd, SZ_LINE-1, "%s -B4 +i0 -u", idxsort);
+ break;
+ case IDX_AND_SORT:
+- pargs[i++] = "-D";
++ snprintf(cmd, SZ_LINE-1, "%s -B4 +i0 -D", idxsort);
+ break;
+ default:
++ snprintf(cmd, SZ_LINE-1, "%s -B4 +i0", idxsort);
+ break;
+ }
+- pargs[i++] = NULL;
+ /* start the sort program */
+- if( !ProcessOpen(idxsort, pargs, ichan, ochan, pid) ){
++ if( !ProcessOpen(cmd, ichan, ochan, pid) ){
+ idxerror("index sort process cannot be started");
+ return 0;
+ }
+--- filter/idx.h.orig 2007-01-04 17:34:57.000000000 +0000
++++ filter/idx.h 2007-12-18 20:10:26.000000000 +0000
+@@ -54,7 +54,7 @@
+ #define IDX_ROW_INC 32
+
+ /* sort program */
+-#define IDX_SORTPROG "_sort"
++#define IDX_SORTPROG "_funsort"
+
+ /* idxinfo which values */
+ #define IDX_COLNAME 1
+--- filter/imfilter.c.orig 2004-02-05 00:24:45.000000000 +0000
++++ filter/imfilter.c 2007-12-18 20:10:26.000000000 +0000
+@@ -192,19 +192,50 @@
+
+ int main(int argc, char **argv)
+ {
+-#ifdef TEST
+ int i;
++ int get, got;
++#if DO_FILTER_SWAP
++ int sgot;
+ #endif
+- int get;
+- int got;
++ int pipes[4];
+ int txmin, txmax, tymin, tymax, tblock;
+ char tbuf[SZ_LINE];
++ char *s=NULL, *t=NULL, *u=NULL;
++
++ /* Launch() sometimes rearranges passed pipes to be stdin/stdout */
++ if( (s=getenv("LAUNCH_PIPES")) ){
++ t = (char *)strdup(s);
++ for(i=0, u=(char *)strtok(t, ","); i<4 && u;
++ i++, u=(char *)strtok(NULL,",")){
++ pipes[i] = atoi(u);
++ }
++ if( t ) free(t);
++ if( i < 4 ) return(1);
++ close(pipes[0]);
++ close(pipes[3]);
++ dup2(pipes[2], 0); close(pipes[2]);
++ dup2(pipes[1], 1); close(pipes[1]);
++ }
+
+ /* process requests for region information for sections of the image */
+ #ifdef TEST
+ while( fgets(tbuf, SZ_LINE, stdin) ){
+ #else
+- while( (read(0, &get, sizeof(int)) >0) && (read(0, tbuf, get)==get) ){
++ while( (read(0, &get, sizeof(int)) >0) ){
++#if DO_FILTER_SWAP
++ switch(sizeof(int)){
++ case 2:
++ _sw2((char *)&get,2,NULL,0);
++ break;
++ case 4:
++ _sw4((char *)&get,4,NULL,0);
++ break;
++ case 8:
++ _sw8((char *)&get,8,NULL,0);
++ break;
++ }
++#endif
++ if(read(0, tbuf, get) != get) break;
+ #endif
+ if(sscanf(tbuf, "%d %d %d %d %d",
+ &txmin, &txmax, &tymin, &tymax, &tblock)!=5){
+@@ -222,7 +253,36 @@
+ #else
+ /* calculate size of data we will write */
+ got = got * sizeof(FilterMaskRec);
+- write(1, &got, 4);
++#if DO_FILTER_SWAP
++ sgot = got;
++ switch(sizeof(int)){
++ case 2:
++ _sw2((char *)&sgot,2,NULL,0);
++ break;
++ case 4:
++ _sw4((char *)&sgot,4,NULL,0);
++ break;
++ case 8:
++ _sw8((char *)&sgot,8,NULL,0);
++ break;
++ }
++ write(1, &sgot, sizeof(int));
++#else
++ write(1, &got, sizeof(int));
++#endif
++#if DO_FILTER_SWAP
++ switch(sizeof(int)){
++ case 2:
++ _sw2((char *)masks,got,NULL,0);
++ break;
++ case 4:
++ _sw4((char *)masks,got,NULL,0);
++ break;
++ case 8:
++ _sw8((char *)masks,got,NULL,0);
++ break;
++ }
++#endif
+ write(1, masks, got);
+ #endif
+ /* free mask records */
+--- filter/swap.c.orig 1970-01-01 01:00:00.000000000 +0100
++++ filter/swap.c 2007-12-18 20:10:26.000000000 +0000
+@@ -0,0 +1,90 @@
++#if __DARWIN_BYTE_ORDER
++#define XBYTE_ORDER __DARWIN_BYTE_ORDER
++#else
++#define XBYTE_ORDER 0
++#endif
++
++#ifndef MYBYTE_ORDER
++#define MYBYTE_ORDER XBYTE_ORDER
++#endif
++
++#ifndef DO_FILTER_SWAP
++#if (XBYTE_ORDER !=0) && (XBYTE_ORDER != MYBYTE_ORDER)
++#define DO_FILTER_SWAP 1
++#endif
++#endif
++
++#if DO_FILTER_SWAP
++char *_sw2(char *s, int n, char *_swf, int off)
++{
++ char c;
++ char *t=s;
++ size_t i;
++ if( !_swf || !_swf[off]++ ){
++ for (i=0; i<n; i += 2, s += 2) {
++ c = *s;
++ *(s) = *(s+1);
++ *(s+1) = c;
++ }
++ }
++ return t;
++}
++
++char *_sw4(char *s, int n, char *_swf, int off)
++{
++ char c;
++ char *t=s;
++ size_t i;
++ if( !_swf || !_swf[off]++ ){
++ for (i=0; i<n; i += 4, s += 4) {
++ c = *s;
++ *s = *(s+3);
++ *(s+3) = c;
++ c = *(s+1);
++ *(s+1) = *(s+2);
++ *(s+2) = c;
++ }
++ }
++ return t;
++}
++
++char *_sw8(char *s, int n, char *_swf, int off)
++{
++ char c;
++ char *t=s;
++ size_t i;
++ if( !_swf || !_swf[off]++ ){
++ for (i=0; i<n; i += 8, s += 8) {
++ c = *(s+0);
++ *(s+0) = *(s+7);
++ *(s+7) = c;
++ c = *(s+1);
++ *(s+1) = *(s+6);
++ *(s+6) = c;
++ c = *(s+2);
++ *(s+2) = *(s+5);
++ *(s+5) = c;
++ c = *(s+3);
++ *(s+3) = *(s+4);
++ *(s+4) = c;
++ }
++ }
++ return t;
++}
++
++#define SW2(a,n,b,i) _sw2(a,n,b,i)
++#define SW4(a,n,b,i) _sw4(a,n,b,i)
++#define SW8(a,n,b,i) _sw8(a,n,b,i)
++
++#if defined(FILTER_PTYPE) && (FILTER_PTYPE != c)
++#error "FILTER_PTYPE environment variable must be 'c' when running with Rosetta"
++#endif
++
++#else
++
++#define SW2(a,n,b,i) a
++#define SW4(a,n,b,i) a
++#define SW8(a,n,b,i) a
++
++#endif
++
+
+--- fitsy/fitsy.h.orig 2007-01-04 22:49:41.000000000 +0000
++++ fitsy/fitsy.h 2007-12-18 20:10:26.000000000 +0000
+@@ -11,7 +11,7 @@
+ #if USE_XFILEIO
+ #include <xfileio.h>
+ #else
+-#include "xfile.h"
++#include <xfile.h>
+ #endif
+
+ #ifdef __STDC__
+@@ -30,7 +30,7 @@
+
+ #include <ctype.h>
+
+-#include "longlong.h"
++#include <longlong.h>
+
+ #ifndef NULL
+ #define NULL 0
+--- funcalc.c.orig 2007-03-01 18:12:12.000000000 +0000
++++ funcalc.c 2007-12-18 20:10:26.000000000 +0000
+@@ -230,7 +230,7 @@
+ stdfiles[0] = NULL;
+ stdfiles[1] = "/dev/null";
+ stdfiles[2] = log;
+- got = launch(cmd, 1, stdfiles);
++ got = Launch(cmd, 1, stdfiles, NULL);
+ #else
+ snprintf(tbuf, SZ_LINE-1, " 1>/dev/null 2>%s", log);
+ strcat(cmd, tbuf);
+@@ -286,7 +286,7 @@
+ s = NULL;
+ }
+ s = FileContents(log, 0, &len);
+- if( *s && len )
++ if( s && *s && len )
+ fprintf(stderr, "Compilation error message:\n%s\n", s);
+ error = 1;
+ goto endgame;
+--- funtable.c.orig 2007-06-11 22:18:31.000000000 +0100
++++ funtable.c 2007-12-18 20:10:26.000000000 +0000
+@@ -11,7 +11,7 @@
+ static int maxrow=MAXROW;
+ static char macrobuf[SZ_LINE];
+
+-#define SORTPROG "_sort"
++#define SORTPROG "_funsort"
+
+ typedef struct rowstruct{
+ int x, y;
+@@ -90,6 +90,7 @@
+ int dtype, doffset, dmode, dn;
+ int plen, elen, flen;
+ int epad, ppad;
++ int rlen;
+ double dval;
+ char *iname=NULL;
+ char *oname=NULL;
+@@ -108,7 +109,7 @@
+ char *extn=NULL;
+ char col[SZ_LINE];
+ char tbuf[SZ_LINE];
+- char *pargs[SZ_LINE];
++ char cmd[SZ_LINE];
+ double *dbuf=NULL;
+ FILE *ifile;
+ Fun fun, tfun=NULL;
+@@ -280,20 +281,21 @@
+ /* if we specified columns, we also can specify "mask=transparent"
+ and get all events, with the regionid (assuming we specified
+ the region column to display as well) */
+- if( argc >= 4 )
+- mode = argv[optind+3];
++ if( args >= 4 ) mode = argv[optind+3];
++
+ /* set up sorting, if necessary */
+ if( dosort ){
+ /* look for sort program */
+ path = (char *)getenv("PATH");
+ if( !(prog=Find(SORTPROG, "x", NULL, path)) )
+ gerror(stderr, "can't locate sort program: %s\n", SORTPROG);
++ /* allow commas as delims */
++ newdtable(",");
+ /* get the size of the input record */
+ FunInfoGet(fun, FUN_ROWSIZE, &isize, 0);
+ /* construct argument list for sort program */
+- pargs[0] = (char *)prog;
+- snprintf(tbuf, SZ_LINE-1, "-B%d", isize);
+- pargs[1] = (char *)xstrdup(tbuf);
++ snprintf(cmd, SZ_LINE-1, "%s -B%d", prog, isize);
++ rlen = SZ_LINE - strlen(cmd) - 1;
+ for(ncol=0; word(sortcols, col, &ip); ncol++ ){
+ if( !FunColumnLookup(fun, col, 0, NULL, &dtype, &dmode, &doffset, &dn,
+ NULL) ){
+@@ -333,15 +335,18 @@
+ default:
+ gerror(stderr, "unsupported sort data type for column %s\n", tbuf);
+ }
+- pargs[ncol+2] = (char *)xstrdup(tbuf);
+- if( ncol > (SZ_LINE-3) ){
+- gerror(stderr, "ERROR: too many sort column arguments: %d\n", ncol);
++ strncat(cmd, " ", rlen);
++ rlen--;
++ strncat(cmd, tbuf, rlen);
++ rlen -= strlen(tbuf);
++ if( rlen <=0 ){
++ gerror(stderr, "too many arguments for sort\n");
++ exit(1);
+ }
+ }
+- /* null terminate arg list */
+- pargs[ncol+2] = NULL;
++ freedtable();
+ /* start the sort program */
+- if( !ProcessOpen(prog, pargs, &ichan, &ochan, &pid) ){
++ if( !ProcessOpen(cmd, &ichan, &ochan, &pid) ){
+ gerror(stderr, "ERROR: can't start sort program: %s\n", prog);
+ }
+ }
+@@ -450,8 +455,6 @@
+ fclose(ifile);
+ if( sortcols ) xfree(sortcols);
+ if( ebuf ) xfree(ebuf);
+- for(i=0; i<ncol+2; i++)
+- if( pargs[i] ) xfree(pargs[i]);
+ }
+ /* write out heap space, if it exists -- this quick hack needs cleanup! */
+ if( fun->header && (ft_pcount(fun->header) > 0) ){
+--- gnu/sort.c.orig 2007-01-04 22:38:51.000000000 +0000
++++ gnu/sort.c 2007-12-18 20:10:27.000000000 +0000
+@@ -2332,8 +2332,30 @@
+ #ifdef _POSIX_VERSION
+ struct sigaction oldact, newact;
+ #endif /* _POSIX_VERSION */
++#ifdef SAOMOD_FIX
++ int pipes[4];
++ char *ss=NULL, *tt=NULL, *uu=NULL;
++#endif
+
+ program_name = argv[0];
++
++#ifdef SAOMOD_FIX
++ /* Launch() sometimes rearranges passed pipes to be stdin/stdout */
++ if( (ss=getenv("LAUNCH_PIPES")) ){
++ tt = (char *)strdup(ss);
++ for(i=0, uu=(char *)strtok(tt, ","); i<4 && uu;
++ i++, uu=(char *)strtok(NULL,",")){
++ pipes[i] = atoi(uu);
++ }
++ if( tt ) free(tt);
++ if( i < 4 ) return(1);
++ close(pipes[0]);
++ close(pipes[3]);
++ dup2(pipes[2], 0); close(pipes[2]);
++ dup2(pipes[1], 1); close(pipes[1]);
++ }
++#endif
++
+ #ifdef SAOMOD_FIX
+ if ( (program_name = (char *)strrchr(program_name, '/')) )
+ program_name++;
+--- gnu/sorttest.c.orig 2004-02-04 14:14:19.000000000 +0000
++++ gnu/sorttest.c 2007-12-18 20:10:27.000000000 +0000
+@@ -1,6 +1,6 @@
+ /*
+ export EVENTS="(dval:D,fval:E,ival:J,uival:V,sval:I,cval:B,cval2:B)"
+- sorttest | _sort -B24 +... | fundisp "stdin[EVENTS()]"
++ sorttest | _funsort -B24 +... | fundisp "stdin[EVENTS()]"
+ */
+
+ #include <stdio.h>
+@@ -52,16 +52,15 @@
+ int c;
+ int ival;
+ int ichan, ochan, pid, status;
++ int rlen;
+ int nrec=NREC;
+ int dodouble=0;
+ int doxeq=0;
+- int narg=0;
+- char *prog="_sort";
++ char *prog="_funsort";
+ char *slist=NULL;
+ char *s;
+ char tbuf[SZ_LINE];
+ char cmd[SZ_LINE];
+- char *args[SZ_LINE];
+ FILE *fp=stdout;
+ Binary b;
+
+@@ -89,9 +88,8 @@
+
+ /* generate sort parameters and start sort program */
+ if( doxeq ){
+- args[narg++] = (char *)NewString(prog);
+- sprintf(tbuf, "-B%d", sizeof(Binary));
+- args[narg++] = (char *)NewString(tbuf);
++ snprintf(cmd, SZ_LINE-1, "%s -B%d %s", prog, sizeof(Binary), tbuf);
++ rlen = SZ_LINE - strlen(cmd);
+ if( !slist ){
+ slist = (char *)NewString("d");
+ }
+@@ -99,39 +97,36 @@
+ switch(*s){
+ case 'd':
+ sprintf(tbuf, "+d0");
+- args[narg++] = (char *)NewString(tbuf);
+ break;
+ case 'f':
+ sprintf(tbuf, "+f8");
+- args[narg++] = (char *)NewString(tbuf);
+ break;
+ case 'i':
+ sprintf(tbuf, "+i12");
+- args[narg++] = (char *)NewString(tbuf);
+ break;
+ case 'I':
+ sprintf(tbuf, "+I16");
+- args[narg++] = (char *)NewString(tbuf);
+ break;
+ case 's':
+ sprintf(tbuf, "+s20");
+- args[narg++] = (char *)NewString(tbuf);
+ break;
+ case 'c':
+ sprintf(tbuf, "+c22");
+- args[narg++] = (char *)NewString(tbuf);
+ break;
+ default:
+ fprintf(stderr, "ERROR: unknown sort type: %s\n", s);
+ exit(1);
+ }
+- if( narg > (SZ_LINE-2) ){
+- fprintf(stderr, "ERROR: too many arguments: %d\n", narg);
++ strncat(cmd, " ", rlen);
++ rlen--;
++ strncat(cmd, tbuf, rlen);
++ rlen -= strlen(tbuf);
++ if( rlen <=0 ){
++ fprintf(stderr, "ERROR: too many arguments\n");
+ exit(1);
+ }
+ }
+- args[narg] = NULL;
+- if( !ProcessOpen(prog, args, &ichan, &ochan, &pid) ){
++ if( !ProcessOpen(cmd, &ichan, &ochan, &pid) ){
+ fprintf(stderr, "ERROR: can't start %s\n", prog);
+ exit(1);
+ }
+--- util/configure.ac.orig 2007-05-22 19:11:26.000000000 +0100
++++ util/configure.ac 2007-12-18 20:10:27.000000000 +0000
+@@ -41,7 +41,7 @@
+
+ AC_C_CONST
+
+-AC_CHECK_FUNCS(strchr memcpy snprintf ftello fseeko)
++AC_CHECK_FUNCS(strchr memcpy snprintf ftello fseeko setenv)
+
+ AC_CHECK_FUNC(connect)
+ if test $ac_cv_func_connect = no; then
+@@ -119,6 +119,14 @@
+ fi
+ AC_SUBST(USE_DL)
+
++AC_MSG_CHECKING(for request to use posix_spawn)
++AC_ARG_ENABLE(posix_spawn, [ --enable-posix_spawn use posix_spawn() if available],
++ [fun_ok=$enableval], [fun_ok=no])
++AC_MSG_RESULT($fun_ok)
++if test "$fun_ok" = "yes"; then
++ AC_CHECK_FUNCS(posix_spawn)
++fi
++
+ SC_PATH_TCLCONFIG
+ if test x"${no_tcl}" = x ; then
+ AC_DEFINE(HAVE_TCL)
+--- util/iraf_zprocess.c.orig 1970-01-01 01:00:00.000000000 +0100
++++ util/iraf_zprocess.c 2007-12-18 20:10:27.000000000 +0000
+@@ -0,0 +1,469 @@
++/*
++ * Copyright (c) 1999-2003 Smithsonian Astrophysical Observatory
++ */
++
++/*
++ *
++ * zprocess.c -- routines to start up and communicate with a slave process
++ *
++ * based on zfiopr.c from NOAO IRAF system
++ *
++ */
++
++#include <zprocess.h>
++
++#ifndef min
++#define min(a,b) (((a)<(b))?(a):(b))
++#endif
++
++/*
++ *
++ * Private Routines
++ *
++ *
++ */
++
++static int pr_debug = 0;
++
++/*
++ *
++ * Process table management code
++ *
++ */
++
++#define MAXPROCS 512
++
++static struct proctable {
++ int pr_pid; /* process id */
++ int pr_active; /* if YES, process is still active */
++ int pr_inchan; /* input IPC channel */
++ int pr_outchan; /* output IPC channel */
++ int pr_exit_status; /* process exit_status */
++} prtable[MAXPROCS];
++
++/* PR_FINDPID -- Search the process table for a process. NULL is returned if
++ * the process cannot be found, otherwise a pointer to the table entry is
++ * returned.
++ */
++#ifdef ANSI_FUNC
++static struct proctable *pr_findpid(int pid)
++#else
++static struct proctable *pr_findpid(pid)
++ int pid;
++#endif
++{
++ register int pr;
++
++ for (pr=0; pr<MAXPROCS; pr++){
++ if (prtable[pr].pr_pid == pid)
++ return (&prtable[pr]);
++ }
++ return (NULL);
++}
++
++/* PR_ENTER -- Make a new entry in the process table. Something is very wrong
++ * if the table overflows.
++ */
++#ifdef ANSI_FUNC
++static int
++pr_enter(int pid, int inchan, int outchan)
++#else
++static int pr_enter(pid, inchan, outchan)
++ int pid;
++ int inchan, outchan;
++#endif
++{
++ int pr;
++
++ for (pr=0; pr<MAXPROCS; pr++){
++ if (prtable[pr].pr_pid == 0){
++ prtable[pr].pr_pid = pid;
++ prtable[pr].pr_active = 1;
++ prtable[pr].pr_inchan = inchan;
++ prtable[pr].pr_outchan = outchan;
++ return(1);
++ }
++ }
++ return(0);
++}
++
++/* PR_GETCHAN -- Get the codes for the IPC channels assigned to a process.
++ */
++#ifdef ANSI_FUNC
++static int pr_getchan (int pid, int *inchan, int *outchan)
++#else
++static int pr_getchan (pid, inchan, outchan)
++ int pid;
++ int *inchan, *outchan;
++#endif
++{
++ register struct proctable *pr;
++
++ /* Lookup process in table. Return an error if there is no entry.
++ */
++ if ((pr = pr_findpid(pid)) == NULL)
++ return(-1);
++ else {
++ *inchan = pr->pr_inchan;
++ *outchan = pr->pr_outchan;
++ return (pid);
++ }
++}
++
++/* PR_RELEASE -- Release the table entry for the process. Used when a process
++ * is killed and we do not wish to wait for process termination.
++ */
++#ifdef ANSI_FUNC
++static void
++pr_release (int pid)
++#else
++static void pr_release (pid)
++ int pid;
++#endif
++{
++ register struct proctable *pr;
++
++ if ((pr = pr_findpid (pid)) != NULL){
++ pr->pr_pid = 0;
++ pr->pr_active = 0;
++ pr->pr_inchan = 0;
++ pr->pr_outchan = 0;
++ }
++}
++
++/*
++ *----------------------------------------------------------------------------
++ *
++ * Routine: PRSleep
++ *
++ * Purpose: sleep for specified milliseconds
++ *
++ * Returns: none
++ *
++ *----------------------------------------------------------------------------
++ */
++#ifdef ANSI_FUNC
++static void
++PRSleep (int msec)
++#else
++static void PRSleep(msec)
++ int msec;
++#endif
++{
++ struct timeval tv;
++
++ if( msec > 0 ){
++ tv.tv_sec = msec / 1000;
++ tv.tv_usec = (msec % 1000) * 1000;
++ select(1, NULL, NULL, NULL, &tv);
++ }
++}
++
++/*
++ *
++ * Public Routines
++ *
++ *
++ */
++
++/*
++ *
++ * ProcessOpen --
++ * Open a connected subprocess. Spawn process and open bidirectional
++ * IPC channels, implemented with pipes for this version of Berkeley UNIX.
++ *
++ */
++#ifdef ANSI_FUNC
++int
++ProcessOpen(char *osfn, char **argv, int *inchan, int *outchan, int *pid)
++#else
++int ProcessOpen(osfn, argv, inchan, outchan, pid)
++ char *osfn; /* name of executable file */
++ char **argv; /* argument list */
++ int *inchan, *outchan; /* IPC channels (parent reads inchan) */
++ int *pid; /* returned process id */
++#endif
++{
++ int pin[2], pout[2];
++ int maxforks = 3;
++ char **targv;
++ char *args[2];
++ char *prog=NULL;
++ static char *path;
++
++ if (pr_debug)
++ fprintf (stderr, "ProcessOpen: '%s'", (char *)osfn);
++
++ if( path == NULL ){
++ path = (char *)getenv("PATH");
++ }
++
++ /* Check that the process file exists and is executable.
++ */
++ if( (prog = Find(osfn, "x", NULL, path)) == NULL ){
++ *pid = 0;
++ return(0);
++ }
++
++ /* open pipes */
++ pipe(pin);
++ if( pipe(pout) != 0){
++ *pid = 0;
++ return(0);
++ }
++
++ /* Create child process. The child inherits the open stdio files.
++ * The fork can fail if swap space is full or if we have too many processes.
++ */
++ while ((*pid = fork()) == -1) {
++ if (--maxforks == 0) {
++ close (pin[0]); close (pin[1]);
++ close (pout[0]); close (pout[1]);
++ *pid = 0;
++ return(0);
++ }
++ sleep (2);
++ }
++
++ if (*pid == 0) {
++
++ /* New child process. Make child think the pipe is its stdin/out.
++ */
++ close (pin[0]);
++ close (pout[1]);
++ close (0); dup (pout[0]); close (pout[0]);
++ close (1); dup (pin[1]); close (pin[1]);
++
++#ifdef IRAF_ONLY
++ /* Disable SIGINT so that child process does not die when the
++ * parent process is interrupted. The child should get an EOF
++ * on reading or writing and clean itself up.
++ */
++ signal (SIGINT, SIG_IGN);
++#endif
++
++ /* Exec the new process. Will not return if successful.
++ */
++ if( argv != NULL ){
++ targv = argv;
++ }
++ else {
++ targv = args;
++ args[0] = prog;
++ args[1] = NULL;
++ }
++ execv(prog, (void *)targv);
++
++ /* If we get here the new process could not be executed for some
++ * reason. Shutdown, calling _exit to avoid flushing parent's
++ * io buffers.
++ */
++ _exit (1);
++
++ } else {
++
++ /* Existing, parent process. */
++ close (pin[1]);
++ close (pout[0]);
++ *inchan = pin[0];
++ *outchan = pout[1];
++
++ /* Save pid in parent's process table. Entry cleared when
++ * CloseProcess is called to wait for process to terminate. Also save
++ * channel numbers in process table since only the pid is passed
++ * when the process is closed.
++ */
++ pr_enter (*pid, pin[0], pout[1]);
++
++ if (pr_debug)
++ fprintf (stderr, " [%d]\n", *pid);
++
++ /* clean up and return */
++ if( prog ) free(prog);
++ return(1);
++
++ }
++ return(1);
++}
++
++
++/*
++ *
++ * ProcessClose -- Close a connected subprocess and
++ * wait for subprocess to terminate.
++ *
++ */
++#ifdef ANSI_FUNC
++int
++ProcessClose(int pid, int *exit_status)
++#else
++int ProcessClose(pid, exit_status)
++ int pid;
++ int *exit_status;
++#endif
++{
++ int inchan, outchan;
++ int tries=0;
++
++ if (pr_getchan (pid, &inchan, &outchan) == -1)
++ *exit_status = 0;
++ else {
++ close (outchan);
++ close (inchan);
++ pr_release(pid);
++retry:
++ if( (waitpid(pid, exit_status, WNOHANG)==0) && (tries<10) ){
++ PRSleep(10);
++ tries++;
++ goto retry;
++ }
++ }
++
++ if (pr_debug)
++ fprintf (stderr, "[%d] terminated, exit code %d\n",
++ pid, *exit_status);
++ return(*exit_status);
++}
++
++
++/*
++ *
++ * ProcessRead -- Read next record from an IPC channel.
++ *
++ * Since UNIX pipes are byte streams we must take special measures to
++ * transmit data through a pipe in records.
++ * Each block of data is preceded by a header of sizeof(int) consisting
++ * containing the number of bytes in the block.
++ * To read a block we must read the count and then issue successive read
++ * requests until the entire block has been read.
++ *
++*/
++#ifdef ANSI_FUNC
++void *
++ProcessRead(int fd, void *buf, int maxbytes, int *got)
++#else
++void *ProcessRead(fd, buf, maxbytes, got)
++ int fd;
++ void *buf;
++ int maxbytes;
++ int *got;
++#endif
++{
++ register char *op;
++ register int nbytes;
++ char *obuf;
++ int record_length, status;
++ int temp;
++
++ /* no data read as yet */
++ *got = 0;
++
++ if (pr_debug)
++ fprintf (stderr,
++ "[%d] initiate read for %d bytes from IPC channel %d\n",
++ (int)getpid(), maxbytes, fd);
++
++ /* Get byte count of record.
++ */
++ if (read (fd, &temp, sizeof(int)) != sizeof(int))
++ return NULL;
++
++ record_length = temp;
++ if( maxbytes >= 0 )
++ nbytes = min(record_length, maxbytes);
++ else
++ nbytes = record_length;
++
++ /* allocate output buffer, if necessary */
++ if( buf )
++ obuf = buf;
++ else{
++ obuf = (char *)malloc(nbytes);
++ if( !obuf )
++ return NULL;
++ }
++ op = (char *)obuf;
++
++ /* Now read exactly nbytes of data from channel into user buffer.
++ * Return actual byte count if EOF is seen. If an error is seen, return.
++ * If necessary multiple read requests are issued to read the
++ * entire record.
++ */
++ while (nbytes > 0)
++ switch (status = read (fd, op, nbytes)) {
++ case -1:
++ if( !buf ) free(obuf);
++ *got = 0;
++ return NULL;
++ case 0:
++ return(obuf);
++ default:
++ nbytes -= status;
++ *got += status;
++ op += status;
++ }
++
++ if (pr_debug) {
++ fprintf (stderr, "[%d] read %d bytes from IPC channel %d:\n",
++ (int)getpid(), (int)(op - (char *)buf), fd);
++ }
++
++ /* If the record is larger than maxbytes, we must read and discard
++ * the additional bytes. The method used is inefficient but it is
++ * unlikely that we will be called to read less than a full record.
++ */
++ if( maxbytes >= 0 ){
++ for (nbytes = maxbytes; nbytes < record_length; nbytes++)
++ if (read (fd, &temp, 1) <= 0)
++ break;
++ }
++
++ return(obuf);
++}
++
++/*
++ *
++ * ProcessWrite -- Write to an IPC channel.
++ * Write the IPC block header followed by the data block.
++ *
++*/
++#ifdef ANSI_FUNC
++int
++ProcessWrite(int fd, void *buf, int nbytes)
++#else
++int ProcessWrite(fd, buf, nbytes)
++ int fd;
++ void *buf;
++ int nbytes;
++#endif
++{
++ int got;
++
++ /* write byte count */
++ write(fd, &nbytes, sizeof(int));
++
++ /* write data block */
++ got = write(fd, buf, nbytes);
++
++ if (pr_debug) {
++ fprintf (stderr, "[%d] wrote %d bytes to IPC channel %d:\n",
++ (int)getpid(), (int)nbytes, fd);
++ }
++
++ return(got);
++}
++
++/*
++ * ProcessGetChan -- Get the codes for the IPC channels assigned to a process.
++ */
++#ifdef ANSI_FUNC
++int
++ProcessGetChan (int pid, int *inchan, int *outchan)
++#else
++int ProcessGetChan (pid, inchan, outchan)
++ int pid;
++ int *inchan, *outchan;
++#endif
++{
++ return pr_getchan(pid, inchan, outchan);
++}
+--- util/launch.c.orig 2007-06-28 21:29:06.000000000 +0100
++++ util/launch.c 2007-12-18 20:10:27.000000000 +0000
+@@ -1,35 +1,9 @@
+ /*
+- * Copyright (c) 1999-2003 Smithsonian Astrophysical Observatory
++ * Copyright (c) 1999-2007 Smithsonian Astrophysical Observatory
+ */
+
+ #include <launch.h>
+
+-#define LAUNCHARGS 1024
+-
+-/* we one of these must be defined ... */
+-#if !defined(USE_PIPE) && !defined(USE_WAITPID)
+-#define USE_PIPE 1
+-#endif
+-/* ... but not both */
+-#if defined(USE_PIPE) && defined(USE_WAITPID)
+-#error "USE_PIPE and USE_WAITPID are mutually exclusive"
+-#endif
+-
+-#ifdef USE_WAITPID
+-#define WAIT_TRIES 100
+-#define WAIT_MSEC 5000
+-#endif
+-
+-#ifndef WAIT_MSEC
+-#define WAIT_MSEC 5000
+-#endif
+-
+-static pid_t _launchpid=0;
+-
+-/* spawnvp seems to be broken on cygwin as of 1/06, so just use fork/exec */
+-#if HAVE_CYGWIN
+-#define HAVE_CYGWIN_USE_SPAWNVP 0
+-#endif
+ /*
+ *----------------------------------------------------------------------------
+ *
+@@ -40,98 +14,104 @@
+ *----------------------------------------------------------------------------
+ */
+
+-#if HAVE_CYGWIN||HAVE_MINGW32
+-#if HAVE_CYGWIN_USE_SPAWNVP
++static pid_t pid=0;
+
++/* wait for child process to start, using waitpid() */
+ #ifdef ANSI_FUNC
+-static int launch_win32(char *cmdstring, int attach, char **stdfiles)
++static int launch_pipes(int *pipes, int flag)
+ #else
+-static int launch_win32(cmdstring, attach, stdfiles)
+- char *cmdstring;
+- int attach;
+- char **stdfiles;
++static int launch_pipes(pipes, flag)
++ int *pipes;
++ int flag;
+ #endif
+ {
+- int i, j;
+- int len;
+- int got;
+- int status;
+- char *argv[LAUNCHARGS+1];
+- char *path=NULL;
+- char *s=NULL, *t=NULL;
+- struct timeval tv;
+-
+- /* for now, we can't support stdfiles */
+- if( stdfiles )
+- return(-1);
+-
+- /* package up the arguments for new process */
+- t = (char *)xstrdup(cmdstring);
+- for(i=0, got=0, s=(char *)strtok(t, " \t"); s;
+- i++, s=(char *)strtok(NULL," \t")){
+- if( i < LAUNCHARGS ){
+- /* save argument */
+- argv[i] = xstrdup(s);
+- /* change back special char to spaces, if necessary */
+- len = strlen(argv[i]);
+- for(j=0; j<len; j++){
+- if( argv[i][j] == LAUNCH_SPACE){
+- argv[i][j] = ' ';
+- }
+- }
+- argv[i+1] = NULL;
+- /* save program name */
+- if( i == 0 ) path = (char *)argv[i];
+- got++;
++ int i;
++ char tbuf[SZ_LINE];
++ if( pipes ){
++ for(i=0; i<4; i++){
++ pipes[i] = -1;
++ }
++ if( (pipe(&pipes[0]) < 0) || (pipe(&pipes[2]) < 0) ) return -1;
++ if( flag ){
++#if HAVE_SETENV
++ snprintf(tbuf, SZ_LINE-1, "%d,%d,%d,%d",
++ pipes[0], pipes[1], pipes[2], pipes[3]);
++ setenv("LAUNCH_PIPES", tbuf, 1);
++#else
++ snprintf(tbuf, SZ_LINE-1, "LAUNCH_PIPES=%d,%d,%d,%d",
++ pipes[0], pipes[1], pipes[2], pipes[3]);
++ putenv(xstrdup(tbuf));
++#endif
+ }
+ }
+- if( t ) xfree(t);
+- if( attach )
+- i = _P_WAIT;
+- else
+- i = _P_NOWAIT;
+- if((status = spawnvp(i, path, (void *)argv)) != -1){
+- status = 0;
+- /* wait for child to start */
+- tv.tv_sec = 0;
+- tv.tv_usec = WAIT_MSEC;
+- xselect(1, NULL, NULL, NULL, &tv);
+- }
+- for(i=0; i<got; i++)
+- if( argv[i] ) xfree((char *)argv[i]);
+- return(status);
++ return 0;
+ }
+
++#ifdef ANSI_FUNC
++static int cleanup_pipes(int *pipes)
++#else
++static int cleanup_pipes(pipes)
++ int *pipes;
+ #endif
+-#endif
+-
+-/*
+- *----------------------------------------------------------------------------
+- *
+- *
+- * Public Routines and Data
+- *
+- *
+- *----------------------------------------------------------------------------
+- */
++{
++ if( pipes ){
++ /* close child pipes */
++ close(pipes[1]);
++ close(pipes[2]);
++ /* move parent write into slot 1 */
++ pipes[1] = pipes[3];
++ /* set unused pipes to impossible value */
++ pipes[2] = -1;
++ pipes[3] = -1;
++ }
++ return 0;
++}
+
+-/*
+- *
+- * launchpid() -- return pid of last launched process
+- *
+- */
++#if LAUNCH_USE_WAITPID
++/* wait for child process to start, using waitpid() */
+ #ifdef ANSI_FUNC
+-pid_t launchpid(void)
++static int launch_waitstart(pid_t pid)
+ #else
+-pid_t launchpid()
++static int launch_waitstart(pid)
++ pid_t pid;
+ #endif
+ {
+- return _launchpid;
++ int i, got;
++ int status=0;
++ struct timeval tv;
++ /* wait up to LAUNCH_WAIT_TRIES millisec to make sure the child started,
++ but if we get an error, we can exit immediately */
++ for(i=0; i<LAUNCH_WAIT_TRIES; i++){
++ errno = 0;
++ got=waitpid(pid, &status, WNOHANG);
++ /* look for error termination */
++ if( (got < 0) || ((got == 0) && xerrno) ){
++ got = -1;
++ /* make sure status shows error */
++ if( status == 0 )
++ status = -1;
++ break;
+ }
+-
+-#if HAVE_MINGW32==0
++ /* look for normal termination */
++ else if( got > 0 ){
++ break;
++ }
++ /* no termination, sleep and wait some more */
++ else{
++ tv.tv_sec = 0;
++ tv.tv_usec = LAUNCH_WAIT_MSEC;
++ xselect(1, NULL, NULL, NULL, &tv);
++ }
++ }
++ /* no termination means the child is still running */
++ if( got == 0 ) status = 0;
++ /* return the news */
++ return status;
++}
++#endif
+
+ /*
++ * standard unix version of launch:
+ * adapted from the system() code in:
+ * W. Richard Stevens
+ * "Advanced Programming in the Unix Environment"
+@@ -139,71 +119,86 @@
+ * p. 314
+ */
+ #ifdef ANSI_FUNC
+-int launch(char *cmdstring, int attach, char **stdfiles)
++static int launch_fork_exec(char *cmdstring, int attach,
++ char **stdfiles, int *pipes)
+ #else
+-int launch(cmdstring, attach, stdfiles)
++ static int launch_fork_exec(cmdstring, attach, stdfiles, pipes)
+ char *cmdstring;
+ int attach;
+ char **stdfiles;
++ int *pipes;
+ #endif
+ {
+ int status;
+- pid_t pid;
++ int tpipes[4];
+ struct sigaction ignore, saveintr, savequit;
+ sigset_t chldmask, savemask;
+-#ifdef USE_PIPE
++#if LAUNCH_USE_PIPE
+ int fd[2];
+ #endif
+
+ /* return false if no command is specified */
+- if( !cmdstring || !*cmdstring )
+- return(-1);
++ if( !cmdstring || !*cmdstring ) return -1;
+
+ ignore.sa_handler = SIG_IGN; /* ignore SIGINT and SIGQUIT */
+ sigemptyset(&ignore.sa_mask);
+ ignore.sa_flags = 0;
+ if (sigaction(SIGINT, &ignore, &saveintr) < 0)
+- return(-1);
++ return -1;
+ if (sigaction(SIGQUIT, &ignore, &savequit) < 0)
+- return(-1);
++ return -1;
+
+ sigemptyset(&chldmask); /* now block SIGCHLD */
+ sigaddset(&chldmask, SIGCHLD);
+ if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0)
+- return(-1);
++ return -1;
+
+-#if HAVE_CYGWIN_USE_SPAWNVP
+- /* if we are on the Cygwin platform, use fork/exec only if we are
+- redirecting stdfiles. Otherwise use spawnvp(), which works better. */
+- if( stdfiles ){
+-#endif
+-
+-#ifdef USE_PIPE
++#if LAUNCH_USE_PIPE
+ /* open a pipe so parent can hear if the child fails to exec */
+ if( !attach ){
+ if( pipe(fd) < 0 )
+- return(-1);
++ return -1;
+ xfcntl(fd[0], F_SETFD, FD_CLOEXEC);
+ xfcntl(fd[1], F_SETFD, FD_CLOEXEC);
+ }
+ #endif
+
++ /* create temp ipc pipes if necessary */
++ if( pipes ){
++ if( launch_pipes(tpipes, 0) < 0 ) return -1;
++ }
++
+ /* start new process */
+ if( (pid = fork()) < 0 ){
+-#ifdef USE_PIPE
++#if LAUNCH_USE_PIPE
+ if( !attach ){
+ close(fd[0]);
+ close(fd[1]);
+ }
+ #endif
++ if( pipes ){
++ close(tpipes[0]);
++ close(tpipes[1]);
++ close(tpipes[2]);
++ close(tpipes[3]);
++ }
+ status = -1; /* ERROR: probably out of processes */
+-
+ } else if( pid == 0 ){ /* child */
+ int i, j, len;
+- char *argv[LAUNCHARGS+1];
++ char *argv[LAUNCH_ARGS+1];
+ char *path=NULL;
+ char *s=NULL, *t=NULL;
+
++ /* reset pipes, if necessary */
++ if( pipes ){
++ /* close parent's read/write pipes */
++ close(tpipes[0]);
++ close(tpipes[3]);
++ /* change child's stdin/stdout to use the passed pipes to parent */
++ dup2(tpipes[2], 0); close(tpipes[2]);
++ dup2(tpipes[1], 1); close(tpipes[1]);
++ }
++
+ /* close and reopen stdio files, if necessary */
+ if( stdfiles ){
+ for(i=0; i<3; i++){
+@@ -243,7 +238,7 @@
+ sigaction(SIGQUIT, &savequit, NULL);
+ sigprocmask(SIG_SETMASK, &savemask, NULL);
+ }
+-#ifdef USE_PIPE
++#if LAUNCH_USE_PIPE
+ /* child closes reader -- only writes status */
+ else{
+ close(fd[0]);
+@@ -254,7 +249,7 @@
+ t = (char *)xstrdup(cmdstring);
+ for(i=0, s=(char *)strtok(t, " \t"); s;
+ i++, s=(char *)strtok(NULL," \t")){
+- if( i < LAUNCHARGS ){
++ if( i < LAUNCH_ARGS ){
+ /* save argument */
+ argv[i] = xstrdup(s);
+ /* change back special char to spaces, if necessary */
+@@ -280,7 +275,7 @@
+ /* start up the new program */
+ if( execvp(path, argv) ){
+ status = 127;
+-#ifdef USE_PIPE
++#if LAUNCH_USE_PIPE
+ if( !attach ){
+ write(fd[1], &status, 4);
+ close(fd[1]);
+@@ -289,7 +284,6 @@
+ _exit(status); /* exec error */
+ }
+ } else { /* parent */
+- _launchpid = pid;
+ /* wait for program termination from attached process */
+ if( attach ){
+ while( waitpid(pid, &status, 0) < 0 ){
+@@ -300,38 +294,10 @@
+ }
+ }
+ else{
+-#ifdef USE_WAITPID
+- int i, got;
+- struct timeval tv;
+- /* we wait up to WAIT_TRIES millisecs to make sure the child started;
+- but if we get an error, we can exit immediately */
+- for(i=0; i<WAIT_TRIES; i++){
+- errno = 0;
+- got=waitpid(pid, &status, WNOHANG);
+- /* look for error termination */
+- if( (got < 0) || ((got == 0) && xerrno) ){
+- got = -1;
+- /* make sure status shows error */
+- if( status == 0 )
+- status = -1;
+- break;
+- }
+- /* look for normal termination */
+- else if( got > 0 ){
+- break;
+- }
+- /* no termination, sleep and wait some more */
+- else{
+- tv.tv_sec = 0;
+- tv.tv_usec = WAIT_MSEC;
+- xselect(1, NULL, NULL, NULL, &tv);
+- }
+- }
+- /* no termination means the child is still running */
+- if( got == 0 )
+- status = 0;
++#if LAUNCH_USE_WAITPID
++ status = launch_waitstart(pid);
+ #endif
+-#ifdef USE_PIPE
++#if LAUNCH_USE_PIPE
+ close(fd[1]);
+ if( read(fd[0], &status, 4) == 0 ){
+ status = 0;
+@@ -341,37 +307,321 @@
+ }
+ }
+
+-#if HAVE_CYGWIN_USE_SPAWNVP
++ /* cleanup temp ipc pipes and move into user space */
++ if( pipes ){
++ cleanup_pipes(tpipes);
++ pipes[0] = tpipes[0];
++ pipes[1] = tpipes[1];
++ }
++
++ /* restore previous signal actions & reset signal mask */
++ if( sigaction(SIGINT, &saveintr, NULL) < 0 ) return -1;
++ if( sigaction(SIGQUIT, &savequit, NULL) < 0 ) return -1;
++ if( sigprocmask(SIG_SETMASK, &savemask, NULL) < 0 ) return -1;
++
++ /* return the news */
++ return status;
+ }
+- /* for Cygwin, call their spawnvp() routine instead of fork()/exec() */
++
++#if HAVE_POSIX_SPAWN
++
++extern char **environ;
++
++/* spawn calls POSIX posix_spawn */
++#ifdef ANSI_FUNC
++static int launch_posix_spawn(char *cmdstring, int attach,
++ char **stdfiles, int *pipes)
++#else
++ static int launch_posix_spawn(cmdstring, attach, stdfiles, pipes)
++ char *cmdstring;
++ int attach;
++ char **stdfiles;
++ int *pipes;
++#endif
++{
++ int i, j, len;
++ int status=0;
++ int got=0;
++ int tpipes[4];
++ char *argv[LAUNCH_ARGS+1];
++ char *path=NULL;
++ char *s=NULL, *t=NULL;
++ posix_spawn_file_actions_t act;
++ posix_spawn_file_actions_t *pact=NULL;
++
++ /* return false if no command is specified */
++ if( !cmdstring || !*cmdstring )
++ return -1;
++
++ /* create temp ipc pipes if necessary */
++ if( pipes ){
++ if( launch_pipes(tpipes, 1) < 0 ) return -1;
++ }
++
++ /* package up the arguments for new process */
++ t = (char *)xstrdup(cmdstring);
++ for(i=0, s=(char *)strtok(t, " \t"); s;
++ i++, s=(char *)strtok(NULL," \t")){
++ if( i < LAUNCH_ARGS ){
++ /* save argument */
++ argv[i] = xstrdup(s);
++ /* change back special char to spaces, if necessary */
++ len = strlen(argv[i]);
++ for(j=0; j<len; j++){
++ if( argv[i][j] == LAUNCH_SPACE){
++ argv[i][j] = ' ';
++ }
++ }
++ /* last arg is always a NULL */
++ argv[i+1] = NULL;
++ /* save program name */
++ if( i == 0 ) path = argv[i];
++ /* inc arg count */
++ got++;
++ }
++ }
++ if( t ) xfree(t);
++ /* arrange stdfiles files, if necessary */
++ if( stdfiles ){
++ if( posix_spawn_file_actions_init(&act) != 0)
++ return -1;
++ /* stdin */
++ if(stdfiles[0] &&
++ posix_spawn_file_actions_addopen(&act, 0, stdfiles[0], O_RDONLY, 0))
++ return -1;
++ /* stdout */
++ if(stdfiles[1] &&
++ posix_spawn_file_actions_addopen(&act, 1, stdfiles[1], O_CREAT|O_WRONLY|O_TRUNC, 0600))
++ return -1;
++ /* stderr */
++ if(stdfiles[2] &&
++ posix_spawn_file_actions_addopen(&act, 2, stdfiles[2], O_CREAT|O_WRONLY|O_TRUNC, 0600))
++ return -1;
++ pact = &act;
++ }
++ /* start the new process */
++ if( (status = posix_spawnp(&pid, path, pact, NULL, argv, environ)) )
++ return status;
++ /* wait for program termination from attached process */
++ if( attach ){
++ while( waitpid(pid, &status, 0) < 0 ){
++ if( xerrno != EINTR ){
++ status = -1; /* error other than EINTR from waitpid() */
++ break;
++ }
++ }
++ }
++#if BIG_DELAY_WHEN_USING_THIS
++ /* wait for child process to start */
+ else{
+- status = launch_win32(cmdstring, attach, stdfiles);
++ status = launch_waitstart(pid);
++ }
++#endif
++ /* clean up */
++ if( stdfiles ) posix_spawn_file_actions_destroy(&act);
++ /* cleanup temp ipc pipes and move into user space */
++ if( pipes ){
++ cleanup_pipes(tpipes);
++ pipes[0] = tpipes[0];
++ pipes[1] = tpipes[1];
++ }
++ for(i=0; i<got; i++){
++ if( argv[i] ) xfree((char *)argv[i]);
++ }
++ /* return status */
++ return status;
+ }
++
+ #endif
+
+- /* restore previous signal actions & reset signal mask */
+- if( sigaction(SIGINT, &saveintr, NULL) < 0 )
+- return(-1);
+- if( sigaction(SIGQUIT, &savequit, NULL) < 0 )
+- return(-1);
+- if( sigprocmask(SIG_SETMASK, &savemask, NULL) < 0 )
+- return(-1);
++#if HAVE_SPAWNVP
++
++#ifdef ANSI_FUNC
++static int launch_spawnvp(char *cmdstring, int attach,
++ char **stdfiles, int *pipes)
++#else
++ static int launch_spawnvp(cmdstring, attach, stdfiles, pipes)
++ char *cmdstring;
++ int attach;
++ char **stdfiles;
++ int *pipes;
++#endif
++{
++ int i, j;
++ int len;
++ int got;
++ int status;
++ int tpipes[4];
++ char *argv[LAUNCH_ARGS+1];
++ char *path=NULL;
++ char *s=NULL, *t=NULL;
++ struct timeval tv;
++
++ /* return false if no command is specified */
++ if( !cmdstring || !*cmdstring ) return -1;
++
++ /* for now, we can't support stdfiles */
++ if( stdfiles ) return -1;
+
+- return(status);
++ /* create temp ipc pipes if necessary */
++ if( pipes ){
++ if( launch_pipes(tpipes, 1) < 0 ) return -1;
++ }
++
++ /* package up the arguments for new process */
++ t = (char *)xstrdup(cmdstring);
++ for(i=0, got=0, s=(char *)strtok(t, " \t"); s;
++ i++, s=(char *)strtok(NULL," \t")){
++ if( i < LAUNCH_ARGS ){
++ /* save argument */
++ argv[i] = xstrdup(s);
++ /* change back special char to spaces, if necessary */
++ len = strlen(argv[i]);
++ for(j=0; j<len; j++){
++ if( argv[i][j] == LAUNCH_SPACE){
++ argv[i][j] = ' ';
++ }
+ }
++ /* last arg is always a NULL */
++ argv[i+1] = NULL;
++ /* save program name */
++ if( i == 0 ) path = (char *)argv[i];
++ /* inc arg count */
++ got++;
++ }
++ }
++ if( t ) xfree(t);
++ if( attach )
++ i = _P_WAIT;
++ else
++ i = _P_NOWAIT;
++ if((status = spawnvp(i, path, (void *)argv)) != -1){
++ status = 0;
++ /* wait for child to start */
++ tv.tv_sec = 0;
++ tv.tv_usec = LAUNCH_WAIT_MSEC;
++ xselect(1, NULL, NULL, NULL, &tv);
++ }
++ /* clean up */
++ for(i=0; i<got; i++){
++ if( argv[i] ) xfree((char *)argv[i]);
++ }
++ /* cleanup temp ipc pipes and move into user space */
++ if( pipes ){
++ cleanup_pipes(tpipes);
++ pipes[0] = tpipes[0];
++ pipes[1] = tpipes[1];
++ }
++ return status;
++}
++
++#endif
+
++/*
++ *----------------------------------------------------------------------------
++ *
++ *
++ * Public Routines and Data
++ *
++ *
++ *----------------------------------------------------------------------------
++ */
++
++/*
++ *
++ * LaunchPid() -- return pid of last launched process
++ *
++ */
++#ifdef ANSI_FUNC
++pid_t LaunchPid(void)
+ #else
++pid_t LaunchPid()
++#endif
++{
++ return pid;
++}
+
+ #ifdef ANSI_FUNC
+-int launch(char *cmdstring, int attach, char **stdfiles)
++int Launch(char *cmdstring, int attach, char **stdfiles, int *pipes)
+ #else
+-int launch(cmdstring, attach, stdfiles)
++int Launch(cmdstring, attach, stdfiles, piles)
+ char *cmdstring;
+ int attach;
+ char **stdfiles;
++ int *pipes;
+ #endif
+ {
+- return launch_win32(cmdstring, attach, stdfiles);
++ static int which_launch=0;
++ static int which_debug=0;
++ char *s=NULL;
++
++ /* return false if no command is specified */
++ if( !cmdstring || !*cmdstring ) return -1;
++
++ /* sanity check: don't specify stdfiles and pipes simultaneously */
++ if( stdfiles && pipes ){
++ fprintf(stderr,
++ "ERROR: stdfiles and pipes are mutually exclusive in Launch()\n");
++ return -1;
+ }
+
++ /* if pipes are specified, we don't attach */
++ if( pipes ) attach = 0;
++
++ /* determine launch method */
++ if( !which_launch ){
++ which_launch = LAUNCH_DEFAULT_WHICH;
++ if( (s=getenv("LAUNCH_ROUTINE")) ){
++ /* fork_exec */
++ if( !strncasecmp(s, "f", 1) ){
++ which_launch = 1;
++ if( *s == 'F' ) which_debug = 1;
++ }
++ /* posix_spawn */
++ else if( !strncasecmp(s, "p", 1) ){
++ which_launch = 2;
++ if( *s == 'P' ) which_debug = 1;
++ }
++ /* spawnvp */
++ else if( !strncasecmp(s, "s", 1) ){
++ which_launch = 3;
++ if( *s == 'S' ) which_debug = 1;
++ }
++ else if( *s == 'V' ) {
++ which_debug = 1;
++ }
++ }
++ }
++ /* call the correct launch method */
++ switch(which_launch){
++ case 1:
++ if( which_debug ) fprintf(stderr, "launch_fork_exec: %s\n", cmdstring);
++ return launch_fork_exec(cmdstring, attach, stdfiles, pipes);
++ break;
++ case 2:
++#if HAVE_POSIX_SPAWN
++ if( which_debug ) fprintf(stderr, "launch_posix_spawn: %s\n", cmdstring);
++ return launch_posix_spawn(cmdstring, attach, stdfiles, pipes);
++#else
++ fprintf(stderr, "ERROR: posix_spawn() not available on this host\n");
++ exit(1);
+ #endif
++ break;
++ case 3:
++#if HAVE_SPAWNVP
++ if( which_debug ) fprintf(stderr, "launch_spawnvp: %s\n", cmdstring);
++ return launch_spawnvp(cmdstring, attach, stdfiles, pipes);
++#else
++ fprintf(stderr, "ERROR: spawnvp() not available on this host\n");
++ exit(1);
++#endif
++ break;
++ default:
++ if( which_debug ) fprintf(stderr, "launch_fork_exec: %s\n", cmdstring);
++ return launch_fork_exec(cmdstring, attach, stdfiles, pipes);
++ break;
++ }
++ /* can't happen */
++ return -1;
++}
++
+--- util/launch.h.orig 2006-01-27 16:25:08.000000000 +0000
++++ util/launch.h 2007-12-18 20:10:27.000000000 +0000
+@@ -30,17 +30,54 @@
+ #if HAVE_UNISTD_H
+ #include <unistd.h>
+ #endif
++#if HAVE_POSIX_SPAWN
++#include <spawn.h>
++#endif
+ #include <xport.h>
+ #include <word.h>
+ #include <xalloc.h>
+ #include <prsetup.h>
+
++#define LAUNCH_ARGS 1024
++
+ #define LAUNCH_SPACE '\001'
+
++/* for fork/exec, one of these is required to specify the technique to be used
++ by the parent when determining if the child started successfully */
++#if !defined(LAUNCH_USE_PIPE) && !defined(LAUNCH_USE_WAITPID)
++#define LAUNCH_USE_PIPE 1
++#endif
++/* ... but not both */
++#if defined(LAUNCH_USE_PIPE) && defined(LAUNCH_USE_WAITPID)
++#error "LAUNCH_USE_PIPE and LAUNCH_USE_WAITPID are mutually exclusive"
++#endif
++
++#ifndef LAUNCH_WAIT_TRIES
++#define LAUNCH_WAIT_TRIES 100
++#endif
++#ifndef LAUNCH_WAIT_MSEC
++#define LAUNCH_WAIT_MSEC 5000
++#endif
++
++#if HAVE_MINGW32|HAVE_CYGWIN
++#define HAVE_SPAWNVP 1
++#endif
++
++#if HAVE_MINGW32
++/* for now, ensure that MinGW utilizes spawnvp() */
++#define LAUNCH_DEFAULT_WHICH 3
++#elif HAVE_POSIX_SPAWN
++/* use posix_spawn if possible (required for OS X 10.5) */
++#define LAUNCH_DEFAULT_WHICH 2
++#else
++/* use our home-grown version */
++#define LAUNCH_DEFAULT_WHICH 1
++#endif
++
+ _PRbeg
+
+-int launch _PRx((char *cmdstring, int wait, char **stdfiles));
+-pid_t launchpid _PRx((void));
++int Launch _PRx((char *cmdstring, int wait, char **stdfiles, int *pipes));
++pid_t LaunchPid _PRx((void));
+
+ _PRend
+
+--- util/tlaunch2.c.orig 1970-01-01 01:00:00.000000000 +0100
++++ util/tlaunch2.c 2007-12-18 20:10:27.000000000 +0000
+@@ -0,0 +1,59 @@
++/*
++ *
++ * tlaunch2 -- test launch routine (child routines)
++ *
++ */
++
++#define HAVE_CONFIG_H 1
++
++#if HAVE_CONFIG_H
++#include <conf.h>
++#endif
++#include <stdio.h>
++#include <ctype.h>
++#if HAVE_STRING_H
++#include <string.h>
++#endif
++#if HAVE_STDLIB_H
++#include <stdlib.h>
++#endif
++#if HAVE_UNISTD_H
++#include <unistd.h>
++#endif
++
++#ifdef ANSI_FUNC
++int main (int argc, char **argv)
++#else
++int main(argc, argv)
++ int argc;
++ char **argv;
++#endif
++{
++ int i;
++ char c;
++ char *s, *t, *u;
++ int pipes[4];
++ if( (s=getenv("LAUNCH_PIPES")) ){
++ t = (char *)strdup(s);
++ for(i=0, u=(char *)strtok(t, ","); i<4 && u;
++ i++, u=(char *)strtok(NULL,",")){
++ pipes[i] = atoi(u);
++ fprintf(stderr, "child pipe #%d: %d\n", i, pipes[i]);
++ }
++ if( t ) free(t);
++ if( i < 4 ) return(1);
++ close(pipes[0]);
++ close(pipes[3]);
++ dup2(pipes[2], 0); close(pipes[2]);
++ dup2(pipes[1], 1); close(pipes[1]);
++ }
++ else{
++ fprintf(stderr, "No LAUNCH_PIPE environment variable\n");
++ }
++ while( read(0, &c, 1) ){
++ if( islower((int)c) ) c = toupper((int)c);
++ write(3, &c, 1);
++ write(1, &c, 1);
++ }
++ return 0;
++}
+--- util/tlaunch.c.orig 1970-01-01 01:00:00.000000000 +0100
++++ util/tlaunch.c 2007-12-18 20:10:27.000000000 +0000
+@@ -0,0 +1,98 @@
++/*
++ * Copyright (c) 2007 Smithsonian Astrophysical Observatory
++ */
++
++/*
++ *
++ * tlaunch -- test launch routine
++ *
++ */
++
++#define HAVE_CONFIG_H 1
++#include <launch.h>
++
++extern char *optarg;
++extern int optind;
++
++#ifdef ANSI_FUNC
++int main (int argc, char **argv)
++#else
++int main(argc, argv)
++ int argc;
++ char **argv;
++#endif
++{
++ int c;
++ int got=0;
++ int doattach=0;
++ int dofiles=0;
++ int dopipes=0;
++ int pipes[2];
++ char *prog=NULL;
++ char *files[3];
++ char *pfile=NULL;
++ char wbuf[SZ_LINE];
++ FILE *fd;
++
++ /* init */
++ memset(files, 0, sizeof(char *)*3);
++ /* process switch arguments */
++ while ((c = getopt(argc, argv, "ae:i:o:p:w:")) != -1){
++ switch(c){
++ case 'a':
++ doattach = 1;
++ break;
++ case 'e':
++ files[2] = optarg;
++ dofiles |= 4;
++ break;
++ case 'i':
++ files[0] = optarg;
++ dofiles |= 1;
++ break;
++ case 'o':
++ files[1] = optarg;
++ dofiles |= 2;
++ break;
++ case 'p':
++ pfile = optarg;
++ dopipes = 1;
++ break;
++ case 'w':
++ snprintf(wbuf, SZ_LINE, "LAUNCH_ROUTINE=%s", optarg);
++ putenv(wbuf);
++ default:
++ break;
++ }
++ }
++ if( optind >= argc ){
++ fprintf(stderr,
++ "usage: %s -a -i stdin -o stdout -e stderr -p pfile [command]\n",
++ argv[0]);
++ return 1;
++ }
++ prog = argv[optind++];
++ if( !strcmp(prog, "tlaunch2") && !dopipes ){
++ fprintf(stderr, "ERROR: use -p [file] with tlaunch2\n");
++ return 1;
++ }
++ if( (got = Launch(prog, doattach, dofiles?files:NULL, dopipes?pipes:NULL)) )
++ fprintf(stderr, "ERROR: got=%d\n", got);
++ else
++ fprintf(stderr, "SUCCESS: got(%x)=%d\n", dofiles, got);
++ /* send pipe file contents to child, read back and display results */
++ if( pfile ){
++ if( !(fd = fopen(pfile,"r")) ){
++ perror("fopen");
++ return 1;
++ }
++ while( fread(&c, sizeof(char), 1, fd) ){
++ write(pipes[1], &c, 1);
++ if( read(pipes[0], &c, 1) ){
++ fwrite(&c, sizeof(char), 1, stdout);
++ }
++ }
++ fclose(fd);
++ }
++ return 0;
++}
+--- util/zprocess.c.orig 2006-02-21 16:34:12.000000000 +0000
++++ util/zprocess.c 2007-12-18 20:10:27.000000000 +0000
+@@ -6,7 +6,8 @@
+ *
+ * zprocess.c -- routines to start up and communicate with a slave process
+ *
+- * based on zfiopr.c from NOAO IRAF system
++ * based on zfiopr.c from NOAO IRAF system (more loosely than previously,
++ * since we replaces the fork/exec with our own Launch()).
+ *
+ */
+
+@@ -65,8 +66,7 @@
+ * if the table overflows.
+ */
+ #ifdef ANSI_FUNC
+-static int
+-pr_enter(int pid, int inchan, int outchan)
++static int pr_enter(int pid, int inchan, int outchan)
+ #else
+ static int pr_enter(pid, inchan, outchan)
+ int pid;
+@@ -114,8 +114,7 @@
+ * is killed and we do not wish to wait for process termination.
+ */
+ #ifdef ANSI_FUNC
+-static void
+-pr_release (int pid)
++static void pr_release (int pid)
+ #else
+ static void pr_release (pid)
+ int pid;
+@@ -143,8 +142,7 @@
+ *----------------------------------------------------------------------------
+ */
+ #ifdef ANSI_FUNC
+-static void
+-PRSleep (int msec)
++static void PRSleep (int msec)
+ #else
+ static void PRSleep(msec)
+ int msec;
+@@ -166,127 +164,36 @@
+ *
+ */
+
+-/*
+- *
+- * ProcessOpen --
+- * Open a connected subprocess. Spawn process and open bidirectional
+- * IPC channels, implemented with pipes for this version of Berkeley UNIX.
+- *
+- */
++
+ #ifdef ANSI_FUNC
+-int
+-ProcessOpen(char *osfn, char **argv, int *inchan, int *outchan, int *pid)
++int ProcessOpen(char *cmd, int *inchan, int *outchan, int *pid)
+ #else
+-int ProcessOpen(osfn, argv, inchan, outchan, pid)
+- char *osfn; /* name of executable file */
+- char **argv; /* argument list */
++int ProcessOpen(cmd, argv, inchan, outchan, pid)
++ char *cmd; /* command line to Launch */
+ int *inchan, *outchan; /* IPC channels (parent reads inchan) */
+ int *pid; /* returned process id */
+ #endif
+ {
+- int pin[2], pout[2];
+- int maxforks = 3;
+- char **targv;
+- char *args[2];
+- char *prog=NULL;
+- static char *path;
+-
+- if (pr_debug)
+- fprintf (stderr, "ProcessOpen: '%s'", (char *)osfn);
+-
+- if( path == NULL ){
+- path = (char *)getenv("PATH");
+- }
+-
+- /* Check that the process file exists and is executable.
+- */
+- if( (prog = Find(osfn, "x", NULL, path)) == NULL ){
++ int pipes[2];
++ if( Launch(cmd, 0, NULL, pipes) != 0 ){
++ /* failure */
++ *inchan = -1;
++ *outchan = -1;
+ *pid = 0;
+- return(0);
+- }
+-
+- /* open pipes */
+- pipe(pin);
+- if( pipe(pout) != 0){
+- *pid = 0;
+- return(0);
+- }
+-
+- /* Create child process. The child inherits the open stdio files.
+- * The fork can fail if swap space is full or if we have too many processes.
+- */
+- while ((*pid = fork()) == -1) {
+- if (--maxforks == 0) {
+- close (pin[0]); close (pin[1]);
+- close (pout[0]); close (pout[1]);
+- *pid = 0;
+- return(0);
+- }
+- sleep (2);
+- }
+-
+- if (*pid == 0) {
+-
+- /* New child process. Make child think the pipe is its stdin/out.
+- */
+- close (pin[0]);
+- close (pout[1]);
+- close (0); dup (pout[0]); close (pout[0]);
+- close (1); dup (pin[1]); close (pin[1]);
+-
+-#ifdef IRAF_ONLY
+- /* Disable SIGINT so that child process does not die when the
+- * parent process is interrupted. The child should get an EOF
+- * on reading or writing and clean itself up.
+- */
+- signal (SIGINT, SIG_IGN);
+-#endif
+-
+- /* Exec the new process. Will not return if successful.
+- */
+- if( argv != NULL ){
+- targv = argv;
++ return 0;
+ }
+ else {
+- targv = args;
+- args[0] = prog;
+- args[1] = NULL;
+- }
+- execv(prog, (void *)targv);
+-
+- /* If we get here the new process could not be executed for some
+- * reason. Shutdown, calling _exit to avoid flushing parent's
+- * io buffers.
+- */
+- _exit (1);
+-
+- } else {
+-
+- /* Existing, parent process. */
+- close (pin[1]);
+- close (pout[0]);
+- *inchan = pin[0];
+- *outchan = pout[1];
+-
+- /* Save pid in parent's process table. Entry cleared when
+- * CloseProcess is called to wait for process to terminate. Also save
+- * channel numbers in process table since only the pid is passed
+- * when the process is closed.
+- */
+- pr_enter (*pid, pin[0], pout[1]);
+-
+- if (pr_debug)
+- fprintf (stderr, " [%d]\n", *pid);
+-
+- /* clean up and return */
+- if( prog ) free(prog);
+- return(1);
+-
++ /* package up process info for return */
++ *inchan = pipes[0];
++ *outchan = pipes[1];
++ *pid = LaunchPid();
++ /* and also save process info for later */
++ pr_enter (*pid, *inchan, *outchan);
++ /* success */
++ return 1;
+ }
+- return(1);
+ }
+
+-
+ /*
+ *
+ * ProcessClose -- Close a connected subprocess and
+@@ -294,8 +201,7 @@
+ *
+ */
+ #ifdef ANSI_FUNC
+-int
+-ProcessClose(int pid, int *exit_status)
++int ProcessClose(int pid, int *exit_status)
+ #else
+ int ProcessClose(pid, exit_status)
+ int pid;
+@@ -339,8 +245,7 @@
+ *
+ */
+ #ifdef ANSI_FUNC
+-void *
+-ProcessRead(int fd, void *buf, int maxbytes, int *got)
++void *ProcessRead(int fd, void *buf, int maxbytes, int *got)
+ #else
+ void *ProcessRead(fd, buf, maxbytes, got)
+ int fd;
+@@ -428,8 +333,7 @@
+ *
+ */
+ #ifdef ANSI_FUNC
+-int
+-ProcessWrite(int fd, void *buf, int nbytes)
++int ProcessWrite(int fd, void *buf, int nbytes)
+ #else
+ int ProcessWrite(fd, buf, nbytes)
+ int fd;
+@@ -457,8 +361,7 @@
+ * ProcessGetChan -- Get the codes for the IPC channels assigned to a process.
+ */
+ #ifdef ANSI_FUNC
+-int
+-ProcessGetChan (int pid, int *inchan, int *outchan)
++int ProcessGetChan (int pid, int *inchan, int *outchan)
+ #else
+ int ProcessGetChan (pid, inchan, outchan)
+ int pid;
+--- util/zprocess.h.orig 2004-09-18 14:34:51.000000000 +0100
++++ util/zprocess.h 2007-12-18 20:10:27.000000000 +0000
+@@ -28,15 +28,12 @@
+ #endif
+ #include <sys/time.h>
+ #include <signal.h>
+-#include <prsetup.h>
++#include <launch.h>
+ #include <find.h>
+-#include <xport.h>
+-#include <xalloc.h>
+
+ _PRbeg
+
+-int ProcessOpen _PRx((char *osfn, char **argv,
+- int *inchan, int *outchan, int *pid));
++int ProcessOpen _PRx((char *cmd, int *inchan, int *outchan, int *pid));
+ void *ProcessRead _PRx((int fd, void *buf, int maxbytes, int *got));
+ int ProcessWrite _PRx((int fd, void *buf, int nbytes));
+ int ProcessClose _PRx((int pid, int *exit_status));
diff --git a/sci-astronomy/funtools/files/funtools-1.4.0-makefiles.patch b/sci-astronomy/funtools/files/funtools-1.4.0-makefiles.patch
new file mode 100644
index 000000000000..0184c23f7d49
--- /dev/null
+++ b/sci-astronomy/funtools/files/funtools-1.4.0-makefiles.patch
@@ -0,0 +1,368 @@
+--- ./Makefile.in.orig 2008-11-02 20:13:46.000000000 +0000
++++ ./Makefile.in 2008-11-02 21:20:42.000000000 +0000
+@@ -28,6 +28,11 @@
+
+ prefix = @prefix@
+ exec_prefix = @exec_prefix@
++bindir = @bindir@
++includedir = @includedir@
++mandir = @mandir@
++datadir = @datadir@
++libdir = @libdir@
+
+ # The following definition can be set to non-null for special systems
+ # like AFS with replication. It allows the pathnames used for installation
+@@ -37,19 +42,19 @@
+ INSTALL_ROOT =
+
+ # Directory in which to install the .a or .so binary for the FUNTOOLS library:
+-LIB_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/lib
++LIB_INSTALL_DIR = $(INSTALL_ROOT)$(libdir)
+
+ # Directory in which to install the program wish:
+-BIN_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/bin
++BIN_INSTALL_DIR = $(INSTALL_ROOT)$(bindir)
+
+ # Directory in which to install the funtools.h include file:
+-INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(prefix)/include
++INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(includedir)/funtools
+
+ # Top-level directory for manual entries:
+-MAN_INSTALL_DIR = $(INSTALL_ROOT)$(prefix)/man
++MAN_INSTALL_DIR = $(INSTALL_ROOT)$(mandir)
+
+ # Top-level directory for share entries:
+-MAN_SHARE_DIR = $(INSTALL_ROOT)$(prefix)/share/funtools
++MAN_SHARE_DIR = $(INSTALL_ROOT)$(datadir)/funtools
+
+ # util files are in the util subdirectory
+ UTIL_INC = -I./util
+@@ -60,7 +65,7 @@
+ # FITSY_LIBS = -L./fitsy -lfitsy
+
+ # wcs files are in the wcs subdirectory
+-WCS_INC = -I./wcs
++WCS_INC = -I/usr/include/wcs
+ # WCS_LIBS = -L./wcs -lwcs
+
+ # filter files are in the filter subdirectory
+@@ -225,7 +230,7 @@
+ echo $(PROGS) | ./mkfunmainlib > funmainlib.c;
+
+ shlib: sublib $(LIBOBJS)
+- @(rm -rf $(PACKAGE)tmp; mkdir $(PACKAGE)tmp; \
++ @(rm -rf $(PACKAGE)tmp; mkdir -p $(PACKAGE)tmp; \
+ (cd $(PACKAGE)tmp && ar x ../$(LIB)); \
+ CC='$(CC)' CXX=$(CXX) \
+ ./mklib -o $(PACKAGE) $(PACKAGE)tmp/*.o; \
+@@ -237,7 +242,7 @@
+ $(RANLIB) lib$(PACKAGE)MainLib.a)
+
+ shmainlib: mainlib
+- @(rm -rf $(PACKAGE)tmp; mkdir $(PACKAGE)tmp; \
++ @(rm -rf $(PACKAGE)tmp; mkdir -p $(PACKAGE)tmp; \
+ (cd $(PACKAGE)tmp && ar x ../lib$(PACKAGE)MainLib.a); \
+ CC='$(CC)' CXX='$(CXX)' \
+ ./mklib -o $(PACKAGE)MainLib -L. -lfuntools $(PACKAGE)tmp/*.o;\
+@@ -248,7 +253,7 @@
+ $(RANLIB) libtclfun.a)
+
+ shtclfun: tclfun
+- @(rm -rf $(PACKAGE)tmp; mkdir $(PACKAGE)tmp; \
++ @(rm -rf $(PACKAGE)tmp; mkdir -p $(PACKAGE)tmp; \
+ (cd $(PACKAGE)tmp && ar x ../$(LIB) && ar x ../libtclfun.a); \
+ CC='$(CC)' CXX='$(CXX)' \
+ ./mklib -o tclfun $(PACKAGE)tmp/*.o; \
+@@ -422,7 +427,7 @@
+ do \
+ if [ ! -d $$i ] ; then \
+ echo "Making directory $$i"; \
+- mkdir $$i; \
++ mkdir -p $$i; \
+ chmod 755 $$i; \
+ else true; \
+ fi; \
+@@ -462,7 +467,7 @@
+ install-man:
+ @if [ ! -d $(MAN_INSTALL_DIR) ] ; then \
+ echo "Making directory $(MAN_INSTALL_DIR)"; \
+- mkdir $(MAN_INSTALL_DIR); \
++ mkdir -p $(MAN_INSTALL_DIR); \
+ chmod 755 $(MAN_INSTALL_DIR); \
+ else true; \
+ fi;
+@@ -473,7 +478,7 @@
+ M="$(MAN_INSTALL_DIR)/man$$E"; \
+ if [ ! -d $$M ] ; then \
+ echo "Making directory $$M"; \
+- mkdir $$M; \
++ mkdir -p $$M; \
+ chmod 755 $$M; \
+ else true; \
+ fi; \
+--- ./filter/Makefile.in.orig 2008-11-02 20:43:46.000000000 +0000
++++ ./filter/Makefile.in 2008-11-03 10:54:33.000000000 +0000
+@@ -29,6 +29,9 @@
+
+ prefix = @prefix@
+ exec_prefix = @exec_prefix@
++bindir = @bindir@
++includedir = @includedir@
++libdir = @libdir@
+
+ # The following definition can be set to non-null for special systems
+ # like AFS with replication. It allows the pathnames used for installation
+@@ -38,13 +41,13 @@
+ INSTALL_ROOT =
+
+ # Directory in which to install the .a, .so, and .o files:
+-LIB_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/lib
++LIB_INSTALL_DIR = $(INSTALL_ROOT)$(libdir)
+
+ # Directory in which to install the programs:
+-BIN_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/bin
++BIN_INSTALL_DIR = $(INSTALL_ROOT)$(bindir)
+
+ # Directory in which to install the include files:
+-INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(prefix)/include
++INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(includedir)/funtools/filter
+
+ # util files are in the util directory at same level
+ UTIL_INC = -I../util
+@@ -55,7 +58,7 @@
+ #FITSY_LIBS = -L../fitsy
+
+ # wcs files are in the wcs subdirectory
+-WCS_INC = -I../wcs
++WCS_INC = -I/usr/include/wcs
+ #WCS_LIBS = -L../wcs -lwcs
+
+ # extra includes for compiling
+@@ -161,7 +164,7 @@
+ do \
+ if [ ! -d $$i ] ; then \
+ echo "Making directory $$i"; \
+- mkdir $$i; \
++ mkdir -p $$i; \
+ chmod 755 $$i; \
+ else true; \
+ fi; \
+@@ -211,7 +214,7 @@
+ .c.o:
+ $(CC) -c $(CC_SWITCHES) $<
+
+-filtprog_c.o: filtprog_c.c regions_h.h xalloc_c.h \
++filtprog_c.o: filtprog_c.c regions_h.h xalloc_c.h swap_c.h \
+ events_c.h image_c.h evregions_c.h imregions_c.h filter.h
+ $(CC) -c $(CC_SWITCHES) -DOBJPATH="$(OBJPATH)" \
+ -DFILTER_CC="$(FILTER_CC)" -DFILTER_CFLAGS="$(FILTER_CFLAGS)" \
+@@ -226,6 +229,10 @@
+ $(RM) xalloc_c.h
+ ./inc.sed XALLOC_C < ../util/xalloc.c > xalloc_c.h
+
++swap_c.h: swap.c inc.sed
++ $(RM) swap_c.h
++ ./inc.sed SWAP_C < swap.c > swap_c.h
++
+ events_c.h: evfilter.c inc.sed
+ $(RM) events_c.h
+ ./inc.sed EVENTS_C < evfilter.c > events_c.h
+@@ -250,7 +257,7 @@
+ $(RM) imregions_c.h
+ ./inc.sed IMREGIONS_C < imregions.c > imregions_c.h
+
+-headers: regions_h.h xalloc_c.h \
++headers: regions_h.h xalloc_c.h swap_c.h \
+ events_c.h image_c.h evregions_c.h imregions_c.h
+
+ # remake the parser
+--- ./fitsy/Makefile.in.orig 2008-11-02 20:50:20.000000000 +0000
++++ ./fitsy/Makefile.in 2008-11-02 21:21:32.000000000 +0000
+@@ -28,6 +28,11 @@
+
+ prefix = @prefix@
+ exec_prefix = @exec_prefix@
++bindir = @bindir@
++includedir = @includedir@
++mandir = @mandir@
++datadir = @datadir@
++libdir = @libdir@
+
+ # The following definition can be set to non-null for special systems
+ # like AFS with replication. It allows the pathnames used for installation
+@@ -37,13 +42,13 @@
+ INSTALL_ROOT =
+
+ # Directory in which to install the .a, .so, and .o files:
+-LIB_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/lib
++LIB_INSTALL_DIR = $(INSTALL_ROOT)$(libdir)
+
+ # Directory in which to install the programs:
+-BIN_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/bin
++BIN_INSTALL_DIR = $(INSTALL_ROOT)$(bindir)
+
+ # Directory in which to install the include files:
+-INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(prefix)/include
++INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(includedir)/funtools/fitsy
+
+ # There are just too many different versions of "install" around;
+ # better to use the install-sh script that comes with the distribution,
+@@ -186,7 +191,7 @@
+ do \
+ if [ ! -d $$i ] ; then \
+ echo "Making directory $$i"; \
+- mkdir $$i; \
++ mkdir -p $$i; \
+ chmod 755 $$i; \
+ else true; \
+ fi; \
+@@ -200,6 +205,8 @@
+ fi;
+ @echo "Installing fitsy.h"
+ @$(INSTALL_DATA) fitsy.h $(INCLUDE_INSTALL_DIR)/fitsy.h
++ @echo "Installing xfile.h"
++ @$(INSTALL_DATA) xfile.h $(INCLUDE_INSTALL_DIR)/xfile.h
+ # @for i in $(PROGS) ; \
+ # do \
+ # if [ -f $$i ] ; then \
+--- ./util/Makefile.in.orig 2008-11-02 20:55:57.000000000 +0000
++++ ./util/Makefile.in 2008-11-02 21:22:30.000000000 +0000
+@@ -29,6 +29,11 @@
+
+ prefix = @prefix@
+ exec_prefix = @exec_prefix@
++bindir = @bindir@
++includedir = @includedir@
++mandir = @mandir@
++datadir = @datadir@
++libdir = @libdir@
+
+ # The following definition can be set to non-null for special systems
+ # like AFS with replication. It allows the pathnames used for installation
+@@ -38,13 +43,13 @@
+ INSTALL_ROOT =
+
+ # Directory in which to install the .a, .so, and .o files:
+-LIB_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/lib
++LIB_INSTALL_DIR = $(INSTALL_ROOT)$(libdir)
+
+ # Directory in which to install the programs:
+-BIN_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/bin
++BIN_INSTALL_DIR = $(INSTALL_ROOT)$(bindir)
+
+ # Directory in which to install the include files:
+-INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(prefix)/include
++INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(includedir)/funtools/util
+
+ # extra includes for compiling
+ INCLUDES =
+@@ -127,7 +132,7 @@
+ # the actual library we are building (if this is a subpackage)
+ LIB = @LIB@
+
+-TESTPROGS = tparse
++TESTPROGS = tparse tlaunch tlaunch2
+
+ PROGS = gcat
+
+@@ -189,12 +194,24 @@
+ $(CC) $(LDFLAGS) tparse.o parse.o -o tparse $(LIB) $(LIBS) \
+ $(EXTRA_LIBS)
+
++tlaunch.o: tlaunch.c
++
++tlaunch: tlaunch.o launch.o $(LIB)
++ $(CC) $(LDFLAGS) tlaunch.o launch.o -o tlaunch $(LIB) $(LIBS) \
++ $(EXTRA_LIBS)
++
++tlaunch2.o: tlaunch2.c
++
++tlaunch2: tlaunch2.o
++ $(CC) $(LDFLAGS) tlaunch2.o -o tlaunch2
++
++
+ install-binaries: $(LIB) $(PROGS)
+ @for i in $(LIB_INSTALL_DIR) $(INCLUDE_INSTALL_DIR) $(BIN_INSTALL_DIR) ; \
+ do \
+ if [ ! -d $$i ] ; then \
+ echo "Making directory $$i"; \
+- mkdir $$i; \
++ mkdir -p $$i; \
+ chmod 755 $$i; \
+ else true; \
+ fi; \
+@@ -254,4 +271,11 @@
+ configure: configure.in
+ autoconf configure.in
+
++pure: tlaunch.pure
++
++tlaunch.pure: tlaunch.o launch.o $(LIB)
++ purift $(CC) $(LDFLAGS) tlaunch.o launch.o -o tlaunch \
++ $(LIB) $(LIBS) $(EXTRA_LIBS)
++
++
+ # DO NOT DELETE THIS LINE -- make depend depends on it.
+--- ./gnu/Makefile.in.orig 2008-11-02 20:53:04.000000000 +0000
++++ ./gnu/Makefile.in 2008-11-02 20:55:46.000000000 +0000
+@@ -21,6 +21,11 @@
+
+ prefix = @prefix@
+ exec_prefix = @exec_prefix@
++bindir = @bindir@
++includedir = @includedir@
++mandir = @mandir@
++datadir = @datadir@
++libdir = @libdir@
+
+ # The following definition can be set to non-null for special systems
+ # like AFS with replication. It allows the pathnames used for installation
+@@ -53,13 +58,13 @@
+ EXTRA_OBJS = @EXTRA_OBJS@
+
+ # Directory in which to install the .a, .so, and .o files:
+-LIB_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/lib
++LIB_INSTALL_DIR = $(INSTALL_ROOT)$(libdir)
+
+ # Directory in which to install the programs:
+-BIN_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/bin
++BIN_INSTALL_DIR = $(INSTALL_ROOT)$(bindir)
+
+ # Directory in which to install the include files:
+-INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(prefix)/include
++INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(includedir)
+
+ # There are just too many different versions of "install" around;
+ # better to use the install-sh script that comes with the distribution,
+@@ -95,14 +100,14 @@
+
+ OBJS = sort.o
+
+-PROGS = _sort
++PROGS = _funsort
+
+ TESTPROGS = sorttest
+
+ all: $(PROGS)
+
+-_sort: $(OBJS)
+- $(CC) $(LDFLAGS) $(OBJS) -o _sort
++_funsort: $(OBJS)
++ $(CC) $(LDFLAGS) $(OBJS) -o _funsort
+
+ sorttest: sorttest.o
+ $(CC) $(LDFLAGS) sorttest.o -o sorttest -L.. -lfuntools
+@@ -141,10 +146,10 @@
+ done;
+
+
+-pure: _sort.pure
++pure: _funsort.pure
+
+-_sort.pure: $(FUNLIB) sort.o
+- purify $(CC) $(LDFLAGS) sort.o -o _sort.pure \
++_funsort.pure: $(FUNLIB) sort.o
++ purify $(CC) $(LDFLAGS) sort.o -o _funsort.pure \
+ $(FUNLIB) $(LIBS)
+
+ # DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/sci-astronomy/funtools/funtools-1.4.0.ebuild b/sci-astronomy/funtools/funtools-1.4.0.ebuild
new file mode 100644
index 000000000000..3ecf242bd88d
--- /dev/null
+++ b/sci-astronomy/funtools/funtools-1.4.0.ebuild
@@ -0,0 +1,55 @@
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sci-astronomy/funtools/funtools-1.4.0.ebuild,v 1.1 2008/11/05 22:13:59 bicatali Exp $
+
+EAPI=2
+inherit eutils
+
+DESCRIPTION="FITS library and utlities for astronomical images"
+HOMEPAGE="http://hea-www.harvard.edu/RD/funtools/"
+SRC_URI="http://hea-www.harvard.edu/saord/download/${PN}/${P}.tar.gz"
+LICENSE="LGPL-2.1"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="doc"
+
+RDEPEND="sys-libs/zlib
+ >=sci-astronomy/wcstools-3.7.6
+ sci-visualization/gnuplot"
+DEPEND="${RDEPEND}
+ dev-util/pkgconfig"
+
+src_prepare() {
+ epatch "${FILESDIR}"/${P}-ds9-5.4.patch
+ epatch "${FILESDIR}"/${P}-makefiles.patch
+}
+
+src_configure() {
+ econf \
+ --enable-shared \
+ --enable-dl \
+ --enable-mainlib \
+ --with-wcslib="$(pkg-config --libs wcstools)" \
+ --with-zlib=-lz \
+ --with-tcl=-ltcl \
+ WCS_INC="$(pkg-config --cflags wcstools)"
+}
+
+src_compile() {
+ emake || die "emake failed"
+ emake shtclfun || die "emake tcl functions failed"
+}
+
+src_install () {
+ emake INSTALL_ROOT="${D}" install || die "emake install failed"
+ # install missing includes
+ insinto /usr/include/funtools/fitsy
+ doins fitsy/*.h || die
+ if use doc; then
+ cd doc
+ insinto /usr/share/doc/${PF}
+ doins *.pdf || die
+ insinto /usr/share/doc/${PF}/html
+ doins *.html *.c || die
+ fi
+}
diff --git a/sci-astronomy/funtools/metadata.xml b/sci-astronomy/funtools/metadata.xml
new file mode 100644
index 000000000000..2ebcdacd5c20
--- /dev/null
+++ b/sci-astronomy/funtools/metadata.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+<herd>sci</herd>
+<longdescription lang="en">
+ Funtools, is a minimal buy-in FITS library and utility package from
+ the SAO/HEAD. The Funtools library provides simplified
+ access to FITS images and binary tables, as well as to raw array and binary
+ event lists. The Funtools utilities provide high-level support for
+ processing astronomical data.
+</longdescription>
+</pkgmetadata>