etcutils 1.0.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,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
+ }