In article <5qkhqu$ev...@hawk.branch.com>
da...@mailrus.fv.com (Dan Pritts) writes:
> In article <5qhudm$93...@enterprise.desy.de>,
> Michael Sievers <sieve...@NOSPAMmail.desy.de> wrote:
>>Hello,
>> I have been despairing on a little problem...
>> I'm trying to write a shell script (might use awk, sed etc as well), that
>> on a system using shadow passwords takes /etc/passwd, looks up the password
>> for every entry in /etc/shadow and creates a new /etc/passwd with the
>> encryted passwords as on a non-shadow system. Now, the password may not
>> be in order of UID etc. Does anyone have an idea of how to do this?
> here's a not particularly elegant solution to your problem:
<ellided>
> the particularly stupid part of this script is that it iterates over
> the shadow file for each and every user in the passwd file, rather
> than keeping track of things, but this is simpler to write than
> something that keeps track and unless you have thousands of lines
> it won't matter (and computer time is cheap for a one-off like this
> anyway).
You could just load each into an associative array
(keyed on their names) and work with the directly.
Here's an awk (gawk) script that does this:
#! /bin/gawk -f
## "Unshadow a passwd and shadow pair"
BEGIN {
FS=":"
OFS=":"
## Load /etc/passwd into an array
while ( getline < "/etc/passwd" )
pwent[$1] = $0
close ("/etc/passwd")
## Load /etc/shadow into an array
while ( getline < "/etc/shadow" )
shadow[$1] = $0
close ("/etc/shadow")
## Use the unames as the key (index) to each
for (i in pwent) {
# Replace the second field of pwent[] with
# the second field of the corresponding shadow[]
if ( i in shadow ) {
split (shadow[i], corrshad)
## corrshad is "corresponding shadow entry"
## i.e. the one whose key (associate index)
## matches that of the current pwent
$0 = pwent[i]
$2 = corrshad[2]
print }
else print "User", i, "not found in shadow" > "/dev/stderr"
}
exit }
That's about 25 lines of code. It
seems to work (though I just hacked it together and
only glanced at the output). One disadvantage is that
it will reorder the lines -- this can be overcome by
by assigning $0 to an element of a "newent[]" array
re-opening /etc/passwd and writing out the "newent"
as we find the pw entries. I know that my passwd and
shadow files are not completely in sync on this system
-- this script ignores that.
The if (i in shadow) clause can be modified to replace
that password with a "*" if you'd prefer. It's just there
so that entries in the /etc/passwd with no corresponding
entry in /etc/shadow will not be printed to the resulting
new password file with a null password (which is what happens
without the "if clause"
This does no checking for entries in the shadow file that have
no corresponding passwd entry. It would be simple to add --
but wouldn't serve the pedagogical purposes of this example.
On a system with 4000 acounts this should take less
than a meg. of core for the associative arrays -- My
guess is that mawk (Mike Brennan) or gawk (the GNU awk
maintained by Arnold Robbins) should be able to handle a
100,000 user passwd/shadow pair on a typical workstation
before it even hits swap space. The brief overhead in
RAM is more than offset by its efficiency compared to the
ellided example -- because it doesn't require lots of
file opens and closes (which are comparitively expensive).
> You could have done more or less the same thing with a bit of awk and
> sh and grep. Personally I suggest learning perl (see www.perl.org for
> a list of books to buy to start you out) since it's got all the
> functionality of sh, sed, and awk rolled in to one, and is powerful
> enough for some projects that these tools are not appropriate for.
You don't need grep or sed when you're using awk (although
somethings are more easily expressed in one or another).
This example (processing a couple of text files) doesn't
require a shell wrapper -- it's just straight awk.
I would agree that a new admin is better served learning
perl if they are not particularly ambitious. If you're
only going to learn one scripting language it should be
perl. However, if you really want to be well-rounded and
really want to understand perl -- I'd learn awk first
(it really is easier) and use it to help learn perl (with
generous dollops of the a2p (awk to perl translator).
This script is so trivial any decent scripting language
can do it. The use of associative arrays makes it
much easier and those are a common feature of modern
scripting languages.
> the downside is that not every system ships with perl, but it's
> pretty easy to get it working on almost any system.
Precisely so. The awk that ships on many systems is
not worth keeping either. One should always get mawk or
gawk (or both!) and install them. Don't trust the vendor
supplied awk (which might be quite old, might not comply
with the POSIX specs. and might have arbitrary line length
and array size limits).
> Others, of course, have different opinions, but whatever.
> danno
My opinion is that we should all learn python, no, make
that REXX (regina?) -- no, no, I meant TCL/expect, or was
that Java. How about elisp? Or we could all change our
shells to Scheme (schsh?).
We should give up on all this scripting, adopt NT and
just take the dialog boxes that our vendor gives us --
all hail Microsoft! (O.K. -- I'm joking!)
--
Jim Dennis, i...@mail.starshine.org
Proprietor, consult...@mail.starshine.org
Starshine Technical Services http://www.starshine.org
PGP 1024/2ABF03B1 Jim Dennis <j...@starshine.org>
Key fingerprint = 2524E3FEF0922A84 A27BDEDB38EBB95A