sys-admin 1.5.6 → 1.6.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.
data/ext/sys/admin.h DELETED
@@ -1,515 +0,0 @@
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.5.6"
12
-
13
- #if defined(__MACH__) || defined(__APPLE__)
14
- #define __BSD__
15
- #endif
16
-
17
- #if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
18
- #define __BSD__
19
- #endif
20
-
21
- #if defined(HAVE_USERSEC_H)
22
- #include <usersec.h>
23
- #else
24
- #if defined(HAVE_UTMPX_H) && defined(HAVE_GETLASTLOGX)
25
- #include <utmpx.h>
26
- #else
27
- #ifdef HAVE_LASTLOG_H
28
- #include <lastlog.h>
29
- #else
30
- #include <utmp.h>
31
- #endif
32
- #endif
33
- #endif
34
-
35
- #ifndef _POSIX_LOGIN_NAME_MAX
36
- #define _POSIX_LOGIN_NAME_MAX 9
37
- #endif
38
-
39
- // BSD platforms are problematic with explicit inclusion of unistd.h
40
- #if defined(__BSD__)
41
- #define USER_BUF_SIZE 1024
42
- #else
43
- #ifdef _SC_GETPW_R_SIZE_MAX
44
- #define USER_BUF_SIZE (sysconf(_SC_GETPW_R_SIZE_MAX))
45
- #else
46
- #define USER_BUF_SIZE 1024
47
- #endif
48
- #endif
49
-
50
- // BSD platforms are problematic with explicit inclusion of unistd.h
51
- #if defined(__BSD__)
52
- #define GROUP_BUF_SIZE 7296
53
- #else
54
- #ifdef _SC_GETGR_R_SIZE_MAX
55
- #define GROUP_BUF_SIZE (sysconf(_SC_GETGR_R_SIZE_MAX))
56
- #else
57
- #define GROUP_BUF_SIZE 7296
58
- #endif
59
- #endif
60
-
61
- #ifndef _PATH_LASTLOG
62
- #define _PATH_LASTLOG "/var/adm/lastlog"
63
- #endif
64
-
65
- /* Function prototypes */
66
- static VALUE admin_users_cleanup();
67
- static VALUE admin_groups_cleanup();
68
- static VALUE get_user(struct passwd* p);
69
- static VALUE get_group(struct group* g);
70
- int get_lastlog_info(struct passwd* p, VALUE v_value);
71
-
72
- VALUE cUser, cGroup, cAdminError;
73
-
74
- /*
75
- * :no-doc:
76
- *
77
- * Helper function that returns a User object based on user ID.
78
- */
79
- static VALUE get_user_by_num(VALUE v_uid){
80
- volatile VALUE v_user;
81
- uid_t uid = NUM2INT(v_uid);
82
-
83
- #ifdef HAVE_GETPWUID_R
84
- char buf[USER_BUF_SIZE];
85
- struct passwd pwd;
86
- struct passwd* pwdbuf;
87
-
88
- if(getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwdbuf) != 0)
89
- rb_raise(cAdminError, "%s", strerror(errno));
90
-
91
- if(!pwdbuf)
92
- rb_raise(cAdminError, "no user found for %i:", uid);
93
-
94
- v_user = get_user(pwdbuf);
95
- #elif HAVE_GETPWUID
96
- struct passwd* pwd;
97
- if( (pwd = getpwuid(uid)) == NULL)
98
- rb_raise(cAdminError, "no user found for: %i", uid);
99
-
100
- v_user = get_user(pwd);
101
- #else
102
- rb_raise(rb_eNotImpError, "getting user by user ID not supported");
103
- #endif
104
-
105
- return v_user;
106
- }
107
-
108
- /*
109
- * :no-doc:
110
- *
111
- * Helper function that returns a User object based on name.
112
- */
113
- static VALUE get_user_by_name(VALUE v_name){
114
- volatile VALUE v_user;
115
- SafeStringValue(v_name);
116
-
117
- #ifdef HAVE_GETPWNAM_R
118
- char buf[USER_BUF_SIZE];
119
- struct passwd pwd;
120
- struct passwd* pwdbuf;
121
-
122
- if(getpwnam_r(RSTRING_PTR(v_name), &pwd, buf, sizeof(buf), &pwdbuf) != 0)
123
- rb_raise(cAdminError, "%s", strerror(errno));
124
-
125
- if(!pwdbuf)
126
- rb_raise(cAdminError, "no user found for %s", StringValuePtr(v_name));
127
-
128
- v_user = get_user(pwdbuf);
129
- #elif HAVE_GETPWNAM
130
- struct passwd* pwd;
131
- if( (pwd = getpwnam(RSTRING(v_name)->ptr)) == NULL)
132
- rb_raise(cAdminError, "no user found for %s", StringValuePtr(v_name));
133
-
134
- v_user = get_user(pwd);
135
- #else
136
- rb_raise(rb_eNotImpError, "getting user by name not supported");
137
- #endif
138
-
139
- return v_user;
140
- }
141
-
142
- /*
143
- * :no-doc:
144
- *
145
- * Helper function that returns a Group object based on group ID.
146
- */
147
- static VALUE get_group_by_num(VALUE v_gid){
148
- volatile VALUE v_group;
149
- gid_t gid = NUM2INT(v_gid);
150
-
151
- #ifdef HAVE_GETGRGID_R
152
- char buf[GROUP_BUF_SIZE];
153
- struct group grp;
154
- struct group* grpbuf;
155
-
156
- if(getgrgid_r(gid, &grp, buf, sizeof(buf), &grpbuf) != 0)
157
- rb_raise(cAdminError, "getgrgid_r() failed: %s", strerror(errno));
158
-
159
- if(!grpbuf)
160
- rb_raise(cAdminError, "no group found for group ID: %i", gid);
161
-
162
- v_group = get_group(grpbuf);
163
- #elif HAVE_GETGRGID
164
- struct group* grp;
165
- if( (grp = getgrgid(gid)) == NULL)
166
- rb_raise(cAdminError, "no group found for group ID: %i", gid);
167
-
168
- v_group = get_group(grp);
169
- #else
170
- rb_raise(rb_eNotImpError, "getting group by group ID not supported");
171
- #endif
172
-
173
- return v_group;
174
- }
175
-
176
- /*
177
- * :no-doc:
178
- *
179
- * Helper function that returns a Group object based on group name.
180
- */
181
- static VALUE get_group_by_name(VALUE v_name){
182
- volatile VALUE v_group = Qnil;
183
- SafeStringValue(v_name);
184
- #ifdef HAVE_GETGRNAM_R
185
- char buf[GROUP_BUF_SIZE];
186
- struct group grp;
187
- struct group* grpbuf;
188
-
189
- if(getgrnam_r(RSTRING_PTR(v_name), &grp, buf, sizeof(buf), &grpbuf) != 0)
190
- rb_raise(cAdminError, "%s", strerror(errno));
191
-
192
- if(!grpbuf)
193
- rb_raise(cAdminError, "no group found for: %s", StringValuePtr(v_name));
194
-
195
- v_group = get_group(grpbuf);
196
- #elif HAVE_GETGRNAM
197
- struct group* grp
198
- if((grp = getgrnam(RSTRING(v_name)->ptr)) == NULL)
199
- rb_raise(cAdminError, "no group found for: %s", StringValuePtr(v_name));
200
-
201
- v_group = get_group(grp);
202
- #else
203
- rb_raise(rb_eNotImpError, "get_group is not supported on this platform");
204
- #endif
205
-
206
- return v_group;
207
- }
208
-
209
- /*
210
- * :no-doc:
211
- *
212
- * Helper function that turns a struct passwd into a User object.
213
- */
214
- static VALUE get_user(struct passwd* pwd){
215
- VALUE v_user = rb_funcall(cUser, rb_intern("new"), 0, 0);
216
-
217
- rb_iv_set(v_user, "@name", rb_str_new2(pwd->pw_name));
218
- rb_iv_set(v_user, "@uid", INT2FIX(pwd->pw_uid));
219
- rb_iv_set(v_user, "@gid", INT2FIX(pwd->pw_gid));
220
- rb_iv_set(v_user, "@dir", rb_str_new2(pwd->pw_dir));
221
- rb_iv_set(v_user, "@shell", rb_str_new2(pwd->pw_shell));
222
-
223
- #ifdef HAVE_ST_PW_PASSWD
224
- rb_iv_set(v_user, "@passwd", rb_str_new2(pwd->pw_passwd));
225
- #endif
226
-
227
- /* TODO: Fix this, or just set it to nil */
228
- #ifdef HAVE_ST_PW_AGE
229
- rb_iv_set(v_user, "@age", INT2FIX(pwd->pw_age));
230
- #endif
231
-
232
- #ifdef HAVE_ST_PW_COMMENT
233
- rb_iv_set(v_user, "@comment", rb_str_new2(pwd->pw_comment));
234
- #endif
235
-
236
- #ifdef HAVE_ST_PW_GECOS
237
- rb_iv_set(v_user, "@gecos", rb_str_new2(pwd->pw_gecos));
238
- #endif
239
-
240
- #ifdef HAVE_ST_PW_QUOTA
241
- rb_iv_set(v_user, "@quota", INT2FIX(pwd->pw_quota));
242
- #endif
243
-
244
- #ifdef HAVE_ST_PW_CLASS
245
- rb_iv_set(v_user, "@access_class", rb_str_new2(pwd->pw_class));
246
- #endif
247
-
248
- #ifdef HAVE_ST_PW_EXPIRE
249
- rb_iv_set(v_user, "@expire", rb_time_new(pwd->pw_expire, 0));
250
- #endif
251
-
252
- #ifdef HAVE_ST_PW_CHANGE
253
- rb_iv_set(v_user, "@change", rb_time_new(pwd->pw_change, 0));
254
- #endif
255
-
256
- #if defined(HAVE_LASTLOG_H) || defined(HAVE_UTMP_H) || defined(HAVE_USERSEC_H)
257
- get_lastlog_info(pwd, v_user);
258
- #endif
259
-
260
- return v_user;
261
- }
262
-
263
- /*
264
- * :no-doc:
265
- *
266
- * Helper function that turns a User object into a struct passwd.
267
- */
268
- void get_user_from_value(VALUE v_user, struct passwd* pwd){
269
-
270
- VALUE v_name = rb_iv_get(v_user, "@name");
271
- VALUE v_uid = rb_iv_get(v_user, "@uid");
272
- VALUE v_gid = rb_iv_get(v_user, "@gid");
273
- VALUE v_dir = rb_iv_get(v_user, "@dir");
274
- VALUE v_shell = rb_iv_get(v_user, "@shell");
275
-
276
- if(NIL_P(v_name))
277
- rb_raise(cAdminError, "user name cannot be nil");
278
-
279
- if(!NIL_P(v_uid))
280
- pwd->pw_uid = NUM2INT(v_uid);
281
-
282
- if(!NIL_P(v_gid))
283
- pwd->pw_gid = NUM2INT(v_gid);
284
-
285
- if(!NIL_P(v_dir)){
286
- SafeStringValue(v_dir);
287
- pwd->pw_dir = StringValuePtr(v_dir);
288
- }
289
-
290
- if(!NIL_P(v_shell)){
291
- SafeStringValue(v_shell);
292
- pwd->pw_shell = StringValuePtr(v_shell);
293
- }
294
-
295
- #ifdef HAVE_ST_PW_PASSWD
296
- VALUE v_passwd = rb_iv_get(v_user, "@passwd");
297
- if(!NIL_P(v_passwd)){
298
- SafeStringValue(v_passwd);
299
- pwd->pw_passwd = StringValuePtr(v_passwd);
300
- }
301
- #endif
302
-
303
- /* TODO: Fix this or just set it to nil */
304
- #ifdef HAVE_ST_PW_AGE
305
- VALUE v_age = rb_iv_get(v_user, "@age");
306
- if(!NIL_P(v_age))
307
- pwd->pw_age = (char*)NUM2INT(v_age);
308
- #endif
309
-
310
- #ifdef HAVE_ST_PW_COMMENT
311
- VALUE v_comment = rb_iv_get(v_user, "@comment");
312
- if(!NIL_P(v_comment)){
313
- SafeStringValue(v_comment);
314
- pwd->pw_comment = StringValuePtr(v_comment);
315
- }
316
- #endif
317
-
318
- #ifdef HAVE_ST_PW_GECOS
319
- VALUE v_gecos = rb_iv_get(v_user, "@gecos");
320
- if(!NIL_P(v_gecos)){
321
- SafeStringValue(v_gecos);
322
- pwd->pw_gecos = StringValuePtr(v_gecos);
323
- }
324
- #endif
325
-
326
- #ifdef HAVE_ST_PW_QUOTA
327
- VALUE v_quota = rb_iv_get(v_user, "@quota");
328
- if(!NIL_P(v_quota))
329
- pwd->pw_quota = NUM2INT(v_quota);
330
- #endif
331
-
332
- #ifdef HAVE_ST_PW_CLASS
333
- VALUE v_class = rb_iv_get(v_user, "@access_class");
334
- if(!NIL_P(v_class)){
335
- SafeStringValue(v_class);
336
- pwd->pw_class = StringValuePtr(v_class);
337
- }
338
- #endif
339
-
340
- #ifdef HAVE_ST_PW_EXPIRE
341
- VALUE v_expire = rb_iv_get(v_user, "@expire");
342
- v_expire = rb_funcall(v_expire, rb_intern("to_i"), 0, 0);
343
- if(!NIL_P(v_expire))
344
- pwd->pw_expire = NUM2ULONG(v_expire);
345
- #endif
346
-
347
- #ifdef HAVE_ST_PW_CHANGE
348
- VALUE v_change = rb_iv_get(v_user, "@change");
349
- v_change = rb_funcall(v_change, rb_intern("to_i"), 0, 0);
350
- if(!NIL_P(v_change))
351
- pwd->pw_change = NUM2ULONG(v_change);
352
- #endif
353
-
354
- }
355
-
356
- /*
357
- * :no-doc:
358
- *
359
- * Helper function that turns a struct grp into a Group object.
360
- */
361
- static VALUE get_group(struct group* g){
362
- VALUE v_group = rb_funcall(cGroup,rb_intern("new"),0,0);
363
- VALUE v_array = rb_ary_new();
364
- char **my_gr_mem = g->gr_mem;
365
-
366
- /* Return the members as an Array of Strings */
367
- while(*my_gr_mem){
368
- rb_ary_push(v_array, rb_str_new2(*my_gr_mem));
369
- my_gr_mem++;
370
- }
371
-
372
- rb_iv_set(v_group, "@name", rb_str_new2(g->gr_name));
373
- rb_iv_set(v_group, "@gid", INT2FIX(g->gr_gid));
374
- rb_iv_set(v_group, "@members", v_array);
375
- #ifdef HAVE_ST_GR_PASSWD
376
- rb_iv_set(v_group, "@passwd", rb_str_new2(g->gr_passwd));
377
- #endif
378
-
379
- return v_group;
380
- }
381
-
382
- /*
383
- * :no-doc:
384
- *
385
- * Helper function that turns a Group object into a struct group.
386
- */
387
- void get_group_from_value(VALUE v_group, struct group* grp){
388
- char** members = malloc(sizeof(char*));
389
- VALUE v_name = rb_iv_get(v_group, "@name");
390
- VALUE v_gid = rb_iv_get(v_group, "@gid");
391
- VALUE v_mem = rb_iv_get(v_group, "@members");
392
- VALUE v_passwd = rb_iv_get(v_group, "@passwd");
393
- int i = 0;
394
-
395
- if(NIL_P(v_name))
396
- rb_raise(cAdminError, "group name must be set");
397
-
398
- SafeStringValue(v_name);
399
- grp->gr_name = StringValuePtr(v_name);
400
-
401
- if(!NIL_P(v_gid))
402
- grp->gr_gid = NUM2INT(v_gid);
403
-
404
- if(!NIL_P(v_mem)){
405
- VALUE v_value;
406
- while((v_value = rb_ary_shift(v_mem)) != Qnil){
407
- members[i] = StringValuePtr(v_value);
408
- i++;
409
- }
410
- members[i] = '\0';
411
- grp->gr_mem = members;
412
- }
413
-
414
- #ifdef HAVE_ST_GR_PASSWD
415
- if(!NIL_P(v_passwd)){
416
- SafeStringValue(v_passwd);
417
- grp->gr_passwd = StringValuePtr(v_passwd);
418
- }
419
- #endif
420
-
421
- free(members);
422
- }
423
-
424
- /*
425
- * :no-doc:
426
- *
427
- * Helper function that gets lastlog information for the User object.
428
- *--
429
- * Note that even if the platform supports lastlog information, it can
430
- * still be empty or nil.
431
- */
432
- int get_lastlog_info(struct passwd* pwd, VALUE v_user){
433
- #ifdef HAVE_USERSEC_H
434
- char *lasthost;
435
- int lasttime;
436
- char *lasttty;
437
-
438
- if (setuserdb(S_READ) == -1) {
439
- return -1;
440
- }
441
-
442
- if (getuserattr(pwd->pw_name, S_LASTTIME, &lasttime, SEC_INT) == -1
443
- || getuserattr(pwd->pw_name, S_LASTTTY, &lasttty, SEC_CHAR) == -1
444
- || getuserattr(pwd->pw_name, S_LASTHOST, &lasthost, SEC_CHAR) == -1) {
445
- enduserdb();
446
- return -1;
447
- }
448
-
449
- rb_iv_set(v_user, "@login_time", rb_time_new(lasttime, 0));
450
- rb_iv_set(v_user, "@login_device", rb_str_new2(lasttty));
451
- rb_iv_set(v_user, "@login_host", rb_str_new2(lasthost));
452
- enduserdb();
453
- #else
454
- #ifdef HAVE_GETLASTLOGX
455
- struct lastlogx log;
456
-
457
- if(getlastlogx(pwd->pw_uid, &log)){
458
- rb_iv_set(v_user, "@login_time", rb_time_new(log.ll_tv.tv_sec, log.ll_tv.tv_usec));
459
- rb_iv_set(v_user, "@login_device", rb_str_new2(log.ll_line));
460
- rb_iv_set(v_user, "@login_host", rb_str_new2(log.ll_host));
461
- }
462
- #else
463
- int fd;
464
- ssize_t bytes_read;
465
- struct lastlog log;
466
- int ll_size = sizeof(struct lastlog);
467
-
468
- /* The lastlog information is not necessarily readable by all users, so
469
- * ignore open() errors if they occur.
470
- */
471
- if((fd = open(_PATH_LASTLOG, O_RDONLY)) == -1)
472
- return -1;
473
-
474
- if((bytes_read = pread(fd, &log, ll_size, pwd->pw_uid * ll_size)) < 0){
475
- close(fd);
476
- rb_raise(cAdminError, "%s", strerror(errno));
477
- }
478
-
479
- close(fd);
480
-
481
- if(bytes_read > 0){
482
- #ifdef HAVE_ST_LL_TIME
483
- if(log.ll_time != 0)
484
- rb_iv_set(v_user, "@login_time", rb_time_new(log.ll_time, 0));
485
- #endif
486
- rb_iv_set(v_user, "@login_device", rb_str_new2(log.ll_line));
487
- rb_iv_set(v_user, "@login_host", rb_str_new2(log.ll_host));
488
- }
489
- #endif
490
- #endif
491
-
492
- return 0;
493
- }
494
-
495
- /*
496
- * :no-doc:
497
- *
498
- * This function is used for an rb_ensure() call where we need to make sure
499
- * that endpwent() is called in the block form of Admin.groups.
500
- */
501
- static VALUE admin_groups_cleanup(){
502
- endgrent();
503
- return Qnil;
504
- }
505
-
506
- /*
507
- * :no-doc:
508
- *
509
- * This function is used for an rb_ensure() call where we need to make sure
510
- * that endpwent() is called in the block form of Admin.users.
511
- */
512
- static VALUE admin_users_cleanup(){
513
- endpwent();
514
- return Qnil;
515
- }