The following example is a revised version of the suite of routines developed in Reading the User Database. See there for an explanation of how the code works.
The formulation here, due mainly to Andrew Schorr, is rather elegant.
All of the implementation functions and variables are in the
passwd
namespace, whereas the main interface functions are
defined in the awk
namespace.
# ns_passwd.awk --- access password file information @namespace "passwd" BEGIN { # tailor this to suit your system Awklib = "/usr/local/libexec/awk/" } function Init( oldfs, oldrs, olddol0, pwcat, using_fw, using_fpat) { if (Inited) return oldfs = FS oldrs = RS olddol0 = $0 using_fw = (PROCINFO["FS"] == "FIELDWIDTHS") using_fpat = (PROCINFO["FS"] == "FPAT") FS = ":" RS = "\n" pwcat = Awklib "pwcat" while ((pwcat | getline) > 0) { Byname[$1] = $0 Byuid[$3] = $0 Bycount[++Total] = $0 } close(pwcat) Count = 0 Inited = 1 FS = oldfs if (using_fw) FIELDWIDTHS = FIELDWIDTHS else if (using_fpat) FPAT = FPAT RS = oldrs $0 = olddol0 } function awk::getpwnam(name) { Init() return Byname[name] } function awk::getpwuid(uid) { Init() return Byuid[uid] } function awk::getpwent() { Init() if (Count < Total) return Bycount[++Count] return "" } function awk::endpwent() { Count = 0 }
As you can see, this version also follows the convention mentioned in Naming Library Function Global Variables, whereby global variable and function names start with a capital letter.
Here is a simple test program. Since it’s in a separate file, unadorned
identifiers are sought for in the awk
namespace:
BEGIN { while ((p = getpwent()) != "") print p }
Here’s what happens when it’s run:
$ gawk -f ns_passwd.awk -f testpasswd.awk -| root:x:0:0:root:/root:/bin/bash -| daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin -| bin:x:2:2:bin:/bin:/usr/sbin/nologin -| sys:x:3:3:sys:/dev:/usr/sbin/nologin ...