sys-admin 1.8.0-universal-mingw32

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.
@@ -0,0 +1,27 @@
1
+ ###########################################################################
2
+ # groups.rb
3
+ #
4
+ # Sample script to demonstrate some of the various group methods. Alter
5
+ # as you see fit.
6
+ ###########################################################################
7
+ require "pp"
8
+ require "sys/admin"
9
+ include Sys
10
+
11
+ if File::ALT_SEPARATOR
12
+ pp Admin.get_group("guests")
13
+ pp Admin.get_group(513)
14
+ else
15
+ pp Admin.get_group("admin")
16
+ pp Admin.get_group(7)
17
+ end
18
+
19
+ sleep 3
20
+
21
+ Admin.groups.each{ |g|
22
+ pp g
23
+ puts
24
+ }
25
+
26
+ # This should raise an error
27
+ Admin.get_group("fofofofof")
@@ -0,0 +1,41 @@
1
+ ###########################################################################
2
+ # users.rb
3
+ #
4
+ # Sample script to demonstrate some of the various user methods. Alter
5
+ # as you see fit.
6
+ ###########################################################################
7
+ require "pp"
8
+ require "sys/admin"
9
+ include Sys
10
+
11
+ =begin
12
+ user = User.new do |u|
13
+ u.name = "Foo"
14
+ u.description = "Test account"
15
+ u.password = "changeme"
16
+ #u.lockout = false
17
+ u.disabled = true
18
+ #u.password_required = true
19
+ end
20
+
21
+ Admin.delete_user(u.name) rescue nil
22
+ Admin.add_user(user)
23
+
24
+ pp Admin.get_user("Foo")
25
+
26
+ Admin.delete_user("Foo")
27
+ =end
28
+
29
+ user = Admin.get_login
30
+
31
+ puts "User: #{user}"
32
+
33
+ sleep 3
34
+
35
+ Admin.users.each{ |u|
36
+ pp u
37
+ puts
38
+ }
39
+
40
+ pp Admin.get_user(user)
41
+ pp Admin.get_user(501)
@@ -0,0 +1,262 @@
1
+ require 'sys/admin/custom'
2
+ require 'sys/admin/common'
3
+ require 'rbconfig'
4
+
5
+ # The BSD specific code.
6
+
7
+ module Sys
8
+ class Admin
9
+ # :no-doc:
10
+ BUF_MAX = 65536 # Max buffer for retry
11
+ private_constant :BUF_MAX
12
+
13
+ # I'm making some aliases here to prevent potential conflicts
14
+ attach_function :open_c, :open, [:string, :int], :int
15
+ attach_function :pread_c, :pread, [:int, :pointer, :size_t, :off_t], :size_t
16
+ attach_function :close_c, :close, [:int], :int
17
+
18
+ attach_function :getlogin_r, [:pointer, :int], :int
19
+ attach_function :getpwnam_r, [:string, :pointer, :pointer, :size_t, :pointer], :int
20
+ attach_function :getpwuid_r, [:long, :pointer, :pointer, :size_t, :pointer], :int
21
+ attach_function :getgrnam_r, [:string, :pointer, :pointer, :size_t, :pointer], :int
22
+ attach_function :getgrgid_r, [:long, :pointer, :pointer, :size_t, :pointer], :int
23
+
24
+ private_class_method :getlogin_r, :getpwnam_r, :getpwuid_r, :getgrnam_r, :getgrgid_r
25
+ private_class_method :open_c, :pread_c, :close_c
26
+
27
+ # struct passwd from /usr/include/pwd.h
28
+ class PasswdStruct < FFI::Struct
29
+ fields = [
30
+ :pw_name, :string,
31
+ :pw_passwd, :string,
32
+ :pw_uid, :uid_t,
33
+ :pw_gid, :gid_t,
34
+ :pw_change, :time_t,
35
+ :pw_class, :string,
36
+ :pw_gecos, :string,
37
+ :pw_dir, :string,
38
+ :pw_shell, :string,
39
+ :pw_expire, :time_t
40
+ ]
41
+
42
+ if RbConfig::CONFIG['host_os'] =~ /freebsd/i
43
+ fields.push(:pw_fields, :int)
44
+ end
45
+
46
+ layout(*fields)
47
+ end
48
+
49
+ private_constant :PasswdStruct
50
+
51
+ # struct group from /usr/include/grp.h
52
+ class GroupStruct < FFI::Struct
53
+ layout(
54
+ :gr_name, :string,
55
+ :gr_passwd, :string,
56
+ :gr_gid, :uint,
57
+ :gr_mem, :pointer
58
+ )
59
+ end
60
+
61
+ private_constant :GroupStruct
62
+
63
+ # I'm blending the timeval struct in directly here
64
+ class LastlogStruct < FFI::Struct
65
+ layout(
66
+ :ll_time, :int32,
67
+ :ll_line, [:char, 32],
68
+ :ll_host, [:char, 256]
69
+ )
70
+ end
71
+
72
+ private_constant :LastlogStruct
73
+
74
+ # Returns the login for the current process.
75
+ #
76
+ def self.get_login
77
+ buf = FFI::MemoryPointer.new(:char, 256)
78
+
79
+ if getlogin_r(buf, buf.size) != 0
80
+ raise Error, "getlogin_r function failed: " + strerror(FFI.errno)
81
+ end
82
+
83
+ buf.read_string
84
+ end
85
+
86
+ # Returns a User object for the given name or uid. Raises an error
87
+ # if a user cannot be found.
88
+ #
89
+ # Examples:
90
+ #
91
+ # Sys::Admin.get_user('joe')
92
+ # Sys::Admin.get_user(501)
93
+ #
94
+ def self.get_user(uid)
95
+ buf = FFI::MemoryPointer.new(:char, 1024)
96
+ pbuf = FFI::MemoryPointer.new(PasswdStruct)
97
+ temp = PasswdStruct.new
98
+
99
+ if uid.is_a?(String)
100
+ if getpwnam_r(uid, temp, buf, buf.size, pbuf) != 0
101
+ raise Error, "getpwnam_r function failed: " + strerror(FFI.errno)
102
+ end
103
+ else
104
+ if getpwuid_r(uid, temp, buf, buf.size, pbuf) != 0
105
+ raise Error, "getpwuid_r function failed: " + strerror(FFI.errno)
106
+ end
107
+ end
108
+
109
+ ptr = pbuf.read_pointer
110
+
111
+ if ptr.null?
112
+ raise Error, "no user found for #{uid}"
113
+ end
114
+
115
+ pwd = PasswdStruct.new(ptr)
116
+ get_user_from_struct(pwd)
117
+ end
118
+
119
+ # Returns a Group object for the given name or uid. Raises an error
120
+ # if a group cannot be found.
121
+ #
122
+ # Examples:
123
+ #
124
+ # Sys::Admin.get_group('admin')
125
+ # Sys::Admin.get_group(101)
126
+ #
127
+ def self.get_group(gid)
128
+ size = 1024
129
+ buf = FFI::MemoryPointer.new(:char, size)
130
+ pbuf = FFI::MemoryPointer.new(PasswdStruct)
131
+ temp = GroupStruct.new
132
+
133
+ begin
134
+ if gid.is_a?(String)
135
+ val = getgrnam_r(gid, temp, buf, buf.size, pbuf)
136
+ fun = 'getgrnam_r'
137
+ else
138
+ val = getgrgid_r(gid, temp, buf, buf.size, pbuf)
139
+ fun = 'getgrgid_r'
140
+ end
141
+ raise SystemCallError.new(fun, val) if val != 0
142
+ rescue Errno::ERANGE
143
+ size += 1024
144
+ raise if size > BUF_MAX
145
+ buf = FFI::MemoryPointer.new(:char, size)
146
+ retry
147
+ end
148
+
149
+ ptr = pbuf.read_pointer
150
+
151
+ if ptr.null?
152
+ raise Error, "no group found for '#{gid}'"
153
+ end
154
+
155
+ grp = GroupStruct.new(ptr)
156
+ get_group_from_struct(grp)
157
+ end
158
+
159
+ # Returns an array of User objects for each user on the system.
160
+ #
161
+ def self.users
162
+ users = []
163
+
164
+ begin
165
+ setpwent()
166
+
167
+ until (ptr = getpwent()).null?
168
+ pwd = PasswdStruct.new(ptr)
169
+ users << get_user_from_struct(pwd)
170
+ end
171
+ ensure
172
+ endpwent()
173
+ end
174
+
175
+ users
176
+ end
177
+
178
+ # Returns an array of Group objects for each user on the system.
179
+ #
180
+ def self.groups
181
+ groups = []
182
+
183
+ begin
184
+ setgrent()
185
+
186
+ until (ptr = getgrent()).null?
187
+ grp = GroupStruct.new(ptr)
188
+ groups << get_group_from_struct(grp)
189
+ end
190
+ ensure
191
+ endgrent()
192
+ end
193
+
194
+ groups
195
+ end
196
+
197
+ # Takes a GroupStruct and converts it to a Group object.
198
+ def self.get_group_from_struct(grp)
199
+ Group.new do |g|
200
+ g.name = grp[:gr_name]
201
+ g.passwd = grp[:gr_passwd]
202
+ g.gid = grp[:gr_gid]
203
+ g.members = grp[:gr_mem].read_array_of_string
204
+ end
205
+ end
206
+
207
+ private_class_method :get_group_from_struct
208
+
209
+ # Takes a UserStruct and converts it to a User object.
210
+ def self.get_user_from_struct(pwd)
211
+ user = User.new do |u|
212
+ u.name = pwd[:pw_name]
213
+ u.passwd = pwd[:pw_passwd]
214
+ u.uid = pwd[:pw_uid]
215
+ u.gid = pwd[:pw_gid]
216
+ u.change = Time.at(pwd[:pw_change])
217
+ u.access_class = pwd[:pw_class]
218
+ u.gecos = pwd[:pw_gecos]
219
+ u.dir = pwd[:pw_dir]
220
+ u.shell = pwd[:pw_shell]
221
+ u.expire = Time.at(pwd[:pw_expire])
222
+ end
223
+
224
+ log = get_lastlog_info(user.uid)
225
+
226
+ if log
227
+ user.login_time = Time.at(log[:ll_time])
228
+ user.login_device = log[:ll_line].to_s
229
+ user.login_host = log[:ll_host].to_s
230
+ end
231
+
232
+ user
233
+ end
234
+
235
+ private_class_method :get_user_from_struct
236
+
237
+ # Get lastlog information for the given user.
238
+ def self.get_lastlog_info(uid)
239
+ logfile = '/var/log/lastlog'
240
+ lastlog = LastlogStruct.new
241
+
242
+ begin
243
+ fd = open_c(logfile, File::RDONLY)
244
+
245
+ if fd != -1
246
+ bytes = pread_c(fd, lastlog, lastlog.size, uid * lastlog.size)
247
+ if bytes < 0
248
+ raise Error, "pread function failed: " + strerror(FFI.errno)
249
+ end
250
+ else
251
+ nil # Ignore, improper permissions
252
+ end
253
+ ensure
254
+ close_c(fd) if fd && fd >= 0
255
+ end
256
+
257
+ lastlog
258
+ end
259
+
260
+ private_class_method :get_lastlog_info
261
+ end
262
+ end
@@ -0,0 +1,244 @@
1
+ require 'sys/admin/custom'
2
+ require 'sys/admin/common'
3
+
4
+ # The Darwin specific code.
5
+
6
+ module Sys
7
+ class Admin
8
+ # :no-doc:
9
+ BUF_MAX = 65536 # Max buf size for retry.
10
+ private_constant :BUF_MAX
11
+
12
+ attach_function :getlogin_r, [:pointer, :int], :int
13
+ attach_function :getpwnam_r, [:string, :pointer, :pointer, :size_t, :pointer], :int
14
+ attach_function :getpwuid_r, [:long, :pointer, :pointer, :size_t, :pointer], :int
15
+ attach_function :getgrnam_r, [:string, :pointer, :pointer, :size_t, :pointer], :int
16
+ attach_function :getgrgid_r, [:long, :pointer, :pointer, :size_t, :pointer], :int
17
+ attach_function :getlastlogx, [:long, :pointer], :pointer
18
+
19
+ private_class_method :getlogin_r, :getpwnam_r, :getpwuid_r
20
+ private_class_method :getgrnam_r, :getgrgid_r, :getlastlogx
21
+
22
+ # struct passwd from /usr/include/pwd.h
23
+ class PasswdStruct < FFI::Struct
24
+ layout(
25
+ :pw_name, :string,
26
+ :pw_passwd, :string,
27
+ :pw_uid, :uint,
28
+ :pw_gid, :uint,
29
+ :pw_change, :ulong,
30
+ :pw_class, :string,
31
+ :pw_gecos, :string,
32
+ :pw_dir, :string,
33
+ :pw_shell, :string,
34
+ :pw_expire, :ulong
35
+ )
36
+ end
37
+
38
+ private_constant :PasswdStruct
39
+
40
+ # struct group from /usr/include/grp.h
41
+ class GroupStruct < FFI::Struct
42
+ layout(
43
+ :gr_name, :string,
44
+ :gr_passwd, :string,
45
+ :gr_gid, :uint,
46
+ :gr_mem, :pointer
47
+ )
48
+ end
49
+
50
+ private_constant :GroupStruct
51
+
52
+ # I'm blending the timeval struct in directly here
53
+ class LastlogxStruct < FFI::Struct
54
+ layout(
55
+ :tv_sec, :long,
56
+ :tv_usec, :long,
57
+ :ll_line, [:char, 32],
58
+ :ll_host, [:char, 256]
59
+ )
60
+ end
61
+
62
+ private_constant :LastlogxStruct
63
+
64
+ # Returns the login for the current process.
65
+ #
66
+ def self.get_login
67
+ buf = FFI::MemoryPointer.new(:char, 256)
68
+
69
+ if getlogin_r(buf, buf.size) != 0
70
+ raise Error, "getlogin_r function failed: " + strerror(FFI.errno)
71
+ end
72
+
73
+ buf.read_string
74
+ end
75
+
76
+ # Returns a User object for the given name or uid. Raises an error
77
+ # if a user cannot be found.
78
+ #
79
+ # Examples:
80
+ #
81
+ # Sys::Admin.get_user('joe')
82
+ # Sys::Admin.get_user(501)
83
+ #
84
+ def self.get_user(uid)
85
+ buf = FFI::MemoryPointer.new(:char, 1024)
86
+ pbuf = FFI::MemoryPointer.new(PasswdStruct)
87
+ temp = PasswdStruct.new
88
+
89
+ if uid.is_a?(String)
90
+ if getpwnam_r(uid, temp, buf, buf.size, pbuf) != 0
91
+ raise Error, "getpwnam_r function failed: " + strerror(FFI.errno)
92
+ end
93
+ else
94
+ if getpwuid_r(uid, temp, buf, buf.size, pbuf) != 0
95
+ raise Error, "getpwuid_r function failed: " + strerror(FFI.errno)
96
+ end
97
+ end
98
+
99
+ ptr = pbuf.read_pointer
100
+
101
+ if ptr.null?
102
+ raise Error, "no user found for #{uid}"
103
+ end
104
+
105
+ pwd = PasswdStruct.new(ptr)
106
+ get_user_from_struct(pwd)
107
+ end
108
+
109
+ # Returns a Group object for the given name or uid. Raises an error
110
+ # if a group cannot be found.
111
+ #
112
+ # Examples:
113
+ #
114
+ # Sys::Admin.get_group('admin')
115
+ # Sys::Admin.get_group(101)
116
+ #
117
+ def self.get_group(gid)
118
+ size = 1024
119
+ buf = FFI::MemoryPointer.new(:char, size)
120
+ pbuf = FFI::MemoryPointer.new(PasswdStruct)
121
+ temp = GroupStruct.new
122
+
123
+ begin
124
+ if gid.is_a?(String)
125
+ val = getgrnam_r(gid, temp, buf, buf.size, pbuf)
126
+ fun = 'getgrnam_r'
127
+ else
128
+ val = getgrgid_r(gid, temp, buf, buf.size, pbuf)
129
+ fun = 'getgrgid_r'
130
+ end
131
+ raise SystemCallError.new(fun, val) if val != 0
132
+ rescue Errno::ERANGE
133
+ size += 1024
134
+ raise if size > BUF_MAX
135
+ buf = FFI::MemoryPointer.new(:char, size)
136
+ retry
137
+ end
138
+
139
+ ptr = pbuf.read_pointer
140
+
141
+ if ptr.null?
142
+ raise Error, "no group found for '#{gid}'"
143
+ end
144
+
145
+ grp = GroupStruct.new(ptr)
146
+ get_group_from_struct(grp)
147
+ end
148
+
149
+ # Returns an array of User objects for each user on the system.
150
+ #
151
+ #--
152
+ # This method is somewhat slow on OSX because of the call to get
153
+ # lastlog information. I'm not sure why.
154
+ #
155
+ def self.users
156
+ users = []
157
+
158
+ begin
159
+ setpwent()
160
+
161
+ until (ptr = getpwent()).null?
162
+ pwd = PasswdStruct.new(ptr)
163
+ users << get_user_from_struct(pwd)
164
+ end
165
+ ensure
166
+ endpwent()
167
+ end
168
+
169
+ users
170
+ end
171
+
172
+ # Returns an array of Group objects for each user on the system.
173
+ #
174
+ def self.groups
175
+ groups = []
176
+
177
+ begin
178
+ setgrent()
179
+
180
+ until (ptr = getgrent()).null?
181
+ grp = GroupStruct.new(ptr)
182
+ groups << get_group_from_struct(grp)
183
+ end
184
+ ensure
185
+ endgrent()
186
+ end
187
+
188
+ groups
189
+ end
190
+
191
+ # Takes a GroupStruct and converts it to a Group object.
192
+ def self.get_group_from_struct(grp)
193
+ Group.new do |g|
194
+ g.name = grp[:gr_name]
195
+ g.passwd = grp[:gr_passwd]
196
+ g.gid = grp[:gr_gid]
197
+ g.members = grp[:gr_mem].read_array_of_string
198
+ end
199
+ end
200
+
201
+ private_class_method :get_group_from_struct
202
+
203
+ # Takes a UserStruct and converts it to a User object.
204
+ def self.get_user_from_struct(pwd)
205
+ user = User.new do |u|
206
+ u.name = pwd[:pw_name]
207
+ u.passwd = pwd[:pw_passwd]
208
+ u.uid = pwd[:pw_uid]
209
+ u.gid = pwd[:pw_gid]
210
+ u.change = Time.at(pwd[:pw_change])
211
+ u.access_class = pwd[:pw_class]
212
+ u.gecos = pwd[:pw_gecos]
213
+ u.dir = pwd[:pw_dir]
214
+ u.shell = pwd[:pw_shell]
215
+ u.expire = Time.at(pwd[:pw_expire])
216
+ end
217
+
218
+ log = get_lastlog_info(user.uid)
219
+
220
+ if log
221
+ user.login_time = Time.at(log[:tv_sec])
222
+ user.login_device = log[:ll_line].to_s
223
+ user.login_host = log[:ll_host].to_s
224
+ end
225
+
226
+ user
227
+ end
228
+
229
+ private_class_method :get_user_from_struct
230
+
231
+ # Gets lastlog information for the given user.
232
+ def self.get_lastlog_info(uid)
233
+ lastlog = LastlogxStruct.new
234
+
235
+ # We don't check for failure here because most will fail due to
236
+ # lack of permissions and/or simple lack of information.
237
+ ptr = getlastlogx(uid, lastlog)
238
+
239
+ ptr.null? ? nil : lastlog
240
+ end
241
+
242
+ private_class_method :get_lastlog_info
243
+ end
244
+ end