⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch16_23.htm

📁 By Tom Christiansen and Nathan Torkington ISBN 1-56592-243-3 First Edition, published August 1998
💻 HTM
字号:
<HTML><HEAD><TITLE>Recipe 16.22. Program: sigrand (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen &amp; Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly &amp; Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:44:16Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="ch16_01.htm"TITLE="16. Process Management and Communication"><LINKREL="prev"HREF="ch16_22.htm"TITLE="16.21. Timing Out an Operation"><LINKREL="next"HREF="ch17_01.htm"TITLE="17. Sockets"></HEAD><BODYBGCOLOR="#FFFFFF"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch16_22.htm"TITLE="16.21. Timing Out an Operation"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 16.21. Timing Out an Operation"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch16_01.htm"TITLE="16. Process Management and Communication"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="chapter"HREF="ch17_01.htm"TITLE="17. Sockets"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 17. Sockets"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch16-chap16_program_0">16.22. Program: sigrand</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch16-pgfId-2256">Description</A></H3><PCLASS="para">The following <ACLASS="indexterm"NAME="ch16-idx-1000006436-0"></A><ACLASS="indexterm"NAME="ch16-idx-1000006436-1"></A><ACLASS="indexterm"NAME="ch16-idx-1000006436-2"></A><ACLASS="indexterm"NAME="ch16-idx-1000006436-3"></A><ACLASS="indexterm"NAME="ch16-idx-1000006436-4"></A>program gives you random signatures by using named pipes. It expects the signatures file to have records in the format of the <EMCLASS="emphasis">fortune</EM> program&nbsp;- that is, each possible multiline record is terminated with <CODECLASS="literal">&quot;%%\n&quot;</CODE>. Here's an example:</P><PRECLASS="programlisting">Make is like Pascal: everybody likes it, so they go in and change it.                                            --Dennis Ritchie%%I eschew embedded capital letters in names; to my prose-oriented eyes,they are too awkward to read comfortably. They jangle like bad typography.                                            --Rob Pike%%God made the integers; all else is the work of Man.                                              --Kronecker%%I'd rather have :rofix than const.          --Dennis Ritchie%%If you want to program in C, program in C.  It's a nice language.I use it occasionally...   :-)              --Larry Wall%%Twisted cleverness is my only skill as a programmer.                                                   --Elizabeth Zwicky%%Basically, avoid comments. If your code needs a comment to be understood,it would be better to rewrite it so it's easier to understand.                                              --Rob Pike%%Comments on data are usually much more helpful than on algorithms.                                              --Rob Pike%% Programs that write programs are the happiest programs in the world.                                            --Andrew Hume %%</PRE><PCLASS="para">We check whether we're already running by using a file with our PID in it. If sending a signal number 0 indicates that PID still exists (or, rarely, that something else has reused it), we just exit. We also look at the current Usenet posting to decide whether to look for a per-newsgroup signature file. That way, you can have different signatures for each newsgroup you post to. For variety, a global signature file is still on occasion used even if a per-newsgroup file exists.</P><PCLASS="para">You can even use <EMCLASS="emphasis">sigrand</EM> on systems without named pipes if you remove the code to create a named pipe and extend the sleep interval before file updates. Then <EMCLASS="emphasis">.signature</EM> would just be a regular file. Another portability concern is that the program forks itself in the background, which is almost like becoming a <ACLASS="indexterm"NAME="ch16-idx-1000008951-0"></A>daemon. If you have no <CODECLASS="literal">fork</CODE> call, just comment it out.</P><PCLASS="para">The full program is shown in <ACLASS="xref"HREF="ch16_23.htm#ch16-36804"TITLE="sigrand">Example 16.12</A>.</P><DIVCLASS="example"><H4CLASS="example"><ACLASS="title"NAME="ch16-36804">Example 16.12: sigrand</A></H4><PRECLASS="programlisting">#!/usr/bin/perl -w# sigrand - supply random fortunes for .signature fileuse strict;# config section variablesuse vars qw( $NG_IS_DIR $MKNOD $FULLNAME $FIFO $ART $NEWS $SIGS $SEMA            $GLOBRAND $NAME );# globalsuse vars qw( $Home $Fortune_Path @Pwd );################################################################# begin configuration section # should really read from ~/.sigrandrcgethome();# for rec/humor/funny instead of rec.humor.funny$NG_IS_DIR      = 1;    $MKNOD          = &quot;/bin/mknod&quot;;$FULLNAME       = &quot;$Home/.fullname&quot;;$FIFO           = &quot;$Home/.signature&quot;;$ART            = &quot;$Home/.article&quot;;$NEWS           = &quot;$Home/News&quot;;$SIGS           = &quot;$NEWS/SIGNATURES&quot;;$SEMA           = &quot;$Home/.sigrandpid&quot;;$GLOBRAND       = 1/4;  # chance to use global sigs anyway# $NAME should be (1) left undef to have program guess# read address for signature maybe looking in ~/.fullname,# (2) set to an exact address, or (3) set to empty string# to be omitted entirely.$NAME           = '';           # means no name used## $NAME        = &quot;me\@home.org\n&quot;;     # end configuration section -- HOME and FORTUNE get autoconf'd################################################################setup();                # pull in initsjustme();               # make sure program not already runningfork &amp;&amp; exit;           # background ourself and go awayopen (SEMA, &quot;&gt; $SEMA&quot;)      or die &quot;can't write $SEMA: $!&quot;;print SEMA &quot;$$\n&quot;;close(SEMA)                    or die &quot;can't close $SEMA: $!&quot;;# now loop forever, writing a signature into the # fifo file.  if you don't have real fifos, change# sleep time at bottom of loop to like 10 to update# only every 10 seconds.for (;;) {    open (FIFO, &quot;&gt; $FIFO&quot;)  or die &quot;can't write $FIFO: $!&quot;;    my $sig = pick_quote();    for ($sig) {         s/^((:?[^\n]*\n){4}).*$/$1/s;   # trunc to 4 lines        s/^(.{1,80}).*? *$/$1/gm;       # trunc long lines    }    # print sig, with name if present, padded to four lines    if ($NAME) {         print FIFO $NAME, &quot;\n&quot; x (3 - ($sig =~ tr/\n//)), $sig;    } else {        print FIFO $sig;    }    close FIFO;    # Without a microsleep, the reading process doesn't finish before    # the writer tries to open it again, which since the reader exists,    # succeeds.  They end up with multiple signatures.  Sleep a tiny bit    # between opens to give readers a chance to finish reading and close    # our pipe so we can block when opening it the next time.    select(undef, undef, undef, 0.2);   # sleep 1/5 second}die &quot;XXX: NOT REACHED&quot;;         # you can't get here from anywhere################################################################# Ignore SIGPIPE in case someone opens us up and then closes the fifo# without reading it; look in a .fullname file for their login name.# Try to determine the fully qualified hostname.  Look our for silly# ampersands in passwd entries.  Make sure we have signatures or fortunes.# Build a fifo if we need to.sub setup {    $SIG{PIPE} = 'IGNORE';                  unless (defined $NAME) {            # if $NAME undef in config        if (-e $FULLNAME) {            $NAME = `cat $FULLNAME`;            die &quot;$FULLNAME should contain only 1 line, aborting&quot;                 if $NAME =~ tr/\n// &gt; 1;        } else {            my($user, $host);            chop($host = `hostname`);            ($host) = gethostbyname($host) unless $host =~ /\./;            $user = $ENV{USER} || $ENV{LOGNAME} || $Pwd[0]                or die &quot;intruder alert&quot;;            ($NAME = $Pwd[6]) =~ s/,.*//;            $NAME =~ s/&amp;/\u\L$user/g; # can't believe some folks still do this            $NAME = &quot;\t$NAME\t$user\@$host\n&quot;;        }     }    check_fortunes() if !-e $SIGS;    unless (-p $FIFO) {         # -p checks whether it's a named pipe        if (!-e _) {             system(&quot;$MKNOD $FIFO p&quot;) &amp;&amp; die &quot;can't mknod $FIFO&quot;;             warn &quot;created $FIFO as a named pipe\n&quot;;        } else {             die &quot;$0: won't overwrite file .signature\n&quot;;        }     } else {        warn &quot;$0: using existing named pipe $FIFO\n&quot;;    }     # get a good random number seed.  not needed if 5.004 or better.    srand(time() ^ ($$ + ($$ &lt;&lt; 15)));}# choose a random signaturesub pick_quote {    my $sigfile = signame();    if (!-e $sigfile) {        return fortune();    }     open (SIGS, &quot;&lt; $sigfile&quot; ) or die &quot;can't open $sigfile&quot;;    local $/  = &quot;%%\n&quot;;    local $_;    my $quip;    rand($.) &lt; 1 &amp;&amp; ($quip = $_) while &lt;SIGS&gt;;    close SIGS;    chomp $quip;    return $quip || &quot;ENOSIG: This signature file is empty.\n&quot;;} # See whether ~/.article contains a Newsgroups line.  if so, see the first# group posted to and find out whether it has a dedicated set of fortunes.# otherwise return the global one.  also, return the global one randomly# now and then to spice up the sigs.sub signame {     (rand(1.0) &gt; ($GLOBRAND) &amp;&amp; open ART) || return $SIGS;        local $/  = '';     local $_  = &lt;ART&gt;;     my($ng)   = /Newsgroups:\s*([^,\s]*)/;     $ng =~ s!\.!/!g if $NG_IS_DIR;     # if rn -/,  or SAVEDIR=%p/%c     $ng = &quot;$NEWS/$ng/SIGNATURES&quot;;     return -f $ng ? $ng : $SIGS;} # Call the fortune program with -s for short flag until# we get a small enough fortune or ask too much.sub fortune {   local $_;   my $tries = 0;   do {        $_ = `$Fortune_Path -s`;    } until tr/\n// &lt; 5 || $tries++ &gt; 20;   s/^/ /mg;   $_ || &quot; SIGRAND: deliver random signals to all processes.\n&quot;;} # Make sure there's a fortune program.  Search # for its full path and set global to that.sub check_fortunes {    return if $Fortune_Path;    # already set    for my $dir (split(/:/, $ENV{PATH}), '/usr/games') {        return if -x ($Fortune_Path = &quot;$dir/fortune&quot;);    }     die &quot;Need either $SIGS or a fortune program, bailing out&quot;;} # figure out our directorysub gethome {    @Pwd = getpwuid($&lt;);    $Home = $ENV{HOME} || $ENV{LOGDIR} || $Pwd[7]       or die &quot;no home directory for user $&lt;&quot;;}# &quot;There can be only one.&quot;  --the Highlandersub justme {    if (open SEMA) {        my $pid;        chop($pid = &lt;SEMA&gt;);        kill(0, $pid) and die &quot;$0 already running (pid $pid), bailing out&quot;;        close SEMA;    } <ACLASS="indexterm"NAME="ch16-idx-1000006438-0"></A><ACLASS="indexterm"NAME="ch16-idx-1000006438-1"></A><ACLASS="indexterm"NAME="ch16-idx-1000006438-2"></A><ACLASS="indexterm"NAME="ch16-idx-1000006438-3"></A><ACLASS="indexterm"NAME="ch16-idx-1000006438-4"></A>} <ACLASS="indexterm"NAME="ch16-idx-1000006184-0"></A></PRE></DIV></DIV></DIV><DIVCLASS="htmlnav"><P></P><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch16_22.htm"TITLE="16.21. Timing Out an Operation"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 16.21. Timing Out an Operation"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="book"HREF="index.htm"TITLE="Perl Cookbook"><IMGSRC="../gifs/txthome.gif"ALT="Perl Cookbook"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="chapter"HREF="ch17_01.htm"TITLE="17. Sockets"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 17. Sockets"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">16.21. Timing Out an Operation</TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="index"HREF="index/index.htm"TITLE="Book Index"><IMGSRC="../gifs/index.gif"ALT="Book Index"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228">17. Sockets</TD></TR></TABLE><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><FONTSIZE="-1"></DIV<!-- LIBRARY NAV BAR --> <img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p> <a href="copyrght.htm">Copyright &copy; 2002</a> O'Reilly &amp; Associates. All rights reserved.</font> </p> <map name="library-map"> <area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map> </BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -