# this module is an OS/2 oriented replacement for the grp standard
# extension module.

# written by Andrew MacIntyre, April 2001.
# updated July 2003, adding field accessor support

# note that this implementation checks whether ":" or ";" as used as
# the field separator character.

"""Replacement for grp standard extension module, intended for use on
OS/2 and similar systems which don't normally have an /etc/group file.

The standard Unix group database is an ASCII text file with 4 fields per
record (line), separated by a colon:
  - group name (string)
  - group password (optional encrypted string)
  - group id (integer)
  - group members (comma delimited list of userids, with no spaces)

Note that members are only included in the group file for groups that
aren't their primary groups.
(see the section 8.2 of the Python Library Reference)

This implementation differs from the standard Unix implementation by
allowing use of the platform's native path separator character - ';' on OS/2,
DOS and MS-Windows - as the field separator in addition to the Unix
standard ":".

The module looks for the group database at the following locations
(in order first to last):
  - ${ETC_GROUP}              (or %ETC_GROUP%)
  - ${ETC}/group              (or %ETC%/group)
  - ${PYTHONHOME}/Etc/group   (or %PYTHONHOME%/Etc/group)

Classes
-------

None

Functions
---------

getgrgid(gid) -  return the record for group-id gid as a 4-tuple

getgrnam(name) - return the record for group 'name' as a 4-tuple

getgrall() -     return a list of 4-tuples, each tuple being one record
                 (NOTE: the order is arbitrary)

Attributes
----------

group_file -     the path of the group database file

"""

import os

# try and find the group file
__group_path = []
if 'ETC_GROUP' in os.environ:
    __group_path.append(os.environ['ETC_GROUP'])
if 'ETC' in os.environ:
    __group_path.append('%s/group' % os.environ['ETC'])
if 'PYTHONHOME' in os.environ:
    __group_path.append('%s/Etc/group' % os.environ['PYTHONHOME'])

group_file = None
for __i in __group_path:
    try:
        __f = open(__i, 'r')
        __f.close()
        group_file = __i
        break
    except:
        pass

# decide what field separator we can try to use - Unix standard, with
# the platform's path separator as an option.  No special field conversion
# handlers are required for the group file.
__field_sep = [':']
if os.pathsep:
    if os.pathsep != ':':
        __field_sep.append(os.pathsep)

# helper routine to identify which separator character is in use
def __get_field_sep(record):
    fs = None
    for c in __field_sep:
        # there should be 3 delimiter characters (for 4 fields)
        if record.count(c) == 3:
            fs = c
            break
    if fs:
        return fs
    else:
        raise KeyError('>> group database fields not delimited <<')

# class to match the new record field name accessors.
# the resulting object is intended to behave like a read-only tuple,
# with each member also accessible by a field name.
class Group:
    def __init__(self, name, passwd, gid, mem):
        self.__dict__['gr_name'] = name
        self.__dict__['gr_passwd'] = passwd
        self.__dict__['gr_gid'] = gid
        self.__dict__['gr_mem'] = mem
        self.__dict__['_record'] = (self.gr_name, self.gr_passwd,
                                    self.gr_gid, self.gr_mem)

    def __len__(self):
        return 4

    def __getitem__(self, key):
        return self._record[key]

    def __setattr__(self, name, value):
        raise AttributeError('attribute read-only: %s' % name)

    def __repr__(self):
        return str(self._record)

    def __cmp__(self, other):
        this = str(self._record)
        if this == other:
            return 0
        elif this < other:
            return -1
        else:
            return 1


# read the whole file, parsing each entry into tuple form
# with dictionaries to speed recall by GID or group name
def __read_group_file():
    if group_file:
        group = open(group_file, 'r')
    else:
        raise KeyError('>> no group database <<')
    gidx = {}
    namx = {}
    sep = None
    while 1:
        entry = group.readline().strip()
        if len(entry) > 3:
            if sep is None:
                sep = __get_field_sep(entry)
            fields = entry.split(sep)
            fields[2] = int(fields[2])
            fields[3] = [f.strip() for f in fields[3].split(',')]
            record = Group(*fields)
            if fields[2] not in gidx:
                gidx[fields[2]] = record
            if fields[0] not in namx:
                namx[fields[0]] = record
        elif len(entry) > 0:
            pass                         # skip empty or malformed records
        else:
            break
    group.close()
    if len(gidx) == 0:
        raise KeyError
    return (gidx, namx)

# return the group database entry by GID
def getgrgid(gid):
    g, n = __read_group_file()
    return g[gid]

# return the group database entry by group name
def getgrnam(name):
    g, n = __read_group_file()
    return n[name]

# return all the group database entries
def getgrall():
    g, n = __read_group_file()
    return g.values()

# test harness
if __name__ == '__main__':
    getgrall()
