home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / lang / perl / 5018 < prev    next >
Encoding:
Internet Message Format  |  1992-07-29  |  7.6 KB

  1. Path: sparky!uunet!olivea!tymix!grimoire!mooring
  2. From: mooring@grimoire.tymnet.com (Ed Mooring)
  3. Newsgroups: comp.lang.perl
  4. Subject: Re: Multiple listeners to a data source
  5. Message-ID: <2164@tymix.Tymnet.COM>
  6. Date: 29 Jul 92 18:36:01 GMT
  7. References: <1992Jul29.145654.6622@nstn.ns.ca>
  8. Sender: usenet@tymix.Tymnet.COM
  9. Organization: BT Tymnet Bit Bucket Brigade
  10. Lines: 249
  11. Nntp-Posting-Host: grimoire
  12.  
  13. In article <1992Jul29.145654.6622@nstn.ns.ca> daniel@nstn.ns.ca (Daniel MacKay) writes:
  14. >Hello!
  15. >
  16. >I will be bringing up a data source in a few days, (it's a connection to a
  17. >weather satellite) that I'd like people to be able to just telnet to a port
  18. >on my machine, and listen in on- say, five or ten people, all with the same
  19. >data scrolling by, kind of like a broadcast ticker tape machine.
  20. >
  21. >I'm looking for suggestions about how to do it.  The boneheaded solution is
  22. >to set up a "tail -f" on a file that the data's being dumped into- but I
  23. >was hoping to not save the data- it's jillions of lines a day.
  24. >
  25. >The data will be arriving on a TCP port to which a Perl program will be
  26. >attached; the program will pull out selected data sets and pop them into
  27. >individual files.  But I'd also like to make the raw data available to
  28. >whoever wants it in real time.
  29.  
  30. Here's something I call a broadcast server that does almost exactly
  31. what you want.  Right now it reads stdin, and writes to whomever
  32. makes a connection to it.  It also has some primitive security,
  33. and an even more primitive man page.
  34. -------------------- snip here-------------------- 
  35. #! /bin/sh
  36. # This is a shell archive.  Remove anything before this line, then unpack
  37. # it by saving it into a file and typing "sh file".  To overwrite existing
  38. # files, type "sh file -c".  You can also feed this as standard input via
  39. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  40. # will see the following message at the end:
  41. #        "End of shell archive."
  42. # Contents:  /home/grimoire/a/mooring/errlogger/bcast
  43. #   /home/grimoire/a/mooring/errlogger/bcast.1
  44. # Wrapped by mooring@grimoire on Wed Jul 29 11:34:09 1992
  45. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  46. if test -f '/home/grimoire/a/mooring/errlogger/bcast' -a "${1}" != "-c" ; then 
  47.   echo shar: Will not clobber existing file \"'/home/grimoire/a/mooring/errlogger/bcast'\"
  48. else
  49. echo shar: Extracting \"'/home/grimoire/a/mooring/errlogger/bcast'\" \(3210 characters\)
  50. sed "s/^X//" >'/home/grimoire/a/mooring/errlogger/bcast' <<'END_OF_FILE'
  51. X#!/usr/local/bin/perl -s
  52. X
  53. X$pat = 'S n C4 x8';
  54. X$inet = 2;
  55. X$echo = 7;
  56. X$smtp = 25;
  57. X$nntp = 119;
  58. X
  59. Xdie "Usage:  $0 port \n" unless @ARGV;
  60. X$this = pack($pat,$inet,$ARGV[0], 0,0,0,0);
  61. X#$this = pack($pat,$inet,2345, 0,0,0,0);
  62. X
  63. Xsocket(LISTENER,2,1,6) || die "Socket $!\n";
  64. Xbind(LISTENER,$this) || die "Bind $!\n";
  65. Xlisten(LISTENER,5) || die "Listen $!\n";
  66. X
  67. X$readbits = $writebits = 8 x "\0";
  68. X# always read from standard input
  69. Xvec($readbits,0,1) = 1;
  70. X
  71. X# and look for new connections
  72. X#
  73. Xvec($readbits,fileno(LISTENER),1) = 1;
  74. X
  75. X$listener = fileno(LISTENER);
  76. X
  77. X$0 = $0;
  78. X#
  79. X# prototype file name
  80. X#
  81. X$sockp = 'clientaa';
  82. Xwhile (1)
  83. X{
  84. X    $rbits = $readbits;
  85. X    $wbits = $writebits;
  86. X    grep(vec($wbits,$_,1) = 1, keys %bcastpending);
  87. X    ($nfound, $timeleft) = select($rbits, $wbits, undef, undef);
  88. X    if ($nfound > 0)
  89. X    {
  90. X    #
  91. X    # we got a hit of some sort
  92. X    # first see if anything to write
  93. X    if ($wbits =~ /[^\0]/)
  94. X    {
  95. X        $bstr = unpack('b*',$wbits);
  96. X        for($fd = index($bstr,'1'); $fd >= 0; $fd = index($bstr,'1',$fd+1))
  97. X        {
  98. X        # we just ignore errors here
  99. X        #
  100. X        $sock = $filenames[$fd];
  101. X        send($sock,$bcastdata,0);
  102. X        delete $bcastpending{$fd};
  103. X        }
  104. X    }
  105. X    if ($rbits =~ /[^\0]/)
  106. X    {
  107. X        $bstr = unpack('b*',$rbits);
  108. X        for($fd = index($bstr,'1'); $fd >= 0; $fd = index($bstr,'1',$fd+1))
  109. X        {
  110. X        if ($fd == 0)
  111. X        {
  112. X            # deal with stdin
  113. X            $incount = sysread(STDIN,$bcastdata,1024);
  114. X            if ($incount == 0)
  115. X            {
  116. X            # lost our connection
  117. X            die "EOF from source\n";
  118. X            }
  119. X            elsif ($incount < 0)
  120. X            {
  121. X            # error
  122. X            die "Error from source($!)\n" if ($! !~ /Interrupted/);
  123. X            }
  124. X            grep($bcastpending{$_} = 1, keys %active);
  125. X        }
  126. X        elsif ($fd == $listener)
  127. X        {
  128. X            # deal with cloning new socket
  129. X            $newsock = $sockp++;
  130. X            if ($addr = accept($newsock,LISTENER))
  131. X            {
  132. X            #
  133. X            # see if we like this host
  134. X            #
  135. X            ($fam,$port,$inetaddr) = unpack('SSL',$addr);
  136. X            if ($verbose)
  137. X            {
  138. X                $hostname = gethostbyaddr($addr, 2);
  139. X                printf "Connection from $hostname %x %d\n", $inetaddr, $port;
  140. X            }
  141. X            # change inet address to match your site
  142. X            if ($inetaddr != 0x7f000001 && $inetaddr & 0xffff0000 != 0x83920000)
  143. X            {
  144. X                #
  145. X                # not a host we like, bounce it.
  146. X                #
  147. X                close ($newsock);
  148. X                if ($verbose)
  149. X                {
  150. X                $hostname = gethostbyaddr($addr, 2);
  151. X                printf "Connection refused from $hostname %x %d\n", $inetaddr, $port;
  152. X                }
  153. X            }
  154. X
  155. X            #
  156. X            # set bit vectors for later use
  157. X            #
  158. X            vec($readbits,fileno($newsock),1) = 1;
  159. X            $bcastpending{fileno($newsock)} = 1 if length $bcastdata;
  160. X            $active{fileno($newsock)} = 1;
  161. X            $filenames[fileno($newsock)] = $newsock;
  162. X            }
  163. X            else
  164. X            {
  165. X            die "Error on accept $!\n";
  166. X            }
  167. X        }
  168. X        else
  169. X        {
  170. X            # read data from socket and toss, check for eof
  171. X            $sock = $filenames[$fd];
  172. X            $incount = read($sock,$waste,1024);
  173. X            if ($incount == 0)
  174. X            {
  175. X            # lost our connection
  176. X            #
  177. X            # reset bit vectors
  178. X            #
  179. X            vec($readbits,$fd,1) = 0;
  180. X            $filenames[$fd] = '';
  181. X            delete $bcastpending{$fd};
  182. X            delete $active{$fd};
  183. X            }
  184. X            elsif ($incount < 0)
  185. X            {
  186. X            # error
  187. X            die "Error from socket($!)\n" if ($! !~ /Interrupted/);
  188. X            }
  189. X        }
  190. X        }
  191. X    }
  192. X    }
  193. X    elsif ($nfound < 0)
  194. X    {
  195. X    die "Error ($!) on select\n" unless $! =~ /Interrupted/;
  196. X    }
  197. X}
  198. Xexit 0;
  199. END_OF_FILE
  200. if test 3210 -ne `wc -c <'/home/grimoire/a/mooring/errlogger/bcast'`; then
  201.     echo shar: \"'/home/grimoire/a/mooring/errlogger/bcast'\" unpacked with wrong size!
  202. fi
  203. chmod +x '/home/grimoire/a/mooring/errlogger/bcast'
  204. # end of '/home/grimoire/a/mooring/errlogger/bcast'
  205. fi
  206. if test -f '/home/grimoire/a/mooring/errlogger/bcast.1' -a "${1}" != "-c" ; then 
  207.   echo shar: Will not clobber existing file \"'/home/grimoire/a/mooring/errlogger/bcast.1'\"
  208. else
  209. echo shar: Extracting \"'/home/grimoire/a/mooring/errlogger/bcast.1'\" \(912 characters\)
  210. sed "s/^X//" >'/home/grimoire/a/mooring/errlogger/bcast.1' <<'END_OF_FILE'
  211. X.TH BCAST 1L
  212. X.SH NAME
  213. Xbcast \- broadcast daemon
  214. X.SH SYNOPSIS
  215. X.LP
  216. X.B bcast
  217. X[
  218. X.B \-verbose
  219. X]
  220. X.I port
  221. X.SH DESCRIPTION
  222. X.LP
  223. X.B bcast
  224. Xis a daemon that binds
  225. X.I port
  226. Xon the local machine and broadcasts whatever it receives on its
  227. Xstandard input to any processes that connect to it.  This is done
  228. Xon a ``you snooze, you lose'' basis; that is, if a process hasn't read
  229. Xthe data that
  230. X.B bcast
  231. Xreceived before it gets another chunk,
  232. X.B bcast
  233. Xwill not attempt to buffer the old data.  Any read done by that process
  234. Xwill get the most recently-received data.
  235. X.SH OPTIONS
  236. X.TP
  237. X.B \-verbose
  238. Xputs the program in verbose mode, causing it to print a message whenever
  239. Xa connection is accepted or rejected.
  240. X.SH DIAGNOSTICS
  241. X.LP
  242. XVarious error messages on system call failures.
  243. X.SH NOTES
  244. X.LP
  245. X.B bcast
  246. Xwill not accept connections from any machines outside
  247. Xof the Tymnet sub-network.
  248. X.SH AUTHOR
  249. X.LP
  250. XEd Mooring (mooring@antares.tymnet.com)
  251. END_OF_FILE
  252. if test 912 -ne `wc -c <'/home/grimoire/a/mooring/errlogger/bcast.1'`; then
  253.     echo shar: \"'/home/grimoire/a/mooring/errlogger/bcast.1'\" unpacked with wrong size!
  254. fi
  255. # end of '/home/grimoire/a/mooring/errlogger/bcast.1'
  256. fi
  257. echo shar: End of shell archive.
  258. exit 0
  259.  
  260. Regards,
  261. Ed Mooring (mooring@tymix.tymnet.com 408-922-7504)
  262.