📄 ch29_02.htm
字号:
contains the wait status value (see its interpretation under <tt class="literal">system</tt>)of the command associated with the other end of the pipe. For example:<blockquote><pre class="programlisting">open(OUTPUT, '| sort -rn | lpr -p') # pipe to sort and lpr or die "Can't start sortlpr pipe: $!";print OUTPUT @lines; # print stuff to outputclose OUTPUT # wait for sort to finish or warn $! ? "Syserr closing sortlpr pipe: $!" : "Wait status $? from sortlpr pipe";</pre></blockquote>A filehandle produced by <em class="emphasis">dup</em>(2)ing a pipe is treated as an ordinaryfilehandle, so <tt class="literal">close</tt> will not wait for the child on that filehandle.You have to wait for the child by closing the original filehandle.For example:<blockquote><pre class="programlisting">open(NETSTAT, "netstat -rn |") or die "can't run netstat: $!";open(STDIN, "<&NETSTAT") or die "can't dup to stdin: $!";</pre></blockquote>If you close <tt class="literal">STDIN</tt> above, there is no wait, but if youclose <tt class="literal">NETSTAT</tt>, there is.</p><p>If you somehow manage to reap an exited pipe child on your own, theclose will fail. This could happen if you had a <tt class="literal">$SIG{CHLD}</tt>handler of your own that got triggered when the pipe child exited, or ifyou intentionally called <tt class="literal">waitpid</tt> on the process ID returned from the<tt class="literal">open</tt> call.</p><h3 class="sect2">29.2.17. closedir <img src="figs/dollarbang.gif"> <img src="figs/xarg.gif"> <img src="figs/xu.gif"></h3><p><blockquote><pre class="programlisting">closedir <em class="replaceable">DIRHANDLE</em></pre></blockquote><a name="INDEX-4701"></a><a name="INDEX-4702"></a>This function closes a directory opened by <tt class="literal">opendir</tt>and returns the success of that operation. See the examples under<tt class="literal">readdir</tt>. <em class="replaceable">DIRHANDLE</em>may be an expression whose value can be used as an indirectdirhandle, usually the real dirhandle name.</p><h3 class="sect2">29.2.18. connect <img src="figs/dollarbang.gif"> <img src="figs/xarg.gif"> <img src="figs/xt.gif"> <img src="figs/xu.gif"></h3><p><blockquote><pre class="programlisting">connect <em class="replaceable">SOCKET</em>, <em class="replaceable">NAME</em></pre></blockquote><a name="INDEX-4703"></a><a name="INDEX-4704"></a>This function initiates a connection with another process that iswaiting at an <tt class="literal">accept</tt>. The function returns true if it succeeded,false otherwise. <em class="replaceable">NAME</em>should be a packed network address of the proper type for the socket.For example, assuming <tt class="literal">SOCK</tt> is a previously created socket:<blockquote><pre class="programlisting">use Socket;my ($remote, $port) = ("www.perl.com", 80);my $destaddr = sockaddr_in($port, inet_aton($remote));connect SOCK, $destaddr or die "Can't connect to $remote at port $port: $!";</pre></blockquote>To disconnect a socket, use either <tt class="literal">close</tt> or <tt class="literal">shutdown</tt>. See also theexamples in the section "Sockets" in <a href="ch16_01.htm">Chapter 16, "Interprocess Communication"</a>. See <em class="emphasis">connect</em>(2).</p><h3 class="sect2">29.2.19. cos <img src="figs/dollarunderscore.gif"></h3><p><blockquote><pre class="programlisting">cos <em class="replaceable">EXPR</em>cos</pre></blockquote><a name="INDEX-4705"></a>This function returns the cosine of <em class="replaceable">EXPR</em> (expressed in radians).For example, the following script will print a cosine table of anglesmeasured in degrees:<blockquote><pre class="programlisting"># Here's the lazy way of getting degrees-to-radians.$pi = atan2(1,1) * 4;$piover180 = $pi/180;# Print table.for ($deg = 0; $deg <= 90; $deg++) { printf "%3d %7.5f\n", $deg, cos($deg * $piover180);}</pre></blockquote>For the inverse cosine operation, you may use the <tt class="literal">acos()</tt> functionfrom the <tt class="literal">Math::Trig</tt> or <tt class="literal">POSIX</tt> modules, or use this relation:<blockquote><pre class="programlisting">sub acos { atan2( sqrt(1 - $_[0] * $_[0]), $_[0] ) }</pre></blockquote></p><h3 class="sect2">29.2.20. crypt <img src="figs/xu.gif"></h3><p><blockquote><pre class="programlisting">crypt <em class="replaceable">PLAINTEXT</em>, <em class="replaceable">SALT</em></pre></blockquote><a name="INDEX-4706"></a><a name="INDEX-4707"></a><a name="INDEX-4708"></a><a name="INDEX-4709"></a>This function computes a one-way hash of a string exactly in themanner of <em class="emphasis">crypt</em>(3). This is somewhatuseful for checking the password file for lousypasswords,<a href="#FOOTNOTE-3">[3]</a> although what you really want todo is prevent people from adding the bad passwords in the first place.</p><blockquote class="footnote"><a name="FOOTNOTE-3"></a><p>[3] Only people with honorable intentions areallowed to do this.</p></blockquote><p><tt class="literal">crypt</tt> is intended to be a one-way function, muchlike breaking eggs to make an omelette. There is no (known) way todecrypt an encrypted password apart from exhaustive, brute-forceguessing.</p><p>When verifying an existing encrypted string, you should use theencrypted text as the <em class="replaceable">SALT</em> (like <tt class="literal">crypt($plain, $crypted) eq $crypted</tt>). This allows your code to work with the standard<tt class="literal">crypt</tt>, and with more exotic implementations, too.</p><p>When choosing a new <em class="replaceable">SALT</em>, you minimally need to create a random two character string whosecharacters come from the set <tt class="literal">[./0-9A-Za-z]</tt>(like <tt class="literal">join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]</tt>).Older implementations of <tt class="literal">crypt</tt> only needed the first two charactersof the <em class="replaceable">SALT</em>, but code that only gives the first two charactersis now considered nonportable. See your local <em class="emphasis">crypt</em>(3) manpagefor interesting details.</p><p>Here's an example that makes sure that whoever runs this program knowstheir own password:<blockquote><pre class="programlisting">$pwd = (getpwuid ($<))[1]; # Assumes we're on Unix.system "stty -echo"; # or look into Term::ReadKey on CPANprint "Password: ";chomp($word = <STDIN>);print "\n";system "stty echo";if (crypt($word, $pwd) ne $pwd) { die "Sorry...\n";} else { print "ok\n";}</pre></blockquote>Of course, typing in your own password to whoever asks for it isunwise.</p><p>Shadow password files are slightly more secure than traditionalpassword files, and you might have to be a superuser to access them.Because few programs should run under such powerful privileges, youmight have the program maintain its own independent authenticationsystem by storing the <tt class="literal">crypt</tt> strings in a differentfile than <em class="emphasis">/etc/passwd</em> or<em class="emphasis">/etc/shadow</em>.</p><p>The <tt class="literal">crypt</tt> function is unsuitable for encrypting large quantitiesof data, not least of all because you can't get the informationback. Look at the <em class="emphasis">by-module/Crypt</em> and <em class="emphasis">by-module/PGP</em> directorieson your favorite CPAN mirror for a slew of potentially usefulmodules.</p><h3 class="sect2">29.2.21. dbmclose <img src="figs/dollarbang.gif"> <img src="figs/xu.gif"></h3><p><blockquote><pre class="programlisting">dbmclose <em class="replaceable">HASH</em></pre></blockquote><a name="INDEX-4710"></a>This function breaks the binding between a DBM (database management)file and a hash. <a name="INDEX-4711"></a><tt class="literal">dbmclose</tt> is really just a call to<tt class="literal">untie</tt> with the proper arguments, but is provided for backward compatibility with ancientversions of Perl.</p><h3 class="sect2">29.2.22. dbmopen <img src="figs/dollarbang.gif"> <img src="figs/xu.gif"></h3><p><blockquote><pre class="programlisting">dbmopen <em class="replaceable">HASH</em>, <em class="replaceable">DBNAME</em>, <em class="replaceable">MODE</em></pre></blockquote><a name="INDEX-4712"></a><a name="INDEX-4713"></a>This binds a DBM file to a hash (that is, an associative array).(DBM stands for database management, and consists of a set of Clibrary routines that allow random access to records via a hashingalgorithm.) <em class="replaceable">HASH</em> is the name of the hash (including the <tt class="literal">%</tt>).<em class="replaceable">DBNAME</em> is the name of the database (without any <em class="emphasis">.dir</em> or <em class="emphasis">.pag</em>extension). If the database does not exist and a valid <em class="replaceable">MODE</em>is specified, the database is created with the protection specifiedby <em class="replaceable">MODE</em>, as modified by the umask. To prevent creation of thedatabase if it doesn't exist, you may specify a <em class="replaceable">MODE</em> of <tt class="literal">undef</tt>,and the function will return false if it can't find anexisting database. Values assigned to the hash prior to the<tt class="literal">dbmopen</tt> are not accessible.</p><p>The <tt class="literal">dbmopen</tt> function is really just a call to<tt class="literal">tie</tt> with the proper arguments, but is provided forbackward compatibility with ancient versions of Perl. You can controlwhich DBM library you use by using the <tt class="literal">tie</tt>interface directly or by loading the appropriate module before youcall <tt class="literal">dbmopen</tt>. Here's an example that works on somesystems for versions of <tt class="literal">DB_File</tt> similar to theversion in your Netscape browser:<blockquote><pre class="programlisting">use DB_File;dbmopen(%NS_Hist, "$ENV{HOME}/.netscape/history.dat", undef) or die "Can't open netscape history file: $!";while (($url, $when) = each %NS_Hist) { next unless defined($when); chop ($url, $when); # kill trailing null bytes printf "Visited %s at %s.\n", $url, scalar(localtime(unpack("V",$when)));}</pre></blockquote>If you don't have write access to the DBM file, you can only readthe hash variables, not set them. If you want to test whether youcan write, either use a file test like <tt class="literal">-w $file</tt>, or try setting adummy hash entry inside an <tt class="literal">eval {}</tt>, which will trap the exception.</p><p>Functions such as <tt class="literal">keys</tt> and <tt class="literal">values</tt> may return huge list valueswhen used on large DBM files. You may prefer to use the <tt class="literal">each</tt>function to iterate over large DBM files so that you don't load thewhole thing in memory at once.</p><p>Hashes bound to DBM files have the same limitations as the type of DBMpackage you're using, including restrictions on how much data you canput into a bucket. If you stick to short keys and values, it's rarelya problem. See also the <tt class="literal">DB_File</tt> module in <a href="ch32_01.htm">Chapter 32, "Standard Modules"</a>.</p><p>Another thing you should bear in mind is that many existing DBMdatabases contain null-terminated keys and values because they wereset up with C programs in mind. The Netscape history file and theold <em class="emphasis">sendmail</em> aliases file are examples. Just use <tt class="literal">"$key\0"</tt>when pulling out a value, and remove the null from the value.<blockquote><pre class="programlisting">$alias = $aliases{"postmaster\0"};chop $alias; # kill the null</pre></blockquote><a name="INDEX-4714"></a><a name="INDEX-4715"></a><a name="INDEX-4716"></a>There is currently no built-in way to lock a generic DBM file. Somewould consider this a bug. The <tt class="literal">GDBM_File</tt> module does attempt to providelocking at the granularity of the entire file. When in doubt,your best bet is to use a separate lock file.</p><h3 class="sect2">29.2.23. defined <img src="figs/dollarunderscore.gif"></h3><p><blockquote><pre class="programlisting">defined <em class="replaceable">EXPR</em>defined</pre></blockquote><a name="INDEX-4717"></a><a name="INDEX-4718"></a><a name="INDEX-4719"></a><a name="INDEX-4720"></a>This function returns a Boolean value saying whether <em class="replaceable">EXPR</em> has adefined value or not. Most of the data you deal with is defined, buta scalar that contains no valid string, numeric, or reference value issaid to contain the undefined value, or <tt class="literal">undef</tt> for short.Initializing a scalar variable to a particular value will define it,and it will stay defined until you assign an undefined value to it orexplicitly call the <tt class="literal">undef</tt> function on that variable.</p><p>Many operations return <tt class="literal">undef</tt> under exceptionalconditions, such as at end-of-file, when using an uninitialized
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -