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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/CHANGES.md +204 -0
- data/Gemfile +2 -0
- data/LICENSE +177 -0
- data/MANIFEST.md +20 -0
- data/README.md +162 -0
- data/Rakefile +44 -0
- data/certs/djberg96_pub.pem +26 -0
- data/doc/sys-admin-unix.txt +162 -0
- data/doc/sys-admin-windows.txt +346 -0
- data/examples/example_groups.rb +27 -0
- data/examples/example_users.rb +41 -0
- data/lib/bsd/sys/admin.rb +262 -0
- data/lib/darwin/sys/admin.rb +244 -0
- data/lib/linux/sys/admin.rb +272 -0
- data/lib/sunos/sys/admin.rb +268 -0
- data/lib/sys/admin/common.rb +134 -0
- data/lib/sys/admin/custom.rb +16 -0
- data/lib/sys/admin.rb +24 -0
- data/lib/sys-admin.rb +1 -0
- data/lib/unix/sys/admin.rb +165 -0
- data/lib/windows/sys/admin.rb +1018 -0
- data/spec/sys_admin_unix_spec.rb +262 -0
- data/spec/sys_admin_windows_spec.rb +350 -0
- data/sys-admin.gemspec +44 -0
- data.tar.gz.sig +0 -0
- metadata +162 -0
- metadata.gz.sig +0 -0
@@ -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
|