sys-admin 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }