mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 18:28:49 +00:00 
			
		
		
		
	 2a691a8149
			
		
	
	
		2a691a8149
		
	
	
	
	
		
			
			svn+ssh://pythondev@svn.python.org/python/trunk ........ r62021 | benjamin.peterson | 2008-03-28 18:11:01 -0500 (Fri, 28 Mar 2008) | 2 lines NIL => NULL ........ r62029 | amaury.forgeotdarc | 2008-03-28 20:42:31 -0500 (Fri, 28 Mar 2008) | 3 lines Correctly call the base class tearDown(); otherwise running test_logging twice produce the errors we see on all buildbots ........ r62035 | raymond.hettinger | 2008-03-29 05:42:07 -0500 (Sat, 29 Mar 2008) | 1 line Be explicit about what efficient means. ........ r62036 | georg.brandl | 2008-03-29 06:46:18 -0500 (Sat, 29 Mar 2008) | 2 lines Fix capitalization. ........ r62037 | amaury.forgeotdarc | 2008-03-29 07:42:54 -0500 (Sat, 29 Mar 2008) | 5 lines lib2to3 should install a logging handler only when run as a main program, not when used as a library. This may please the buildbots, which fail when test_lib2to3 is run before test_logging. ........ r62043 | benjamin.peterson | 2008-03-29 10:24:25 -0500 (Sat, 29 Mar 2008) | 3 lines #2503 make singletons compared with "is" not == or != Thanks to Wummel for the patch ........ r62044 | gerhard.haering | 2008-03-29 14:11:52 -0500 (Sat, 29 Mar 2008) | 2 lines Documented the lastrowid attribute. ........ r62052 | benjamin.peterson | 2008-03-30 14:35:10 -0500 (Sun, 30 Mar 2008) | 2 lines Updated README regarding doc formats ........ r62053 | georg.brandl | 2008-03-30 14:41:39 -0500 (Sun, 30 Mar 2008) | 2 lines The other download formats will be available for 2.6 too. ........
		
			
				
	
	
		
			208 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # this module is an OS/2 oriented replacement for the pwd 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.  Path conversions are are applied when
 | |
| # the database uses ":" as the field separator character.
 | |
| 
 | |
| """Replacement for pwd standard extension module, intended for use on
 | |
| OS/2 and similar systems which don't normally have an /etc/passwd file.
 | |
| 
 | |
| The standard Unix password database is an ASCII text file with 7 fields
 | |
| per record (line), separated by a colon:
 | |
|   - user name (string)
 | |
|   - password (encrypted string, or "*" or "")
 | |
|   - user id (integer)
 | |
|   - group id (integer)
 | |
|   - description (usually user's name)
 | |
|   - home directory (path to user's home directory)
 | |
|   - shell (path to the user's login shell)
 | |
| 
 | |
| (see the section 8.1 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 ":".  Additionally, when ":" is the separator path conversions
 | |
| are applied to deal with any munging of the drive letter reference.
 | |
| 
 | |
| The module looks for the password database at the following locations
 | |
| (in order first to last):
 | |
|   - ${ETC_PASSWD}             (or %ETC_PASSWD%)
 | |
|   - ${ETC}/passwd             (or %ETC%/passwd)
 | |
|   - ${PYTHONHOME}/Etc/passwd  (or %PYTHONHOME%/Etc/passwd)
 | |
| 
 | |
| Classes
 | |
| -------
 | |
| 
 | |
| None
 | |
| 
 | |
| Functions
 | |
| ---------
 | |
| 
 | |
| getpwuid(uid) -  return the record for user-id uid as a 7-tuple
 | |
| 
 | |
| getpwnam(name) - return the record for user 'name' as a 7-tuple
 | |
| 
 | |
| getpwall() -     return a list of 7-tuples, each tuple being one record
 | |
|                  (NOTE: the order is arbitrary)
 | |
| 
 | |
| Attributes
 | |
| ----------
 | |
| 
 | |
| passwd_file -    the path of the password database file
 | |
| 
 | |
| """
 | |
| 
 | |
| import os
 | |
| 
 | |
| # try and find the passwd file
 | |
| __passwd_path = []
 | |
| if 'ETC_PASSWD' in os.environ:
 | |
|     __passwd_path.append(os.environ['ETC_PASSWD'])
 | |
| if 'ETC' in os.environ:
 | |
|     __passwd_path.append('%s/passwd' % os.environ['ETC'])
 | |
| if 'PYTHONHOME' in os.environ:
 | |
|     __passwd_path.append('%s/Etc/passwd' % os.environ['PYTHONHOME'])
 | |
