sys-admin 1.8.0-universal-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -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