1 ! Copyright (C) 2008 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien alien.c-types alien.data alien.strings
4 assocs byte-arrays classes.struct combinators
5 combinators.short-circuit continuations fry io.encodings.utf8
6 kernel math math.parser namespaces sequences splitting strings
7 unix unix.ffi unix.users unix.utilities ;
12 TUPLE: group id name passwd members ;
16 GENERIC: group-struct ( obj -- group/f )
20 : group-members ( group-struct -- seq )
21 gr_mem>> utf8 alien>strings ;
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* <ref> ;
27 : check-group-struct ( group-struct ptr -- group-struct/f )
28 void* deref [ drop f ] unless ;
30 M: integer group-struct ( id -- group/f )
32 [ [ unix.ffi:getgrgid_r ] unix-system-call drop ] keep
35 M: string group-struct ( string -- group/f )
37 [ [ unix.ffi:getgrnam_r ] unix-system-call drop ] keep
40 : group-struct>group ( group-struct -- group )
44 [ gr_passwd>> >>passwd ]
46 [ group-members >>members ]
51 : group-name ( id -- string )
53 ?at [ name>> ] [ number>string ] if
55 group-struct [ gr_name>> ] [ f ] if*
57 [ nip ] [ number>string ] if* ;
59 : group-id ( string -- id/f )
60 group-struct dup [ gr_gid>> ] when ;
62 ERROR: no-group string ;
64 : ?group-id ( string -- id )
65 dup group-struct [ nip gr_gid>> ] [ throw-no-group ] if* ;
69 : >groups ( byte-array n -- groups )
70 [ 4 grouping:group ] dip head-slice [ uint deref group-name ] map ;
72 : (user-groups) ( string -- seq )
74 gid>> 64 [ 4 * <byte-array> ] keep
75 int <ref> [ [ unix.ffi:getgrouplist ] unix-system-call drop ] 2keep
83 GENERIC: user-groups ( string/id -- seq )
85 M: string user-groups ( string -- seq )
88 M: integer user-groups ( id -- seq )
89 user-name (user-groups) ;
91 : all-groups ( -- seq )
92 [ unix.ffi:getgrent dup ] [ group-struct>group ] produce nip
95 : all-group-names ( -- seq )
96 all-groups [ name>> ] map ;
98 : <group-cache> ( -- assoc )
99 all-groups [ [ id>> ] keep ] H{ } map>assoc ;
101 : with-group-cache ( quot -- )
102 [ <group-cache> group-cache ] dip with-variable ; inline
104 : real-group-id ( -- id ) unix.ffi:getgid ; inline
106 : real-group-name ( -- string ) real-group-id group-name ; inline
108 : effective-group-id ( -- string ) unix.ffi:getegid ; inline
110 : effective-group-name ( -- string )
111 effective-group-id group-name ; inline
113 : group-exists? ( name/id -- ? ) group-id >boolean ;
115 GENERIC: set-real-group ( obj -- )
117 GENERIC: set-effective-group ( obj -- )
119 : (with-real-group) ( string/id quot -- )
120 '[ _ set-real-group @ ]
121 real-group-id '[ _ set-real-group ] [ ] cleanup ; inline
123 : with-real-group ( string/id/f quot -- )
124 over [ (with-real-group) ] [ nip call ] if ; inline
126 : (with-effective-group) ( string/id quot -- )
127 '[ _ set-effective-group @ ]
128 effective-group-id '[ _ set-effective-group ] [ ] cleanup ; inline
130 : with-effective-group ( string/id/f quot -- )
131 over [ (with-effective-group) ] [ nip call ] if ; inline
135 : (set-real-group) ( id -- )
136 [ unix.ffi:setgid ] unix-system-call drop ; inline
138 : (set-effective-group) ( id -- )
139 [ unix.ffi:setegid ] unix-system-call drop ; inline
143 M: integer set-real-group ( id -- )
146 M: string set-real-group ( string -- )
147 ?group-id (set-real-group) ;
149 M: integer set-effective-group ( id -- )
150 (set-effective-group) ;
152 M: string set-effective-group ( string -- )
153 ?group-id (set-effective-group) ;