etcutils 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,189 @@
1
+ #include "extconf.h"
2
+ #include "ruby.h"
3
+ #include <errno.h>
4
+
5
+
6
+ #define EUVERSION "0.1.5"
7
+
8
+ #ifdef HAVE_RUBY_IO_H
9
+ #include "ruby/io.h"
10
+ #define RTIME_VAL(x) (x)
11
+ #else
12
+ #include "rubyio.h"
13
+ #define RTIME_VAL(x) (x.tv_sec)
14
+ #endif
15
+
16
+ #ifdef HAVE_SHADOW_H
17
+ #include <shadow.h>
18
+ #ifndef SHADOW
19
+ #define SHADOW "/etc/shadow"
20
+ #endif
21
+ #define PW_DEFAULT_PASS setup_safe_str("x")
22
+ #else
23
+ #define PW_DEFAULT_PASS setup_safe_str("*")
24
+ #endif
25
+
26
+ #ifdef HAVE_PWD_H
27
+ #include <pwd.h>
28
+ #ifndef PASSWD
29
+ #define PASSWD "/etc/passwd"
30
+ #endif
31
+ #endif
32
+
33
+ #ifdef HAVE_GSHADOW_H
34
+ #include <gshadow.h>
35
+ #elif defined(HAVE_GSHADOW__H)
36
+ #include <gshadow_.h>
37
+ #define HAVE_GSHADOW_H 1
38
+ #endif
39
+
40
+ #ifdef HAVE_GSHADOW_H
41
+ #ifndef GSHADOW
42
+ #define GSHADOW "/etc/gshadow"
43
+ #endif
44
+ #endif
45
+
46
+ #ifdef HAVE_GRP_H
47
+ #include <grp.h>
48
+ #ifndef GROUP
49
+ #define GROUP "/etc/group"
50
+ #endif
51
+ #endif
52
+
53
+ #ifndef DEFAULT_SHELL
54
+ #define DEFAULT_SHELL "/bin/bash"
55
+ #endif
56
+
57
+ #ifdef HAVE_ST_SG_NAMP
58
+ #define SGRP_NAME(s) (s)->sg_namp
59
+ #else
60
+ #define SGRP_NAME(s) (s)->sg_name
61
+ #endif
62
+
63
+ #ifndef HAVE_EACCESS
64
+ extern int eaccess(const char*, int);
65
+ #endif
66
+
67
+ #ifdef HAVE_STRUCT_RB_IO_T_PATHV
68
+ #define RFILE_PATH(x) (RFILE(x)->fptr)->pathv
69
+ #else
70
+ #define RFILE_PATH(x) ( setup_safe_str( (RFILE(x)->fptr)->path ) )
71
+ #endif
72
+
73
+ #ifdef HAVE_RB_IO_STDIO_FILE
74
+ #define RFILE_FPTR(x) rb_io_stdio_file( RFILE(x)->fptr )
75
+ #else
76
+ #define RFILE_FPTR(x) (RFILE(x)->fptr)->f
77
+ #endif
78
+
79
+ #ifndef RSTRING_BLANK_P
80
+ #define RSTRING_BLANK_P(x) (NIL_P(x) || (RSTRING_LEN(x) <= 0))
81
+ #endif
82
+
83
+ #ifndef UIDT2NUM
84
+ #define UIDT2NUM(v) LONG2NUM(v)
85
+ #endif
86
+ #ifndef NUM2UIDT
87
+ #define NUM2UIDT(v) NUM2LONG(v)
88
+ #endif
89
+ #ifndef GIDT2NUM
90
+ #define GIDT2NUM(v) LONG2NUM(v)
91
+ #endif
92
+ #ifndef NUM2GIDT
93
+ #define NUM2GIDT(v) NUM2LONG(v)
94
+ #endif
95
+
96
+ #ifndef INT2QFIX
97
+ #define INT2QFIX(v) (v >= 0 ? INT2FIX(v) : Qnil)
98
+ #endif
99
+ #ifndef UINT2QFIX
100
+ #define UINT2QFIX(v) INT2QFIX( (int)v )
101
+ #endif
102
+
103
+ #ifndef QFIX2INT
104
+ #define QFIX2INT(v) (RTEST(v) ? FIX2INT(v) : (long)-1 )
105
+ #endif
106
+ #ifndef QFIX2ULONG
107
+ #define QFIX2ULONG(v) (RTEST(v) ? FIX2ULONG(v) : (unsigned long)-1)
108
+ #endif
109
+
110
+ extern ID id_name, id_passwd, id_uid, id_gid;
111
+ extern VALUE mEtcUtils;
112
+
113
+ extern VALUE rb_cPasswd;
114
+ extern VALUE rb_cShadow;
115
+ extern VALUE rb_cGroup;
116
+ extern VALUE rb_cGshadow;
117
+
118
+ /* EU helper functions */
119
+ extern VALUE next_uid( int argc, VALUE *argv, VALUE self);
120
+ extern VALUE next_gid( int argc, VALUE *argv, VALUE self);
121
+ extern VALUE iv_get_time(VALUE self, const char *name);
122
+ extern VALUE iv_set_time(VALUE self, VALUE v, const char *name);
123
+ extern VALUE rb_current_time();
124
+ extern void eu_errno(VALUE str);
125
+ extern void ensure_file(VALUE io);
126
+ extern void ensure_writes(VALUE io, int t);
127
+ #define Check_Writes(v,t) ensure_writes((VALUE)(io),(int)(t));
128
+ extern void ensure_eu_type(VALUE self, VALUE klass);
129
+ #define Check_EU_Type(v,t) ensure_eu_type((VALUE)(v),(VALUE)(t))
130
+
131
+ extern char** setup_char_members(VALUE ary);
132
+ extern void free_char_members(char ** mem, int c);
133
+
134
+ extern VALUE setup_safe_str(const char *str);
135
+ extern VALUE setup_safe_array(char **arr);
136
+
137
+ #ifdef HAVE_SHADOW_H
138
+ extern VALUE setup_shadow(struct spwd *shadow);
139
+ #endif
140
+ extern VALUE setup_passwd(struct passwd *pwd);
141
+
142
+ extern VALUE setup_group(struct group *grp);
143
+ #if defined(HAVE_GSHADOW_H) || defined(HAVE_GSHADOW__H)
144
+ extern VALUE setup_gshadow(struct sgrp *sgroup);
145
+ #endif
146
+
147
+ extern VALUE eu_to_entry(VALUE self, VALUE(*user_to)(VALUE, VALUE));
148
+
149
+ extern VALUE eu_setpwent(VALUE self);
150
+ extern VALUE eu_setspent(VALUE self);
151
+ extern VALUE eu_setgrent(VALUE self);
152
+ extern VALUE eu_setsgent(VALUE self);
153
+
154
+ extern VALUE eu_endpwent(VALUE self);
155
+ extern VALUE eu_endspent(VALUE self);
156
+ extern VALUE eu_endsgent(VALUE self);
157
+ extern VALUE eu_endgrent(VALUE self);
158
+
159
+ extern VALUE eu_getpwent(VALUE self);
160
+ extern VALUE eu_getspent(VALUE self);
161
+ extern VALUE eu_getgrent(VALUE self);
162
+ extern VALUE eu_getsgent(VALUE self);
163
+
164
+ extern VALUE eu_getpwd(VALUE self, VALUE v);
165
+ extern VALUE eu_getspwd(VALUE self, VALUE v);
166
+ extern VALUE eu_getgrp(VALUE self, VALUE v);
167
+ extern VALUE eu_getsgrp(VALUE self, VALUE v);
168
+
169
+ extern VALUE eu_sgetpwent(VALUE self, VALUE nam);
170
+ extern VALUE eu_sgetspent(VALUE self, VALUE nam);
171
+ extern VALUE eu_sgetgrent(VALUE self, VALUE nam);
172
+ extern VALUE eu_sgetsgent(VALUE self, VALUE nam);
173
+ /* END EU helper functions */
174
+
175
+ /* EU User functions */
176
+ extern VALUE user_putpwent(VALUE self, VALUE io);
177
+ extern VALUE user_putspent(VALUE self, VALUE io);
178
+ /* END EU User functions */
179
+
180
+ /* EU Group functions */
181
+ extern VALUE group_putgrent(VALUE self, VALUE io);
182
+ extern VALUE group_putsgent(VALUE self, VALUE io);
183
+ /* END EU Group functions */
184
+
185
+ extern VALUE rb_ary_uniq_bang(VALUE ary);
186
+
187
+ extern void Init_etcutils_main();
188
+ extern void Init_etcutils_user();
189
+ extern void Init_etcutils_group();
@@ -0,0 +1,51 @@
1
+ #
2
+ # extconf.rb
3
+ #
4
+ # Modified at: <2013/07/04 16:12:45 by dcampbell>
5
+ #
6
+
7
+ require 'mkmf'
8
+
9
+ have_header('ruby/io.h')
10
+ have_struct_member("struct rb_io_t", "pathv", "ruby/io.h")
11
+ have_func('rb_io_stdio_file')
12
+ have_func('eaccess')
13
+
14
+ have_header('etcutils.h')
15
+
16
+ if (have_header('pwd.h') && have_header('grp.h'))
17
+ short_v = ['pw','gr']
18
+
19
+ if have_header('shadow.h')
20
+ short_v << 'sp'
21
+ end
22
+
23
+ ["gshadow.h","gshadow_.h"].each do |h|
24
+ short_v << 'sg'
25
+ if have_header(h)
26
+ nam = "sg_nam"+ (h =~ /_/ ? 'e' : 'p')
27
+ [nam, "sg_passwd", "sg_adm", "sg_mem"].each do |m|
28
+ have_struct_member("struct sgrp", m, h)
29
+ end
30
+ end
31
+ end
32
+
33
+ have_func("lckpwdf")
34
+ have_func("ulckpwdf")
35
+
36
+ short_v.each do |h|
37
+ ["get#{h}ent","sget#{h}ent","fget#{h}ent","put#{h}ent","set#{h}ent","end#{h}ent"].each do |func|
38
+ have_func(func)
39
+ end
40
+ end
41
+ have_struct_member("struct passwd", "pw_change", "pwd.h")
42
+ have_struct_member("struct passwd", "pw_expire", "pwd.h")
43
+ have_struct_member("struct passwd", "pw_class", "pwd.h")
44
+ have_struct_member("struct passwd", "pw_field", "pwd.h")
45
+
46
+
47
+ create_header
48
+ create_makefile("etcutils")
49
+ else
50
+ puts "This system is not managed by passwd/group files.","Exiting"
51
+ end
@@ -0,0 +1,192 @@
1
+ #include "etcutils.h"
2
+ VALUE rb_cGroup, rb_cGshadow;
3
+
4
+ #ifdef HAVE_PUTGRENT
5
+ static VALUE group_gr_put(VALUE self, VALUE io)
6
+ {
7
+ struct group grp;
8
+ VALUE path;
9
+ #ifdef HAVE_FGETGRENT
10
+ struct group *tmp_grp;
11
+ long i = 0;
12
+ #endif
13
+
14
+ Check_EU_Type(self, rb_cGroup);
15
+ Check_Writes(io, FMODE_WRITABLE);
16
+
17
+ path = RFILE_PATH(io);
18
+
19
+ rewind(RFILE_FPTR(io));
20
+ grp.gr_name = RSTRING_PTR(rb_ivar_get(self, id_name));
21
+
22
+ #ifdef HAVE_FGETGRENT
23
+ while ( (tmp_grp = fgetgrent(RFILE_FPTR(io))) )
24
+ if ( !strcmp(tmp_grp->gr_name, grp.gr_name) )
25
+ rb_raise(rb_eArgError, "%s is already mentioned in %s:%ld",
26
+ tmp_grp->gr_name, StringValuePtr(path), ++i );
27
+ #endif
28
+
29
+ grp.gr_passwd = RSTRING_PTR(rb_ivar_get(self, id_passwd));
30
+ grp.gr_gid = NUM2GIDT( rb_ivar_get(self, id_gid) );
31
+ grp.gr_mem = setup_char_members( rb_iv_get(self, "@members") );
32
+
33
+ if ( putgrent(&grp,RFILE_FPTR(io)) )
34
+ eu_errno(RFILE_PATH(io));
35
+
36
+ free_char_members(grp.gr_mem, (int)RARRAY_LEN( rb_iv_get(self, "@members") ));
37
+
38
+ return Qtrue;
39
+ }
40
+ #endif
41
+
42
+ static VALUE group_gr_sprintf(VALUE self)
43
+ {
44
+ VALUE args[5];
45
+ args[0] = setup_safe_str("%s:%s:%s:%s\n");
46
+ args[1] = rb_ivar_get(self, id_name);
47
+ args[2] = rb_ivar_get(self, id_passwd);
48
+ args[3] = rb_ivar_get(self,id_gid);
49
+ args[4] = rb_ary_join((VALUE)rb_iv_get(self, "@members"), (VALUE)setup_safe_str(","));
50
+ return rb_f_sprintf(5, args);
51
+ }
52
+
53
+ VALUE group_putgrent(VALUE self, VALUE io)
54
+ {
55
+ #ifdef HAVE_PUTGRENT
56
+ return group_gr_put(self, io);
57
+ #else
58
+ return group_gr_sprintf(self);
59
+ #endif
60
+ }
61
+
62
+ VALUE group_gr_entry(VALUE self)
63
+ {
64
+ return eu_to_entry(self, group_putgrent);
65
+ }
66
+
67
+ VALUE group_putsgent(VALUE self, VALUE io)
68
+ {
69
+ #ifdef GSHADOW
70
+ struct sgrp sgroup, *tmp_sgrp;
71
+ VALUE path;
72
+ long i = 0;
73
+
74
+ Check_EU_Type(self, rb_cGshadow);
75
+ Check_Writes(io, FMODE_WRITABLE);
76
+
77
+ path = RFILE_PATH(io);
78
+
79
+ rewind(RFILE_FPTR(io));
80
+ SGRP_NAME(&sgroup) = RSTRING_PTR(rb_ivar_get(self, id_name));
81
+
82
+ while ( (tmp_sgrp = fgetsgent(RFILE_FPTR(io))) )
83
+ if ( !strcmp(SGRP_NAME(tmp_sgrp), SGRP_NAME(&sgroup)) )
84
+ rb_raise(rb_eArgError, "%s is already mentioned in %s:%ld",
85
+ RSTRING_PTR(rb_ivar_get(self, id_name)), StringValuePtr(path), ++i );
86
+
87
+ sgroup.sg_passwd = RSTRING_PTR(rb_ivar_get(self, id_passwd));
88
+ sgroup.sg_adm = setup_char_members( rb_iv_get(self,"@admins") );
89
+ sgroup.sg_mem = setup_char_members( rb_iv_get(self, "@members") );
90
+
91
+ if ( putsgent(&sgroup,RFILE_FPTR(io)) )
92
+ eu_errno(RFILE_PATH(io));
93
+
94
+ free_char_members(sgroup.sg_adm, RARRAY_LEN( rb_iv_get(self, "@admins") ));
95
+ free_char_members(sgroup.sg_mem, RARRAY_LEN( rb_iv_get(self, "@members") ));
96
+
97
+ return Qtrue;
98
+ #else
99
+ return Qnil;
100
+ #endif
101
+ }
102
+
103
+ VALUE group_sg_entry(VALUE self)
104
+ {
105
+ return eu_to_entry(self, group_putsgent);
106
+ }
107
+
108
+ VALUE setup_group(struct group *grp)
109
+ {
110
+ VALUE obj;
111
+ if (!grp) errno || (errno = 61); // ENODATA
112
+ eu_errno( setup_safe_str ( "Error setting up Group instance." ) );
113
+
114
+ obj = rb_obj_alloc(rb_cGroup);
115
+
116
+ rb_ivar_set(obj, id_name, setup_safe_str(grp->gr_name));
117
+ rb_ivar_set(obj, id_passwd, setup_safe_str(grp->gr_passwd));
118
+ rb_ivar_set(obj, id_gid, GIDT2NUM(grp->gr_gid));
119
+ rb_iv_set(obj, "@members", setup_safe_array(grp->gr_mem));
120
+
121
+ return obj;
122
+ }
123
+
124
+ #if defined(HAVE_GSHADOW_H) || defined(HAVE_GSHADOW__H)
125
+ VALUE setup_gshadow(struct sgrp *sgroup)
126
+ {
127
+ VALUE obj;
128
+ if (!sgroup) errno || (errno = 61); // ENODATA
129
+ eu_errno( setup_safe_str ( "Error setting up GShadow instance." ) );
130
+
131
+ obj = rb_obj_alloc(rb_cGshadow);
132
+
133
+ rb_ivar_set(obj, id_name, setup_safe_str(SGRP_NAME(sgroup)));
134
+ rb_ivar_set(obj, id_passwd, setup_safe_str(sgroup->sg_passwd));
135
+ rb_iv_set(obj, "@admins", setup_safe_array(sgroup->sg_adm));
136
+ rb_iv_set(obj, "@members", setup_safe_array(sgroup->sg_mem));
137
+ return obj;
138
+ }
139
+ #endif
140
+
141
+ void Init_etcutils_group()
142
+ {
143
+ /* Define-const: Group
144
+ *
145
+ * The struct contains the following members:
146
+ *
147
+ * name::
148
+ * contains the name of the group as a String.
149
+ * passwd::
150
+ * contains the encrypted password as a String. An 'x' is
151
+ * returned if password access to the group is not available; an empty
152
+ * string is returned if no password is needed to obtain membership of
153
+ * the group.
154
+ * gid::
155
+ * contains the group's numeric ID as an integer.
156
+ * mem::
157
+ * is an Array of Strings containing the short login names of the
158
+ * members of the group.
159
+ */
160
+ #ifdef GROUP
161
+ rb_define_attr(rb_cGroup, "name", 1, 1);
162
+ rb_define_attr(rb_cGroup, "passwd", 1, 1);
163
+ rb_define_attr(rb_cGroup, "gid", 1, 1);
164
+ rb_define_attr(rb_cGroup, "members", 1, 1);
165
+
166
+ rb_define_singleton_method(rb_cGroup,"get",eu_getgrent,0);
167
+ rb_define_singleton_method(rb_cGroup,"find",eu_getgrp,1);
168
+ rb_define_singleton_method(rb_cGroup,"parse",eu_sgetgrent,1);
169
+ rb_define_singleton_method(rb_cGroup,"set",eu_setgrent,0);
170
+ rb_define_singleton_method(rb_cGroup,"end",eu_endgrent,0);
171
+ rb_define_singleton_method(rb_cGroup,"each",eu_getgrent,0);
172
+
173
+ rb_define_method(rb_cGroup, "fputs", group_putgrent,1);
174
+ rb_define_method(rb_cGroup, "to_entry", group_gr_entry,0);
175
+ #endif
176
+
177
+ #ifdef GSHADOW
178
+ rb_define_attr(rb_cGshadow, "name", 1, 1);
179
+ rb_define_attr(rb_cGshadow, "passwd", 1, 1);
180
+ rb_define_attr(rb_cGshadow, "admins", 1, 1);
181
+ rb_define_attr(rb_cGshadow, "members", 1, 1);
182
+
183
+ rb_define_singleton_method(rb_cGshadow,"get",eu_getsgent,0);
184
+ rb_define_singleton_method(rb_cGshadow,"find",eu_getsgrp,1); //getsgent, getsguid
185
+ rb_define_singleton_method(rb_cGshadow,"parse",eu_sgetsgent,1);
186
+ rb_define_singleton_method(rb_cGshadow,"set",eu_setsgent,0);
187
+ rb_define_singleton_method(rb_cGshadow,"end",eu_endsgent,0);
188
+ rb_define_singleton_method(rb_cGshadow,"each",eu_getsgent,0);
189
+ rb_define_method(rb_cGshadow, "fputs", group_putsgent, 1);
190
+ rb_define_method(rb_cGshadow, "to_entry", group_sg_entry,0);
191
+ #endif
192
+ }
@@ -0,0 +1,297 @@
1
+ #include "etcutils.h"
2
+
3
+ VALUE rb_cPasswd, rb_cShadow;
4
+ int expire_warned = 0;
5
+
6
+ static VALUE
7
+ user_get_pw_change(VALUE self)
8
+ {
9
+ return iv_get_time(self, "@last_pw_change");
10
+ }
11
+
12
+ static VALUE
13
+ user_set_pw_change(VALUE self, VALUE pw)
14
+ {
15
+ rb_ivar_set(self, id_passwd, pw);
16
+ return iv_set_time(self, rb_current_time(), "@last_pw_change");
17
+ }
18
+
19
+ static VALUE
20
+ user_get_expire(VALUE self)
21
+ {
22
+ return iv_get_time(self, "@expire");
23
+ }
24
+
25
+ static VALUE
26
+ user_set_expire(VALUE self, VALUE v)
27
+ {
28
+ if ((rb_equal(v, INT2FIX(0))) && (expire_warned == 0)) {
29
+ rb_warn("Setting %s#expire to 0 should not be used as it is interpreted as either an account with no expiration, or as an expiration of Jan 1, 1970.", rb_obj_classname(self));
30
+ expire_warned = 1;
31
+ }
32
+
33
+ return iv_set_time(self, v, "@expire");
34
+ }
35
+
36
+ #ifdef HAVE_PUTPWENT
37
+ static VALUE user_pw_put(VALUE self, VALUE io)
38
+ {
39
+ struct passwd pwd;
40
+ VALUE path;
41
+
42
+ #ifdef HAVE_FGETPWENT
43
+ struct passwd *tmp_pwd;
44
+ long i = 0;
45
+ #endif
46
+
47
+ Check_EU_Type(self, rb_cPasswd);
48
+ Check_Writes(io, FMODE_WRITABLE);
49
+
50
+ path = RFILE_PATH(io);
51
+
52
+ rewind(RFILE_FPTR(io));
53
+ pwd.pw_name = RSTRING_PTR(rb_ivar_get(self, id_name));
54
+
55
+ #ifdef HAVE_FGETPWENT
56
+ while ( (tmp_pwd = fgetpwent(RFILE_FPTR(io))) )
57
+ if ( !strcmp(tmp_pwd->pw_name, pwd.pw_name) )
58
+ rb_raise(rb_eArgError, "%s is already mentioned in %s:%ld",
59
+ tmp_pwd->pw_name, StringValuePtr(path), ++i );
60
+ #endif
61
+
62
+ pwd.pw_passwd = RSTRING_PTR(rb_ivar_get(self, id_passwd));
63
+ pwd.pw_uid = NUM2UIDT( rb_ivar_get(self,id_uid) );
64
+ pwd.pw_gid = NUM2GIDT( rb_ivar_get(self,id_gid) );
65
+ pwd.pw_gecos = RSTRING_PTR(rb_iv_get(self, "@gecos"));
66
+ pwd.pw_dir = RSTRING_PTR(rb_iv_get(self, "@directory"));
67
+ pwd.pw_shell = RSTRING_PTR(rb_iv_get(self, "@shell"));
68
+
69
+ if ( (putpwent(&pwd, RFILE_FPTR(io))) )
70
+ eu_errno(path);
71
+
72
+ return Qtrue;
73
+ }
74
+ #endif
75
+
76
+ static VALUE user_pw_sprintf(VALUE self)
77
+ {
78
+ VALUE args[11];
79
+ args[0] = setup_safe_str("%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n");
80
+ args[1] = rb_ivar_get(self, id_name);
81
+ args[2] = rb_ivar_get(self, id_passwd);
82
+ args[3] = rb_ivar_get(self, id_uid);
83
+ args[4] = rb_ivar_get(self,id_gid);
84
+ args[5] = rb_iv_get(self, "@access_classs");
85
+ args[6] = rb_iv_get(self, "@last_pw_change");
86
+ args[7] = rb_iv_get(self, "@expire");
87
+ args[8] = rb_iv_get(self, "@gecos");
88
+ args[9] = rb_iv_get(self, "@directory");
89
+ args[10] = rb_iv_get(self, "@shell");
90
+ return rb_f_sprintf(11, args);
91
+ }
92
+
93
+ VALUE user_putpwent(VALUE self, VALUE io)
94
+ {
95
+ #ifdef HAVE_PUTPWENT
96
+ return user_pw_put(self, io);
97
+ #else
98
+ return user_pw_sprintf(self);
99
+ #endif
100
+ }
101
+
102
+ VALUE user_pw_entry(VALUE self)
103
+ {
104
+ return eu_to_entry(self, user_putpwent);
105
+ }
106
+
107
+ VALUE user_putspent(VALUE self, VALUE io)
108
+ {
109
+ #ifdef SHADOW
110
+ struct spwd spasswd, *tmp_spwd;
111
+ VALUE path;
112
+ long i;
113
+ errno = 0;
114
+ i = 0;
115
+
116
+ Check_EU_Type(self, rb_cShadow);
117
+ Check_Writes(io, FMODE_WRITABLE);
118
+
119
+ path = RFILE_PATH(io);
120
+
121
+ rewind(RFILE_FPTR(io));
122
+ spasswd.sp_namp = RSTRING_PTR(rb_ivar_get(self, id_name));
123
+
124
+ while ( (tmp_spwd = fgetspent(RFILE_FPTR(io))) )
125
+ if ( !strcmp(tmp_spwd->sp_namp, spasswd.sp_namp) )
126
+ rb_raise(rb_eArgError, "%s is already mentioned in %s:%ld",
127
+ tmp_spwd->sp_namp, StringValuePtr(path), ++i );
128
+
129
+ spasswd.sp_pwdp = RSTRING_PTR(rb_ivar_get(self, id_passwd));
130
+ spasswd.sp_lstchg = FIX2INT( rb_iv_get(self, "@last_pw_change") );
131
+ spasswd.sp_min = FIX2INT( rb_iv_get(self, "@min_pw_age") );
132
+ spasswd.sp_max = FIX2INT( rb_iv_get(self, "@max_pw_age") );
133
+ spasswd.sp_warn = QFIX2INT( rb_iv_get(self, "@warning") );
134
+ spasswd.sp_inact = QFIX2INT( rb_iv_get(self, "@inactive") );
135
+ spasswd.sp_expire = QFIX2INT( rb_iv_get(self, "@expire") );
136
+ spasswd.sp_flag = QFIX2ULONG( rb_iv_get(self, "@flag") );
137
+
138
+ if ( (putspent(&spasswd, RFILE_FPTR(io))) )
139
+ eu_errno(path);
140
+
141
+ return Qtrue;
142
+ #else
143
+ return Qnil;
144
+ #endif
145
+ }
146
+
147
+ VALUE user_sp_entry(VALUE self)
148
+ {
149
+ return eu_to_entry(self, user_putspent);
150
+ }
151
+
152
+ #ifdef SHADOW
153
+ VALUE setup_shadow(struct spwd *spasswd)
154
+ {
155
+ VALUE obj;
156
+ if (!spasswd) errno || (errno = 61); // ENODATA
157
+ eu_errno( setup_safe_str ( "Error setting up Shadow instance." ) );
158
+
159
+ obj = rb_obj_alloc(rb_cShadow);
160
+
161
+ rb_ivar_set(obj, id_name, setup_safe_str(spasswd->sp_namp));
162
+ rb_ivar_set(obj, id_passwd, setup_safe_str(spasswd->sp_pwdp));
163
+
164
+ rb_iv_set(obj, "@last_pw_change", INT2FIX(spasswd->sp_lstchg));
165
+ rb_iv_set(obj, "@min_pw_age", INT2FIX(spasswd->sp_min));
166
+ rb_iv_set(obj, "@max_pw_age", INT2FIX(spasswd->sp_max));
167
+ rb_iv_set(obj, "@warning", INT2QFIX(spasswd->sp_warn));
168
+ rb_iv_set(obj, "@inactive", INT2QFIX(spasswd->sp_inact));
169
+ rb_iv_set(obj, "@expire", INT2QFIX(spasswd->sp_expire));
170
+ rb_iv_set(obj, "@flag", UINT2QFIX(spasswd->sp_flag));
171
+
172
+ return obj;
173
+ }
174
+ #endif
175
+
176
+ VALUE setup_passwd(struct passwd *pwd)
177
+ {
178
+ VALUE obj;
179
+ if (!pwd) errno || (errno = 61); // ENODATA
180
+ eu_errno( setup_safe_str ( "Error setting up Password instance." ) );
181
+
182
+ obj = rb_obj_alloc(rb_cPasswd);
183
+
184
+ rb_ivar_set(obj, id_name, setup_safe_str(pwd->pw_name));
185
+ rb_ivar_set(obj, id_passwd, setup_safe_str(pwd->pw_passwd));
186
+ rb_ivar_set(obj, id_uid, UIDT2NUM(pwd->pw_uid));
187
+ rb_ivar_set(obj, id_gid, GIDT2NUM(pwd->pw_gid));
188
+
189
+ rb_iv_set(obj, "@gecos", setup_safe_str(pwd->pw_gecos));
190
+ rb_iv_set(obj, "@directory", setup_safe_str(pwd->pw_dir));
191
+ rb_iv_set(obj, "@shell", setup_safe_str(pwd->pw_shell));
192
+ #ifdef HAVE_ST_PW_CHANGE
193
+ if (!pwd->pw_change)
194
+ pwd->pw_change = (time_t)0;
195
+ rb_iv_set(obj, "@last_pw_change", INT2FIX(pwd->pw_change));
196
+ #endif
197
+ #ifdef HAVE_ST_PW_EXPIRE
198
+ if (!pwd->pw_expire)
199
+ pwd->pw_expire = (time_t)0;
200
+
201
+ rb_iv_set(obj, "@expire", INT2QFIX(pwd->pw_expire));
202
+ #endif
203
+ #ifdef HAVE_ST_PW_CLASS
204
+ if (pwd->pw_class)
205
+ rb_iv_set(obj, "@access_class", setup_safe_str(pwd->pw_class));
206
+ #endif
207
+
208
+ #ifdef HAVE_ST_PW_FIELD
209
+ if (pwd->pw_field)
210
+ rb_iv_set(obj, "@field", setup_safe_str(pwd->pw_field));
211
+ #endif
212
+
213
+ return obj;
214
+ }
215
+
216
+ void Init_etcutils_user()
217
+ {
218
+
219
+ #ifdef HAVE_PWD_H
220
+ rb_define_attr(rb_cPasswd, "name", 1, 1);
221
+ rb_define_attr(rb_cPasswd, "uid", 1, 1);
222
+ rb_define_attr(rb_cPasswd, "gid", 1, 1);
223
+ rb_define_attr(rb_cPasswd, "gecos", 1, 1);
224
+ rb_define_attr(rb_cPasswd, "directory", 1, 1);
225
+ rb_define_attr(rb_cPasswd, "shell", 1, 1);
226
+
227
+ #ifdef HAVE_ST_PW_CHANGE
228
+ rb_define_attr(rb_cPasswd, "last_pw_change", 1, 0); /* Number expressed as a count of days since Jan 1, 1970
229
+ since the last password change */
230
+ rb_define_method(rb_cPasswd, "last_pw_change_date", user_get_pw_change, 0);
231
+ rb_define_attr(rb_cPasswd, "passwd", 1, 0);
232
+ rb_define_method(rb_cPasswd, "passwd=", user_set_pw_change, 1);
233
+ #else
234
+ rb_define_attr(rb_cPasswd, "passwd", 1, 1);
235
+ #endif
236
+ #ifdef HAVE_ST_PW_EXPIRE
237
+ rb_define_attr(rb_cPasswd, "expire", 1, 0); /* Number expressed as a count of days since Jan 1, 1970
238
+ on which the account will be disabled */
239
+ rb_define_method(rb_cPasswd, "expire=", user_set_expire, 1);
240
+ rb_define_method(rb_cPasswd, "expire_date", user_get_expire, 0);
241
+ rb_define_method(rb_cPasswd, "expire_date=", user_set_expire, 1);
242
+ #endif
243
+
244
+ #ifdef HAVE_ST_PW_CLASS
245
+ rb_define_attr(rb_cPasswd, "access_class", 1, 1);
246
+ #endif
247
+
248
+ #ifdef HAVE_ST_PW_FIELD
249
+ rb_define_attr(rb_cPasswd, "field", 1, 0);
250
+ #endif
251
+
252
+ rb_define_method(rb_cPasswd, "to_entry", user_pw_entry,0);
253
+ rb_define_method(rb_cPasswd, "fputs", user_putpwent, 1);
254
+
255
+ rb_define_singleton_method(rb_cPasswd,"get",eu_getpwent,0);
256
+ rb_define_singleton_method(rb_cPasswd,"each",eu_getpwent,0);
257
+ rb_define_singleton_method(rb_cPasswd,"find",eu_getpwd,1); // -1 return array
258
+ rb_define_singleton_method(rb_cPasswd,"parse",eu_sgetpwent,1);
259
+
260
+
261
+ rb_define_singleton_method(rb_cPasswd,"set", eu_setpwent, 0);
262
+ rb_define_singleton_method(rb_cPasswd,"end", eu_endpwent, 0);
263
+ #endif
264
+
265
+ #ifdef HAVE_SHADOW_H // Shadow specific methods
266
+ rb_define_attr(rb_cShadow, "name", 1, 1); /* Login name. */
267
+ rb_define_attr(rb_cShadow, "passwd", 1, 0); /* Encrypted password. */
268
+ rb_define_attr(rb_cShadow, "min_pw_age", 1, 1); /* Minimum number of days between changes. */
269
+ rb_define_attr(rb_cShadow, "max_pw_age", 1, 1); /* Maximum number of days between changes. */
270
+ rb_define_attr(rb_cShadow, "last_pw_change", 1, 0); /* Number expressed as a count of days since Jan 1, 1970
271
+ since the last password change */
272
+ rb_define_attr(rb_cShadow, "warning", 1, 1); /* Number of days to warn user to change
273
+ the password. */
274
+ rb_define_attr(rb_cShadow, "inactive", 1, 1); /* Number of days after password expires
275
+ that account is considered inactive and disabled */
276
+ rb_define_attr(rb_cShadow, "expire", 1, 0); /* Number expressed as a count of days since Jan 1, 1970
277
+ on which the account will be disabled */
278
+ rb_define_attr(rb_cShadow, "flag", 1, 0); /* Reserved */
279
+
280
+ rb_define_method(rb_cShadow, "passwd=", user_set_pw_change, 1);
281
+ rb_define_method(rb_cShadow, "expire=", user_set_expire, 1);
282
+ rb_define_method(rb_cShadow, "last_pw_change_date", user_get_pw_change, 0);
283
+ rb_define_method(rb_cShadow, "expire_date", user_get_expire, 0);
284
+ rb_define_method(rb_cShadow, "expire_date=", user_set_expire, 1);
285
+
286
+ rb_define_method(rb_cShadow, "to_entry", user_sp_entry,0);
287
+ rb_define_method(rb_cShadow, "fputs", user_putspent, 1);
288
+
289
+ rb_define_singleton_method(rb_cShadow,"get",eu_getspent,0);
290
+ rb_define_singleton_method(rb_cShadow,"each",eu_getspent,0);
291
+ rb_define_singleton_method(rb_cShadow,"find",eu_getspwd,1);
292
+ rb_define_singleton_method(rb_cShadow,"parse",eu_sgetspent,1);
293
+
294
+ rb_define_singleton_method(rb_cShadow,"set", eu_setspent, 0);
295
+ rb_define_singleton_method(rb_cShadow,"end", eu_endspent, 0);
296
+ #endif
297
+ }