sys-admin 1.7.0 → 1.7.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.
@@ -1,261 +1,261 @@
1
- require 'sys/admin/custom'
2
- require 'sys/admin/common'
3
-
4
- # The Solaris specific code.
5
-
6
- module Sys
7
- class Admin
8
- private
9
-
10
- # :no-doc:
11
- BUF_MAX = 65536 # Max buffer size for retry.
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, :size_t], :pointer
19
- attach_function :getpwnam_r, [:string, :pointer, :pointer, :size_t], :pointer
20
- attach_function :getpwuid_r, [:long, :pointer, :pointer, :size_t], :pointer
21
- attach_function :getpwent_r, [:pointer, :pointer, :int], :pointer
22
- attach_function :getgrent_r, [:pointer, :pointer, :int], :pointer
23
- attach_function :getgrnam_r, [:string, :pointer, :pointer, :int], :pointer
24
- attach_function :getgrgid_r, [:long, :pointer, :pointer, :int], :pointer
25
-
26
- private_class_method :getlogin_r, :getpwnam_r, :getpwuid_r, :getpwent_r
27
- private_class_method :getgrent_r, :getgrnam_r, :getgrgid_r
28
- private_class_method :open_c, :pread_c, :close_c
29
-
30
- # struct passwd from /usr/include/pwd.h
31
- class PasswdStruct < FFI::Struct
32
- layout(
33
- :pw_name, :string,
34
- :pw_passwd, :string,
35
- :pw_uid, :uint,
36
- :pw_gid, :uint,
37
- :pw_age, :string,
38
- :pw_comment, :string,
39
- :pw_gecos, :string,
40
- :pw_dir, :string,
41
- :pw_shell, :string
42
- )
43
- end
44
-
45
- # struct group from /usr/include/grp.h
46
- class GroupStruct < FFI::Struct
47
- layout(
48
- :gr_name, :string,
49
- :gr_passwd, :string,
50
- :gr_gid, :uint,
51
- :gr_mem, :pointer
52
- )
53
- end
54
-
55
- # I'm blending the timeval struct in directly here
56
- class LastlogStruct < FFI::Struct
57
- layout(
58
- :ll_time, :uint,
59
- :ll_line, [:char, 32],
60
- :ll_host, [:char, 256]
61
- )
62
- end
63
-
64
- public
65
-
66
- # Returns the login for the current process.
67
- #
68
- def self.get_login
69
- buf = FFI::MemoryPointer.new(:char, 256)
70
-
71
- ptr = getlogin_r(buf, buf.size)
72
-
73
- if ptr.null?
74
- raise Error, "getlogin_r function failed: " + strerror(FFI.errno)
75
- end
76
-
77
- buf.read_string
78
- end
79
-
80
- # Returns a User object for the given name or uid. Raises an error
81
- # if a user cannot be found.
82
- #
83
- # Examples:
84
- #
85
- # Sys::Admin.get_user('joe')
86
- # Sys::Admin.get_user(501)
87
- #
88
- def self.get_user(uid)
89
- buf = FFI::MemoryPointer.new(:char, 1024)
90
- temp = PasswdStruct.new
91
-
92
- if uid.is_a?(String)
93
- ptr = getpwnam_r(uid, temp, buf, buf.size)
94
- else
95
- ptr = getpwuid_r(uid, temp, buf, buf.size)
96
- end
97
-
98
- if ptr.null?
99
- raise Error, "getpwnam_r or getpwuid_r function failed: " + strerror(FFI.errno)
100
- end
101
-
102
- pwd = PasswdStruct.new(ptr)
103
- get_user_from_struct(pwd)
104
- end
105
-
106
- # Returns a Group object for the given name or uid. Raises an error
107
- # if a group cannot be found.
108
- #
109
- # Examples:
110
- #
111
- # Sys::Admin.get_group('admin')
112
- # Sys::Admin.get_group(101)
113
- #
114
- def self.get_group(gid)
115
- size = 1024
116
- buf = FFI::MemoryPointer.new(:char, size)
117
- temp = GroupStruct.new
118
-
119
- begin
120
- if gid.is_a?(String)
121
- ptr = getgrnam_r(gid, temp, buf, buf.size)
122
- fun = 'getgrnam_r'
123
- else
124
- ptr = getgrgid_r(gid, temp, buf, buf.size)
125
- fun = 'getgrgid_r'
126
- end
127
-
128
- # SunOS distinguishes between a failed function call and a
129
- # group that isn't found.
130
-
131
- if ptr.null?
132
- if FFI.errno > 0
133
- raise SystemCallError.new(fun, FFI.errno)
134
- else
135
- raise Error, "group '#{gid}' not found"
136
- end
137
- end
138
- rescue Errno::ERANGE
139
- size += 1024
140
- raise if size > BUF_MAX
141
- buf = FFI::MemoryPointer.new(:char, size)
142
- retry
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
- def self.users
152
- users = []
153
-
154
- buf = FFI::MemoryPointer.new(:char, 1024)
155
- temp = PasswdStruct.new
156
-
157
- begin
158
- setpwent()
159
-
160
- while !(ptr = getpwent_r(temp, buf, buf.size)).null?
161
- break if ptr.null?
162
-
163
- pwd = PasswdStruct.new(ptr)
164
- users << get_user_from_struct(pwd)
165
- end
166
- ensure
167
- endpwent()
168
- end
169
-
170
- users
171
- end
172
-
173
- # Returns an array of Group objects for each user on the system.
174
- #
175
- def self.groups
176
- groups = []
177
-
178
- buf = FFI::MemoryPointer.new(:char, 1024)
179
- temp = GroupStruct.new
180
-
181
- begin
182
- setgrent()
183
-
184
- while !(ptr = getgrent_r(temp, buf, buf.size)).null?
185
- break if ptr.null?
186
-
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
- private
198
-
199
- # Takes a GroupStruct and converts it to a Group object.
200
- def self.get_group_from_struct(grp)
201
- Group.new do |g|
202
- g.name = grp[:gr_name]
203
- g.passwd = grp[:gr_passwd]
204
- g.gid = grp[:gr_gid]
205
- g.members = grp[:gr_mem].read_array_of_string
206
- end
207
- end
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.gecos = pwd[:pw_gecos]
217
- u.dir = pwd[:pw_dir]
218
- u.shell = pwd[:pw_shell]
219
- end
220
-
221
- log = get_lastlog_info(user.uid)
222
-
223
- if log
224
- login_device = log[:ll_line].to_s
225
- login_host = log[:ll_host].to_s
226
-
227
- user.login_time = Time.at(log[:ll_time]) if log[:ll_time] > 0
228
- user.login_device = login_device unless login_device.empty?
229
- user.login_host = login_host unless login_host.empty?
230
- end
231
-
232
- user
233
- end
234
-
235
- # The use of pread was necessary here because it's a sparse file. Note
236
- # also that while Solaris supports the getuserattr function, it doesn't
237
- # appear to store anything regarding login information.
238
- #
239
- def self.get_lastlog_info(uid)
240
- logfile = '/var/adm/lastlog'
241
- lastlog = LastlogStruct.new
242
-
243
- begin
244
- fd = open_c(logfile, File::RDONLY)
245
-
246
- if fd != -1
247
- bytes = pread_c(fd, lastlog, lastlog.size, uid * lastlog.size)
248
- if bytes < 0
249
- raise Error, "pread function failed: " + strerror(FFI.errno)
250
- end
251
- else
252
- nil # Ignore, improper permissions
253
- end
254
- ensure
255
- close_c(fd) if fd && fd >= 0
256
- end
257
-
258
- lastlog
259
- end
260
- end
261
- end
1
+ require 'sys/admin/custom'
2
+ require 'sys/admin/common'
3
+
4
+ # The Solaris specific code.
5
+
6
+ module Sys
7
+ class Admin
8
+ private
9
+
10
+ # :no-doc:
11
+ BUF_MAX = 65536 # Max buffer size for retry.
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, :size_t], :pointer
19
+ attach_function :getpwnam_r, [:string, :pointer, :pointer, :size_t], :pointer
20
+ attach_function :getpwuid_r, [:long, :pointer, :pointer, :size_t], :pointer
21
+ attach_function :getpwent_r, [:pointer, :pointer, :int], :pointer
22
+ attach_function :getgrent_r, [:pointer, :pointer, :int], :pointer
23
+ attach_function :getgrnam_r, [:string, :pointer, :pointer, :int], :pointer
24
+ attach_function :getgrgid_r, [:long, :pointer, :pointer, :int], :pointer
25
+
26
+ private_class_method :getlogin_r, :getpwnam_r, :getpwuid_r, :getpwent_r
27
+ private_class_method :getgrent_r, :getgrnam_r, :getgrgid_r
28
+ private_class_method :open_c, :pread_c, :close_c
29
+
30
+ # struct passwd from /usr/include/pwd.h
31
+ class PasswdStruct < FFI::Struct
32
+ layout(
33
+ :pw_name, :string,
34
+ :pw_passwd, :string,
35
+ :pw_uid, :uint,
36
+ :pw_gid, :uint,
37
+ :pw_age, :string,
38
+ :pw_comment, :string,
39
+ :pw_gecos, :string,
40
+ :pw_dir, :string,
41
+ :pw_shell, :string
42
+ )
43
+ end
44
+
45
+ # struct group from /usr/include/grp.h
46
+ class GroupStruct < FFI::Struct
47
+ layout(
48
+ :gr_name, :string,
49
+ :gr_passwd, :string,
50
+ :gr_gid, :uint,
51
+ :gr_mem, :pointer
52
+ )
53
+ end
54
+
55
+ # I'm blending the timeval struct in directly here
56
+ class LastlogStruct < FFI::Struct
57
+ layout(
58
+ :ll_time, :uint,
59
+ :ll_line, [:char, 32],
60
+ :ll_host, [:char, 256]
61
+ )
62
+ end
63
+
64
+ public
65
+
66
+ # Returns the login for the current process.
67
+ #
68
+ def self.get_login
69
+ buf = FFI::MemoryPointer.new(:char, 256)
70
+
71
+ ptr = getlogin_r(buf, buf.size)
72
+
73
+ if ptr.null?
74
+ raise Error, "getlogin_r function failed: " + strerror(FFI.errno)
75
+ end
76
+
77
+ buf.read_string
78
+ end
79
+
80
+ # Returns a User object for the given name or uid. Raises an error
81
+ # if a user cannot be found.
82
+ #
83
+ # Examples:
84
+ #
85
+ # Sys::Admin.get_user('joe')
86
+ # Sys::Admin.get_user(501)
87
+ #
88
+ def self.get_user(uid)
89
+ buf = FFI::MemoryPointer.new(:char, 1024)
90
+ temp = PasswdStruct.new
91
+
92
+ if uid.is_a?(String)
93
+ ptr = getpwnam_r(uid, temp, buf, buf.size)
94
+ else
95
+ ptr = getpwuid_r(uid, temp, buf, buf.size)
96
+ end
97
+
98
+ if ptr.null?
99
+ raise Error, "getpwnam_r or getpwuid_r function failed: " + strerror(FFI.errno)
100
+ end
101
+
102
+ pwd = PasswdStruct.new(ptr)
103
+ get_user_from_struct(pwd)
104
+ end
105
+
106
+ # Returns a Group object for the given name or uid. Raises an error
107
+ # if a group cannot be found.
108
+ #
109
+ # Examples:
110
+ #
111
+ # Sys::Admin.get_group('admin')
112
+ # Sys::Admin.get_group(101)
113
+ #
114
+ def self.get_group(gid)
115
+ size = 1024
116
+ buf = FFI::MemoryPointer.new(:char, size)
117
+ temp = GroupStruct.new
118
+
119
+ begin
120
+ if gid.is_a?(String)
121
+ ptr = getgrnam_r(gid, temp, buf, buf.size)
122
+ fun = 'getgrnam_r'
123
+ else
124
+ ptr = getgrgid_r(gid, temp, buf, buf.size)
125
+ fun = 'getgrgid_r'
126
+ end
127
+
128
+ # SunOS distinguishes between a failed function call and a
129
+ # group that isn't found.
130
+
131
+ if ptr.null?
132
+ if FFI.errno > 0
133
+ raise SystemCallError.new(fun, FFI.errno)
134
+ else
135
+ raise Error, "group '#{gid}' not found"
136
+ end
137
+ end
138
+ rescue Errno::ERANGE
139
+ size += 1024
140
+ raise if size > BUF_MAX
141
+ buf = FFI::MemoryPointer.new(:char, size)
142
+ retry
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
+ def self.users
152
+ users = []
153
+
154
+ buf = FFI::MemoryPointer.new(:char, 1024)
155
+ temp = PasswdStruct.new
156
+
157
+ begin
158
+ setpwent()
159
+
160
+ while !(ptr = getpwent_r(temp, buf, buf.size)).null?
161
+ break if ptr.null?
162
+
163
+ pwd = PasswdStruct.new(ptr)
164
+ users << get_user_from_struct(pwd)
165
+ end
166
+ ensure
167
+ endpwent()
168
+ end
169
+
170
+ users
171
+ end
172
+
173
+ # Returns an array of Group objects for each user on the system.
174
+ #
175
+ def self.groups
176
+ groups = []
177
+
178
+ buf = FFI::MemoryPointer.new(:char, 1024)
179
+ temp = GroupStruct.new
180
+
181
+ begin
182
+ setgrent()
183
+
184
+ while !(ptr = getgrent_r(temp, buf, buf.size)).null?
185
+ break if ptr.null?
186
+
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
+ private
198
+
199
+ # Takes a GroupStruct and converts it to a Group object.
200
+ def self.get_group_from_struct(grp)
201
+ Group.new do |g|
202
+ g.name = grp[:gr_name]
203
+ g.passwd = grp[:gr_passwd]
204
+ g.gid = grp[:gr_gid]
205
+ g.members = grp[:gr_mem].read_array_of_string
206
+ end
207
+ end
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.gecos = pwd[:pw_gecos]
217
+ u.dir = pwd[:pw_dir]
218
+ u.shell = pwd[:pw_shell]
219
+ end
220
+
221
+ log = get_lastlog_info(user.uid)
222
+
223
+ if log
224
+ login_device = log[:ll_line].to_s
225
+ login_host = log[:ll_host].to_s
226
+
227
+ user.login_time = Time.at(log[:ll_time]) if log[:ll_time] > 0
228
+ user.login_device = login_device unless login_device.empty?
229
+ user.login_host = login_host unless login_host.empty?
230
+ end
231
+
232
+ user
233
+ end
234
+
235
+ # The use of pread was necessary here because it's a sparse file. Note
236
+ # also that while Solaris supports the getuserattr function, it doesn't
237
+ # appear to store anything regarding login information.
238
+ #
239
+ def self.get_lastlog_info(uid)
240
+ logfile = '/var/adm/lastlog'
241
+ lastlog = LastlogStruct.new
242
+
243
+ begin
244
+ fd = open_c(logfile, File::RDONLY)
245
+
246
+ if fd != -1
247
+ bytes = pread_c(fd, lastlog, lastlog.size, uid * lastlog.size)
248
+ if bytes < 0
249
+ raise Error, "pread function failed: " + strerror(FFI.errno)
250
+ end
251
+ else
252
+ nil # Ignore, improper permissions
253
+ end
254
+ ensure
255
+ close_c(fd) if fd && fd >= 0
256
+ end
257
+
258
+ lastlog
259
+ end
260
+ end
261
+ end