sys-admin 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES ADDED
@@ -0,0 +1,31 @@
1
+ == 1.3.1 - 29-Jun-2005
2
+ * Fixed a bug where the inability to read the lastlog file caused an error.
3
+ From now on that error is ignored, and the lastlog attributes of the User
4
+ object are set to nil.
5
+ * Added a beta version of Admin.delete_user (Windows only).
6
+
7
+ == 1.3.0 - 3-Jun-2005
8
+ * Bug fixes for Linux.
9
+ * Removed the version.h file - no longer needed since the Win32 version is
10
+ pure Ruby.
11
+
12
+ == 1.2.0 - 30-Apr-2005
13
+ * Replaced the Win32 version with a pure Ruby version that uses Win32API and
14
+ win32ole + WMI.
15
+ * The LocalGroup class no longer exists in the Win32 version. Instead, it is
16
+ now an attribute of a Group object. The issue was forced by WMI.
17
+ * The default for users and groups on Win32 systems is now local rather than
18
+ global. See the documentation for why you probably don't want to iterate
19
+ over global accounts.
20
+ * Corresponding doc changes and test suite changes.
21
+
22
+ == 1.1.0 - 1-Apr-2005
23
+ * Fixed bug where a segfault could occur when trying to retrieve a user or
24
+ group by an ID that didn't exist (Unix).
25
+ * Added tests for intentional failures.
26
+ * Added lastlog information tothe User class (Unix).
27
+ * Modified the way User objects are created internally (Unix).
28
+ * Fixed a bug in the User#shell attribute (Unix).
29
+
30
+ == 1.0.0 - 25-Mar-2005
31
+ * Initial release
@@ -0,0 +1,17 @@
1
+ extconf.rb
2
+ install.rb
3
+ sys-admin.gemspec
4
+ CHANGES
5
+ MANIFEST
6
+ README
7
+
8
+ examples/groups.rb
9
+ examples/users.rb
10
+
11
+ lib/sys/unix.c
12
+ lib/sys/unix.h
13
+ lib/sys/win32.rb
14
+
15
+ test/tc_admin.rb
16
+ test/tc_unix.rb
17
+ test/tc_win32.rb
data/README ADDED
@@ -0,0 +1,174 @@
1
+ == Description
2
+ The sys-admin package is a unified, cross platform replacement for the
3
+ Etc module.
4
+
5
+ == Installation
6
+ === Win32
7
+ ruby test\tc_admin.rb # optional
8
+ ruby install.rb
9
+
10
+ === Unix
11
+ ruby extconf.rb
12
+ nmake
13
+ ruby test\tc_admin.rb # optional
14
+ nmake site-install
15
+
16
+ == Synopsis
17
+ require "sys/admin"
18
+ include Sys
19
+
20
+ # Yields a User object for each user
21
+ Admin.users{ |user|
22
+ p user
23
+ }
24
+
25
+ # Returns an Array of User objects
26
+ a = Admin.users
27
+
28
+ # Yields a Group object for each group
29
+ Admin.groups{ |group|
30
+ p group
31
+ }
32
+
33
+ # Returns an Array of Group objects
34
+ g = Admin.groups
35
+
36
+ # Get information about a particular user
37
+ p Admin.get_user("nobody")
38
+
39
+ # Get information about a particular group
40
+ p Admin.get_group("adm")
41
+
42
+ == Admin
43
+ Admin.get_login
44
+ Returns the user name (only) of the current login.
45
+
46
+ Admin.get_user(name, host=localhost)
47
+ Admin.get_user(uid, host=localhost, local=true)
48
+ Returns a User object based on +name+ or +uid+.
49
+
50
+ Win32 only: you may specify a host from which information is retrieved.
51
+ The default is the local machine. You may also specify whether to
52
+ retrieve a local or global account. The default is local.
53
+
54
+ Admin.get_group(name, host=localhost, local=true)
55
+ Admin.get_group(gid, host=localhost, local=true)
56
+ Returns a Group object based on +name+ or +uid+.
57
+
58
+ Win32 only: you may specify a host from which information is retrieved.
59
+ The default is the local machine. You can retrieve either a global or
60
+ local group, depending on the value of the +local+ argument.
61
+
62
+ Admin.groups(host=localhost, local=true)
63
+ Admin.groups(host=localhost, local=true){ |group| ... }
64
+ In block form, yields a Group object for each user on the system. In
65
+ non-block form, returns an Array of Group objects.
66
+
67
+ Win32 only: you may specify a host from which information is retrieved.
68
+ The default is the local machine. You can retrieve either a global or
69
+ local group, depending on the value of the +local+ argument.
70
+
71
+ Admin.users(host=localhost, local=true)
72
+ Admin.users(host=localhost, local=true){ |user| ... }
73
+ In block form, yields a User object for each user on the system. In
74
+ non-block form, returns an Array of User objects.
75
+
76
+ Win32 only: you may specify a host from which information is retrieved.
77
+ The default is the local machine. You can retrieve either a global or
78
+ local group, depending on the value of the +local+ argument.
79
+
80
+ == User class
81
+ === User (Win32)
82
+ The User class has the following attributes on Win32 systems:
83
+
84
+ * account_type
85
+ * caption
86
+ * description
87
+ * domain
88
+ * password
89
+ * full_name
90
+ * install_date
91
+ * name
92
+ * sid
93
+ * status
94
+ * disabled?
95
+ * local?
96
+ * lockout?
97
+ * password_changeable?
98
+ * password_expires?
99
+ * password_required?
100
+
101
+ === User (Unix)
102
+ The User class has the following attributes on Unix systems:
103
+
104
+ * name
105
+ * passwd
106
+ * uid
107
+ * gid
108
+ * dir
109
+ * shell
110
+ * gecos
111
+ * quota
112
+ * age
113
+ * class
114
+ * comment
115
+ * expire
116
+
117
+ == Group Classes
118
+ === Group (Win32)
119
+ The Group class has the following attributes on Win32 systems:
120
+
121
+ * caption
122
+ * description
123
+ * domain
124
+ * install_date
125
+ * name
126
+ * sid
127
+ * status
128
+ * gid
129
+ * local?
130
+
131
+ === Group (Unix)
132
+ The Group class has the following attributes on Unix systems:
133
+
134
+ * name
135
+ * gid
136
+ * members
137
+ * passwd
138
+
139
+ == Error Classes
140
+ AdminError < StandardError
141
+ Raised if anything goes wrong with any of the above methods.
142
+
143
+ == Developer's Notes
144
+ === Win32
145
+ The Win32 version now uses a win32ole + WMI approach to getting
146
+ information. This means that the WMI service must be running on the
147
+ target machine in order to work (which it is, by default).
148
+
149
+ Note that, by default, local user and group information is retrieved
150
+ instead of global. You probably do NOT want to iterate over global users
151
+ or groups because there can be quite a few on your domain.
152
+
153
+ == Future Plans
154
+ The following methods will be added for both platforms:
155
+
156
+ * Admin.add_user
157
+ * Admin.config_user
158
+ * Admin.delete_user
159
+
160
+ == Known Bugs
161
+ None that I'm aware of. If you find any, please log them on the project
162
+ page at http://www.rubyforge.org/projects/sysutils.
163
+
164
+ == License
165
+ Ruby's
166
+
167
+ == Copyright
168
+ (C) 2005, Daniel J. Berger
169
+ All Rights Reserved
170
+
171
+ == Author
172
+ Daniel J. Berger
173
+ djberg96@yahoo.com
174
+ IRC nickname: imperator/mok/rubyhacker1
@@ -0,0 +1,39 @@
1
+ ###########################################################################
2
+ # groups.rb
3
+ #
4
+ # Sample script to demonstrate some of the various group methods. Alter
5
+ # as you see fit.
6
+ ###########################################################################
7
+ base = File.basename(Dir.pwd)
8
+
9
+ if base == "examples" || base =~ /sys-admin.*/
10
+ require "ftools"
11
+ Dir.chdir("..") if base == "examples"
12
+ Dir.mkdir("sys") unless File.exists?("sys")
13
+ if File::ALT_SEPARATOR
14
+ File.copy("lib/sys/win32.rb", "sys/admin.rb")
15
+ else
16
+ File.copy("admin.so","sys") if File.exists?("admin.so")
17
+ end
18
+ $LOAD_PATH.unshift(Dir.pwd)
19
+ end
20
+
21
+ require "pp"
22
+ require "sys/admin"
23
+ include Sys
24
+
25
+ if File::ALT_SEPARATOR
26
+ pp Admin.get_group("guests")
27
+ pp Admin.get_group(513)
28
+ else
29
+ pp Admin.get_group("adm")
30
+ pp Admin.get_group(7)
31
+ end
32
+
33
+ Admin.groups{ |g|
34
+ pp g
35
+ puts
36
+ }
37
+
38
+ # This should raise an error
39
+ Admin.get_group("fofofofof")
@@ -0,0 +1,35 @@
1
+ ###########################################################################
2
+ # users.rb
3
+ #
4
+ # Sample script to demonstrate some of the various user methods. Alter
5
+ # as you see fit.
6
+ ###########################################################################
7
+ base = File.basename(Dir.pwd)
8
+
9
+ if base == "examples" || base =~ /sys-admin.*/
10
+ require "ftools"
11
+ Dir.chdir("..") if base == "examples"
12
+ Dir.mkdir("sys") unless File.exists?("sys")
13
+ if File::ALT_SEPARATOR
14
+ File.copy("lib/sys/win32.rb", "sys/admin.rb")
15
+ else
16
+ File.copy("admin.so","sys") if File.exists?("admin.so")
17
+ end
18
+ $LOAD_PATH.unshift(Dir.pwd)
19
+ end
20
+
21
+ require "pp"
22
+ require "sys/admin"
23
+ include Sys
24
+
25
+ user = Admin.get_login
26
+
27
+ puts "User: #{user}"
28
+
29
+ Admin.users{ |u|
30
+ pp u
31
+ puts
32
+ }
33
+
34
+ pp Admin.get_user(user)
35
+ pp Admin.get_user(501)
@@ -0,0 +1,62 @@
1
+ require "mkmf"
2
+ require "ftools"
3
+
4
+ if PLATFORM.match('mswin')
5
+ STDERR.puts "Use the install.rb file on Win32 systems."
6
+ STDERR.puts "Exiting. The sys-admin package was NOT installed."
7
+ exit
8
+ else
9
+ File.move("lib/sys/win32.rb", "lib/sys/win32.orig") rescue nil # Don't install
10
+
11
+ have_func("getlogin_r")
12
+ have_func("getlogin")
13
+ have_func("getenv")
14
+
15
+ have_func("cuserid")
16
+
17
+ have_func("getpwuid_r")
18
+ have_func("getpwuid")
19
+ have_func("getpwnam_r")
20
+ have_func("getpwnam")
21
+ have_func("getpwent_r")
22
+ have_func("getpwent")
23
+
24
+ have_func("getgrgid_r")
25
+ have_func("getgrgid")
26
+ have_func("getgrnam_r")
27
+ have_func("getgrnam")
28
+ have_func("getgrent_r")
29
+ have_func("getgrent")
30
+
31
+ have_struct_member("struct passwd", "pw_gecos", "pwd.h")
32
+ have_struct_member("struct passwd", "pw_change", "pwd.h")
33
+ have_struct_member("struct passwd", "pw_quota", "pwd.h")
34
+ have_struct_member("struct passwd", "pw_age", "pwd.h")
35
+ have_struct_member("struct passwd", "pw_class", "pwd.h")
36
+ have_struct_member("struct passwd", "pw_comment", "pwd.h")
37
+ have_struct_member("struct passwd", "pw_expire", "pwd.h")
38
+ have_struct_member("struct passwd", "pw_passwd", "pwd.h")
39
+
40
+ have_struct_member("struct group", "gr_passwd", "grp.h")
41
+
42
+ utmp = have_header("utmp.h")
43
+ lastlog = have_header("lastlog.h")
44
+
45
+ if utmp || lastlog
46
+ have_struct_member(
47
+ "struct lastlog",
48
+ "ll_time",
49
+ ["utmp.h", "time.h", "lastlog.h"]
50
+ )
51
+ end
52
+
53
+ $CFLAGS += " -D_POSIX_PTHREAD_SEMANTICS"
54
+ if PLATFORM.match("linux")
55
+ $CFLAGS += " -D_GNU_SOURCE -D_REENTRANT"
56
+ end
57
+
58
+ File.copy("lib/sys/unix.c", "admin.c")
59
+ File.copy("lib/sys/unix.h", "admin.h")
60
+ end
61
+
62
+ create_makefile("sys/admin")
@@ -0,0 +1,283 @@
1
+ #include "ruby.h"
2
+ #include "admin.h"
3
+
4
+ /*
5
+ * call-seq:
6
+ * User.new
7
+ * User.new{ |user| ... }
8
+ *
9
+ * Creates and returns a User object. If a block is provided, yields the
10
+ * object back to the block.
11
+ */
12
+ static VALUE user_init(VALUE self){
13
+ if(rb_block_given_p())
14
+ rb_yield(self);
15
+
16
+ return self;
17
+ }
18
+
19
+ /*
20
+ * call-seq:
21
+ * Group.new
22
+ * Group.new{ |user| ... }
23
+ *
24
+ * Creates and returns a Group object. If a block is provided, yields the
25
+ * object back to the block.
26
+ */
27
+ static VALUE group_init(VALUE self){
28
+ if(rb_block_given_p())
29
+ rb_yield(self);
30
+
31
+ return self;
32
+ }
33
+
34
+ /*
35
+ * call-seq:
36
+ * Sys::Admin.get_login
37
+ *
38
+ * Returns the login for the process. If this is called from a process that
39
+ * has no controlling terminal, then it resorts to returning the "USER"
40
+ * environment variable. If that still isn't defined, nil is returned.
41
+ *
42
+ *--
43
+ * Developer's Note:
44
+ *
45
+ * Uses the (POSIX) reentrant version of getlogin_r() if supported. Otherwise
46
+ * it resorts to the standard getlogin function. If that fails, it resorts to
47
+ * cuserid(). If that fails, it resorts to getenv("USER"). If that fails,
48
+ * then nil is returned.
49
+ */
50
+ static VALUE admin_get_login(VALUE klass){
51
+ char login[_POSIX_LOGIN_NAME_MAX];
52
+ VALUE rbLogin = Qnil;
53
+
54
+ #ifdef HAVE_GETLOGIN_R
55
+ getlogin_r(login,sizeof(login));
56
+ #elif HAVE_GETLOGIN
57
+ strcpy(login,getlogin());
58
+ #endif
59
+
60
+ #ifdef HAVE_CUSERID
61
+ if(!login)
62
+ cuserid(login);
63
+ #endif
64
+
65
+ #ifdef HAVE_GETENV
66
+ if(!login)
67
+ strcpy(login,getenv("USER"));
68
+ #endif
69
+
70
+ if(login)
71
+ rbLogin = rb_str_new2(login);
72
+
73
+ return rbLogin;
74
+ }
75
+
76
+ /* call-seq:
77
+ * Admin.get_user(name)
78
+ * Admin.get_user(uid)
79
+ *
80
+ * Returns a User object for the given +name+ or +uid+. Raises an AdminError
81
+ * if a user cannot be found for that name or user ID.
82
+ */
83
+ static VALUE admin_get_user(VALUE klass, VALUE rbVal){
84
+ VALUE rbUser;
85
+
86
+ if(FIXNUM_P(rbVal)){
87
+ rbUser = get_user_by_num(rbVal);
88
+ }
89
+ else{
90
+ rbUser = get_user_by_name(rbVal);
91
+ }
92
+
93
+ return rbUser;
94
+ }
95
+
96
+ /* call-seq:
97
+ * Admin.get_group(name)
98
+ * Admin.get_group(gid)
99
+ *
100
+ * Returns a Group object for the given +name+ or +gid+. Raises an AdminError
101
+ * if a group cannot be found for that name or GID.
102
+ *
103
+ *--
104
+ * Developer's Note:
105
+ *
106
+ * I generally oppose method overloading like this, but for this method, and
107
+ * for only two types, I can live with it for the added convenience it
108
+ * provides.
109
+ */
110
+ static VALUE admin_get_group(VALUE klass, VALUE rbVal){
111
+ VALUE rbGroup;
112
+
113
+ if(FIXNUM_P(rbVal)){
114
+ rbGroup = get_group_by_num(rbVal);
115
+ }
116
+ else{
117
+ rbGroup = get_group_by_name(rbVal);
118
+ }
119
+
120
+ return rbGroup;
121
+ }
122
+
123
+ /* call-seq:
124
+ * Admin.groups
125
+ * Admin.groups{ |group| ... }
126
+ *
127
+ * In block form, yields a Group object for each group on the system. In
128
+ * non-block form, returns an Array of Group objects.
129
+ */
130
+ static VALUE admin_groups(VALUE klass){
131
+ VALUE rbArray = Qnil;
132
+
133
+ if(!rb_block_given_p())
134
+ rbArray = rb_ary_new();
135
+
136
+ setgrent();
137
+
138
+ #ifdef HAVE_GETGRENT_R
139
+ struct group grp;
140
+ char buf[GROUP_BUF_SIZE];
141
+ #ifdef _GNU_SOURCE
142
+ struct group* grp_p;
143
+ while(!getgrent_r(&grp, buf, GROUP_BUF_SIZE, &grp_p)){
144
+ if(rb_block_given_p()){
145
+ rb_yield(get_group(grp_p));
146
+ }
147
+ else{
148
+ rb_ary_push(rbArray, get_group(grp_p));
149
+ }
150
+ }
151
+ #else
152
+ while(getgrent_r(&grp, buf, GROUP_BUF_SIZE) != NULL){
153
+ if(rb_block_given_p()){
154
+ rb_yield(get_group(&grp));
155
+ }
156
+ else{
157
+ rb_ary_push(rbArray, get_group(&grp));
158
+ }
159
+ }
160
+ #endif
161
+ #elif HAVE_GETGRENT
162
+ struct group* grp;
163
+ while((grp = getgrent()) != NULL){
164
+ if(rb_block_given_p()){
165
+ rb_yield(get_group(grp));
166
+ }
167
+ else{
168
+ rb_ary_push(rbArray, get_group(grp));
169
+ }
170
+ }
171
+ #else
172
+ rb_raise(rb_eNotImpError, "groups method not supported on this platform");
173
+ #endif
174
+
175
+ endgrent();
176
+ return rbArray;
177
+ }
178
+
179
+ /* call-seq:
180
+ * Admin.users
181
+ * Admin.users{ |user| ... }
182
+ *
183
+ * In block form, yields a User object for each user on the system. In
184
+ * non-block form, returns an Array of User objects.
185
+ */
186
+ static VALUE admin_users(VALUE klass){
187
+ VALUE rbArray = Qnil;
188
+
189
+ if(!rb_block_given_p())
190
+ rbArray = rb_ary_new();
191
+
192
+ setpwent();
193
+
194
+ #ifdef HAVE_GETPWENT_R
195
+ struct passwd pwd;
196
+ char buf[USER_BUF_SIZE];
197
+
198
+ #ifdef _GNU_SOURCE
199
+ struct passwd* pwd_p;
200
+ while(!getpwent_r(&pwd, buf, USER_BUF_SIZE, &pwd_p)){
201
+ if(rb_block_given_p()){
202
+ rb_yield(get_user(pwd_p));
203
+ }
204
+ else{
205
+ rb_ary_push(rbArray, get_user(pwd_p));
206
+ }
207
+ }
208
+ #else
209
+ while(getpwent_r(&pwd, buf, USER_BUF_SIZE) != NULL){
210
+ if(rb_block_given_p()){
211
+ rb_yield(get_user(&pwd));
212
+ }
213
+ else{
214
+ rb_ary_push(rbArray, get_user(&pwd));
215
+ }
216
+ }
217
+ #endif
218
+ #elif HAVE_GETPWENT
219
+ struct passwd* pwd;
220
+
221
+ while((pwd = getpwent()) != NULL){
222
+ if(rb_block_given_p()){
223
+ rb_yield(get_user(pwd));
224
+ }
225
+ else{
226
+ rb_ary_push(rbArray, get_user(pwd));
227
+ }
228
+ }
229
+ #else
230
+ rb_raise(rb_eNotImpError, "users method not supported on this platform");
231
+ #endif
232
+
233
+ endpwent();
234
+ return rbArray;
235
+ }
236
+
237
+ void Init_admin(){
238
+ VALUE mSys, cAdmin;
239
+
240
+ /* Module and class definitions */
241
+ mSys = rb_define_module("Sys");
242
+ cAdmin = rb_define_class_under(mSys, "Admin", rb_cObject);
243
+ cUser = rb_define_class_under(mSys, "User", rb_cObject);
244
+ cGroup = rb_define_class_under(mSys, "Group", rb_cObject);
245
+ cAdminError = rb_define_class_under(mSys, "AdminError", rb_eStandardError);
246
+
247
+ /* Class Methods */
248
+ rb_define_singleton_method(cAdmin, "get_login", admin_get_login, 0);
249
+ rb_define_singleton_method(cAdmin, "get_user", admin_get_user, 1);
250
+ rb_define_singleton_method(cAdmin, "get_group", admin_get_group, 1);
251
+ rb_define_singleton_method(cAdmin, "users", admin_users, 0);
252
+ rb_define_singleton_method(cAdmin, "groups", admin_groups, 0);
253
+
254
+ /* Instance Methods */
255
+ rb_define_method(cUser, "initialize", user_init, 0);
256
+ rb_define_method(cGroup,"initialize", group_init, 0);
257
+
258
+ /* User Attributes */
259
+ rb_define_attr(cUser, "name", 1, 1);
260
+ rb_define_attr(cUser, "passwd", 1, 1);
261
+ rb_define_attr(cUser, "uid", 1, 1);
262
+ rb_define_attr(cUser, "gid", 1, 1);
263
+ rb_define_attr(cUser, "dir", 1, 1);
264
+ rb_define_attr(cUser, "shell", 1, 1);
265
+ rb_define_attr(cUser, "gecos", 1, 1);
266
+ rb_define_attr(cUser, "quota", 1, 1);
267
+ rb_define_attr(cUser, "age", 1, 1);
268
+ rb_define_attr(cUser, "class", 1, 1);
269
+ rb_define_attr(cUser, "comment", 1, 1);
270
+ rb_define_attr(cUser, "expire", 1, 1);
271
+ rb_define_attr(cUser, "login_time", 1, 0);
272
+ rb_define_attr(cUser, "login_device", 1, 0);
273
+ rb_define_attr(cUser, "login_host", 1, 0);
274
+
275
+ /* Group Attributes */
276
+ rb_define_attr(cGroup, "name", 1, 1);
277
+ rb_define_attr(cGroup, "gid", 1, 1);
278
+ rb_define_attr(cGroup, "members", 1, 1);
279
+ rb_define_attr(cGroup, "passwd", 1, 1);
280
+
281
+ /* Constants */
282
+ rb_define_const(cAdmin, "VERSION", rb_str_new2(SYS_ADMIN_VERSION));
283
+ }