20
20
#include <caml/fail.h>
21
21
#include <caml/callback.h>
22
22
#include <caml/memory.h>
23
+ #include <caml/threads.h>
24
+ #include <caml/unixsupport.h>
23
25
24
26
#include "unixpwd.h"
25
27
26
-
27
- CAMLprim value
28
- caml_unixpwd_getpwd (value caml_user )
28
+ static CAMLprim value caml_unixpwd_get_ (value caml_user , const char * fname , char * (* f )(const char * ))
29
29
{
30
30
CAMLparam1 (caml_user );
31
- const char * user ;
32
- char * passwd ;
31
+ char * user ;
32
+ char * passwd ;
33
+ int saved_errno ;
33
34
CAMLlocal1 (pw );
34
35
35
- user = String_val (caml_user );
36
- passwd = unixpwd_getpwd (user );
37
- if (passwd == NULL && errno != 0 )
38
- caml_failwith (strerror (errno ));
39
- if (passwd == NULL )
40
- caml_failwith ("unspecified error in caml_unixpwd_getpwd()" );
36
+ user = caml_stat_strdup (String_val (caml_user ));
37
+ caml_enter_blocking_section ();
38
+ errno = 0 ;
39
+ passwd = f (user );
40
+ saved_errno = errno ;
41
+ caml_stat_free (user ); user = NULL ;
42
+ caml_leave_blocking_section ();
43
+ errno = saved_errno ;
44
+
45
+ if (passwd == NULL ) /* errno of 0 will be mapped to `EUNKNOWNERR of 0` */
46
+ uerror (fname , caml_user );
41
47
42
48
pw = caml_copy_string (passwd );
43
49
free (passwd );
44
50
CAMLreturn (pw );
45
51
}
46
52
47
53
CAMLprim value
48
- caml_unixpwd_getspw (value caml_user )
54
+ caml_unixpwd_getpwd (value caml_user )
49
55
{
50
- CAMLparam1 (caml_user );
51
- const char * user ;
52
- char * passwd ;
53
- CAMLlocal1 (pw );
54
-
55
- user = String_val (caml_user );
56
- passwd = unixpwd_getspw (user );
57
- if (passwd == NULL && errno != 0 )
58
- caml_failwith (strerror (errno ));
59
- if (passwd == NULL )
60
- caml_failwith ("unspecified error in caml_unixpwd_getspw()" );
61
-
62
- pw = caml_copy_string (passwd );
63
- free (passwd );
64
- CAMLreturn (pw );
56
+ return caml_unixpwd_get_ (caml_user , "unixpwd_getpwd" , unixpwd_getpwd );
65
57
}
66
58
67
-
59
+ CAMLprim value
60
+ caml_unixpwd_getspw (value caml_user )
61
+ {
62
+ return caml_unixpwd_get_ (caml_user , "unixpwd_getspw" , unixpwd_getspw );
63
+ }
68
64
69
65
CAMLprim value
70
66
caml_unixpwd_get (value caml_user )
71
67
{
72
- CAMLparam1 (caml_user );
73
- const char * user ;
74
- char * passwd ;
75
- CAMLlocal1 (pw );
76
-
77
- user = String_val (caml_user );
78
- passwd = unixpwd_get (user );
79
- if (passwd == NULL && errno != 0 )
80
- caml_failwith (strerror (errno ));
81
- if (passwd == NULL )
82
- caml_failwith ("unspecified error in caml_unixpwd_get()" );
83
-
84
- pw = caml_copy_string (passwd );
85
- free (passwd );
86
- CAMLreturn (pw );
68
+ return caml_unixpwd_get_ (caml_user , "unixpwd_get" , unixpwd_get );
87
69
}
88
70
89
- CAMLprim value
90
- caml_unixpwd_setpwd (value caml_user , value caml_password )
71
+ static CAMLprim value caml_unixpwd_set_ (value caml_user , value caml_password , const char * fname , int (* f )(const char * , char * ))
91
72
{
92
73
CAMLparam2 (caml_user , caml_password );
93
- const char * user ;
94
- char * password ;
95
- int rc ;
74
+ char * user ;
75
+ char * password ;
76
+ int saved_errno ;
77
+ int rc ;
96
78
97
- user = String_val (caml_user );
79
+ user = caml_stat_strdup ( String_val (caml_user ) );
98
80
password = caml_stat_strdup (String_val (caml_password ));
99
- rc = unixpwd_setpwd (user , password );
81
+ caml_enter_blocking_section ();
82
+ errno = 0 ;
83
+ rc = f (user , password );
84
+ saved_errno = errno ;
85
+ caml_stat_free (user );
100
86
caml_stat_free (password );
87
+ caml_leave_blocking_section ();
88
+ errno = saved_errno ;
89
+
101
90
if (rc != 0 )
102
- caml_failwith ( strerror ( rc ));
91
+ uerror ( fname , caml_user ); /* only raise with user not pass */
103
92
CAMLreturn (Val_unit );
104
93
}
105
94
106
95
CAMLprim value
107
- caml_unixpwd_setspw (value caml_user , value caml_password )
96
+ caml_unixpwd_setpwd (value caml_user , value caml_password )
108
97
{
109
- CAMLparam2 (caml_user , caml_password );
110
- const char * user ;
111
- char * password ;
112
- int rc ;
98
+ return caml_unixpwd_set_ (caml_user , caml_password , "unix_setpwd" ,
99
+ unixpwd_setpwd );
100
+ }
113
101
114
- user = String_val (caml_user );
115
- password = caml_stat_strdup (String_val (caml_password ));
116
- rc = unixpwd_setspw (user , password );
117
- caml_stat_free (password );
118
- if (rc != 0 )
119
- caml_failwith (strerror (rc ));
120
- CAMLreturn (Val_unit );
102
+ CAMLprim value
103
+ caml_unixpwd_setspw (value caml_user , value caml_password )
104
+ {
105
+ return caml_unixpwd_set_ (caml_user , caml_password , "unix_setpwd" ,
106
+ unixpwd_setspw );
121
107
}
122
108
123
109
CAMLprim value
@@ -127,11 +113,11 @@ caml_unixpwd_unshadow(value unused)
127
113
char * passwords ;
128
114
CAMLlocal1 (str );
129
115
116
+ /* NOT thread safe, retain runtime lock for now, it uses setpwent/endpwent,
117
+ * this should be replaced by fopen/fpwgetent_r/etc. */
130
118
passwords = unixpwd_unshadow ();
131
- if (passwords == NULL && errno != 0 )
132
- caml_failwith (strerror (errno ));
133
119
if (passwords == NULL )
134
- caml_failwith ( "unspecified error in caml_unixpwd_unshadow()" );
120
+ uerror ( "unixpwd_unshadow" , Nothing );
135
121
136
122
str = caml_copy_string (passwords );
137
123
free (passwords );
0 commit comments