| 
 | |
| passwd_file = None
 | |
| for __i in __passwd_path:
 | |
|     try:
 | |
|         __f = open(__i, 'r')
 | |
|         __f.close()
 | |
|         passwd_file = __i
 | |
|         break
 | |
|     except:
 | |
|         pass
 | |
| 
 | |
| # path conversion handlers
 | |
| def __nullpathconv(path):
 | |
|     return path.replace(os.altsep, os.sep)
 | |
| 
 | |
| def __unixpathconv(path):
 | |
|     # two known drive letter variations: "x;" and "$x"
 | |
|     if path[0] == '$':
 | |
|         conv = path[1] + ':' + path[2:]
 | |
|     elif path[1] == ';':
 | |
|         conv = path[0] + ':' + path[2:]
 | |
|     else:
 | |
|         conv = path
 | |
|     return conv.replace(os.altsep, os.sep)
 | |
| 
 | |
| # decide what field separator we can try to use - Unix standard, with
 | |
| # the platform's path separator as an option.  No special field conversion
 | |
| # handler is required when using the platform's path separator as field
 | |
| # separator, but are required for the home directory and shell fields when
 | |
| # using the standard Unix (":") field separator.
 | |
| __field_sep = {':': __unixpathconv}
 | |
| if os.pathsep:
 | |
|     if os.pathsep != ':':
 | |
|         __field_sep[os.pathsep] = __nullpathconv
 | |
| 
 | |
| # helper routine to identify which separator character is in use
 | |
| def __get_field_sep(record):
 | |
|     fs = None
 | |
|     for c in __field_sep.keys():
 | |
|         # there should be 6 delimiter characters (for 7 fields)
 | |
|         if record.count(c) == 6:
 | |
|             fs = c
 | |
|             break
 | |
|     if fs:
 | |
|         return fs
 | |
|     else:
 | |
|         raise KeyError('>> passwd 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 Passwd:
 | |
|     def __init__(self, name, passwd, uid, gid, gecos, dir, shell):
 | |
|         self.__dict__['pw_name'] = name
 | |
|         self.__dict__['pw_passwd'] = passwd
 | |
|         self.__dict__['pw_uid'] = uid
 | |
|         self.__dict__['pw_gid'] = gid
 | |
|         self.__dict__['pw_gecos'] = gecos
 | |
|         self.__dict__['pw_dir'] = dir
 | |
|         self.__dict__['pw_shell'] = shell
 | |
|         self.__dict__['_record'] = (self.pw_name, self.pw_passwd,
 | |
|                                     self.pw_uid, self.pw_gid,
 | |
|                                     self.pw_gecos, self.pw_dir,
 | |
|                                     self.pw_shell)
 | |
| 
 | |
|     def __len__(self):
 | |
|         return 7
 | |
| 
 | |
|     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 UID or passwd name
 | |
| def __read_passwd_file():
 | |
|     if passwd_file:
 | |
|         passwd = open(passwd_file, 'r')
 | |
|     else:
 | |
|         raise KeyError('>> no password database <<')
 | |
|     uidx = {}
 | |
|     namx = {}
 | |
|     sep = None
 | |
|     while True:
 | |
|         entry = passwd.readline().strip()
 | |
|         if len(entry) > 6:
 | |
|             if sep is None:
 | |
|                 sep = __get_field_sep(entry)
 | |
|             fields = entry.split(sep)
 | |
|             for i in (2, 3):
 | |
|                 fields[i] = int(fields[i])
 | |
|             for i in (5, 6):
 | |
|                 fields[i] = __field_sep[sep](fields[i])
 | |
|             record = Passwd(*fields)
 | |
|             if fields[2] not in uidx:
 | |
|                 uidx[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
 | |
|     passwd.close()
 | |
|     if len(uidx) == 0:
 | |
|         raise KeyError
 | |
|     return (uidx, namx)
 | |
| 
 | |
| # return the passwd database entry by UID
 | |
| def getpwuid(uid):
 | |
|     u, n = __read_passwd_file()
 | |
|     return u[uid]
 | |
| 
 | |
| # return the passwd database entry by passwd name
 | |
| def getpwnam(name):
 | |
|     u, n = __read_passwd_file()
 | |
|     return n[name]
 | |
| 
 | |
| # return all the passwd database entries
 | |
| def getpwall():
 | |
|     u, n = __read_passwd_file()
 | |
|     return n.values()
 | |
| 
 | |
| # test harness
 | |
| if __name__ == '__main__':
 | |
|     getpwall()
 |