[comp.sources.misc] v18i023: perl - The perl programming language, Part05/36

lwall@netlabs.com (Larry Wall) (04/15/91)

Submitted-by: Larry Wall <lwall@netlabs.com>
Posting-number: Volume 18, Issue 23
Archive-name: perl/part05

[There are 36 kits for perl version 4.0.]

#! /bin/sh

# Make a new directory for the perl sources, cd to it, and run kits 1
# thru 36 through sh.  When all 36 kits have been run, read README.

echo "This is perl 4.0 kit 5 (of 36).  If kit 5 is complete, the line"
echo '"'"End of kit 5 (of 36)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
mkdir  2>/dev/null
echo Extracting perl.man:AB
sed >perl.man:AB <<'!STUFFY!FUNK!' -e 's/X//'
X''' 
X''' Revision 3.0.1.10  90/11/10  01:46:29  lwall
X''' patch38: random cleanup
X''' patch38: added alarm function
X''' 
X''' Revision 3.0.1.9  90/10/15  18:17:37  lwall
X''' patch29: added caller
X''' patch29: index and substr now have optional 3rd args
X''' patch29: added SysV IPC
X''' 
X''' Revision 3.0.1.8  90/08/13  22:21:00  lwall
X''' patch28: documented that you can't interpolate $) or $| in pattern
X''' 
X''' Revision 3.0.1.7  90/08/09  04:27:04  lwall
X''' patch19: added require operator
X''' 
X''' Revision 3.0.1.6  90/08/03  11:15:29  lwall
X''' patch19: Intermediate diffs for Randal
X''' 
X''' Revision 3.0.1.5  90/03/27  16:15:17  lwall
X''' patch16: MSDOS support
X''' 
X''' Revision 3.0.1.4  90/03/12  16:46:02  lwall
X''' patch13: documented behavior of @array = /noparens/
X''' 
X''' Revision 3.0.1.3  90/02/28  17:55:58  lwall
X''' patch9: grep now returns number of items matched in scalar context
X''' patch9: documented in-place modification capabilites of grep
X''' 
X''' Revision 3.0.1.2  89/11/17  15:30:16  lwall
X''' patch5: fixed some manual typos and indent problems
X''' 
X''' Revision 3.0.1.1  89/11/11  04:43:10  lwall
X''' patch2: made some line breaks depend on troff vs. nroff
X''' patch2: example of unshift had args backwards
X''' 
X''' Revision 3.0  89/10/18  15:21:37  lwall
X''' 3.0 baseline
X''' 
X'''
X.PP
XAlong with the literals and variables mentioned earlier,
Xthe operations in the following section can serve as terms in an expression.
XSome of these operations take a LIST as an argument.
XSuch a list can consist of any combination of scalar arguments or array values;
Xthe array values will be included in the list as if each individual element were
Xinterpolated at that point in the list, forming a longer single-dimensional
Xarray value.
XElements of the LIST should be separated by commas.
XIf an operation is listed both with and without parentheses around its
Xarguments, it means you can either use it as a unary operator or
Xas a function call.
XTo use it as a function call, the next token on the same line must
Xbe a left parenthesis.
X(There may be intervening white space.)
XSuch a function then has highest precedence, as you would expect from
Xa function.
XIf any token other than a left parenthesis follows, then it is a
Xunary operator, with a precedence depending only on whether it is a LIST
Xoperator or not.
XLIST operators have lowest precedence.
XAll other unary operators have a precedence greater than relational operators
Xbut less than arithmetic operators.
XSee the section on Precedence.
X.Ip "/PATTERN/" 8 4
XSee m/PATTERN/.
X.Ip "?PATTERN?" 8 4
XThis is just like the /pattern/ search, except that it matches only once between
Xcalls to the
X.I reset
Xoperator.
XThis is a useful optimization when you only want to see the first occurrence of
Xsomething in each file of a set of files, for instance.
XOnly ?? patterns local to the current package are reset.
X.Ip "accept(NEWSOCKET,GENERICSOCKET)" 8 2
XDoes the same thing that the accept system call does.
XReturns true if it succeeded, false otherwise.
XSee example in section on Interprocess Communication.
X.Ip "alarm(SECONDS)" 8 4
X.Ip "alarm SECONDS" 8
XArranges to have a SIGALRM delivered to this process after the specified number
Xof seconds (minus 1, actually) have elapsed.  Thus, alarm(15) will cause
Xa SIGALRM at some point more than 14 seconds in the future.
XOnly one timer may be counting at once.  Each call disables the previous
Xtimer, and an argument of 0 may be supplied to cancel the previous timer
Xwithout starting a new one.
XThe returned value is the amount of time remaining on the previous timer.
X.Ip "atan2(Y,X)" 8 2
XReturns the arctangent of Y/X in the range
X.if t \-\(*p to \(*p.
X.if n \-PI to PI.
X.Ip "bind(SOCKET,NAME)" 8 2
XDoes the same thing that the bind system call does.
XReturns true if it succeeded, false otherwise.
XNAME should be a packed address of the proper type for the socket.
XSee example in section on Interprocess Communication.
X.Ip "binmode(FILEHANDLE)" 8 4
X.Ip "binmode FILEHANDLE" 8 4
XArranges for the file to be read in \*(L"binary\*(R" mode in operating systems
Xthat distinguish between binary and text files.
XFiles that are not read in binary mode have CR LF sequences translated
Xto LF on input and LF translated to CR LF on output.
XBinmode has no effect under Unix.
XIf FILEHANDLE is an expression, the value is taken as the name of
Xthe filehandle.
X.Ip "caller(EXPR)"
X.Ip "caller"
XReturns the context of the current subroutine call:
X.nf
X
X	($package,$filename,$line) = caller;
X
X.fi
XWith EXPR, returns some extra information that the debugger uses to print
Xa stack trace.  The value of EXPR indicates how many call frames to go
Xback before the current one.
X.Ip "chdir(EXPR)" 8 2
X.Ip "chdir EXPR" 8 2
XChanges the working directory to EXPR, if possible.
XIf EXPR is omitted, changes to home directory.
XReturns 1 upon success, 0 otherwise.
XSee example under
X.IR die .
X.Ip "chmod(LIST)" 8 2
X.Ip "chmod LIST" 8 2
XChanges the permissions of a list of files.
XThe first element of the list must be the numerical mode.
XReturns the number of files successfully changed.
X.nf
X
X.ne 2
X	$cnt = chmod 0755, \'foo\', \'bar\';
X	chmod 0755, @executables;
X
X.fi
X.Ip "chop(LIST)" 8 7
X.Ip "chop(VARIABLE)" 8
X.Ip "chop VARIABLE" 8
X.Ip "chop" 8
XChops off the last character of a string and returns the character chopped.
XIt's used primarily to remove the newline from the end of an input record,
Xbut is much more efficient than s/\en// because it neither scans nor copies
Xthe string.
XIf VARIABLE is omitted, chops $_.
XExample:
X.nf
X
X.ne 5
X	while (<>) {
X		chop;	# avoid \en on last field
X		@array = split(/:/);
X		.\|.\|.
X	}
X
X.fi
XYou can actually chop anything that's an lvalue, including an assignment:
X.nf
X
X	chop($cwd = \`pwd\`);
X	chop($answer = <STDIN>);
X
X.fi
XIf you chop a list, each element is chopped.
XOnly the value of the last chop is returned.
X.Ip "chown(LIST)" 8 2
X.Ip "chown LIST" 8 2
XChanges the owner (and group) of a list of files.
XThe first two elements of the list must be the NUMERICAL uid and gid,
Xin that order.
XReturns the number of files successfully changed.
X.nf
X
X.ne 2
X	$cnt = chown $uid, $gid, \'foo\', \'bar\';
X	chown $uid, $gid, @filenames;
X
X.fi
X.ne 23
XHere's an example of looking up non-numeric uids:
X.nf
X
X	print "User: ";
X	$user = <STDIN>;
X	chop($user);
X	print "Files: "
X	$pattern = <STDIN>;
X	chop($pattern);
X.ie t \{\
X	open(pass, \'/etc/passwd\') || die "Can't open passwd: $!\en";
X'br\}
X.el \{\
X	open(pass, \'/etc/passwd\')
X		|| die "Can't open passwd: $!\en";
X'br\}
X	while (<pass>) {
X		($login,$pass,$uid,$gid) = split(/:/);
X		$uid{$login} = $uid;
X		$gid{$login} = $gid;
X	}
X	@ary = <${pattern}>;	# get filenames
X	if ($uid{$user} eq \'\') {
X		die "$user not in passwd file";
X	}
X	else {
X		chown $uid{$user}, $gid{$user}, @ary;
X	}
X
X.fi
X.Ip "chroot(FILENAME)" 8 5
X.Ip "chroot FILENAME" 8
XDoes the same as the system call of that name.
XIf you don't know what it does, don't worry about it.
XIf FILENAME is omitted, does chroot to $_.
X.Ip "close(FILEHANDLE)" 8 5
X.Ip "close FILEHANDLE" 8
XCloses the file or pipe associated with the file handle.
XYou don't have to close FILEHANDLE if you are immediately going to
Xdo another open on it, since open will close it for you.
X(See
X.IR open .)
XHowever, an explicit close on an input file resets the line counter ($.), while
Xthe implicit close done by
X.I open
Xdoes not.
XAlso, closing a pipe will wait for the process executing on the pipe to complete,
Xin case you want to look at the output of the pipe afterwards.
XClosing a pipe explicitly also puts the status value of the command into $?.
XExample:
X.nf
X
X.ne 4
X	open(OUTPUT, \'|sort >foo\');	# pipe to sort
X	.\|.\|.	# print stuff to output
X	close OUTPUT;		# wait for sort to finish
X	open(INPUT, \'foo\');	# get sort's results
X
X.fi
XFILEHANDLE may be an expression whose value gives the real filehandle name.
X.Ip "closedir(DIRHANDLE)" 8 5
X.Ip "closedir DIRHANDLE" 8
XCloses a directory opened by opendir().
X.Ip "connect(SOCKET,NAME)" 8 2
XDoes the same thing that the connect system call does.
XReturns true if it succeeded, false otherwise.
XNAME should be a package address of the proper type for the socket.
XSee example in section on Interprocess Communication.
X.Ip "cos(EXPR)" 8 6
X.Ip "cos EXPR" 8 6
XReturns the cosine of EXPR (expressed in radians).
XIf EXPR is omitted takes cosine of $_.
X.Ip "crypt(PLAINTEXT,SALT)" 8 6
XEncrypts a string exactly like the crypt() function in the C library.
XUseful for checking the password file for lousy passwords.
XOnly the guys wearing white hats should do this.
X.Ip "dbmclose(ASSOC_ARRAY)" 8 6
X.Ip "dbmclose ASSOC_ARRAY" 8
XBreaks the binding between a dbm file and an associative array.
XThe values remaining in the associative array are meaningless unless
Xyou happen to want to know what was in the cache for the dbm file.
XThis function is only useful if you have ndbm.
X.Ip "dbmopen(ASSOC,DBNAME,MODE)" 8 6
XThis binds a dbm or ndbm file to an associative array.
XASSOC is the name of the associative array.
X(Unlike normal open, the first argument is NOT a filehandle, even though
Xit looks like one).
XDBNAME is the name of the database (without the .dir or .pag extension).
XIf the database does not exist, it is created with protection specified
Xby MODE (as modified by the umask).
XIf your system only supports the older dbm functions, you may only have one
Xdbmopen in your program.
XIf your system has neither dbm nor ndbm, calling dbmopen produces a fatal
Xerror.
X.Sp
XValues assigned to the associative array prior to the dbmopen are lost.
XA certain number of values from the dbm file are cached in memory.
XBy default this number is 64, but you can increase it by preallocating
Xthat number of garbage entries in the associative array before the dbmopen.
XYou can flush the cache if necessary with the reset command.
X.Sp
XIf you don't have write access to the dbm file, you can only read
Xassociative array variables, not set them.
XIf you want to test whether you can write, either use file tests or
Xtry setting a dummy array entry inside an eval, which will trap the error.
X.Sp
XNote that functions such as keys() and values() may return huge array values
Xwhen used on large dbm files.
XYou may prefer to use the each() function to iterate over large dbm files.
XExample:
X.nf
X
X.ne 6
X	# print out history file offsets
X	dbmopen(HIST,'/usr/lib/news/history',0666);
X	while (($key,$val) = each %HIST) {
X		print $key, ' = ', unpack('L',$val), "\en";
X	}
X	dbmclose(HIST);
X
X.fi
X.Ip "defined(EXPR)" 8 6
X.Ip "defined EXPR" 8
XReturns a boolean value saying whether the lvalue EXPR has a real value
Xor not.
XMany operations return the undefined value under exceptional conditions,
Xsuch as end of file, uninitialized variable, system error and such.
XThis function allows you to distinguish between an undefined null string
Xand a defined null string with operations that might return a real null
Xstring, in particular referencing elements of an array.
XYou may also check to see if arrays or subroutines exist.
XUse on predefined variables is not guaranteed to produce intuitive results.
XExamples:
X.nf
X
X.ne 7
X	print if defined $switch{'D'};
X	print "$val\en" while defined($val = pop(@ary));
X	die "Can't readlink $sym: $!"
X		unless defined($value = readlink $sym);
X	eval '@foo = ()' if defined(@foo);
X	die "No XYZ package defined" unless defined %_XYZ;
X	sub foo { defined &bar ? &bar(@_) : die "No bar"; }
X
X.fi
XSee also undef.
X.Ip "delete $ASSOC{KEY}" 8 6
XDeletes the specified value from the specified associative array.
XReturns the deleted value, or the undefined value if nothing was deleted.
XDeleting from $ENV{} modifies the environment.
XDeleting from an array bound to a dbm file deletes the entry from the dbm
Xfile.
X.Sp
XThe following deletes all the values of an associative array:
X.nf
X
X.ne 3
X	foreach $key (keys %ARRAY) {
X		delete $ARRAY{$key};
X	}
X
X.fi
X(But it would be faster to use the
X.I reset
Xcommand.
XSaying undef %ARRAY is faster yet.)
X.Ip "die(LIST)" 8
X.Ip "die LIST" 8
XOutside of an eval, prints the value of LIST to
X.I STDERR
Xand exits with the current value of $!
X(errno).
XIf $! is 0, exits with the value of ($? >> 8) (\`command\` status).
XIf ($? >> 8) is 0, exits with 255.
XInside an eval, the error message is stuffed into $@ and the eval is terminated
Xwith the undefined value.
X.Sp
XEquivalent examples:
X.nf
X
X.ne 3
X.ie t \{\
X	die "Can't cd to spool: $!\en" unless chdir \'/usr/spool/news\';
X'br\}
X.el \{\
X	die "Can't cd to spool: $!\en"
X		unless chdir \'/usr/spool/news\';
X'br\}
X
X	chdir \'/usr/spool/news\' || die "Can't cd to spool: $!\en" 
X
X.fi
X.Sp
XIf the value of EXPR does not end in a newline, the current script line
Xnumber and input line number (if any) are also printed, and a newline is
Xsupplied.
XHint: sometimes appending \*(L", stopped\*(R" to your message will cause it to make
Xbetter sense when the string \*(L"at foo line 123\*(R" is appended.
XSuppose you are running script \*(L"canasta\*(R".
X.nf
X
X.ne 7
X	die "/etc/games is no good";
X	die "/etc/games is no good, stopped";
X
Xproduce, respectively
X
X	/etc/games is no good at canasta line 123.
X	/etc/games is no good, stopped at canasta line 123.
X
X.fi
XSee also
X.IR exit .
X.Ip "do BLOCK" 8 4
XReturns the value of the last command in the sequence of commands indicated
Xby BLOCK.
XWhen modified by a loop modifier, executes the BLOCK once before testing the
Xloop condition.
X(On other statements the loop modifiers test the conditional first.)
X.Ip "do SUBROUTINE (LIST)" 8 3
XExecutes a SUBROUTINE declared by a
X.I sub
Xdeclaration, and returns the value
Xof the last expression evaluated in SUBROUTINE.
XIf there is no subroutine by that name, produces a fatal error.
X(You may use the \*(L"defined\*(R" operator to determine if a subroutine
Xexists.)
XIf you pass arrays as part of LIST you may wish to pass the length
Xof the array in front of each array.
X(See the section on subroutines later on.)
XSUBROUTINE may be a scalar variable, in which case the variable contains
Xthe name of the subroutine to execute.
XThe parentheses are required to avoid confusion with the \*(L"do EXPR\*(R"
Xform.
X.Sp
XAs an alternate form, you may call a subroutine by prefixing the name with
Xan ampersand: &foo(@args).
XIf you aren't passing any arguments, you don't have to use parentheses.
XIf you omit the parentheses, no @_ array is passed to the subroutine.
XThe & form is also used to specify subroutines to the defined and undef
Xoperators.
X.Ip "do EXPR" 8 3
XUses the value of EXPR as a filename and executes the contents of the file
Xas a
X.I perl
Xscript.
XIts primary use is to include subroutines from a
X.I perl
Xsubroutine library.
X.nf
X
X	do \'stat.pl\';
X
Xis just like
X
X	eval \`cat stat.pl\`;
X
X.fi
Xexcept that it's more efficient, more concise, keeps track of the current
Xfilename for error messages, and searches all the
X.B \-I
Xlibraries if the file
Xisn't in the current directory (see also the @INC array in Predefined Names).
XIt's the same, however, in that it does reparse the file every time you
Xcall it, so if you are going to use the file inside a loop you might prefer
Xto use \-P and #include, at the expense of a little more startup time.
X(The main problem with #include is that cpp doesn't grok # comments\*(--a
Xworkaround is to use \*(L";#\*(R" for standalone comments.)
XNote that the following are NOT equivalent:
X.nf
X
X.ne 2
X	do $foo;	# eval a file
X	do $foo();	# call a subroutine
X
X.fi
XNote that inclusion of library routines is better done with
Xthe \*(L"require\*(R" operator.
X.Ip "dump LABEL" 8 6
XThis causes an immediate core dump.
XPrimarily this is so that you can use the undump program to turn your
Xcore dump into an executable binary after having initialized all your
Xvariables at the beginning of the program.
XWhen the new binary is executed it will begin by executing a "goto LABEL"
X(with all the restrictions that goto suffers).
XThink of it as a goto with an intervening core dump and reincarnation.
XIf LABEL is omitted, restarts the program from the top.
XWARNING: any files opened at the time of the dump will NOT be open any more
Xwhen the program is reincarnated, with possible resulting confusion on the part
Xof perl.
XSee also \-u.
X.Sp
XExample:
X.nf
X
X.ne 16
X	#!/usr/bin/perl
X	require 'getopt.pl';
X	require 'stat.pl';
X	%days = (
X	    'Sun',1,
X	    'Mon',2,
X	    'Tue',3,
X	    'Wed',4,
X	    'Thu',5,
X	    'Fri',6,
X	    'Sat',7);
X
X	dump QUICKSTART if $ARGV[0] eq '-d';
X
X    QUICKSTART:
X	do Getopt('f');
X
X.fi
X.Ip "each(ASSOC_ARRAY)" 8 6
X.Ip "each ASSOC_ARRAY" 8
XReturns a 2 element array consisting of the key and value for the next
Xvalue of an associative array, so that you can iterate over it.
XEntries are returned in an apparently random order.
XWhen the array is entirely read, a null array is returned (which when
Xassigned produces a FALSE (0) value).
XThe next call to each() after that will start iterating again.
XThe iterator can be reset only by reading all the elements from the array.
XYou must not modify the array while iterating over it.
XThere is a single iterator for each associative array, shared by all
Xeach(), keys() and values() function calls in the program.
XThe following prints out your environment like the printenv program, only
Xin a different order:
X.nf
X
X.ne 3
X	while (($key,$value) = each %ENV) {
X		print "$key=$value\en";
X	}
X
X.fi
XSee also keys() and values().
X.Ip "eof(FILEHANDLE)" 8 8
X.Ip "eof()" 8
X.Ip "eof" 8
XReturns 1 if the next read on FILEHANDLE will return end of file, or if
XFILEHANDLE is not open.
XFILEHANDLE may be an expression whose value gives the real filehandle name.
X(Note that this function actually reads a character and then ungetc's it,
Xso it is not very useful in an interactive context.)
XAn eof without an argument returns the eof status for the last file read.
XEmpty parentheses () may be used to indicate the pseudo file formed of the
Xfiles listed on the command line, i.e. eof() is reasonable to use inside
Xa while (<>) loop to detect the end of only the last file.
XUse eof(ARGV) or eof without the parentheses to test EACH file in a while (<>) loop.
XExamples:
X.nf
X
X.ne 7
X	# insert dashes just before last line of last file
X	while (<>) {
X		if (eof()) {
X			print "\-\|\-\|\-\|\-\|\-\|\-\|\-\|\-\|\-\|\-\|\-\|\-\|\-\|\-\en";
X		}
X		print;
X	}
X
X.ne 7
X	# reset line numbering on each input file
X	while (<>) {
X		print "$.\et$_";
X		if (eof) {	# Not eof().
X			close(ARGV);
X		}
X	}
X
X.fi
X.Ip "eval(EXPR)" 8 6
X.Ip "eval EXPR" 8 6
XEXPR is parsed and executed as if it were a little
X.I perl
Xprogram.
XIt is executed in the context of the current
X.I perl
Xprogram, so that
Xany variable settings, subroutine or format definitions remain afterwards.
XThe value returned is the value of the last expression evaluated, just
Xas with subroutines.
XIf there is a syntax error or runtime error, or a die statement is
Xexecuted, an undefined value is returned by
Xeval, and $@ is set to the error message.
XIf there was no error, $@ is guaranteed to be a null string.
XIf EXPR is omitted, evaluates $_.
XThe final semicolon, if any, may be omitted from the expression.
X.Sp
XNote that, since eval traps otherwise-fatal errors, it is useful for
Xdetermining whether a particular feature
X(such as dbmopen or symlink) is implemented.
XIt is also Perl's exception trapping mechanism, where the die operator is
Xused to raise exceptions.
X.Ip "exec(LIST)" 8 8
X.Ip "exec LIST" 8 6
XIf there is more than one argument in LIST, or if LIST is an array with
Xmore than one value,
Xcalls execvp() with the arguments in LIST.
XIf there is only one scalar argument, the argument is checked for shell metacharacters.
XIf there are any, the entire argument is passed to \*(L"/bin/sh \-c\*(R" for parsing.
XIf there are none, the argument is split into words and passed directly to
Xexecvp(), which is more efficient.
XNote: exec (and system) do not flush your output buffer, so you may need to
Xset $| to avoid lost output.
XExamples:
X.nf
X
X	exec \'/bin/echo\', \'Your arguments are: \', @ARGV;
X	exec "sort $outfile | uniq";
X
X.fi
X.Sp
XIf you don't really want to execute the first argument, but want to lie
Xto the program you are executing about its own name, you can specify
Xthe program you actually want to run by assigning that to a variable and
Xputting the name of the variable in front of the LIST without a comma.
X(This always forces interpretation of the LIST as a multi-valued list, even
Xif there is only a single scalar in the list.)
XExample:
X.nf
X
X.ne 2
X	$shell = '/bin/csh';
X	exec $shell '-sh';		# pretend it's a login shell
X
X.fi
X.Ip "exit(EXPR)" 8 6
X.Ip "exit EXPR" 8
XEvaluates EXPR and exits immediately with that value.
XExample:
X.nf
X
X.ne 2
X	$ans = <STDIN>;
X	exit 0 \|if \|$ans \|=~ \|/\|^[Xx]\|/\|;
X
X.fi
XSee also
X.IR die .
XIf EXPR is omitted, exits with 0 status.
X.Ip "exp(EXPR)" 8 3
X.Ip "exp EXPR" 8
XReturns
X.I e
Xto the power of EXPR.
XIf EXPR is omitted, gives exp($_).
X.Ip "fcntl(FILEHANDLE,FUNCTION,SCALAR)" 8 4
XImplements the fcntl(2) function.
XYou'll probably have to say
X.nf
X
X	require "fcntl.ph";	# probably /usr/local/lib/perl/fcntl.ph
X
X.fi
Xfirst to get the correct function definitions.
XIf fcntl.ph doesn't exist or doesn't have the correct definitions
Xyou'll have to roll
Xyour own, based on your C header files such as <sys/fcntl.h>.
X(There is a perl script called h2ph that comes with the perl kit
Xwhich may help you in this.)
XArgument processing and value return works just like ioctl below.
XNote that fcntl will produce a fatal error if used on a machine that doesn't implement
Xfcntl(2).
X.Ip "fileno(FILEHANDLE)" 8 4
X.Ip "fileno FILEHANDLE" 8 4
XReturns the file descriptor for a filehandle.
XUseful for constructing bitmaps for select().
XIf FILEHANDLE is an expression, the value is taken as the name of
Xthe filehandle.
X.Ip "flock(FILEHANDLE,OPERATION)" 8 4
XCalls flock(2) on FILEHANDLE.
XSee manual page for flock(2) for definition of OPERATION.
XReturns true for success, false on failure.
XWill produce a fatal error if used on a machine that doesn't implement
Xflock(2).
XHere's a mailbox appender for BSD systems.
X.nf
X
X.ne 20
X	$LOCK_SH = 1;
X	$LOCK_EX = 2;
X	$LOCK_NB = 4;
X	$LOCK_UN = 8;
X
X	sub lock {
X	    flock(MBOX,$LOCK_EX);
X	    # and, in case someone appended
X	    # while we were waiting...
X	    seek(MBOX, 0, 2);
X	}
X
X	sub unlock {
X	    flock(MBOX,$LOCK_UN);
X	}
X
X	open(MBOX, ">>/usr/spool/mail/$ENV{'USER'}")
X		|| die "Can't open mailbox: $!";
X
X	do lock();
X	print MBOX $msg,"\en\en";
X	do unlock();
X
X.fi
X.Ip "fork" 8 4
XDoes a fork() call.
XReturns the child pid to the parent process and 0 to the child process.
XNote: unflushed buffers remain unflushed in both processes, which means
Xyou may need to set $| to avoid duplicate output.
X.Ip "getc(FILEHANDLE)" 8 4
X.Ip "getc FILEHANDLE" 8
X.Ip "getc" 8
XReturns the next character from the input file attached to FILEHANDLE, or
Xa null string at EOF.
XIf FILEHANDLE is omitted, reads from STDIN.
X.Ip "getlogin" 8 3
XReturns the current login from /etc/utmp, if any.
XIf null, use getpwuid.
X
X	$login = getlogin || (getpwuid($<))[0] || "Somebody";
X
X.Ip "getpeername(SOCKET)" 8 3
XReturns the packed sockaddr address of other end of the SOCKET connection.
X.nf
X
X.ne 4
X	# An internet sockaddr
X	$sockaddr = 'S n a4 x8';
X	$hersockaddr = getpeername(S);
X.ie t \{\
X	($family, $port, $heraddr) = unpack($sockaddr,$hersockaddr);
X'br\}
X.el \{\
X	($family, $port, $heraddr) =
X			unpack($sockaddr,$hersockaddr);
X'br\}
X
X.fi
X.Ip "getpgrp(PID)" 8 4
X.Ip "getpgrp PID" 8
XReturns the current process group for the specified PID, 0 for the current
Xprocess.
XWill produce a fatal error if used on a machine that doesn't implement
Xgetpgrp(2).
XIf EXPR is omitted, returns process group of current process.
X.Ip "getppid" 8 4
XReturns the process id of the parent process.
X.Ip "getpriority(WHICH,WHO)" 8 4
XReturns the current priority for a process, a process group, or a user.
X(See getpriority(2).)
XWill produce a fatal error if used on a machine that doesn't implement
Xgetpriority(2).
X.Ip "getpwnam(NAME)" 8
X.Ip "getgrnam(NAME)" 8
X.Ip "gethostbyname(NAME)" 8
X.Ip "getnetbyname(NAME)" 8
X.Ip "getprotobyname(NAME)" 8
X.Ip "getpwuid(UID)" 8
X.Ip "getgrgid(GID)" 8
X.Ip "getservbyname(NAME,PROTO)" 8
X.Ip "gethostbyaddr(ADDR,ADDRTYPE)" 8
X.Ip "getnetbyaddr(ADDR,ADDRTYPE)" 8
X.Ip "getprotobynumber(NUMBER)" 8
X.Ip "getservbyport(PORT,PROTO)" 8
X.Ip "getpwent" 8
X.Ip "getgrent" 8
X.Ip "gethostent" 8
X.Ip "getnetent" 8
X.Ip "getprotoent" 8
X.Ip "getservent" 8
X.Ip "setpwent" 8
X.Ip "setgrent" 8
X.Ip "sethostent(STAYOPEN)" 8
X.Ip "setnetent(STAYOPEN)" 8
X.Ip "setprotoent(STAYOPEN)" 8
X.Ip "setservent(STAYOPEN)" 8
X.Ip "endpwent" 8
X.Ip "endgrent" 8
X.Ip "endhostent" 8
X.Ip "endnetent" 8
X.Ip "endprotoent" 8
X.Ip "endservent" 8
XThese routines perform the same functions as their counterparts in the
Xsystem library.
XThe return values from the various get routines are as follows:
X.nf
X
X	($name,$passwd,$uid,$gid,
X	   $quota,$comment,$gcos,$dir,$shell) = getpw.\|.\|.
X	($name,$passwd,$gid,$members) = getgr.\|.\|.
X	($name,$aliases,$addrtype,$length,@addrs) = gethost.\|.\|.
X	($name,$aliases,$addrtype,$net) = getnet.\|.\|.
X	($name,$aliases,$proto) = getproto.\|.\|.
X	($name,$aliases,$port,$proto) = getserv.\|.\|.
X
X.fi
XThe $members value returned by getgr.\|.\|. is a space separated list
Xof the login names of the members of the group.
X.Sp
XThe @addrs value returned by the gethost.\|.\|. functions is a list of the
Xraw addresses returned by the corresponding system library call.
XIn the Internet domain, each address is four bytes long and you can unpack
Xit by saying something like:
X.nf
X
X	($a,$b,$c,$d) = unpack('C4',$addr[0]);
X
X.fi
X.Ip "getsockname(SOCKET)" 8 3
XReturns the packed sockaddr address of this end of the SOCKET connection.
X.nf
X
X.ne 4
X	# An internet sockaddr
X	$sockaddr = 'S n a4 x8';
X	$mysockaddr = getsockname(S);
X.ie t \{\
X	($family, $port, $myaddr) = unpack($sockaddr,$mysockaddr);
X'br\}
X.el \{\
X	($family, $port, $myaddr) =
X			unpack($sockaddr,$mysockaddr);
X'br\}
X
X.fi
X.Ip "getsockopt(SOCKET,LEVEL,OPTNAME)" 8 3
XReturns the socket option requested, or undefined if there is an error.
X.Ip "gmtime(EXPR)" 8 4
X.Ip "gmtime EXPR" 8
XConverts a time as returned by the time function to a 9-element array with
Xthe time analyzed for the Greenwich timezone.
XTypically used as follows:
X.nf
X
X.ne 3
X.ie t \{\
X    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);
X'br\}
X.el \{\
X    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
X						gmtime(time);
X'br\}
X
X.fi
XAll array elements are numeric, and come straight out of a struct tm.
XIn particular this means that $mon has the range 0.\|.11 and $wday has the
Xrange 0.\|.6.
XIf EXPR is omitted, does gmtime(time).
X.Ip "goto LABEL" 8 6
XFinds the statement labeled with LABEL and resumes execution there.
XCurrently you may only go to statements in the main body of the program
Xthat are not nested inside a do {} construct.
XThis statement is not implemented very efficiently, and is here only to make
Xthe
X.IR sed -to- perl
Xtranslator easier.
XI may change its semantics at any time, consistent with support for translated
X.I sed
Xscripts.
XUse it at your own risk.
XBetter yet, don't use it at all.
X.Ip "grep(EXPR,LIST)" 8 4
XEvaluates EXPR for each element of LIST (locally setting $_ to each element)
Xand returns the array value consisting of those elements for which the
Xexpression evaluated to true.
XIn a scalar context, returns the number of times the expression was true.
X.nf
X
X	@foo = grep(!/^#/, @bar);    # weed out comments
X
X.fi
XNote that, since $_ is a reference into the array value, it can be
Xused to modify the elements of the array.
XWhile this is useful and supported, it can cause bizarre results if
Xthe LIST is not a named array.
X.Ip "hex(EXPR)" 8 4
X.Ip "hex EXPR" 8
XReturns the decimal value of EXPR interpreted as an hex string.
X(To interpret strings that might start with 0 or 0x see oct().)
XIf EXPR is omitted, uses $_.
X.Ip "index(STR,SUBSTR,POSITION)" 8 4
X.Ip "index(STR,SUBSTR)" 8 4
XReturns the position of the first occurrence of SUBSTR in STR at or after
XPOSITION.
XIf POSITION is omitted, starts searching from the beginning of the string.
XThe return value is based at 0, or whatever you've
Xset the $[ variable to.
XIf the substring is not found, returns one less than the base, ordinarily \-1.
X.Ip "int(EXPR)" 8 4
X.Ip "int EXPR" 8
XReturns the integer portion of EXPR.
XIf EXPR is omitted, uses $_.
X.Ip "ioctl(FILEHANDLE,FUNCTION,SCALAR)" 8 4
XImplements the ioctl(2) function.
XYou'll probably have to say
X.nf
X
X	require "ioctl.ph";	# probably /usr/local/lib/perl/ioctl.ph
X
X.fi
Xfirst to get the correct function definitions.
XIf ioctl.ph doesn't exist or doesn't have the correct definitions
Xyou'll have to roll
Xyour own, based on your C header files such as <sys/ioctl.h>.
X(There is a perl script called h2ph that comes with the perl kit
Xwhich may help you in this.)
XSCALAR will be read and/or written depending on the FUNCTION\*(--a pointer
Xto the string value of SCALAR will be passed as the third argument of
Xthe actual ioctl call.
X(If SCALAR has no string value but does have a numeric value, that value
Xwill be passed rather than a pointer to the string value.
XTo guarantee this to be true, add a 0 to the scalar before using it.)
XThe pack() and unpack() functions are useful for manipulating the values
Xof structures used by ioctl().
XThe following example sets the erase character to DEL.
X.nf
X
X.ne 9
X	require 'ioctl.ph';
X	$sgttyb_t = "ccccs";		# 4 chars and a short
X	if (ioctl(STDIN,$TIOCGETP,$sgttyb)) {
X		@ary = unpack($sgttyb_t,$sgttyb);
X		$ary[2] = 127;
X		$sgttyb = pack($sgttyb_t,@ary);
X		ioctl(STDIN,$TIOCSETP,$sgttyb)
X			|| die "Can't ioctl: $!";
X	}
X
X.fi
XThe return value of ioctl (and fcntl) is as follows:
X.nf
X
X.ne 4
X	if OS returns:\h'|3i'perl returns:
X	  -1\h'|3i'  undefined value
X	  0\h'|3i'  string "0 but true"
X	  anything else\h'|3i'  that number
X
X.fi
XThus perl returns true on success and false on failure, yet you can still
Xeasily determine the actual value returned by the operating system:
X.nf
X
X	($retval = ioctl(...)) || ($retval = -1);
X	printf "System returned %d\en", $retval;
X.fi
X.Ip "join(EXPR,LIST)" 8 8
X.Ip "join(EXPR,ARRAY)" 8
XJoins the separate strings of LIST or ARRAY into a single string with fields
Xseparated by the value of EXPR, and returns the string.
XExample:
X.nf
X    
X.ie t \{\
X    $_ = join(\|\':\', $login,$passwd,$uid,$gid,$gcos,$home,$shell);
X'br\}
X.el \{\
X    $_ = join(\|\':\',
X		$login,$passwd,$uid,$gid,$gcos,$home,$shell);
X'br\}
X
X.fi
XSee
X.IR split .
X.Ip "keys(ASSOC_ARRAY)" 8 6
X.Ip "keys ASSOC_ARRAY" 8
XReturns a normal array consisting of all the keys of the named associative
Xarray.
XThe keys are returned in an apparently random order, but it is the same order
Xas either the values() or each() function produces (given that the associative array
Xhas not been modified).
XHere is yet another way to print your environment:
X.nf
X
X.ne 5
X	@keys = keys %ENV;
X	@values = values %ENV;
X	while ($#keys >= 0) {
X		print pop(@keys), \'=\', pop(@values), "\en";
X	}
X
Xor how about sorted by key:
X
X.ne 3
X	foreach $key (sort(keys %ENV)) {
X		print $key, \'=\', $ENV{$key}, "\en";
X	}
X
X.fi
X.Ip "kill(LIST)" 8 8
X.Ip "kill LIST" 8 2
XSends a signal to a list of processes.
XThe first element of the list must be the signal to send.
XReturns the number of processes successfully signaled.
X.nf
X
X	$cnt = kill 1, $child1, $child2;
X	kill 9, @goners;
X
X.fi
XIf the signal is negative, kills process groups instead of processes.
X(On System V, a negative \fIprocess\fR number will also kill process groups,
Xbut that's not portable.)
XYou may use a signal name in quotes.
X.Ip "last LABEL" 8 8
X.Ip "last" 8
XThe
X.I last
Xcommand is like the
X.I break
Xstatement in C (as used in loops); it immediately exits the loop in question.
XIf the LABEL is omitted, the command refers to the innermost enclosing loop.
XThe
X.I continue
Xblock, if any, is not executed:
X.nf
X
X.ne 4
X	line: while (<STDIN>) {
X		last line if /\|^$/;	# exit when done with header
X		.\|.\|.
X	}
X
X.fi
X.Ip "length(EXPR)" 8 4
X.Ip "length EXPR" 8
XReturns the length in characters of the value of EXPR.
XIf EXPR is omitted, returns length of $_.
X.Ip "link(OLDFILE,NEWFILE)" 8 2
XCreates a new filename linked to the old filename.
XReturns 1 for success, 0 otherwise.
X.Ip "listen(SOCKET,QUEUESIZE)" 8 2
XDoes the same thing that the listen system call does.
XReturns true if it succeeded, false otherwise.
XSee example in section on Interprocess Communication.
X.Ip "local(LIST)" 8 4
XDeclares the listed variables to be local to the enclosing block,
Xsubroutine, eval or \*(L"do\*(R".
XAll the listed elements must be legal lvalues.
XThis operator works by saving the current values of those variables in LIST
Xon a hidden stack and restoring them upon exiting the block, subroutine or eval.
XThis means that called subroutines can also reference the local variable,
Xbut not the global one.
XThe LIST may be assigned to if desired, which allows you to initialize
Xyour local variables.
X(If no initializer is given for a particular variable, it is created with
Xan undefined value.)
XCommonly this is used to name the parameters to a subroutine.
XExamples:
X.nf
X
X.ne 13
X	sub RANGEVAL {
X		local($min, $max, $thunk) = @_;
X		local($result) = \'\';
X		local($i);
X
X		# Presumably $thunk makes reference to $i
X
X		for ($i = $min; $i < $max; $i++) {
X			$result .= eval $thunk;
X		}
X
X		$result;
X	}
X
X.ne 6
X	if ($sw eq \'-v\') {
X	    # init local array with global array
X	    local(@ARGV) = @ARGV;
X	    unshift(@ARGV,\'echo\');
X	    system @ARGV;
X	}
X	# @ARGV restored
X
X.ne 6
X	# temporarily add to digits associative array
X	if ($base12) {
X		# (NOTE: not claiming this is efficient!)
X		local(%digits) = (%digits,'t',10,'e',11);
X		do parse_num();
X	}
X
X.fi
XNote that local() is a run-time command, and so gets executed every time
Xthrough a loop, using up more stack storage each time until it's all
Xreleased at once when the loop is exited.
X.Ip "localtime(EXPR)" 8 4
X.Ip "localtime EXPR" 8
XConverts a time as returned by the time function to a 9-element array with
Xthe time analyzed for the local timezone.
XTypically used as follows:
X.nf
X
X.ne 3
X.ie t \{\
X    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
X'br\}
X.el \{\
X    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
X						localtime(time);
X'br\}
X
X.fi
XAll array elements are numeric, and come straight out of a struct tm.
XIn particular this means that $mon has the range 0.\|.11 and $wday has the
Xrange 0.\|.6.
XIf EXPR is omitted, does localtime(time).
X.Ip "log(EXPR)" 8 4
X.Ip "log EXPR" 8
XReturns logarithm (base
X.IR e )
Xof EXPR.
XIf EXPR is omitted, returns log of $_.
X.Ip "lstat(FILEHANDLE)" 8 6
X.Ip "lstat FILEHANDLE" 8
X.Ip "lstat(EXPR)" 8
X.Ip "lstat SCALARVARIABLE" 8
XDoes the same thing as the stat() function, but stats a symbolic link
Xinstead of the file the symbolic link points to.
XIf symbolic links are unimplemented on your system, a normal stat is done.
X.Ip "m/PATTERN/io" 8 4
X.Ip "/PATTERN/io" 8
XSearches a string for a pattern match, and returns true (1) or false (\'\').
XIf no string is specified via the =~ or !~ operator,
Xthe $_ string is searched.
X(The string specified with =~ need not be an lvalue\*(--it may be the result of an expression evaluation, but remember the =~ binds rather tightly.)
XSee also the section on regular expressions.
X.Sp
XIf / is the delimiter then the initial \*(L'm\*(R' is optional.
XWith the \*(L'm\*(R' you can use any pair of non-alphanumeric characters
Xas delimiters.
XThis is particularly useful for matching Unix path names that contain \*(L'/\*(R'.
XIf the final delimiter is followed by the optional letter \*(L'i\*(R', the matching is
Xdone in a case-insensitive manner.
XPATTERN may contain references to scalar variables, which will be interpolated
X(and the pattern recompiled) every time the pattern search is evaluated.
X(Note that $) and $| may not be interpolated because they look like end-of-string tests.)
XIf you want such a pattern to be compiled only once, add an \*(L"o\*(R" after
Xthe trailing delimiter.
XThis avoids expensive run-time recompilations, and
Xis useful when the value you are interpolating won't change over the
Xlife of the script.
XIf the PATTERN evaluates to a null string, the most recent successful
Xregular expression is used instead.
X.Sp
XIf used in a context that requires an array value, a pattern match returns an
Xarray consisting of the subexpressions matched by the parentheses in the
Xpattern,
Xi.e. ($1, $2, $3.\|.\|.).
XIt does NOT actually set $1, $2, etc. in this case, nor does it set $+, $`, $&
Xor $'.
XIf the match fails, a null array is returned.
XIf the match succeeds, but there were no parentheses, an array value of (1)
Xis returned.
X.Sp
XExamples:
X.nf
X
X.ne 4
X    open(tty, \'/dev/tty\');
X    <tty> \|=~ \|/\|^y\|/i \|&& \|do foo(\|);	# do foo if desired
X
X    if (/Version: \|*\|([0\-9.]*\|)\|/\|) { $version = $1; }
X
X    next if m#^/usr/spool/uucp#;
X
X.ne 5
X    # poor man's grep
X    $arg = shift;
X    while (<>) {
X	    print if /$arg/o;	# compile only once
X    }
X
X    if (($F1, $F2, $Etc) = ($foo =~ /^(\eS+)\es+(\eS+)\es*(.*)/))
X
X.fi
XThis last example splits $foo into the first two words and the remainder
Xof the line, and assigns those three fields to $F1, $F2 and $Etc.
XThe conditional is true if any variables were assigned, i.e. if the pattern
Xmatched.
X.Ip "mkdir(FILENAME,MODE)" 8 3
XCreates the directory specified by FILENAME, with permissions specified by
XMODE (as modified by umask).
XIf it succeeds it returns 1, otherwise it returns 0 and sets $! (errno).
X.Ip "msgctl(ID,CMD,ARG)" 8 4
XCalls the System V IPC function msgctl.  If CMD is &IPC_STAT, then ARG
Xmust be a variable which will hold the returned msqid_ds structure.
XReturns like ioctl: the undefined value for error, "0 but true" for
Xzero, or the actual return value otherwise.
X.Ip "msgget(KEY,FLAGS)" 8 4
XCalls the System V IPC function msgget.  Returns the message queue id,
Xor the undefined value if there is an error.
X.Ip "msgsnd(ID,MSG,FLAGS)" 8 4
XCalls the System V IPC function msgsnd to send the message MSG to the
Xmessage queue ID.  MSG must begin with the long integer message type,
Xwhich may be created with pack("L", $type).  Returns true if
Xsuccessful, or false if there is an error.
X.Ip "msgrcv(ID,VAR,SIZE,TYPE,FLAGS)" 8 4
XCalls the System V IPC function msgrcv to receive a message from
Xmessage queue ID into variable VAR with a maximum message size of
XSIZE.  Note that if a message is received, the message type will be
Xthe first thing in VAR, and the maximum length of VAR is SIZE plus the
Xsize of the message type.  Returns true if successful, or false if
Xthere is an error.
X''' Beginning of part 3
X''' $RCSfile: perl.man,v $$Revision: 4.0.1.1 $$Date: 91/04/11 17:50:44 $
X'''
X''' $Log:	perl.man,v $
X''' Revision 4.0.1.1  91/04/11  17:50:44  lwall
X''' patch1: fixed some typos
X''' 
X''' Revision 4.0  91/03/20  01:38:08  lwall
X''' 4.0 baseline.
X''' 
X''' Revision 3.0.1.12  91/01/11  18:18:15  lwall
X''' patch42: added binary and hex pack/unpack options
X''' 
X''' Revision 3.0.1.11  90/11/10  01:48:21  lwall
X''' patch38: random cleanup
X''' patch38: documented tr///cds
X''' 
X''' Revision 3.0.1.10  90/10/20  02:15:17  lwall
X''' patch37: patch37: fixed various typos in man page
X''' 
X''' Revision 3.0.1.9  90/10/16  10:02:43  lwall
X''' patch29: you can now read into the middle string
X''' patch29: index and substr now have optional 3rd args
X''' patch29: added scalar reverse
X''' patch29: added scalar
X''' patch29: added SysV IPC
X''' patch29: added waitpid
X''' patch29: added sysread and syswrite
X''' 
X''' Revision 3.0.1.8  90/08/09  04:39:04  lwall
X''' patch19: added require operator
X''' patch19: added truncate operator
X''' patch19: unpack can do checksumming
X''' 
X''' Revision 3.0.1.7  90/08/03  11:15:42  lwall
X''' patch19: Intermediate diffs for Randal
X''' 
X''' Revision 3.0.1.6  90/03/27  16:17:56  lwall
X''' patch16: MSDOS support
X''' 
X''' Revision 3.0.1.5  90/03/12  16:52:21  lwall
X''' patch13: documented that print $filehandle &foo is ambiguous
X''' patch13: added splice operator: @oldelems = splice(@array,$offset,$len,LIST)
X''' 
X''' Revision 3.0.1.4  90/02/28  18:00:09  lwall
X''' patch9: added pipe function
X''' patch9: documented how to handle arbitrary weird characters in filenames
X''' patch9: documented the unflushed buffers problem on piped opens
X''' patch9: documented how to force top of page
X''' 
X''' Revision 3.0.1.3  89/12/21  20:10:12  lwall
X''' patch7: documented that s`pat`repl` does command substitution on replacement
X''' patch7: documented that $timeleft from select() is likely not implemented
X''' 
X''' Revision 3.0.1.2  89/11/17  15:31:05  lwall
X''' patch5: fixed some manual typos and indent problems
X''' patch5: added warning about print making an array context
X''' 
X''' Revision 3.0.1.1  89/11/11  04:45:06  lwall
X''' patch2: made some line breaks depend on troff vs. nroff
X''' 
X''' Revision 3.0  89/10/18  15:21:46  lwall
X''' 3.0 baseline
X''' 
X.Ip "next LABEL" 8 8
X.Ip "next" 8
XThe
X.I next
Xcommand is like the
X.I continue
Xstatement in C; it starts the next iteration of the loop:
X.nf
X
X.ne 4
X	line: while (<STDIN>) {
X		next line if /\|^#/;	# discard comments
X		.\|.\|.
X	}
X
X.fi
XNote that if there were a
X.I continue
Xblock on the above, it would get executed even on discarded lines.
XIf the LABEL is omitted, the command refers to the innermost enclosing loop.
X.Ip "oct(EXPR)" 8 4
X.Ip "oct EXPR" 8
XReturns the decimal value of EXPR interpreted as an octal string.
X(If EXPR happens to start off with 0x, interprets it as a hex string instead.)
XThe following will handle decimal, octal and hex in the standard notation:
X.nf
X
X	$val = oct($val) if $val =~ /^0/;
X
X.fi
XIf EXPR is omitted, uses $_.
X.Ip "open(FILEHANDLE,EXPR)" 8 8
X.Ip "open(FILEHANDLE)" 8
X.Ip "open FILEHANDLE" 8
XOpens the file whose filename is given by EXPR, and associates it with
XFILEHANDLE.
XIf FILEHANDLE is an expression, its value is used as the name of the
Xreal filehandle wanted.
XIf EXPR is omitted, the scalar variable of the same name as the FILEHANDLE
Xcontains the filename.
XIf the filename begins with \*(L"<\*(R" or nothing, the file is opened for
Xinput.
XIf the filename begins with \*(L">\*(R", the file is opened for output.
XIf the filename begins with \*(L">>\*(R", the file is opened for appending.
X(You can put a \'+\' in front of the \'>\' or \'<\' to indicate that you
Xwant both read and write access to the file.)
XIf the filename begins with \*(L"|\*(R", the filename is interpreted
Xas a command to which output is to be piped, and if the filename ends
Xwith a \*(L"|\*(R", the filename is interpreted as command which pipes
Xinput to us.
X(You may not have a command that pipes both in and out.)
XOpening \'\-\' opens
X.I STDIN
Xand opening \'>\-\' opens
X.IR STDOUT .
XOpen returns non-zero upon success, the undefined value otherwise.
XIf the open involved a pipe, the return value happens to be the pid
Xof the subprocess.
XExamples:
X.nf
X    
X.ne 3
X	$article = 100;
X	open article || die "Can't find article $article: $!\en";
X	while (<article>) {\|.\|.\|.
X
X.ie t \{\
X	open(LOG, \'>>/usr/spool/news/twitlog\'\|);	# (log is reserved)
X'br\}
X.el \{\
X	open(LOG, \'>>/usr/spool/news/twitlog\'\|);
X					# (log is reserved)
X'br\}
X
X.ie t \{\
X	open(article, "caesar <$article |"\|);		# decrypt article
X'br\}
X.el \{\
X	open(article, "caesar <$article |"\|);
X					# decrypt article
X'br\}
X
X.ie t \{\
X	open(extract, "|sort >/tmp/Tmp$$"\|);		# $$ is our process#
X'br\}
X.el \{\
X	open(extract, "|sort >/tmp/Tmp$$"\|);
X					# $$ is our process#
X'br\}
X
X.ne 7
X	# process argument list of files along with any includes
X
X	foreach $file (@ARGV) {
X		do process($file, \'fh00\');	# no pun intended
X	}
X
X	sub process {
X		local($filename, $input) = @_;
X		$input++;		# this is a string increment
X		unless (open($input, $filename)) {
X			print STDERR "Can't open $filename: $!\en";
X			return;
X		}
X.ie t \{\
X		while (<$input>) {		# note the use of indirection
X'br\}
X.el \{\
X		while (<$input>) {		# note use of indirection
X'br\}
X			if (/^#include "(.*)"/) {
X				do process($1, $input);
X				next;
X			}
X			.\|.\|.		# whatever
X		}
X	}
X
X.fi
XYou may also, in the Bourne shell tradition, specify an EXPR beginning
Xwith \*(L">&\*(R", in which case the rest of the string
Xis interpreted as the name of a filehandle
X(or file descriptor, if numeric) which is to be duped and opened.
XYou may use & after >, >>, <, +>, +>> and +<.
XThe mode you specify should match the mode of the original filehandle.
XHere is a script that saves, redirects, and restores
X.I STDOUT
Xand
X.IR STDERR :
X.nf
X
X.ne 21
X	#!/usr/bin/perl
X	open(SAVEOUT, ">&STDOUT");
X	open(SAVEERR, ">&STDERR");
X
X	open(STDOUT, ">foo.out") || die "Can't redirect stdout";
X	open(STDERR, ">&STDOUT") || die "Can't dup stdout";
X
X	select(STDERR); $| = 1;		# make unbuffered
X	select(STDOUT); $| = 1;		# make unbuffered
X
X	print STDOUT "stdout 1\en";	# this works for
X	print STDERR "stderr 1\en"; 	# subprocesses too
X
X	close(STDOUT);
X	close(STDERR);
X
X	open(STDOUT, ">&SAVEOUT");
X	open(STDERR, ">&SAVEERR");
X
X	print STDOUT "stdout 2\en";
X	print STDERR "stderr 2\en";
X
X.fi
XIf you open a pipe on the command \*(L"\-\*(R", i.e. either \*(L"|\-\*(R" or \*(L"\-|\*(R",
Xthen there is an implicit fork done, and the return value of open
Xis the pid of the child within the parent process, and 0 within the child
Xprocess.
X(Use defined($pid) to determine if the open was successful.)
XThe filehandle behaves normally for the parent, but i/o to that
Xfilehandle is piped from/to the
X.IR STDOUT / STDIN
Xof the child process.
XIn the child process the filehandle isn't opened\*(--i/o happens from/to
Xthe new
X.I STDOUT
Xor
X.IR STDIN .
XTypically this is used like the normal piped open when you want to exercise
Xmore control over just how the pipe command gets executed, such as when
Xyou are running setuid, and don't want to have to scan shell commands
Xfor metacharacters.
XThe following pairs are more or less equivalent:
X.nf
X
X.ne 5
X	open(FOO, "|tr \'[a\-z]\' \'[A\-Z]\'");
X	open(FOO, "|\-") || exec \'tr\', \'[a\-z]\', \'[A\-Z]\';
X
X	open(FOO, "cat \-n '$file'|");
X	open(FOO, "\-|") || exec \'cat\', \'\-n\', $file;
X
X.fi
XExplicitly closing any piped filehandle causes the parent process to wait for the
Xchild to finish, and returns the status value in $?.
XNote: on any operation which may do a fork,
Xunflushed buffers remain unflushed in both
Xprocesses, which means you may need to set $| to
Xavoid duplicate output.
X.Sp
XThe filename that is passed to open will have leading and trailing
Xwhitespace deleted.
XIn order to open a file with arbitrary weird characters in it, it's necessary
Xto protect any leading and trailing whitespace thusly:
X.nf
X
X.ne 2
X        $file =~ s#^(\es)#./$1#;
X        open(FOO, "< $file\e0");
X
X.fi
X.Ip "opendir(DIRHANDLE,EXPR)" 8 3
XOpens a directory named EXPR for processing by readdir(), telldir(), seekdir(),
Xrewinddir() and closedir().
XReturns true if successful.
XDIRHANDLEs have their own namespace separate from FILEHANDLEs.
X.Ip "ord(EXPR)" 8 4
X.Ip "ord EXPR" 8
XReturns the numeric ascii value of the first character of EXPR.
XIf EXPR is omitted, uses $_.
X''' Comments on f & d by gnb@melba.bby.oz.au	22/11/89
X.Ip "pack(TEMPLATE,LIST)" 8 4
XTakes an array or list of values and packs it into a binary structure,
Xreturning the string containing the structure.
XThe TEMPLATE is a sequence of characters that give the order and type
Xof values, as follows:
X.nf
X
X	A	An ascii string, will be space padded.
X	a	An ascii string, will be null padded.
X	c	A signed char value.
X	C	An unsigned char value.
X	s	A signed short value.
X	S	An unsigned short value.
X	i	A signed integer value.
X	I	An unsigned integer value.
X	l	A signed long value.
X	L	An unsigned long value.
X	n	A short in \*(L"network\*(R" order.
X	N	A long in \*(L"network\*(R" order.
X	f	A single-precision float in the native format.
X	d	A double-precision float in the native format.
X	p	A pointer to a string.
X	x	A null byte.
X	X	Back up a byte.
X	@	Null fill to absolute position.
X	u	A uuencoded string.
X	b	A bit string (ascending bit order, like vec()).
X	B	A bit string (descending bit order).
X	h	A hex string (low nybble first).
X	H	A hex string (high nybble first).
X
X.fi
XEach letter may optionally be followed by a number which gives a repeat
Xcount.
XWith all types except "a", "A", "b", "B", "h" and "H",
Xthe pack function will gobble up that many values
Xfrom the LIST.
XA * for the repeat count means to use however many items are left.
XThe "a" and "A" types gobble just one value, but pack it as a string of length
Xcount,
!STUFFY!FUNK!
echo " "
echo "End of kit 5 (of 36)"
cat /dev/null >kit5isdone
run=''
config=''
for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36; do
    if test -f kit${iskit}isdone; then
	run="$run $iskit"
    else
	todo="$todo $iskit"
    fi
done
case $todo in
    '')
	echo "You have run all your kits.  Please read README and then type Configure."
	for combo in *:AA; do
	    if test -f "$combo"; then
		realfile=`basename $combo :AA`
		cat $realfile:[A-Z][A-Z] >$realfile
		rm -rf $realfile:[A-Z][A-Z]
	    fi
	done
	rm -rf kit*isdone
	chmod 755 Configure
	;;
    *)  echo "You have run$run."
	echo "You still need to run$todo."
	;;
esac
: Someone might mail this, so...
exit

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.