Cygwin-multitee

From YobiWiki
Jump to navigation Jump to search

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]:

--- multitee-3.0/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ multitee-3.0-cygwin/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-cygwin/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-cygwin/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-cygwin/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-cygwin/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;
 }