sys-admin 1.7.0 → 1.7.1

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