]> gitweb.factorcode.org Git - factor.git/blob - basis/unix/groups/groups.factor
117b60d8f599f61e54428eca14567e2240def5bd
[factor.git] / basis / unix / groups / groups.factor
1 ! Copyright (C) 2008 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien alien.c-types alien.strings assocs
4 byte-arrays classes.struct combinators
5 combinators.short-circuit continuations fry io.backend.unix
6 io.encodings.utf8 kernel math math.parser namespaces sequences
7 splitting strings unix unix.ffi unix.users unix.utilities ;
8 QUALIFIED: unix.ffi
9 QUALIFIED: grouping
10 IN: unix.groups
11
12 TUPLE: group id name passwd members ;
13
14 SYMBOL: group-cache
15
16 GENERIC: group-struct ( obj -- group/f )
17
18 <PRIVATE
19
20 : group-members ( group-struct -- seq )
21     gr_mem>> utf8 alien>strings ;
22
23 : (group-struct) ( id -- group-struct id group-struct byte-array length void* )
24     [ \ unix.ffi:group <struct> ] dip over 4096
25     [ <byte-array> ] keep f <void*> ;
26
27 : check-group-struct ( group-struct ptr -- group-struct/f )
28     *void* [ drop f ] unless ;
29
30 M: integer group-struct ( id -- group/f )
31     (group-struct)
32     [ [ unix.ffi:getgrgid_r ] unix-system-call drop ] keep
33     check-group-struct ;
34
35 M: string group-struct ( string -- group/f )
36     (group-struct)
37     [ [ unix.ffi:getgrnam_r ] unix-system-call drop ] keep
38     check-group-struct ;
39
40 : group-struct>group ( group-struct -- group )
41     [ \ group new ] dip
42     {
43         [ gr_name>> >>name ]
44         [ gr_passwd>> >>passwd ]
45         [ gr_gid>> >>id ]
46         [ group-members >>members ]
47     } cleave ;
48
49 PRIVATE>
50
51 : group-name ( id -- string )
52     dup group-cache get [
53         ?at [ name>> ] [ number>string ] if
54     ] [
55         group-struct [ gr_name>> ] [ f ] if*
56     ] if*
57     [ nip ] [ number>string ] if* ;
58
59 : group-id ( string -- id/f )
60     group-struct dup [ gr_gid>> ] when ;
61
62 ERROR: no-group string ;
63
64 : ?group-id ( string -- id )
65     dup group-struct [ nip gr_gid>> ] [ no-group ] if* ;
66
67 <PRIVATE
68
69 : >groups ( byte-array n -- groups )
70     [ 4 grouping:group ] dip head-slice [ uint deref group-name ] map ;
71
72 : (user-groups) ( string -- seq )
73     #! first group is -1337, legacy unix code
74     -1337 unix.ffi:NGROUPS_MAX [ 4 * <byte-array> ] keep
75     int <ref> [ [ unix.ffi:getgrouplist ] unix-system-call drop ] 2keep
76     [ 4 tail-slice ] [ int deref 1 - ] bi* >groups ;
77
78 PRIVATE>
79     
80 GENERIC: user-groups ( string/id -- seq )
81
82 M: string user-groups ( string -- seq )
83     (user-groups) ; 
84
85 M: integer user-groups ( id -- seq )
86     user-name (user-groups) ;
87     
88 : all-groups ( -- seq )
89     [ unix.ffi:getgrent dup ] [ group-struct>group ] produce nip
90     endgrent ;
91
92 : all-group-names ( -- seq )
93     all-groups [ name>> ] map ;
94
95 : <group-cache> ( -- assoc )
96     all-groups [ [ id>> ] keep ] H{ } map>assoc ;
97
98 : with-group-cache ( quot -- )
99     [ <group-cache> group-cache ] dip with-variable ; inline
100
101 : real-group-id ( -- id ) unix.ffi:getgid ; inline
102
103 : real-group-name ( -- string ) real-group-id group-name ; inline
104
105 : effective-group-id ( -- string ) unix.ffi:getegid ; inline
106
107 : effective-group-name ( -- string )
108     effective-group-id group-name ; inline
109
110 : group-exists? ( name/id -- ? ) group-id >boolean ;
111
112 GENERIC: set-real-group ( obj -- )
113
114 GENERIC: set-effective-group ( obj -- )
115
116 : (with-real-group) ( string/id quot -- )
117     '[ _ set-real-group @ ]
118     real-group-id '[ _ set-real-group ] [ ] cleanup ; inline
119
120 : with-real-group ( string/id/f quot -- )
121     over [ (with-real-group) ] [ nip call ] if ; inline
122
123 : (with-effective-group) ( string/id quot -- )
124     '[ _ set-effective-group @ ]
125     effective-group-id '[ _ set-effective-group ] [ ] cleanup ; inline
126
127 : with-effective-group ( string/id/f quot -- )
128     over [ (with-effective-group) ] [ nip call ] if ; inline
129
130 <PRIVATE
131
132 : (set-real-group) ( id -- )
133     [ unix.ffi:setgid ] unix-system-call drop ; inline
134
135 : (set-effective-group) ( id -- )
136     [ unix.ffi:setegid ] unix-system-call drop ; inline
137
138 PRIVATE>
139     
140 M: integer set-real-group ( id -- )
141     (set-real-group) ;
142
143 M: string set-real-group ( string -- )
144     ?group-id (set-real-group) ;
145
146 M: integer set-effective-group ( id -- )    
147     (set-effective-group) ;
148
149 M: string set-effective-group ( string -- )
150     ?group-id (set-effective-group) ;