sys-admin 1.3.1 → 1.4.0

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,428 @@
1
+ #include <limits.h>
2
+ #include <stdlib.h>
3
+ #include <stdio.h>
4
+ #include <unistd.h>
5
+ #include <pwd.h>
6
+ #include <grp.h>
7
+ #include <fcntl.h>
8
+ #include <errno.h>
9
+ #include <string.h>
10
+
11
+ #define SYS_ADMIN_VERSION "1.4.0"
12
+
13
+ #ifdef HAVE_LASTLOG_H
14
+ #include <lastlog.h>
15
+ #else
16
+ #include <utmp.h>
17
+ #endif
18
+
19
+ #ifndef _POSIX_LOGIN_NAME_MAX
20
+ #define _POSIX_LOGIN_NAME_MAX 9
21
+ #endif
22
+
23
+ #ifdef _SC_GETPW_R_SIZE_MAX
24
+ #define USER_BUF_SIZE (sysconf(_SC_GETPW_R_SIZE_MAX))
25
+ #else
26
+ #define USER_BUF_SIZE 1024
27
+ #endif
28
+
29
+ #ifdef _SC_GETGR_R_SIZE_MAX
30
+ #define GROUP_BUF_SIZE (sysconf(_SC_GETGR_R_SIZE_MAX))
31
+ #else
32
+ #define GROUP_BUF_SIZE 7296
33
+ #endif
34
+
35
+ #ifndef _PATH_LASTLOG
36
+ #define _PATH_LASTLOG "/var/adm/lastlog"
37
+ #endif
38
+
39
+ /* Function prototypes */
40
+ static VALUE get_user(struct passwd* p);
41
+ static VALUE get_group(struct group* g);
42
+ int get_lastlog_info(struct passwd* p, VALUE v_value);
43
+
44
+ VALUE cUser, cGroup, cAdminError;
45
+
46
+ /*
47
+ * :no-doc:
48
+ *
49
+ * Helper function that returns a User object based on user ID.
50
+ */
51
+ static VALUE get_user_by_num(VALUE v_uid){
52
+ VALUE v_user;
53
+ uid_t uid = NUM2INT(v_uid);
54
+
55
+ #ifdef HAVE_GETPWUID_R
56
+ char buf[USER_BUF_SIZE];
57
+ struct passwd pwd;
58
+ struct passwd* pwdbuf;
59
+
60
+ if(getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwdbuf) != 0)
61
+ rb_raise(cAdminError, "%s", strerror(errno));
62
+
63
+ if(!pwdbuf)
64
+ rb_raise(cAdminError, "no user found for %i:", uid);
65
+
66
+ v_user = get_user(pwdbuf);
67
+ #elif HAVE_GETPWUID
68
+ struct passwd* pwd;
69
+ if( (pwd = getpwuid(uid)) == NULL)
70
+ rb_raise(cAdminError, "no user found for: %i", uid);
71
+
72
+ v_user = get_user(pwd);
73
+ #else
74
+ rb_raise(rb_eNotImpError, "getting user by user ID not supported");
75
+ #endif
76
+
77
+ return v_user;
78
+ }
79
+
80
+ /*
81
+ * :no-doc:
82
+ *
83
+ * Helper function that returns a User object based on name.
84
+ */
85
+ static VALUE get_user_by_name(VALUE v_name){
86
+ VALUE v_user;
87
+ SafeStringValue(v_name);
88
+
89
+ #ifdef HAVE_GETPWNAM_R
90
+ char buf[USER_BUF_SIZE];
91
+ struct passwd pwd;
92
+ struct passwd* pwdbuf;
93
+
94
+ if(getpwnam_r(RSTRING(v_name)->ptr, &pwd, buf, sizeof(buf), &pwdbuf) != 0)
95
+ rb_raise(cAdminError, "%s", strerror(errno));
96
+
97
+ if(!pwdbuf)
98
+ rb_raise(cAdminError, "no user found for %s", StringValuePtr(v_name));
99
+
100
+ v_user = get_user(pwdbuf);
101
+ #elif HAVE_GETPWNAM
102
+ struct passwd* pwd;
103
+ if( (pwd = getpwnam(RSTRING(v_name)->ptr)) == NULL)
104
+ rb_raise(cAdminError, "no user found for %s", StringValuePtr(v_name));
105
+
106
+ v_user = get_user(pwd);
107
+ #else
108
+ rb_raise(rb_eNotImpError, "getting user by name not supported");
109
+ #endif
110
+
111
+ return v_user;
112
+ }
113
+
114
+ /*
115
+ * :no-doc:
116
+ *
117
+ * Helper function that returns a Group object based on group ID.
118
+ */
119
+ static VALUE get_group_by_num(VALUE v_gid){
120
+ VALUE v_group;
121
+ gid_t gid = NUM2INT(v_gid);
122
+
123
+ #ifdef HAVE_GETGRGID_R
124
+ char buf[GROUP_BUF_SIZE];
125
+ struct group grp;
126
+ struct group* grpbuf;
127
+
128
+ if(getgrgid_r(gid, &grp, buf, sizeof(buf), &grpbuf) != 0)
129
+ rb_raise(cAdminError, "%s", strerror(errno));
130
+
131
+ if(!grpbuf)
132
+ rb_raise(cAdminError, "no group found for group ID: %i", gid);
133
+
134
+ v_group = get_group(grpbuf);
135
+ #elif HAVE_GETGRGID
136
+ struct group* grp;
137
+ if( (grp = getgrgid(gid)) == NULL)
138
+ rb_raise(cAdminError, "no group found for group ID: %i", gid);
139
+
140
+ v_group = get_group(grp);
141
+ #else
142
+ rb_raise(rb_eNotImpError, "getting group by group ID not supported");
143
+ #endif
144
+
145
+ return v_group;
146
+ }
147
+
148
+ /*
149
+ * :no-doc:
150
+ *
151
+ * Helper function that returns a Group object based on group name.
152
+ */
153
+ static VALUE get_group_by_name(VALUE v_name){
154
+ VALUE v_group = Qnil;
155
+ SafeStringValue(v_name);
156
+ #ifdef HAVE_GETGRNAM_R
157
+ char buf[GROUP_BUF_SIZE];
158
+ struct group grp;
159
+ struct group* grpbuf;
160
+
161
+ if(getgrnam_r(RSTRING(v_name)->ptr, &grp, buf, sizeof(buf), &grpbuf) != 0)
162
+ rb_raise(cAdminError, "%s", strerror(errno));
163
+
164
+ if(!grpbuf)
165
+ rb_raise(cAdminError, "no group found for: %s", StringValuePtr(v_name));
166
+
167
+ v_group = get_group(grpbuf);
168
+ #elif HAVE_GETGRNAM
169
+ struct group* grp
170
+ if((grp = getgrnam(RSTRING(v_name)->ptr)) == NULL)
171
+ rb_raise(cAdminError, "no group found for: %s", StringValuePtr(v_name));
172
+
173
+ v_group = get_group(grp);
174
+ #else
175
+ rb_raise(rb_eNotImpError,"get_group is not supported on this platform");
176
+ #endif
177
+
178
+ return v_group;
179
+ }
180
+
181
+ /*
182
+ * :no-doc:
183
+ *
184
+ * Helper function that turns a struct passwd into a User object.
185
+ */
186
+ static VALUE get_user(struct passwd* pwd){
187
+ VALUE v_user = rb_funcall(cUser, rb_intern("new"), 0, 0);
188
+
189
+ rb_iv_set(v_user, "@name", rb_str_new2(pwd->pw_name));
190
+ rb_iv_set(v_user, "@uid", INT2FIX(pwd->pw_uid));
191
+ rb_iv_set(v_user, "@gid", INT2FIX(pwd->pw_gid));
192
+ rb_iv_set(v_user, "@dir", rb_str_new2(pwd->pw_dir));
193
+ rb_iv_set(v_user, "@shell", rb_str_new2(pwd->pw_shell));
194
+
195
+ #ifdef HAVE_ST_PW_PASSWD
196
+ rb_iv_set(v_user, "@passwd", rb_str_new2(pwd->pw_passwd));
197
+ #endif
198
+
199
+ /* TODO: Fix this, or just set it to nil */
200
+ #ifdef HAVE_ST_PW_AGE
201
+ rb_iv_set(v_user, "@age", INT2FIX(pwd->pw_age));
202
+ #endif
203
+
204
+ #ifdef HAVE_ST_PW_COMMENT
205
+ rb_iv_set(v_user, "@comment", rb_str_new2(pwd->pw_comment));
206
+ #endif
207
+
208
+ #ifdef HAVE_ST_PW_GECOS
209
+ rb_iv_set(v_user, "@gecos", rb_str_new2(pwd->pw_gecos));
210
+ #endif
211
+
212
+ #ifdef HAVE_ST_PW_QUOTA
213
+ rb_iv_set(v_user, "@quota", INT2FIX(pwd->pw_quota));
214
+ #endif
215
+
216
+ #ifdef HAVE_ST_PW_CLASS
217
+ rb_iv_set(v_user, "@class", rb_str_new2(pwd->pw_class));
218
+ #endif
219
+
220
+ #ifdef HAVE_ST_PW_EXPIRE
221
+ rb_iv_set(v_user, "@expire", rb_time_new(pwd->pw_expire, 0));
222
+ #endif
223
+
224
+ #ifdef HAVE_ST_PW_CHANGE
225
+ rb_iv_set(v_user, "@change", rb_time_new(pwd->pw_change, 0));
226
+ #endif
227
+
228
+ /* Get the lastlog info for the given user */
229
+ get_lastlog_info(pwd, v_user);
230
+
231
+ return v_user;
232
+ }
233
+
234
+ /*
235
+ * :no-doc:
236
+ *
237
+ * Helper function that turns a User object into a struct passwd.
238
+ */
239
+ void get_user_from_value(VALUE v_user, struct passwd* pwd){
240
+
241
+ VALUE v_name = rb_iv_get(v_user, "@name");
242
+ VALUE v_uid = rb_iv_get(v_user, "@uid");
243
+ VALUE v_gid = rb_iv_get(v_user, "@gid");
244
+ VALUE v_dir = rb_iv_get(v_user, "@dir");
245
+ VALUE v_shell = rb_iv_get(v_user, "@shell");
246
+
247
+ if(NIL_P(v_name))
248
+ rb_raise(cAdminError, "user name cannot be nil");
249
+
250
+ if(!NIL_P(v_uid))
251
+ pwd->pw_uid = NUM2INT(v_uid);
252
+
253
+ if(!NIL_P(v_gid))
254
+ pwd->pw_gid = NUM2INT(v_gid);
255
+
256
+ if(!NIL_P(v_dir)){
257
+ SafeStringValue(v_dir);
258
+ pwd->pw_dir = StringValuePtr(v_dir);
259
+ }
260
+
261
+ if(!NIL_P(v_shell)){
262
+ SafeStringValue(v_shell);
263
+ pwd->pw_shell = StringValuePtr(v_shell);
264
+ }
265
+
266
+ #ifdef HAVE_ST_PW_PASSWD
267
+ VALUE v_passwd = rb_iv_get(v_user, "@passwd");
268
+ if(!NIL_P(v_passwd)){
269
+ SafeStringValue(v_passwd);
270
+ pwd->pw_passwd = StringValuePtr(v_passwd);
271
+ }
272
+ #endif
273
+
274
+ /* TODO: Fix this or just set it to nil */
275
+ #ifdef HAVE_ST_PW_AGE
276
+ VALUE v_age = rb_iv_get(v_user, "@age");
277
+ if(!NIL_P(v_age))
278
+ pwd->pw_age = (char*)NUM2INT(v_age);
279
+ #endif
280
+
281
+ #ifdef HAVE_ST_PW_COMMENT
282
+ VALUE v_comment = rb_iv_get(v_user, "@comment");
283
+ if(!NIL_P(v_comment)){
284
+ SafeStringValue(v_comment);
285
+ pwd->pw_comment = StringValuePtr(v_comment);
286
+ }
287
+ #endif
288
+
289
+ #ifdef HAVE_ST_PW_GECOS
290
+ VALUE v_gecos = rb_iv_get(v_user, "@gecos");
291
+ if(!NIL_P(v_gecos)){
292
+ SafeStringValue(v_gecos);
293
+ pwd->pw_gecos = StringValuePtr(v_gecos);
294
+ }
295
+ #endif
296
+
297
+ #ifdef HAVE_ST_PW_QUOTA
298
+ VALUE v_quota = rb_iv_get(v_user, "@quota");
299
+ if(!NIL_P(v_quota))
300
+ pwd->pw_quota = NUM2INT(v_quota);
301
+ #endif
302
+
303
+ #ifdef HAVE_ST_PW_CLASS
304
+ VALUE v_class = rb_iv_get(v_user, "@class");
305
+ if(!NIL_P(v_class)){
306
+ SafeStringValue(v_class);
307
+ pwd->pw_class = StringValuePtr(v_class);
308
+ }
309
+ #endif
310
+
311
+ #ifdef HAVE_ST_PW_EXPIRE
312
+ VALUE v_expire = rb_iv_get(v_user, "@expire");
313
+ v_expire = rb_funcall(v_expire, rb_intern("to_i"), 0, 0);
314
+ if(!NIL_P(v_expire))
315
+ pwd->pw_expire = NUM2ULONG(v_expire);
316
+ #endif
317
+
318
+ #ifdef HAVE_ST_PW_CHANGE
319
+ VALUE v_change = rb_iv_get(v_user, "@change");
320
+ v_change = rb_funcall(v_change, rb_intern("to_i"), 0, 0);
321
+ if(!NIL_P(v_change))
322
+ pwd->pw_change = NUM2ULONG(v_change);
323
+ #endif
324
+
325
+ }
326
+
327
+ /*
328
+ * :no-doc:
329
+ *
330
+ * Helper function that turns a struct grp into a Group object.
331
+ */
332
+ static VALUE get_group(struct group* g){
333
+ VALUE v_group = rb_funcall(cGroup,rb_intern("new"),0,0);
334
+ VALUE v_array = rb_ary_new();
335
+
336
+ /* Return the members as an Array of Strings */
337
+ while(*g->gr_mem){
338
+ rb_ary_push(v_array, rb_str_new2(*g->gr_mem));
339
+ g->gr_mem++;
340
+ }
341
+
342
+ rb_iv_set(v_group, "@name", rb_str_new2(g->gr_name));
343
+ rb_iv_set(v_group, "@gid", INT2FIX(g->gr_gid));
344
+ rb_iv_set(v_group, "@members", v_array);
345
+ #ifdef HAVE_ST_GR_PASSWD
346
+ rb_iv_set(v_group, "@passwd", rb_str_new2(g->gr_passwd));
347
+ #endif
348
+
349
+ return v_group;
350
+ }
351
+
352
+ /*
353
+ * :no-doc:
354
+ *
355
+ * Helper function that turns a Group object into a struct group.
356
+ */
357
+ void get_group_from_value(VALUE v_group, struct group* grp){
358
+ char** members = malloc(sizeof(char*));
359
+ VALUE v_name = rb_iv_get(v_group, "@name");
360
+ VALUE v_gid = rb_iv_get(v_group, "@gid");
361
+ VALUE v_mem = rb_iv_get(v_group, "@members");
362
+ VALUE v_passwd = rb_iv_get(v_group, "@passwd");
363
+ int i = 0;
364
+
365
+ if(NIL_P(v_name))
366
+ rb_raise(cAdminError, "group name must be set");
367
+
368
+ SafeStringValue(v_name);
369
+ grp->gr_name = StringValuePtr(v_name);
370
+
371
+ if(!NIL_P(v_gid))
372
+ grp->gr_gid = NUM2INT(v_gid);
373
+
374
+ if(!NIL_P(v_mem)){
375
+ VALUE v_value;
376
+ while((v_value = rb_ary_shift(v_mem)) != Qnil){
377
+ members[i] = StringValuePtr(v_value);
378
+ i++;
379
+ }
380
+ members[i] = '\0';
381
+ grp->gr_mem = members;
382
+ }
383
+
384
+ #ifdef HAVE_ST_GR_PASSWD
385
+ if(!NIL_P(v_passwd)){
386
+ SafeStringValue(v_passwd);
387
+ grp->gr_passwd = StringValuePtr(v_passwd);
388
+ }
389
+ #endif
390
+
391
+ free(members);
392
+ }
393
+
394
+ /*
395
+ * :no-doc:
396
+ *
397
+ * Helper function that gets lastlog information for the User object.
398
+ */
399
+ int get_lastlog_info(struct passwd* pwd, VALUE v_user){
400
+ int fd;
401
+ ssize_t bytes_read;
402
+ struct lastlog log;
403
+ int ll_size = sizeof(struct lastlog);
404
+
405
+ /* The lastlog information is not necessarily readable by all users, so
406
+ * ignore open() errors if they occur.
407
+ */
408
+ if((fd = open(_PATH_LASTLOG, O_RDONLY)) == -1)
409
+ return -1;
410
+
411
+ if((bytes_read = pread(fd, &log, ll_size, pwd->pw_uid * ll_size)) < 0){
412
+ close(fd);
413
+ rb_raise(cAdminError, "%s", strerror(errno));
414
+ }
415
+
416
+ close(fd);
417
+
418
+ if(bytes_read > 0){
419
+ #ifdef HAVE_ST_LL_TIME
420
+ if(log.ll_time != 0)
421
+ rb_iv_set(v_user, "@login_time", rb_time_new(log.ll_time, 0));
422
+ #endif
423
+ rb_iv_set(v_user, "@login_device", rb_str_new2(log.ll_line));
424
+ rb_iv_set(v_user, "@login_host", rb_str_new2(log.ll_host));
425
+ }
426
+
427
+ return 0;
428
+ }
@@ -1,13 +1,12 @@
1
1
  require "mkmf"
2
- require "ftools"
3
2
 
4
- if PLATFORM.match('mswin')
3
+ if RUBY_PLATFORM.match('mswin')
5
4
  STDERR.puts "Use the install.rb file on Win32 systems."
6
5
  STDERR.puts "Exiting. The sys-admin package was NOT installed."
7
6
  exit
8
7
  else
9
- File.move("lib/sys/win32.rb", "lib/sys/win32.orig") rescue nil # Don't install
10
-
8
+ dir_config('admin')
9
+
11
10
  have_func("getlogin_r")
12
11
  have_func("getlogin")
13
12
  have_func("getenv")
@@ -51,12 +50,9 @@ else
51
50
  end
52
51
 
53
52
  $CFLAGS += " -D_POSIX_PTHREAD_SEMANTICS"
54
- if PLATFORM.match("linux")
53
+ if RUBY_PLATFORM.match("linux")
55
54
  $CFLAGS += " -D_GNU_SOURCE -D_REENTRANT"
56
55
  end
57
-
58
- File.copy("lib/sys/unix.c", "admin.c")
59
- File.copy("lib/sys/unix.h", "admin.h")
60
56
  end
61
57
 
62
58
  create_makefile("sys/admin")