Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

297 lines
9.9 KiB

  1. package User::pwent;
  2. use 5.006;
  3. use strict;
  4. use warnings;
  5. use Config;
  6. use Carp;
  7. our(@EXPORT, @EXPORT_OK, %EXPORT_TAGS);
  8. BEGIN {
  9. use Exporter ();
  10. @EXPORT = qw(getpwent getpwuid getpwnam getpw);
  11. @EXPORT_OK = qw(
  12. pw_has
  13. $pw_name $pw_passwd $pw_uid $pw_gid
  14. $pw_gecos $pw_dir $pw_shell
  15. $pw_expire $pw_change $pw_class
  16. $pw_age
  17. $pw_quota $pw_comment
  18. $pw_expire
  19. );
  20. %EXPORT_TAGS = (
  21. FIELDS => [ grep(/^\$pw_/, @EXPORT_OK), @EXPORT ],
  22. ALL => [ @EXPORT, @EXPORT_OK ],
  23. );
  24. }
  25. use vars grep /^\$pw_/, @EXPORT_OK;
  26. #
  27. # XXX: these mean somebody hacked this module's source
  28. # without understanding the underlying assumptions.
  29. #
  30. my $IE = "[INTERNAL ERROR]";
  31. # Class::Struct forbids use of @ISA
  32. sub import { goto &Exporter::import }
  33. use Class::Struct qw(struct);
  34. struct 'User::pwent' => [
  35. name => '$', # pwent[0]
  36. passwd => '$', # pwent[1]
  37. uid => '$', # pwent[2]
  38. gid => '$', # pwent[3]
  39. # you'll only have one/none of these three
  40. change => '$', # pwent[4]
  41. age => '$', # pwent[4]
  42. quota => '$', # pwent[4]
  43. # you'll only have one/none of these two
  44. comment => '$', # pwent[5]
  45. class => '$', # pwent[5]
  46. # you might not have this one
  47. gecos => '$', # pwent[6]
  48. dir => '$', # pwent[7]
  49. shell => '$', # pwent[8]
  50. # you might not have this one
  51. expire => '$', # pwent[9]
  52. ];
  53. # init our groks hash to be true if the built platform knew how
  54. # to do each struct pwd field that perl can ever under any circumstances
  55. # know about. we do not use /^pw_?/, but just the tails.
  56. sub _feature_init {
  57. our %Groks; # whether build system knew how to do this feature
  58. for my $feep ( qw{
  59. pwage pwchange pwclass pwcomment
  60. pwexpire pwgecos pwpasswd pwquota
  61. }
  62. )
  63. {
  64. my $short = $feep =~ /^pw(.*)/
  65. ? $1
  66. : do {
  67. # not cluck, as we know we called ourselves,
  68. # and a confession is probably imminent anyway
  69. warn("$IE $feep is a funny struct pwd field");
  70. $feep;
  71. };
  72. exists $Config{ "d_" . $feep }
  73. || confess("$IE Configure doesn't d_$feep");
  74. $Groks{$short} = defined $Config{ "d_" . $feep };
  75. }
  76. # assume that any that are left are always there
  77. for my $feep (grep /^\$pw_/s, @EXPORT_OK) {
  78. $feep =~ /^\$pw_(.*)/;
  79. $Groks{$1} = 1 unless defined $Groks{$1};
  80. }
  81. }
  82. # With arguments, reports whether one or more fields are all implemented
  83. # in the build machine's struct pwd pw_*. May be whitespace separated.
  84. # We do not use /^pw_?/, just the tails.
  85. #
  86. # Without arguments, returns the list of fields implemented on build
  87. # machine, space separated in scalar context.
  88. #
  89. # Takes exception to being asked whether this machine's struct pwd has
  90. # a field that Perl never knows how to provide under any circumstances.
  91. # If the module does this idiocy to itself, the explosion is noisier.
  92. #
  93. sub pw_has {
  94. our %Groks; # whether build system knew how to do this feature
  95. my $cando = 1;
  96. my $sploder = caller() ne __PACKAGE__
  97. ? \&croak
  98. : sub { confess("$IE @_") };
  99. if (@_ == 0) {
  100. my @valid = sort grep { $Groks{$_} } keys %Groks;
  101. return wantarray ? @valid : "@valid";
  102. }
  103. for my $feep (map { split } @_) {
  104. defined $Groks{$feep}
  105. || $sploder->("$feep is never a valid struct pwd field");
  106. $cando &&= $Groks{$feep};
  107. }
  108. return $cando;
  109. }
  110. sub _populate (@) {
  111. return unless @_;
  112. my $pwob = new();
  113. # Any that haven't been pw_had are assumed on "all" platforms of
  114. # course, this may not be so, but you can't get here otherwise,
  115. # since the underlying core call already took exception to your
  116. # impudence.
  117. $pw_name = $pwob->name ( $_[0] );
  118. $pw_passwd = $pwob->passwd ( $_[1] ) if pw_has("passwd");
  119. $pw_uid = $pwob->uid ( $_[2] );
  120. $pw_gid = $pwob->gid ( $_[3] );
  121. if (pw_has("change")) {
  122. $pw_change = $pwob->change ( $_[4] );
  123. }
  124. elsif (pw_has("age")) {
  125. $pw_age = $pwob->age ( $_[4] );
  126. }
  127. elsif (pw_has("quota")) {
  128. $pw_quota = $pwob->quota ( $_[4] );
  129. }
  130. if (pw_has("class")) {
  131. $pw_class = $pwob->class ( $_[5] );
  132. }
  133. elsif (pw_has("comment")) {
  134. $pw_comment = $pwob->comment( $_[5] );
  135. }
  136. $pw_gecos = $pwob->gecos ( $_[6] ) if pw_has("gecos");
  137. $pw_dir = $pwob->dir ( $_[7] );
  138. $pw_shell = $pwob->shell ( $_[8] );
  139. $pw_expire = $pwob->expire ( $_[9] ) if pw_has("expire");
  140. return $pwob;
  141. }
  142. sub getpwent ( ) { _populate(CORE::getpwent()) }
  143. sub getpwnam ($) { _populate(CORE::getpwnam(shift)) }
  144. sub getpwuid ($) { _populate(CORE::getpwuid(shift)) }
  145. sub getpw ($) { ($_[0] =~ /^\d+\z/s) ? &getpwuid : &getpwnam }
  146. _feature_init();
  147. 1;
  148. __END__
  149. =head1 NAME
  150. User::pwent - by-name interface to Perl's built-in getpw*() functions
  151. =head1 SYNOPSIS
  152. use User::pwent;
  153. $pw = getpwnam('daemon') || die "No daemon user";
  154. if ( $pw->uid == 1 && $pw->dir =~ m#^/(bin|tmp)?\z#s ) {
  155. print "gid 1 on root dir";
  156. }
  157. $real_shell = $pw->shell || '/bin/sh';
  158. for (($fullname, $office, $workphone, $homephone) =
  159. split /\s*,\s*/, $pw->gecos)
  160. {
  161. s/&/ucfirst(lc($pw->name))/ge;
  162. }
  163. use User::pwent qw(:FIELDS);
  164. getpwnam('daemon') || die "No daemon user";
  165. if ( $pw_uid == 1 && $pw_dir =~ m#^/(bin|tmp)?\z#s ) {
  166. print "gid 1 on root dir";
  167. }
  168. $pw = getpw($whoever);
  169. use User::pwent qw/:DEFAULT pw_has/;
  170. if (pw_has(qw[gecos expire quota])) { .... }
  171. if (pw_has("name uid gid passwd")) { .... }
  172. print "Your struct pwd has: ", scalar pw_has(), "\n";
  173. =head1 DESCRIPTION
  174. This module's default exports override the core getpwent(), getpwuid(),
  175. and getpwnam() functions, replacing them with versions that return
  176. C<User::pwent> objects. This object has methods that return the
  177. similarly named structure field name from the C's passwd structure
  178. from F<pwd.h>, stripped of their leading "pw_" parts, namely C<name>,
  179. C<passwd>, C<uid>, C<gid>, C<change>, C<age>, C<quota>, C<comment>,
  180. C<class>, C<gecos>, C<dir>, C<shell>, and C<expire>. The C<passwd>,
  181. C<gecos>, and C<shell> fields are tainted when running in taint mode.
  182. You may also import all the structure fields directly into your
  183. namespace as regular variables using the :FIELDS import tag. (Note
  184. that this still overrides your core functions.) Access these fields
  185. as variables named with a preceding C<pw_> in front their method
  186. names. Thus, C<< $passwd_obj->shell >> corresponds to $pw_shell
  187. if you import the fields.
  188. The getpw() function is a simple front-end that forwards
  189. a numeric argument to getpwuid() and the rest to getpwnam().
  190. To access this functionality without the core overrides, pass the
  191. C<use> an empty import list, and then access function functions
  192. with their full qualified names. The built-ins are always still
  193. available via the C<CORE::> pseudo-package.
  194. =head2 System Specifics
  195. Perl believes that no machine ever has more than one of C<change>,
  196. C<age>, or C<quota> implemented, nor more than one of either
  197. C<comment> or C<class>. Some machines do not support C<expire>,
  198. C<gecos>, or allegedly, C<passwd>. You may call these methods
  199. no matter what machine you're on, but they return C<undef> if
  200. unimplemented.
  201. You may ask whether one of these was implemented on the system Perl
  202. was built on by asking the importable C<pw_has> function about them.
  203. This function returns true if all parameters are supported fields
  204. on the build platform, false if one or more were not, and raises
  205. an exception if you asked about a field that Perl never knows how
  206. to provide. Parameters may be in a space-separated string, or as
  207. separate arguments. If you pass no parameters, the function returns
  208. the list of C<struct pwd> fields supported by your build platform's
  209. C library, as a list in list context, or a space-separated string
  210. in scalar context. Note that just because your C library had
  211. a field doesn't necessarily mean that it's fully implemented on
  212. that system.
  213. Interpretation of the C<gecos> field varies between systems, but
  214. traditionally holds 4 comma-separated fields containing the user's
  215. full name, office location, work phone number, and home phone number.
  216. An C<&> in the gecos field should be replaced by the user's properly
  217. capitalized login C<name>. The C<shell> field, if blank, must be
  218. assumed to be F</bin/sh>. Perl does not do this for you. The
  219. C<passwd> is one-way hashed garble, not clear text, and may not be
  220. unhashed save by brute-force guessing. Secure systems use more a
  221. more secure hashing than DES. On systems supporting shadow password
  222. systems, Perl automatically returns the shadow password entry when
  223. called by a suitably empowered user, even if your underlying
  224. vendor-provided C library was too short-sighted to realize it should
  225. do this.
  226. See passwd(5) and getpwent(3) for details.
  227. =head1 NOTE
  228. While this class is currently implemented using the Class::Struct
  229. module to build a struct-like class, you shouldn't rely upon this.
  230. =head1 AUTHOR
  231. Tom Christiansen
  232. =head1 HISTORY
  233. =over
  234. =item March 18th, 2000
  235. Reworked internals to support better interface to dodgey fields
  236. than normal Perl function provides. Added pw_has() field. Improved
  237. documentation.
  238. =back