sys-admin 1.3.1 → 1.4.0

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