The perl 5.005_03 and 5.6.1 shipped with Solaris 8, 9 and 10 were
built with the Forte compilers, and therefore assume that any add-on
modules will also be built with the Forte compiler. The perlgcc
command will allow gcc to be used to compile add-on modules for
use with the perl versions shipped with Solaris.
If the boot disk is attached to the controller you want to change,
then you can boot from the CDROM and then make changes to said boot
disk:
reboot
You may also find Sun Infodoc ID 13774 useful if you have a SPARC
Storage Array.
Q I'm a C programmer trying
to write a Perl program where I push an element onto a multidimensional
array, but I can't seem to get this to work correctly. Here's
the code I'm using:
$myarray[0][0] = 'hello';
push $myarray[0], 'world';
I'm trying to wind up with:
$myarray[0][1] = 'world';
Obviously, I'm not doing this right, but Perl must have something
as simple as a multidimensional array. Any hints on how I can get
my code working?
A Perl is a bit different from
C, as I'm sure you've discovered. In Perl, $array[0]
is not an array, but an array reference. An important note to remember
from the Perl documentation: "Perl does no implicit referencing
or dereferencing. When a scalar is holding a reference, it always
behaves as a simple scalar. It doesn't magically start being
an array or hash or subroutine; you have to tell it explicitly to
do so, by dereferencing it." For information on Perl's
use of references, do:
perldoc perlref
perldoc perlreftut
The section most pertinent to your question can be found in the Perl
reference tutorial:
Let's see a quick example of how all this is useful.
First, remember that [1, 2, 3] makes an anonymous array containing
(1, 2, 3), and gives you a reference to that array.
Now think about
@a = ( [1, 2, 3],
[4, 5, 6],
[7, 8, 9]
);
@a is an array with three elements, and each one is a reference
to another array.
$a[1] is one of these references. It refers to an array, the array
containing (4, 5, 6), and because it is a reference to an array,
USE RULE 2 says that we can write $a[1]->[2] to get the third
element from that array. $a[1]->[2] is the 6. Similarly, $a[0]->[1]
is the 2. What we have here is like a two-dimensional array; you
can write $a[ROW]->[COLUMN] to get or set the element in any
row and any column of the array.
The notation still looks a little cumbersome, so there's
one more abbreviation:
Arrow Rule In between two subscripts, the arrow is optional.
Instead of $a[1]->[2], we can write $a[1][2]; it means the
same thing. Instead of $a[0]->[1], we can write $a[0][1]; it
means the same thing.
Now it really looks like two-dimensional arrays!
You can see why the arrows are important. Without them, we would
have had to write ${$a[1]}[2] instead of $a[1][2]. For three-dimensional
arrays, they let us write $x[2][3][5] instead of the unreadable
${${$x[2]}[3]}[5].
Anywhere you'd put an identifier as part of a variable or
subroutine name, you can replace the identifier with a block returning
a reference of the correct type:
$myarray[0][0] = 'hello';
push @{$myarray[0]}, 'world';
You can print out your "hello world" statement by using
the same notation as the push:
print "myarray == @{$myarray[0]}.\n";
Q I'm running Solaris 8 and Sun's
stock sendmail (8.11.6). I have about 30 lines of denied addresses
and IPs in /etc/mail/access. The problem is that, because my connection
to the Internet is rather poor, a good chunk of my mail goes through
two lower-priority MX hosts on which I do not have administrative
control. Unfortunately, this means that all of the mail that gets
blocked on Connect to my machine now gets through.
Is there any way to get around this? Is there some sort of per-host
(or domain) way to apply access lists? If so, then I can request
that the admins of the MX hosts just use this setting to apply my
access rules to my mail coming through their machines?
A Unfortunately, access rules apply
to all incoming mail and there is no way to apply rules on a per-host
or domain basis. This would be quite useful for people who are doing
virtual hosting of many domains, though. In your case, it might
be more trouble than it's worth if you're frequently updating
your access list. You'd not only have to modify your own, but
then send a copy out to all of your MX hosts as well.
Though you won't be able to reject on Connect, you could
write a ruleset to bounce mail back based on the received headers.
Below lies some code from Greg Shapiro at Sendmail, Inc. that you
could add to your mc file (note that the syntax is different for
the current version of sendmail, 8.12).
Replace the hosts in the MXers class, C{MXers}, with any hosts
that MX for you. Remember to generate a new /etc/mail/sendmail.cf
from the mc file and HUP the sendmail daemon.
FEATURE('access_db')dnl
LOCAL_CONFIG
HReceived: $>+CheckRecvd
C{MXers}your.first.mxhost your.second.mxhost
LOCAL_RULESETS
SCheckRecvd
Rfrom $* ( $+ [ $+ ] ) by $={MXers} $* $: <?> $2 $| $3
R<?> $+ $| $+ $: $>LookUpDomain <$1> <?> <$2> <+ Connect>
R<?> <$+> $: $>LookUpAddress <$1> <?> <> <+ Connect>
R<?> $* $@ok
R<$={Accept}> <$*> $@ $1
R<<TMPF>> $* $#error $@ tempfail $: "450 Temporary lookup failure"
R<REJECT> $* $#error $@ 5.7.1 $: "550 Access denied"
R<DISCARD> <$*> $#discard $: discard
R<ERROR:$-.$-.$-:$+> $* $#error $@ $1.$2.$3 $: $4
R<ERROR:$+> $* $#error $: $1
R<$+> $* $#error $: $1
If the message came to your machine from one of the machines listed
in the MXers class, then the above ruleset will take the host and
IP information from the previous relaying machine by parsing the Received:
header. It will then check the access file with the "new" information,
and reject it if necessary. I suggest that your MX hosts turn off
DoubleBounceAddress if you choose to use this ruleset. Most spam you
get will have forged headers and no valid address capable of accepting
a bounce back.
Q Due to a runaway program that
one of our junior people was working on, we're left with a
very large directory structure that has some valid data in it (which
we don't want deleted), and a lot of empty directories, or
directories that only contain other empty directories. These levels
of nested directories are at least 20 deep in some cases, and there
are thousands of top-level directories to start with. What's
the best way to remove all of the directories that have no leaf
nodes (a.k.a. files) somewhere along the way?
A Find is the perfect tool for
this job. Because you have nested subdirectories with no actual
data (files) in them, you want to do a depth-first search and removal.
Depending on your operating system, the command might be:
find /starting/dir/name -d -type d -exec rmdir {} \;
as with FreeBSD, in the case of Solaris and GNU-like versions of find:
find /starting/dir/name -depth -type d -exec rmdir {} \;
You'll almost certainly want to redirect STDERR to /dev/null
since it sounds like there's a lot of "good" directories
that you're going to receive errors on when you try to use rmdir.
If, for some reason, you know all of the "bad" leafnode
directories, you can also use rmdir -p for each of them.
This is much more time consuming and more prone to error, though.
Q Solaris package creation seems
like a big pain. When building third-party software from source,
sometimes it's easy to install into a different root and sometimes
it's not. Is there any software out there that can take all
or even most source bundles and make packages from them?
A I've heard good things about
Simes's PkgTools:
http://www.bpfh.net/computing/software/pkg-tools/
PkgTools requires Solaris 2.6 (or later) and Perl, and it's useful
to have the Digest::MD5 Perl module.
Amy Rich, president of the Boston-based Oceanwave Consulting,
Inc. (http://www.oceanwave.com), has been a UNIX systems
administrator for more than 10 years. She received a BSCS at Worcester
Polytechnic Institute, and can be reached at: qna@oceanwave.com.