Cygwin-multitee
multitee sends multiple inputs to multiple outputs.
Check this page.
Original is here, or can also be found here on Debian.
Below you'll find a patch to build multitee on cygwin (and possibly any other POSIX distribution). To build, just untar the multitee archive, and then in a shell:
$ patch -Np1 <../multitee-3.0-cygwin.patch
$ make
$ cp multitee.1 /usr/local/man/man1
$ cp multitee.exe /usr/local/bin
Example of use:
$ multitee 0-1,4,5 4> foo 5> bar # same as tee foo bar with better blocking behavior
$ multitee 0:1 3:1 4:1,2 6:7 # various merge and copy
$ tcpclient server smtp multitee 0:7 6:1e0 # e0 tell multitee to quit as soon connection close
$ multitee 0:3 3:1 # same as 'socat - FD:3'
The patch
The patch ports calls to BSD signal.h API (struct sigvec, sigvec(), sigmask(), sigblock()...) to the POSIX API (struct sigaction, sigaction(), sigprocmask(), sigfillset()...).
Here the [{{#file: multitee-3.0-cygwin.patch}} patch (you can download it here)]:
--- multitee-3.0/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ multitee-3.0/Makefile 2008-11-24 03:35:43.875000000 +0100
@@ -0,0 +1,9 @@
+
+all: multitee tee
+
+multitee: multitee.o sigdfl.o sigsched.o ralloc.o getopt.o fmt.o scan.o
+tee: tee.o getopt.o ralloc.o fmt.o
+
+clean:
+ rm -f tee multitee *.o *.a *.0 *~ core
+
--- multitee-3.0/multitee.c 1998-02-17 03:25:43.000000000 +0100
+++ multitee-3.0/multitee.c 2008-11-24 03:38:51.296875000 +0100
@@ -180,7 +180,7 @@
int in;
int w;
- ioscp = (ioscstack) p;
+ ioscp = (struct iosc *) p;
in = ioscp->in;
if (ioscp->dead)
--- multitee-3.0/ralloc.c 1998-02-17 03:25:43.000000000 +0100
+++ multitee-3.0/ralloc.c 2008-11-24 03:41:24.093750000 +0100
@@ -40,7 +40,7 @@
#include "ralloc.h"
#include "sod.h"
-extern char *malloc(); /*XXXX*/
+extern void *malloc(); /*XXXX*/
extern void free();
typedef int (*foo)();
--- multitee-3.0/sigdfl.c 1998-02-17 03:25:44.000000000 +0100
+++ multitee-3.0/sigdfl.c 2008-11-24 03:39:57.734375000 +0100
@@ -2,6 +2,7 @@
Daniel J. Bernstein, brnstnd@nyu.edu.
No dependencies.
Requires BSD signal syscalls.
+24/11/08: Michael Peeters - Ported to POSIX signal.h (tested under Cygwin)
7/18/91: Baseline. sigdfl 1.0, public domain.
No known patent problems.
@@ -18,18 +19,20 @@
static int cont = 0;
-static sigcont() /* XXX: should declare with right signal type */
+static void sigcont(int sig) /* XXX: should declare with right signal type */
{
+ (void)sig;
cont = 1;
}
int sigdfl(sig)
int sig;
{
- int oldmask;
- struct sigvec oldvec;
- struct sigvec vec;
- struct sigvec contvec;
+ sigset_t oldmask;
+ sigset_t workmask;
+ struct sigaction oldvec;
+ struct sigaction vec;
+ struct sigaction contvec;
if (sig == SIGCONT)
return 0; /* strategy below simply cannot work for CONT */
@@ -43,19 +46,20 @@
/* killing the process and without stopping the process so that it'll */
/* receive CONT later, then we will enter an infinite loop. [sigh] */
/* XXX: put maximum time wastage on this? */
- oldmask = sigblock(0);
- sigblock(~0);
+ sigprocmask(SIG_BLOCK,NULL,&oldmask);
+ sigfillset(&workmask);
+ sigprocmask(SIG_BLOCK,&workmask,NULL);
/* now we won't receive any signals */
- vec.sv_handler = SIG_DFL;
- vec.sv_mask = ~0;
- vec.sv_flags = 0;
- if (sigvec(sig,&vec,&oldvec) == -1)
+ vec.sa_handler = SIG_DFL;
+ vec.sa_mask = ~0;
+ vec.sa_flags = 0;
+ if (sigaction(sig,&vec,&oldvec) == -1)
if ((sig != SIGSTOP) && (sig != SIGKILL))
return -1;
- vec.sv_handler = sigcont;
- vec.sv_mask = ~0;
- vec.sv_flags = 0;
- if (sigvec(SIGCONT,&vec,&contvec) == -1)
+ vec.sa_handler = sigcont;
+ vec.sa_mask = ~0;
+ vec.sa_flags = 0;
+ if (sigaction(SIGCONT,&vec,&contvec) == -1)
return -1;
cont = 0;
if (kill(getpid(),sig) == -1)
@@ -66,16 +70,20 @@
reached this point, sigcont() might already have been run. that's
why cont must be set to 0 before the kill(). */
/* after this next bit we may receive sig and/or CONT */
- sigsetmask(~(sigmask(sig) | sigmask(SIGCONT)));
+ sigfillset(&workmask);
+ sigdelset(&workmask,sig);
+ sigdelset(&workmask,SIGCONT);
+ sigprocmask(SIG_SETMASK,&workmask,NULL);
/* in the near future, sig will in fact be received */
while (!cont) /* dead loop until we receive CONT */
; /* XXX: there should be a syscall so we don't have to loop here */
- sigblock(~0);
+ sigfillset(&workmask);
+ sigprocmask(SIG_BLOCK,&workmask,NULL);
/* now we won't receive any signals */
- (void) sigvec(sig,&oldvec,&vec); /* we don't care if it fails */
- (void) sigvec(SIGCONT,&contvec,&vec);
+ (void) sigaction(sig,&oldvec,&vec); /* we don't care if it fails */
+ (void) sigaction(SIGCONT,&contvec,&vec);
/* now signal handlers are back to normal */
- (void) sigsetmask(oldmask);
+ (void) sigprocmask(SIG_SETMASK,&oldmask,NULL);
return 0;
}
--- multitee-3.0/sigsched.c 1998-02-17 03:25:44.000000000 +0100
+++ multitee-3.0/sigsched.c 2008-11-24 03:35:43.906250000 +0100
@@ -2,6 +2,7 @@
Daniel J. Bernstein, brnstnd@nyu.edu.
Depends on ralloc.h, sod.h, config/fdsettrouble.h.
Requires BSDish environment: reliable signals, sig{vec,block,setmask}, select.
+24/11/08: Michael Peeters - Ported to POSIX signal.h (tested under Cygwin)
9/1/91: Added worst-case fdset, FD_ZERO, etc. definitions.
8/25/91: sigsched 1.1, public domain.
8/25/91: Fixed bug that sigs[sched->blah].r didn't force instant timeout.
@@ -31,17 +32,6 @@
/* XXX: should restore signal set exactly after ss_exec returns */
-typedef int sigc_set; /*XXX */
-
-#define sigc_ismember(x,i) (*(x) & (1 << ((i) - 1)))
-#define sigc_addset(x,i) (*(x) |= (1 << ((i) - 1)))
-#define sigc_emptyset(x) (*(x) = 0)
-
-/* sigprocmask(SIG_UNBLOCK,xxxx,(sigc_set *) 0); */
-#define sigc_unblock(x) (sigsetmask(sigblock(0) & ~*(x)))
-/* sigprocmask(SIG_BLOCK,xxxx,(sigc_set *) 0); */
-#define sigc_block(x) (sigblock(*(x)))
-
#ifndef NSIG
#define NSIG 64 /* it's not as if any sane system has more than 32 */
#endif
@@ -333,8 +323,8 @@
sigs[i].r = 1;
}
-static sigc_set sigstorage;
-static sigc_set *xxxx = 0;
+static sigset_t sigstorage;
+static sigset_t *xxxx = 0;
int ss_addsig(i)
int i;
@@ -344,9 +334,9 @@
if (!xxxx)
{
xxxx = &sigstorage;
- sigc_emptyset(xxxx);
+ sigemptyset(xxxx);
}
- sigc_addset(xxxx,i);
+ sigaddset(xxxx,i);
return 0;
}
@@ -362,7 +352,7 @@
int ss_exec()
{
int i;
- struct sigvec sv;
+ struct sigaction sv;
recvlist recvhead;
recvlist temp;
schedlist sch;
@@ -371,18 +361,18 @@
if (xxxx)
{
- sigc_block(xxxx);
+ sigprocmask(SIG_BLOCK,xxxx,NULL);
- sv.sv_handler = handle;
- sv.sv_mask = *xxxx; /* so handle won't interrupt itself */
- sv.sv_flags = 0;
+ sv.sa_handler = handle;
+ sv.sa_mask = *xxxx; /* so handle won't interrupt itself */
+ sv.sa_flags = 0;
/* XXX: Does anyone but me find it absolutely idiotic that POSIX
doesn't provide a way to get each member of a signal set in turn? */
for (i = 0;i < NUMSIGS;i++)
{
- if (sigc_ismember(xxxx,i))
- if (sigvec(i,&sv,(struct sigvec *) 0) == -1) /*XXX: really trash orig? */
+ if (sigismember(xxxx,i))
+ if (sigaction(i,&sv,(struct sigaction *) 0) == -1) /*XXX: really trash orig? */
; /* not our problem */
}
}
@@ -498,7 +488,7 @@
}
if (xxxx)
- sigc_unblock(xxxx);
+ sigprocmask(SIG_UNBLOCK,xxxx,NULL);
/* This is the only section where handle() can be called. */
/* XXX: If maxfd == -1, this select functions as a pause. */
/* XXX: If maxfd == -1 and timeout is instant, should skip select. */
@@ -510,7 +500,7 @@
r = select(maxfd + 1,&rfds,&wfds,&efds,&timeout);
/* XXX: does this necessarily prevent timeout race conditions? */
if (xxxx)
- sigc_block(xxxx);
+ sigprocmask(SIG_BLOCK,xxxx,NULL);
if (r == -1)
{
@@ -529,7 +519,7 @@
for (sp = schedhead;sp;sp = SODnext(sp))
{
- switch(SODdata(sp).sig->type)
+ switch(SODdata(sp).sig->type)
{
case JUNK:
break;
@@ -595,7 +585,7 @@
}
}
if (xxxx)
- sigc_unblock(xxxx);
+ sigprocmask(SIG_UNBLOCK,xxxx,NULL);
/* XXX: should put this at other returns as well */
return 0;
}