📄 ch15.htm
字号:
<HTML>
<HEAD>
<TITLE>Chapter 15 -- Direct Access to System Facilities</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.0b5aGold (WinNT; I) [Netscape]">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT COLOR=#FF0000>Chapter 15</FONT></H1>
<H1><B><FONT SIZE=5 COLOR=#FF0000>Direct Access to System Facilities</FONT></B>
</H1>
<P>
<HR WIDTH="100%"></P>
<P>
<H3 ALIGN=CENTER><FONT COLOR="#000000"><FONT SIZE=+2>CONTENTS<A NAME="CONTENTS"></A>
</FONT></FONT></H3>
<UL>
<LI><A HREF="#Introduction" >Introduction</A>
<LI><A HREF="#WorkingwithUNIXUsersandGroups" >Working with UNIX Users and Groups</A>
<UL>
<LI><A HREF="#Informationfrometcpasswdwithgetpwe" >Information from /etc/passwd with getpwent()</A>
<LI><A HREF="#GettingGroupRelatedInformationwithg" >Getting Group-Related Information with getgrent() and getgrnam()</A>
</UL>
<LI><A HREF="#GettingInformationinNetworkFiles" >Getting Information in Network Files</A>
<UL>
<LI><A HREF="#ThegetnetentFunction" >The getnetent Function</A>
<LI><A HREF="#WorkingwithHostNamesUsinggethostbya" >Working with Host Names Using gethostbyaddr() Functions</A>
<LI><A HREF="#WorkingwithProcessGroupsUsingthege" >Working with Process Groups Using the getpgrp() Function</A>
</UL>
<LI><A HREF="#GettingandChangingthePriorityofaP" >Getting and Changing the Priority of a Process</A>
<UL>
<LI><A HREF="#ThesetpriorityFunction" >The setpriority Function</A>
<LI><A HREF="#ThegetpriorityFunction" >The getpriority Function</A>
<LI><A HREF="#WorkingwithProtocolFilesUsingthege" >Working with Protocol Files Using the getprotoent() Function</A>
<LI><A HREF="#ThegetserventFunction" >The getservent Function</A>
</UL>
<LI><A HREF="#SystemLevelFunctions" >System-Level Functions</A>
<UL>
<LI><A HREF="#ThechrootFunction" >The chroot Function</A>
<LI><A HREF="#ThedumpFunction" >The dump Function</A>
<LI><A HREF="#UsingtheioctlFunction" >Using the ioctl Function</A>
<LI><A HREF="#UsingtheselectCall" >Using the select Call</A>
<LI><A HREF="#ThesyscallFunction" >The syscall Function</A>
</UL>
<LI><A HREF="#Summary" >Summary</A>
</UL>
<HR>
<P>
Perl can be used to access system facilities not directly available
in shell or <TT><FONT FACE="Courier">awk</FONT></TT> programs.
This chapter discusses some of the ways in which Perl programs
can access system files and resources. The bulk of this chapter
provides information on accessing data structures within system
files on a UNIX system. In <A HREF="ch9.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch9.htm" >Chapter 9</A>, "Portability
Issues with Windows and Perl," and <A HREF="ch10.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch10.htm" >Chapter 10</A>,
"Win32 Modules on Windows NT," I discussed ways of accessing
files on an NT system when covering portability issues.
<H2><A NAME="Introduction"><FONT SIZE=5 COLOR=#FF0000>Introduction</FONT></A>
</H2>
<P>
Accessing system facilities enables you to add that extra spice
to your Perl programs. You have already seen how to call UNIX
programs with the back quote (<TT><FONT FACE="Courier">`</FONT></TT>)
operators or the <TT><FONT FACE="Courier">system()</FONT></TT>
call. Both these mechanisms are costly in terms of using system
resources because they start a subshell to execute another process.
Perl offers many utilities to access system files and affects
process parameters (such as process priorities) without resorting
to firing up another process to perform a simple command.
<P>
Let's start with an example that shows you how to get more information
about the user running your Perl program. Sometimes it might be
nice to personalize your Perl scripts by sending messages back
to the user running your script. It's easy to derive the user
name from the <TT><FONT FACE="Courier">/etc/passwd</FONT></TT>
file or from calling the <TT><FONT FACE="Courier">getlogin()</FONT></TT>
function. Here's the syntax for the <TT><FONT FACE="Courier">getlogin()</FONT></TT>
function:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$userName = getlogin();</FONT></TT>
</BLOCKQUOTE>
<P>
<TT><FONT FACE="Courier">$userName</FONT></TT> is the returned
user ID. For example, you could write a script to get the name
and print out an appropriate greeting based on the user name:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$logname = getlogin();<BR>
if ($logname == "khusain") {<BR>
</FONT></TT> <TT><FONT FACE="Courier"> print
("Hello, Kamran! How are you?\n");<BR>
} else {<BR>
if ($logname == "mgr2") {<BR>
print ("Oh
no, it's you again !! !!!! !!\n");<BR>
}</FONT></TT>
</BLOCKQUOTE>
<P>
I am sure that you can come up with more practical applications
rather than spewing greetings and salutations based on a user
name. Practical examples include getting files, mail, and so on
based on the user name. A number of utilities are available that
do such things as answer your mail while you're on vacation and
manage your mail from multiple sources. Check out the archives
at the various Perl archive sites listed in appendix B, "Perl
Module Archives," for these files. Most of these utilities
are copyrighted by their authors, so they cannot be printed here,
but you will get a good idea of what they can do.
<H2><A NAME="WorkingwithUNIXUsersandGroups"><FONT SIZE=5 COLOR=#FF0000>Working
with UNIX Users and Groups</FONT></A></H2>
<P>
Perl is great for working with user and group information files
in the <TT><FONT FACE="Courier">/etc</FONT></TT> directory. You
can get user and group names, IDs, and other useful information
from within your Perl programs to create powerful system administration
applications.
<H3><A NAME="Informationfrometcpasswdwithgetpwe">Information from
<TT><FONT SIZE=4 FACE="Courier">/etc/passwd</FONT></TT><FONT SIZE=4>
with</FONT><TT><FONT SIZE=4 FACE="Courier"> getpwent()</FONT></TT></A>
</H3>
<P>
The <TT><FONT FACE="Courier">getpwent()</FONT></TT> function enables
you to access sequentially entries in the <TT><FONT FACE="Courier">/etc/passwd</FONT></TT>
file. Here's the syntax for the <TT><FONT FACE="Courier">getpwent</FONT></TT>
function:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">($username,<BR>
$password,<BR>
$userid,<BR>
$groupid,<BR>
$quota,<BR>
$comment,<BR>
$userInfo,<BR>
$userHome,<BR>
$loginShell) = getpwent();</FONT></TT>
</BLOCKQUOTE>
<P>
Here are the returned values from the <TT><FONT FACE="Courier">getpwent</FONT></TT>
call:<P>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR VALIGN=TOP><TD WIDTH=129><TT><FONT FACE="Courier">$username</FONT></TT>
</TD><TD WIDTH=275>Contains the login name of the user</TD></TR>
<TR VALIGN=TOP><TD WIDTH=129><TT><FONT FACE="Courier">$password</FONT></TT>
</TD><TD WIDTH=275>Contains the user's encrypted password</TD>
</TR>
<TR VALIGN=TOP><TD WIDTH=129><TT><FONT FACE="Courier">$userid</FONT></TT>
</TD><TD WIDTH=275>The user ID</TD></TR>
<TR VALIGN=TOP><TD WIDTH=129><TT><FONT FACE="Courier">$groupid</FONT></TT>
</TD><TD WIDTH=275>The group ID</TD></TR>
<TR VALIGN=TOP><TD WIDTH=129><TT><FONT FACE="Courier">$quota</FONT></TT>
</TD><TD WIDTH=275>System dependent and may not exist</TD></TR>
<TR VALIGN=TOP><TD WIDTH=129><TT><FONT FACE="Courier">$comment</FONT></TT>
</TD><TD WIDTH=275>System dependent and may not exist</TD></TR>
<TR VALIGN=TOP><TD WIDTH=129><TT><FONT FACE="Courier">$userInfo</FONT></TT>
</TD><TD WIDTH=275>Personal information about the user</TD></TR>
<TR VALIGN=TOP><TD WIDTH=129><TT><FONT FACE="Courier">$userHome</FONT></TT>
</TD><TD WIDTH=275>The user's home directory</TD></TR>
<TR VALIGN=TOP><TD WIDTH=129><TT><FONT FACE="Courier">$loginShell</FONT></TT>
</TD><TD WIDTH=275>The user's startup command shell</TD></TR>
</TABLE></CENTER>
<P>
<P>
To access each entry of the password file in turn, you can use
the <TT><FONT FACE="Courier">getpwent()</FONT></TT> function.
Calling the <TT><FONT FACE="Courier">getpwent()</FONT></TT> function
for the first time in a program returns the first item in the
<TT><FONT FACE="Courier">/etc/passwd</FONT></TT> file. Every subsequent
call to <TT><FONT FACE="Courier">getpwent()</FONT></TT>returns
the next entry in the file. The function returns an empty list
after reaching the last entry in the file. Calling the <TT><FONT FACE="Courier">getpwent()</FONT></TT>
function after an empty list is received returns the first item
in <TT><FONT FACE="Courier">/etc/passwd</FONT></TT>, and you can
start over. The <TT><FONT FACE="Courier">getpwent()</FONT></TT>
function has two related functions: <TT><FONT FACE="Courier">setpwent()</FONT></TT>
to rewind the file and <TT><FONT FACE="Courier">endpwent()</FONT></TT>
to close the <TT><FONT FACE="Courier">/etc/passwd</FONT></TT>
file. Here's the syntax for the <TT><FONT FACE="Courier">setpwent</FONT></TT>
function:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">setpwent (keepopen);</FONT></TT>
</BLOCKQUOTE>
<P>
If <TT><FONT FACE="Courier">keepopen</FONT></TT> is non-zero,
the <TT><FONT FACE="Courier">/etc/passwd</FONT></TT> file is left
open for reading and any previously cached information about the
file is kept in memory. If <TT><FONT FACE="Courier">keepopen</FONT></TT>
is set to zero, any cached information in memory is flushed and
the file is read again with the first entry available for a call
to <TT><FONT FACE="Courier">getpwent()</FONT></TT>. The <TT><FONT FACE="Courier">endpwent</FONT></TT>
function simply closes the <TT><FONT FACE="Courier">/etc/password</FONT></TT>
file.
<P>
Listing 15.1 uses <TT><FONT FACE="Courier">getpwent</FONT></TT>
to list the user names known by the machine as well as their user
IDs.
<HR>
<BLOCKQUOTE>
<B>Listing 15.1. Listing password entries.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2<BR>
3 while
(1) {<BR>
4 last
unless (($username, $password, $userid)<BR>
5 =
getpwent());<BR>
6 $users{$username}
= $userid;<BR>
7 }<BR>
8 print ("Users on this machine:\n");
<BR>
9<BR>
10 foreach $user (sort keys (%users)) {<BR>
11 printf
("%-20s %d\n", $user, $users{$user});<BR>
12 }</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
The <TT><FONT FACE="Courier">while</FONT></TT> loop in this listing
calls <TT><FONT FACE="Courier">getpwent()</FONT></TT> to read
every entry in the <TT><FONT FACE="Courier">/etc/password</FONT></TT>
file. For this script, we are using only the first three elements
of the returned list: the users' names, their encrypted passwords,
and their IDs. The values are stored in the <TT><FONT FACE="Courier">%users</FONT></TT>
associative array and displayed in the <TT><FONT FACE="Courier">for()</FONT></TT>
loop. The output should look like this:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">Users on this machine:<BR>
adm 3
<BR>
bin 1
<BR>
daemon 2
<BR>
ftp 404
<BR>
games 12
<BR>
guest 405
<BR>
halt 7
<BR>
khusain 501
<BR>
lp 4
<BR>
mail 8
<BR>
man 13
<BR>
news 9
<BR>
nobody 65535
<BR>
operator 11
<BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -