/Lib/plat-os2emx/grp.py

http://unladen-swallow.googlecode.com/ · Python · 182 lines · 129 code · 28 blank · 25 comment · 28 complexity · 3aab061eef3b59d4bd1972d75548af82 MD5 · raw file

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