Home | History | Annotate | Download | only in plat-os2emx
      1 # this module is an OS/2 oriented replacement for the grp standard
      2 # extension module.
      3 
      4 # written by Andrew MacIntyre, April 2001.
      5 # updated July 2003, adding field accessor support
      6 
      7 # note that this implementation checks whether ":" or ";" as used as
      8 # the field separator character.
      9 
     10 """Replacement for grp standard extension module, intended for use on
     11 OS/2 and similar systems which don't normally have an /etc/group file.
     12 
     13 The standard Unix group database is an ASCII text file with 4 fields per
     14 record (line), separated by a colon:
     15   - group name (string)
     16   - group password (optional encrypted string)
     17   - group id (integer)
     18   - group members (comma delimited list of userids, with no spaces)
     19 
     20 Note that members are only included in the group file for groups that
     21 aren't their primary groups.
     22 (see the section 8.2 of the Python Library Reference)
     23 
     24 This implementation differs from the standard Unix implementation by
     25 allowing use of the platform's native path separator character - ';' on OS/2,
     26 DOS and MS-Windows - as the field separator in addition to the Unix
     27 standard ":".
     28 
     29 The module looks for the group database at the following locations
     30 (in order first to last):
     31   - ${ETC_GROUP}              (or %ETC_GROUP%)
     32   - ${ETC}/group              (or %ETC%/group)
     33   - ${PYTHONHOME}/Etc/group   (or %PYTHONHOME%/Etc/group)
     34 
     35 Classes
     36 -------
     37 
     38 None
     39 
     40 Functions
     41 ---------
     42 
     43 getgrgid(gid) -  return the record for group-id gid as a 4-tuple
     44 
     45 getgrnam(name) - return the record for group 'name' as a 4-tuple
     46 
     47 getgrall() -     return a list of 4-tuples, each tuple being one record
     48                  (NOTE: the order is arbitrary)
     49 
     50 Attributes
     51 ----------
     52 
     53 group_file -     the path of the group database file
     54 
     55 """
     56 
     57 import os
     58 
     59 # try and find the group file
     60 __group_path = []
     61 if os.environ.has_key('ETC_GROUP'):
     62     __group_path.append(os.environ['ETC_GROUP'])
     63 if os.environ.has_key('ETC'):
     64     __group_path.append('%s/group' % os.environ['ETC'])
     65 if os.environ.has_key('PYTHONHOME'):
     66     __group_path.append('%s/Etc/group' % os.environ['PYTHONHOME'])
     67 
     68 group_file = None
     69 for __i in __group_path:
     70     try:
     71         __f = open(__i, 'r')
     72         __f.close()
     73         group_file = __i
     74         break
     75     except:
     76         pass
     77 
     78 # decide what field separator we can try to use - Unix standard, with
     79 # the platform's path separator as an option.  No special field conversion
     80 # handlers are required for the group file.
     81 __field_sep = [':']
     82 if os.pathsep:
     83     if os.pathsep != ':':
     84         __field_sep.append(os.pathsep)
     85 
     86 # helper routine to identify which separator character is in use
     87 def __get_field_sep(record):
     88     fs = None
     89     for c in __field_sep:
     90         # there should be 3 delimiter characters (for 4 fields)
     91         if record.count(c) == 3:
     92             fs = c
     93             break
     94     if fs:
     95         return fs
     96     else:
     97         raise KeyError, '>> group database fields not delimited <<'
     98 
     99 # class to match the new record field name accessors.
    100 # the resulting object is intended to behave like a read-only tuple,
    101 # with each member also accessible by a field name.
    102 class Group:
    103     def __init__(self, name, passwd, gid, mem):
    104         self.__dict__['gr_name'] = name
    105         self.__dict__['gr_passwd'] = passwd
    106         self.__dict__['gr_gid'] = gid
    107         self.__dict__['gr_mem'] = mem
    108         self.__dict__['_record'] = (self.gr_name, self.gr_passwd,
    109                                     self.gr_gid, self.gr_mem)
    110 
    111     def __len__(self):
    112         return 4
    113 
    114     def __getitem__(self, key):
    115         return self._record[key]
    116 
    117     def __setattr__(self, name, value):
    118         raise AttributeError('attribute read-only: %s' % name)
    119 
    120     def __repr__(self):
    121         return str(self._record)
    122 
    123     def __cmp__(self, other):
    124         this = str(self._record)
    125         if this == other:
    126             return 0
    127         elif this < other:
    128             return -1
    129         else:
    130             return 1
    131 
    132 
    133 # read the whole file, parsing each entry into tuple form
    134 # with dictionaries to speed recall by GID or group name
    135 def __read_group_file():
    136     if group_file:
    137         group = open(group_file, 'r')
    138     else:
    139         raise KeyError, '>> no group database <<'
    140     gidx = {}
    141     namx = {}
    142     sep = None
    143     while 1:
    144         entry = group.readline().strip()
    145         if len(entry) > 3:
    146             if sep is None:
    147                 sep = __get_field_sep(entry)
    148             fields = entry.split(sep)
    149             fields[2] = int(fields[2])
    150             fields[3] = [f.strip() for f in fields[3].split(',')]
    151             record = Group(*fields)
    152             if not gidx.has_key(fields[2]):
    153                 gidx[fields[2]] = record
    154             if not namx.has_key(fields[0]):
    155                 namx[fields[0]] = record
    156         elif len(entry) > 0:
    157             pass                         # skip empty or malformed records
    158         else:
    159             break
    160     group.close()
    161     if len(gidx) == 0:
    162         raise KeyError
    163     return (gidx, namx)
    164 
    165 # return the group database entry by GID
    166 def getgrgid(gid):
    167     g, n = __read_group_file()
    168     return g[gid]
    169 
    170 # return the group database entry by group name
    171 def getgrnam(name):
    172     g, n = __read_group_file()
    173     return n[name]
    174 
    175 # return all the group database entries
    176 def getgrall():
    177     g, n = __read_group_file()
    178     return g.values()
    179 
    180 # test harness
    181 if __name__ == '__main__':
    182     getgrall()
    183