WvStreams
wvstreams.cc
00001 #include "wvistreamlist.h"
00002 #include "wvlog.h"
00003 #include "pwvstream.h"
00004 #include "wvstreamclone.h"
00005 #include "wvlinkerhack.h"
00006 #include <signal.h>
00007 
00008 WV_LINK_TO(WvConStream);
00009 WV_LINK_TO(WvTCPConn);
00010 
00011 
00012 volatile bool want_to_die = false;
00013 
00014 static void signalhandler(int sig)
00015 {
00016     fprintf(stderr, "Caught signal %d.  Exiting...\n", sig);
00017     want_to_die = true;
00018     signal(sig, SIG_DFL);
00019 }
00020 
00021 
00022 static void bounce_to_list(IWvStream *in, WvIStreamList *list)
00023 {
00024     char buf[4096];
00025     size_t len;
00026     
00027     len = in->read(buf, sizeof(buf));
00028     
00029     WvIStreamList::Iter i(*list);
00030     for (i.rewind(); i.next(); )
00031     {
00032         if (in != i.ptr())
00033         {
00034             // you might think this assumes IWvStream has a buffer; but in
00035             // fact, we already know that everything in the list is a
00036             // WvStreamClone, and WvStreamClone *does* have an output
00037             // buffer, so this is safe.
00038             i->write(buf, len);
00039         }
00040     }
00041 }
00042 
00043 
00044 static void died(WvLog &log, WvStringParm name, IWvStream *s)
00045 {
00046     if (s->geterr())
00047         log("%s: %s\n", name, s->errstr());
00048 }
00049 
00050 
00051 static void add(WvLog &log, WvIStreamList &list, const char *_mon)
00052 {
00053     WvString mon(_mon);
00054     if (mon == "-")
00055         mon = "stdio";
00056     log("Creating stream: '%s'\n", mon);
00057     PWvStream s(mon);
00058     if (!s->isok())
00059         died(log, _mon, s.addRef());
00060     else
00061     {
00062         s->setcallback(wv::bind(bounce_to_list, s.get(), &list));
00063         s->setclosecallback(wv::bind(died, log, _mon, s.addRef()));
00064     }
00065     list.append(s.addRef(), true, _mon);
00066 }
00067 
00068 
00069 int main(int argc, char **argv)
00070 {
00071     WvIStreamList list;
00072     WvLog log(argv[0], WvLog::Debug);
00073     
00074     signal(SIGTERM, signalhandler);
00075     signal(SIGINT, signalhandler);
00076 
00077     if (argc <= 1)
00078     {
00079         fprintf(stderr, "Usage: %s <stream1> [stream2 [stream3...]]\n",
00080                 argv[0]);
00081         return 1;
00082     }
00083     
00084     if (argc == 2) // talking to just one stream means send it to stdio
00085         add(log, list, "-");
00086     
00087     for (int count = 1; count < argc; count++)
00088         add(log, list, argv[count]);
00089     
00090     while (!want_to_die && list.count() >= 2)
00091         list.runonce();
00092 }