Blame


1 6f4d00ee 2013-09-23 0intro #include "stdinc.h"
2 6f4d00ee 2013-09-23 0intro
3 6f4d00ee 2013-09-23 0intro #include "9.h"
4 6f4d00ee 2013-09-23 0intro
5 6f4d00ee 2013-09-23 0intro enum {
6 6f4d00ee 2013-09-23 0intro NUserHash = 1009,
7 6f4d00ee 2013-09-23 0intro };
8 6f4d00ee 2013-09-23 0intro
9 6f4d00ee 2013-09-23 0intro typedef struct Ubox Ubox;
10 6f4d00ee 2013-09-23 0intro typedef struct User User;
11 6f4d00ee 2013-09-23 0intro
12 6f4d00ee 2013-09-23 0intro struct User {
13 6f4d00ee 2013-09-23 0intro char* uid;
14 6f4d00ee 2013-09-23 0intro char* uname;
15 6f4d00ee 2013-09-23 0intro char* leader;
16 6f4d00ee 2013-09-23 0intro char** group;
17 6f4d00ee 2013-09-23 0intro int ngroup;
18 6f4d00ee 2013-09-23 0intro
19 6f4d00ee 2013-09-23 0intro User* next; /* */
20 6f4d00ee 2013-09-23 0intro User* ihash; /* lookup by .uid */
21 6f4d00ee 2013-09-23 0intro User* nhash; /* lookup by .uname */
22 6f4d00ee 2013-09-23 0intro };
23 6f4d00ee 2013-09-23 0intro
24 6f4d00ee 2013-09-23 0intro #pragma varargck type "U" User*
25 6f4d00ee 2013-09-23 0intro
26 6f4d00ee 2013-09-23 0intro struct Ubox {
27 6f4d00ee 2013-09-23 0intro User* head;
28 6f4d00ee 2013-09-23 0intro User* tail;
29 6f4d00ee 2013-09-23 0intro int nuser;
30 6f4d00ee 2013-09-23 0intro int len;
31 6f4d00ee 2013-09-23 0intro
32 6f4d00ee 2013-09-23 0intro User* ihash[NUserHash]; /* lookup by .uid */
33 6f4d00ee 2013-09-23 0intro User* nhash[NUserHash]; /* lookup by .uname */
34 6f4d00ee 2013-09-23 0intro };
35 6f4d00ee 2013-09-23 0intro
36 6f4d00ee 2013-09-23 0intro static struct {
37 4b576658 2013-09-23 0intro RWLock lock;
38 6f4d00ee 2013-09-23 0intro
39 6f4d00ee 2013-09-23 0intro Ubox* box;
40 6f4d00ee 2013-09-23 0intro } ubox;
41 6f4d00ee 2013-09-23 0intro
42 6f4d00ee 2013-09-23 0intro static char usersDefault[] = {
43 6f4d00ee 2013-09-23 0intro "adm:adm:adm:sys\n"
44 6f4d00ee 2013-09-23 0intro "none:none::\n"
45 6f4d00ee 2013-09-23 0intro "noworld:noworld::\n"
46 6f4d00ee 2013-09-23 0intro "sys:sys::glenda\n"
47 6f4d00ee 2013-09-23 0intro "glenda:glenda:glenda:\n"
48 6f4d00ee 2013-09-23 0intro };
49 6f4d00ee 2013-09-23 0intro
50 6f4d00ee 2013-09-23 0intro static char* usersMandatory[] = {
51 6f4d00ee 2013-09-23 0intro "adm",
52 6f4d00ee 2013-09-23 0intro "none",
53 6f4d00ee 2013-09-23 0intro "noworld",
54 6f4d00ee 2013-09-23 0intro "sys",
55 6f4d00ee 2013-09-23 0intro nil,
56 6f4d00ee 2013-09-23 0intro };
57 6f4d00ee 2013-09-23 0intro
58 6f4d00ee 2013-09-23 0intro char* uidadm = "adm";
59 6f4d00ee 2013-09-23 0intro char* unamenone = "none";
60 6f4d00ee 2013-09-23 0intro char* uidnoworld = "noworld";
61 6f4d00ee 2013-09-23 0intro
62 6f4d00ee 2013-09-23 0intro static u32int
63 6f4d00ee 2013-09-23 0intro userHash(char* s)
64 6f4d00ee 2013-09-23 0intro {
65 6f4d00ee 2013-09-23 0intro uchar *p;
66 6f4d00ee 2013-09-23 0intro u32int hash;
67 6f4d00ee 2013-09-23 0intro
68 6f4d00ee 2013-09-23 0intro hash = 0;
69 6f4d00ee 2013-09-23 0intro for(p = (uchar*)s; *p != '\0'; p++)
70 6f4d00ee 2013-09-23 0intro hash = hash*7 + *p;
71 6f4d00ee 2013-09-23 0intro
72 6f4d00ee 2013-09-23 0intro return hash % NUserHash;
73 6f4d00ee 2013-09-23 0intro }
74 6f4d00ee 2013-09-23 0intro
75 6f4d00ee 2013-09-23 0intro static User*
76 6f4d00ee 2013-09-23 0intro _userByUid(Ubox* box, char* uid)
77 6f4d00ee 2013-09-23 0intro {
78 6f4d00ee 2013-09-23 0intro User *u;
79 6f4d00ee 2013-09-23 0intro
80 6f4d00ee 2013-09-23 0intro if(box != nil){
81 6f4d00ee 2013-09-23 0intro for(u = box->ihash[userHash(uid)]; u != nil; u = u->ihash){
82 6f4d00ee 2013-09-23 0intro if(strcmp(u->uid, uid) == 0)
83 6f4d00ee 2013-09-23 0intro return u;
84 6f4d00ee 2013-09-23 0intro }
85 6f4d00ee 2013-09-23 0intro }
86 4b576658 2013-09-23 0intro werrstr("uname: uid '%s' not found", uid);
87 6f4d00ee 2013-09-23 0intro return nil;
88 6f4d00ee 2013-09-23 0intro }
89 6f4d00ee 2013-09-23 0intro
90 6f4d00ee 2013-09-23 0intro char*
91 6f4d00ee 2013-09-23 0intro unameByUid(char* uid)
92 6f4d00ee 2013-09-23 0intro {
93 6f4d00ee 2013-09-23 0intro User *u;
94 6f4d00ee 2013-09-23 0intro char *uname;
95 6f4d00ee 2013-09-23 0intro
96 4b576658 2013-09-23 0intro rlock(&ubox.lock);
97 6f4d00ee 2013-09-23 0intro if((u = _userByUid(ubox.box, uid)) == nil){
98 4b576658 2013-09-23 0intro runlock(&ubox.lock);
99 6f4d00ee 2013-09-23 0intro return nil;
100 6f4d00ee 2013-09-23 0intro }
101 4b576658 2013-09-23 0intro uname = vtstrdup(u->uname);
102 4b576658 2013-09-23 0intro runlock(&ubox.lock);
103 6f4d00ee 2013-09-23 0intro
104 6f4d00ee 2013-09-23 0intro return uname;
105 6f4d00ee 2013-09-23 0intro }
106 6f4d00ee 2013-09-23 0intro
107 6f4d00ee 2013-09-23 0intro static User*
108 6f4d00ee 2013-09-23 0intro _userByUname(Ubox* box, char* uname)
109 6f4d00ee 2013-09-23 0intro {
110 6f4d00ee 2013-09-23 0intro User *u;
111 6f4d00ee 2013-09-23 0intro
112 6f4d00ee 2013-09-23 0intro if(box != nil){
113 6f4d00ee 2013-09-23 0intro for(u = box->nhash[userHash(uname)]; u != nil; u = u->nhash){
114 6f4d00ee 2013-09-23 0intro if(strcmp(u->uname, uname) == 0)
115 6f4d00ee 2013-09-23 0intro return u;
116 6f4d00ee 2013-09-23 0intro }
117 6f4d00ee 2013-09-23 0intro }
118 4b576658 2013-09-23 0intro werrstr("uname: uname '%s' not found", uname);
119 6f4d00ee 2013-09-23 0intro return nil;
120 6f4d00ee 2013-09-23 0intro }
121 6f4d00ee 2013-09-23 0intro
122 6f4d00ee 2013-09-23 0intro char*
123 6f4d00ee 2013-09-23 0intro uidByUname(char* uname)
124 6f4d00ee 2013-09-23 0intro {
125 6f4d00ee 2013-09-23 0intro User *u;
126 6f4d00ee 2013-09-23 0intro char *uid;
127 6f4d00ee 2013-09-23 0intro
128 4b576658 2013-09-23 0intro rlock(&ubox.lock);
129 6f4d00ee 2013-09-23 0intro if((u = _userByUname(ubox.box, uname)) == nil){
130 4b576658 2013-09-23 0intro runlock(&ubox.lock);
131 6f4d00ee 2013-09-23 0intro return nil;
132 6f4d00ee 2013-09-23 0intro }
133 4b576658 2013-09-23 0intro uid = vtstrdup(u->uid);
134 4b576658 2013-09-23 0intro runlock(&ubox.lock);
135 6f4d00ee 2013-09-23 0intro
136 6f4d00ee 2013-09-23 0intro return uid;
137 6f4d00ee 2013-09-23 0intro }
138 6f4d00ee 2013-09-23 0intro
139 6f4d00ee 2013-09-23 0intro static int
140 6f4d00ee 2013-09-23 0intro _groupMember(Ubox* box, char* group, char* member, int whenNoGroup)
141 6f4d00ee 2013-09-23 0intro {
142 6f4d00ee 2013-09-23 0intro int i;
143 6f4d00ee 2013-09-23 0intro User *g, *m;
144 6f4d00ee 2013-09-23 0intro
145 6f4d00ee 2013-09-23 0intro /*
146 6f4d00ee 2013-09-23 0intro * Is 'member' a member of 'group'?
147 6f4d00ee 2013-09-23 0intro * Note that 'group' is a 'uid' and not a 'uname'.
148 6f4d00ee 2013-09-23 0intro * A 'member' is automatically in their own group.
149 6f4d00ee 2013-09-23 0intro */
150 6f4d00ee 2013-09-23 0intro if((g = _userByUid(box, group)) == nil)
151 6f4d00ee 2013-09-23 0intro return whenNoGroup;
152 6f4d00ee 2013-09-23 0intro if((m = _userByUname(box, member)) == nil)
153 6f4d00ee 2013-09-23 0intro return 0;
154 6f4d00ee 2013-09-23 0intro if(m == g)
155 6f4d00ee 2013-09-23 0intro return 1;
156 6f4d00ee 2013-09-23 0intro for(i = 0; i < g->ngroup; i++){
157 6f4d00ee 2013-09-23 0intro if(strcmp(g->group[i], member) == 0)
158 6f4d00ee 2013-09-23 0intro return 1;
159 6f4d00ee 2013-09-23 0intro }
160 6f4d00ee 2013-09-23 0intro return 0;
161 6f4d00ee 2013-09-23 0intro }
162 6f4d00ee 2013-09-23 0intro
163 6f4d00ee 2013-09-23 0intro int
164 6f4d00ee 2013-09-23 0intro groupWriteMember(char* uname)
165 6f4d00ee 2013-09-23 0intro {
166 6f4d00ee 2013-09-23 0intro int ret;
167 6f4d00ee 2013-09-23 0intro
168 6f4d00ee 2013-09-23 0intro /*
169 6f4d00ee 2013-09-23 0intro * If there is a ``write'' group, then only its members can write
170 6f4d00ee 2013-09-23 0intro * to the file system, no matter what the permission bits say.
171 6f4d00ee 2013-09-23 0intro *
172 6f4d00ee 2013-09-23 0intro * To users not in the ``write'' group, the file system appears
173 6f4d00ee 2013-09-23 0intro * read only. This is used to serve sources.cs.bell-labs.com
174 6f4d00ee 2013-09-23 0intro * to the world.
175 6f4d00ee 2013-09-23 0intro *
176 6f4d00ee 2013-09-23 0intro * Note that if there is no ``write'' group, then this routine
177 6f4d00ee 2013-09-23 0intro * makes it look like everyone is a member -- the opposite
178 6f4d00ee 2013-09-23 0intro * of what groupMember does.
179 6f4d00ee 2013-09-23 0intro *
180 6f4d00ee 2013-09-23 0intro * We use this for sources.cs.bell-labs.com.
181 6f4d00ee 2013-09-23 0intro * If this slows things down too much on systems that don't
182 6f4d00ee 2013-09-23 0intro * use this functionality, we could cache the write group lookup.
183 6f4d00ee 2013-09-23 0intro */
184 6f4d00ee 2013-09-23 0intro
185 4b576658 2013-09-23 0intro rlock(&ubox.lock);
186 6f4d00ee 2013-09-23 0intro ret = _groupMember(ubox.box, "write", uname, 1);
187 4b576658 2013-09-23 0intro runlock(&ubox.lock);
188 6f4d00ee 2013-09-23 0intro return ret;
189 6f4d00ee 2013-09-23 0intro }
190 6f4d00ee 2013-09-23 0intro
191 6f4d00ee 2013-09-23 0intro static int
192 6f4d00ee 2013-09-23 0intro _groupRemMember(Ubox* box, User* g, char* member)
193 6f4d00ee 2013-09-23 0intro {
194 6f4d00ee 2013-09-23 0intro int i;
195 6f4d00ee 2013-09-23 0intro
196 6f4d00ee 2013-09-23 0intro if(_userByUname(box, member) == nil)
197 6f4d00ee 2013-09-23 0intro return 0;
198 6f4d00ee 2013-09-23 0intro
199 6f4d00ee 2013-09-23 0intro for(i = 0; i < g->ngroup; i++){
200 6f4d00ee 2013-09-23 0intro if(strcmp(g->group[i], member) == 0)
201 6f4d00ee 2013-09-23 0intro break;
202 6f4d00ee 2013-09-23 0intro }
203 6f4d00ee 2013-09-23 0intro if(i >= g->ngroup){
204 6f4d00ee 2013-09-23 0intro if(strcmp(g->uname, member) == 0)
205 4b576658 2013-09-23 0intro werrstr("uname: '%s' always in own group", member);
206 6f4d00ee 2013-09-23 0intro else
207 4b576658 2013-09-23 0intro werrstr("uname: '%s' not in group '%s'",
208 6f4d00ee 2013-09-23 0intro member, g->uname);
209 6f4d00ee 2013-09-23 0intro return 0;
210 6f4d00ee 2013-09-23 0intro }
211 6f4d00ee 2013-09-23 0intro
212 4b576658 2013-09-23 0intro vtfree(g->group[i]);
213 6f4d00ee 2013-09-23 0intro
214 6f4d00ee 2013-09-23 0intro box->len -= strlen(member);
215 6f4d00ee 2013-09-23 0intro if(g->ngroup > 1)
216 6f4d00ee 2013-09-23 0intro box->len--;
217 6f4d00ee 2013-09-23 0intro g->ngroup--;
218 6f4d00ee 2013-09-23 0intro switch(g->ngroup){
219 6f4d00ee 2013-09-23 0intro case 0:
220 4b576658 2013-09-23 0intro vtfree(g->group);
221 6f4d00ee 2013-09-23 0intro g->group = nil;
222 6f4d00ee 2013-09-23 0intro break;
223 6f4d00ee 2013-09-23 0intro default:
224 6f4d00ee 2013-09-23 0intro for(; i < g->ngroup; i++)
225 6f4d00ee 2013-09-23 0intro g->group[i] = g->group[i+1];
226 6f4d00ee 2013-09-23 0intro g->group[i] = nil; /* prevent accidents */
227 4b576658 2013-09-23 0intro g->group = vtrealloc(g->group, g->ngroup * sizeof(char*));
228 6f4d00ee 2013-09-23 0intro break;
229 6f4d00ee 2013-09-23 0intro }
230 6f4d00ee 2013-09-23 0intro
231 6f4d00ee 2013-09-23 0intro return 1;
232 6f4d00ee 2013-09-23 0intro }
233 6f4d00ee 2013-09-23 0intro
234 6f4d00ee 2013-09-23 0intro static int
235 6f4d00ee 2013-09-23 0intro _groupAddMember(Ubox* box, User* g, char* member)
236 6f4d00ee 2013-09-23 0intro {
237 6f4d00ee 2013-09-23 0intro User *u;
238 6f4d00ee 2013-09-23 0intro
239 6f4d00ee 2013-09-23 0intro if((u = _userByUname(box, member)) == nil)
240 6f4d00ee 2013-09-23 0intro return 0;
241 6f4d00ee 2013-09-23 0intro if(_groupMember(box, g->uid, u->uname, 0)){
242 6f4d00ee 2013-09-23 0intro if(strcmp(g->uname, member) == 0)
243 4b576658 2013-09-23 0intro werrstr("uname: '%s' always in own group", member);
244 6f4d00ee 2013-09-23 0intro else
245 4b576658 2013-09-23 0intro werrstr("uname: '%s' already in group '%s'",
246 6f4d00ee 2013-09-23 0intro member, g->uname);
247 6f4d00ee 2013-09-23 0intro return 0;
248 6f4d00ee 2013-09-23 0intro }
249 6f4d00ee 2013-09-23 0intro
250 4b576658 2013-09-23 0intro g->group = vtrealloc(g->group, (g->ngroup+1)*sizeof(char*));
251 4b576658 2013-09-23 0intro g->group[g->ngroup] = vtstrdup(member);
252 6f4d00ee 2013-09-23 0intro box->len += strlen(member);
253 6f4d00ee 2013-09-23 0intro g->ngroup++;
254 6f4d00ee 2013-09-23 0intro if(g->ngroup > 1)
255 6f4d00ee 2013-09-23 0intro box->len++;
256 6f4d00ee 2013-09-23 0intro
257 6f4d00ee 2013-09-23 0intro return 1;
258 6f4d00ee 2013-09-23 0intro }
259 6f4d00ee 2013-09-23 0intro
260 6f4d00ee 2013-09-23 0intro int
261 6f4d00ee 2013-09-23 0intro groupMember(char* group, char* member)
262 6f4d00ee 2013-09-23 0intro {
263 6f4d00ee 2013-09-23 0intro int r;
264 6f4d00ee 2013-09-23 0intro
265 6f4d00ee 2013-09-23 0intro if(group == nil)
266 6f4d00ee 2013-09-23 0intro return 0;
267 6f4d00ee 2013-09-23 0intro
268 4b576658 2013-09-23 0intro rlock(&ubox.lock);
269 6f4d00ee 2013-09-23 0intro r = _groupMember(ubox.box, group, member, 0);
270 4b576658 2013-09-23 0intro runlock(&ubox.lock);
271 6f4d00ee 2013-09-23 0intro
272 6f4d00ee 2013-09-23 0intro return r;
273 6f4d00ee 2013-09-23 0intro }
274 6f4d00ee 2013-09-23 0intro
275 6f4d00ee 2013-09-23 0intro int
276 6f4d00ee 2013-09-23 0intro groupLeader(char* group, char* member)
277 6f4d00ee 2013-09-23 0intro {
278 6f4d00ee 2013-09-23 0intro int r;
279 6f4d00ee 2013-09-23 0intro User *g;
280 6f4d00ee 2013-09-23 0intro
281 6f4d00ee 2013-09-23 0intro /*
282 6f4d00ee 2013-09-23 0intro * Is 'member' the leader of 'group'?
283 6f4d00ee 2013-09-23 0intro * Note that 'group' is a 'uid' and not a 'uname'.
284 6f4d00ee 2013-09-23 0intro * Uname 'none' cannot be a group leader.
285 6f4d00ee 2013-09-23 0intro */
286 6f4d00ee 2013-09-23 0intro if(strcmp(member, unamenone) == 0 || group == nil)
287 6f4d00ee 2013-09-23 0intro return 0;
288 6f4d00ee 2013-09-23 0intro
289 4b576658 2013-09-23 0intro rlock(&ubox.lock);
290 6f4d00ee 2013-09-23 0intro if((g = _userByUid(ubox.box, group)) == nil){
291 4b576658 2013-09-23 0intro runlock(&ubox.lock);
292 6f4d00ee 2013-09-23 0intro return 0;
293 6f4d00ee 2013-09-23 0intro }
294 6f4d00ee 2013-09-23 0intro if(g->leader != nil){
295 6f4d00ee 2013-09-23 0intro if(strcmp(g->leader, member) == 0){
296 4b576658 2013-09-23 0intro runlock(&ubox.lock);
297 6f4d00ee 2013-09-23 0intro return 1;
298 6f4d00ee 2013-09-23 0intro }
299 6f4d00ee 2013-09-23 0intro r = 0;
300 6f4d00ee 2013-09-23 0intro }
301 6f4d00ee 2013-09-23 0intro else
302 6f4d00ee 2013-09-23 0intro r = _groupMember(ubox.box, group, member, 0);
303 4b576658 2013-09-23 0intro runlock(&ubox.lock);
304 6f4d00ee 2013-09-23 0intro
305 6f4d00ee 2013-09-23 0intro return r;
306 6f4d00ee 2013-09-23 0intro }
307 6f4d00ee 2013-09-23 0intro
308 6f4d00ee 2013-09-23 0intro static void
309 6f4d00ee 2013-09-23 0intro userFree(User* u)
310 6f4d00ee 2013-09-23 0intro {
311 6f4d00ee 2013-09-23 0intro int i;
312 6f4d00ee 2013-09-23 0intro
313 4b576658 2013-09-23 0intro vtfree(u->uid);
314 4b576658 2013-09-23 0intro vtfree(u->uname);
315 6f4d00ee 2013-09-23 0intro if(u->leader != nil)
316 4b576658 2013-09-23 0intro vtfree(u->leader);
317 6f4d00ee 2013-09-23 0intro if(u->ngroup){
318 6f4d00ee 2013-09-23 0intro for(i = 0; i < u->ngroup; i++)
319 4b576658 2013-09-23 0intro vtfree(u->group[i]);
320 4b576658 2013-09-23 0intro vtfree(u->group);
321 6f4d00ee 2013-09-23 0intro }
322 4b576658 2013-09-23 0intro vtfree(u);
323 6f4d00ee 2013-09-23 0intro }
324 6f4d00ee 2013-09-23 0intro
325 6f4d00ee 2013-09-23 0intro static User*
326 6f4d00ee 2013-09-23 0intro userAlloc(char* uid, char* uname)
327 6f4d00ee 2013-09-23 0intro {
328 6f4d00ee 2013-09-23 0intro User *u;
329 6f4d00ee 2013-09-23 0intro
330 4b576658 2013-09-23 0intro u = vtmallocz(sizeof(User));
331 4b576658 2013-09-23 0intro u->uid = vtstrdup(uid);
332 4b576658 2013-09-23 0intro u->uname = vtstrdup(uname);
333 6f4d00ee 2013-09-23 0intro
334 6f4d00ee 2013-09-23 0intro return u;
335 6f4d00ee 2013-09-23 0intro }
336 6f4d00ee 2013-09-23 0intro
337 6f4d00ee 2013-09-23 0intro int
338 6f4d00ee 2013-09-23 0intro validUserName(char* name)
339 6f4d00ee 2013-09-23 0intro {
340 6f4d00ee 2013-09-23 0intro Rune *r;
341 b32de4ae 2013-09-26 0intro #ifdef PLAN9PORT
342 b32de4ae 2013-09-26 0intro static Rune invalid[] = {'#', ':', ',', '(', ')', '\0'};
343 b32de4ae 2013-09-26 0intro #else
344 6f4d00ee 2013-09-23 0intro static Rune invalid[] = L"#:,()";
345 b32de4ae 2013-09-26 0intro #endif
346 6f4d00ee 2013-09-23 0intro
347 6f4d00ee 2013-09-23 0intro for(r = invalid; *r != '\0'; r++){
348 6f4d00ee 2013-09-23 0intro if(utfrune(name, *r))
349 6f4d00ee 2013-09-23 0intro return 0;
350 6f4d00ee 2013-09-23 0intro }
351 6f4d00ee 2013-09-23 0intro return 1;
352 6f4d00ee 2013-09-23 0intro }
353 6f4d00ee 2013-09-23 0intro
354 6f4d00ee 2013-09-23 0intro static int
355 6f4d00ee 2013-09-23 0intro userFmt(Fmt* fmt)
356 6f4d00ee 2013-09-23 0intro {
357 6f4d00ee 2013-09-23 0intro User *u;
358 6f4d00ee 2013-09-23 0intro int i, r;
359 6f4d00ee 2013-09-23 0intro
360 6f4d00ee 2013-09-23 0intro u = va_arg(fmt->args, User*);
361 6f4d00ee 2013-09-23 0intro
362 6f4d00ee 2013-09-23 0intro r = fmtprint(fmt, "%s:%s:", u->uid, u->uname);
363 6f4d00ee 2013-09-23 0intro if(u->leader != nil)
364 6f4d00ee 2013-09-23 0intro r += fmtprint(fmt, u->leader);
365 6f4d00ee 2013-09-23 0intro r += fmtprint(fmt, ":");
366 6f4d00ee 2013-09-23 0intro if(u->ngroup){
367 6f4d00ee 2013-09-23 0intro r += fmtprint(fmt, u->group[0]);
368 6f4d00ee 2013-09-23 0intro for(i = 1; i < u->ngroup; i++)
369 6f4d00ee 2013-09-23 0intro r += fmtprint(fmt, ",%s", u->group[i]);
370 6f4d00ee 2013-09-23 0intro }
371 6f4d00ee 2013-09-23 0intro
372 6f4d00ee 2013-09-23 0intro return r;
373 6f4d00ee 2013-09-23 0intro }
374 6f4d00ee 2013-09-23 0intro
375 6f4d00ee 2013-09-23 0intro static int
376 6f4d00ee 2013-09-23 0intro usersFileWrite(Ubox* box)
377 6f4d00ee 2013-09-23 0intro {
378 6f4d00ee 2013-09-23 0intro Fs *fs;
379 6f4d00ee 2013-09-23 0intro User *u;
380 6f4d00ee 2013-09-23 0intro int i, r;
381 6f4d00ee 2013-09-23 0intro Fsys *fsys;
382 6f4d00ee 2013-09-23 0intro char *p, *q, *s;
383 6f4d00ee 2013-09-23 0intro File *dir, *file;
384 6f4d00ee 2013-09-23 0intro
385 6f4d00ee 2013-09-23 0intro if((fsys = fsysGet("main")) == nil)
386 6f4d00ee 2013-09-23 0intro return 0;
387 6f4d00ee 2013-09-23 0intro fsysFsRlock(fsys);
388 6f4d00ee 2013-09-23 0intro fs = fsysGetFs(fsys);
389 6f4d00ee 2013-09-23 0intro
390 6f4d00ee 2013-09-23 0intro /*
391 6f4d00ee 2013-09-23 0intro * BUG:
392 6f4d00ee 2013-09-23 0intro * the owner/group/permissions need to be thought out.
393 6f4d00ee 2013-09-23 0intro */
394 6f4d00ee 2013-09-23 0intro r = 0;
395 6f4d00ee 2013-09-23 0intro if((dir = fileOpen(fs, "/active")) == nil)
396 6f4d00ee 2013-09-23 0intro goto tidy0;
397 6f4d00ee 2013-09-23 0intro if((file = fileWalk(dir, uidadm)) == nil)
398 6f4d00ee 2013-09-23 0intro file = fileCreate(dir, uidadm, ModeDir|0775, uidadm);
399 6f4d00ee 2013-09-23 0intro fileDecRef(dir);
400 6f4d00ee 2013-09-23 0intro if(file == nil)
401 6f4d00ee 2013-09-23 0intro goto tidy;
402 6f4d00ee 2013-09-23 0intro dir = file;
403 6f4d00ee 2013-09-23 0intro if((file = fileWalk(dir, "users")) == nil)
404 6f4d00ee 2013-09-23 0intro file = fileCreate(dir, "users", 0664, uidadm);
405 6f4d00ee 2013-09-23 0intro fileDecRef(dir);
406 6f4d00ee 2013-09-23 0intro if(file == nil)
407 6f4d00ee 2013-09-23 0intro goto tidy;
408 6f4d00ee 2013-09-23 0intro if(!fileTruncate(file, uidadm))
409 6f4d00ee 2013-09-23 0intro goto tidy;
410 6f4d00ee 2013-09-23 0intro
411 4b576658 2013-09-23 0intro p = s = vtmalloc(box->len+1);
412 6f4d00ee 2013-09-23 0intro q = p + box->len+1;
413 6f4d00ee 2013-09-23 0intro for(u = box->head; u != nil; u = u->next){
414 6f4d00ee 2013-09-23 0intro p += snprint(p, q-p, "%s:%s:", u->uid, u->uname);
415 6f4d00ee 2013-09-23 0intro if(u->leader != nil)
416 6f4d00ee 2013-09-23 0intro p+= snprint(p, q-p, u->leader);
417 6f4d00ee 2013-09-23 0intro p += snprint(p, q-p, ":");
418 6f4d00ee 2013-09-23 0intro if(u->ngroup){
419 6f4d00ee 2013-09-23 0intro p += snprint(p, q-p, u->group[0]);
420 6f4d00ee 2013-09-23 0intro for(i = 1; i < u->ngroup; i++)
421 6f4d00ee 2013-09-23 0intro p += snprint(p, q-p, ",%s", u->group[i]);
422 6f4d00ee 2013-09-23 0intro }
423 6f4d00ee 2013-09-23 0intro p += snprint(p, q-p, "\n");
424 6f4d00ee 2013-09-23 0intro }
425 6f4d00ee 2013-09-23 0intro r = fileWrite(file, s, box->len, 0, uidadm);
426 4b576658 2013-09-23 0intro vtfree(s);
427 6f4d00ee 2013-09-23 0intro
428 6f4d00ee 2013-09-23 0intro tidy:
429 6f4d00ee 2013-09-23 0intro if(file != nil)
430 6f4d00ee 2013-09-23 0intro fileDecRef(file);
431 6f4d00ee 2013-09-23 0intro tidy0:
432 6f4d00ee 2013-09-23 0intro fsysFsRUnlock(fsys);
433 6f4d00ee 2013-09-23 0intro fsysPut(fsys);
434 6f4d00ee 2013-09-23 0intro
435 6f4d00ee 2013-09-23 0intro return r;
436 6f4d00ee 2013-09-23 0intro }
437 6f4d00ee 2013-09-23 0intro
438 6f4d00ee 2013-09-23 0intro static void
439 6f4d00ee 2013-09-23 0intro uboxRemUser(Ubox* box, User *u)
440 6f4d00ee 2013-09-23 0intro {
441 6f4d00ee 2013-09-23 0intro User **h, *up;
442 6f4d00ee 2013-09-23 0intro
443 6f4d00ee 2013-09-23 0intro h = &box->ihash[userHash(u->uid)];
444 6f4d00ee 2013-09-23 0intro for(up = *h; up != nil && up != u; up = up->ihash)
445 6f4d00ee 2013-09-23 0intro h = &up->ihash;
446 6f4d00ee 2013-09-23 0intro assert(up == u);
447 6f4d00ee 2013-09-23 0intro *h = up->ihash;
448 6f4d00ee 2013-09-23 0intro box->len -= strlen(u->uid);
449 6f4d00ee 2013-09-23 0intro
450 6f4d00ee 2013-09-23 0intro h = &box->nhash[userHash(u->uname)];
451 6f4d00ee 2013-09-23 0intro for(up = *h; up != nil && up != u; up = up->nhash)
452 6f4d00ee 2013-09-23 0intro h = &up->nhash;
453 6f4d00ee 2013-09-23 0intro assert(up == u);
454 6f4d00ee 2013-09-23 0intro *h = up->nhash;
455 6f4d00ee 2013-09-23 0intro box->len -= strlen(u->uname);
456 6f4d00ee 2013-09-23 0intro
457 6f4d00ee 2013-09-23 0intro h = &box->head;
458 6f4d00ee 2013-09-23 0intro for(up = *h; up != nil && strcmp(up->uid, u->uid) != 0; up = up->next)
459 6f4d00ee 2013-09-23 0intro h = &up->next;
460 6f4d00ee 2013-09-23 0intro assert(up == u);
461 6f4d00ee 2013-09-23 0intro *h = u->next;
462 6f4d00ee 2013-09-23 0intro u->next = nil;
463 6f4d00ee 2013-09-23 0intro
464 6f4d00ee 2013-09-23 0intro box->len -= 4;
465 6f4d00ee 2013-09-23 0intro box->nuser--;
466 6f4d00ee 2013-09-23 0intro }
467 6f4d00ee 2013-09-23 0intro
468 6f4d00ee 2013-09-23 0intro static void
469 6f4d00ee 2013-09-23 0intro uboxAddUser(Ubox* box, User* u)
470 6f4d00ee 2013-09-23 0intro {
471 6f4d00ee 2013-09-23 0intro User **h, *up;
472 6f4d00ee 2013-09-23 0intro
473 6f4d00ee 2013-09-23 0intro h = &box->ihash[userHash(u->uid)];
474 6f4d00ee 2013-09-23 0intro u->ihash = *h;
475 6f4d00ee 2013-09-23 0intro *h = u;
476 6f4d00ee 2013-09-23 0intro box->len += strlen(u->uid);
477 6f4d00ee 2013-09-23 0intro
478 6f4d00ee 2013-09-23 0intro h = &box->nhash[userHash(u->uname)];
479 6f4d00ee 2013-09-23 0intro u->nhash = *h;
480 6f4d00ee 2013-09-23 0intro *h = u;
481 6f4d00ee 2013-09-23 0intro box->len += strlen(u->uname);
482 6f4d00ee 2013-09-23 0intro
483 6f4d00ee 2013-09-23 0intro h = &box->head;
484 6f4d00ee 2013-09-23 0intro for(up = *h; up != nil && strcmp(up->uid, u->uid) < 0; up = up->next)
485 6f4d00ee 2013-09-23 0intro h = &up->next;
486 6f4d00ee 2013-09-23 0intro u->next = *h;
487 6f4d00ee 2013-09-23 0intro *h = u;
488 6f4d00ee 2013-09-23 0intro
489 6f4d00ee 2013-09-23 0intro box->len += 4;
490 6f4d00ee 2013-09-23 0intro box->nuser++;
491 6f4d00ee 2013-09-23 0intro }
492 6f4d00ee 2013-09-23 0intro
493 6f4d00ee 2013-09-23 0intro static void
494 6f4d00ee 2013-09-23 0intro uboxDump(Ubox* box)
495 6f4d00ee 2013-09-23 0intro {
496 6f4d00ee 2013-09-23 0intro User* u;
497 6f4d00ee 2013-09-23 0intro
498 6f4d00ee 2013-09-23 0intro consPrint("nuser %d len = %d\n", box->nuser, box->len);
499 6f4d00ee 2013-09-23 0intro
500 6f4d00ee 2013-09-23 0intro for(u = box->head; u != nil; u = u->next)
501 6f4d00ee 2013-09-23 0intro consPrint("%U\n", u);
502 6f4d00ee 2013-09-23 0intro }
503 6f4d00ee 2013-09-23 0intro
504 6f4d00ee 2013-09-23 0intro static void
505 6f4d00ee 2013-09-23 0intro uboxFree(Ubox* box)
506 6f4d00ee 2013-09-23 0intro {
507 6f4d00ee 2013-09-23 0intro User *next, *u;
508 6f4d00ee 2013-09-23 0intro
509 6f4d00ee 2013-09-23 0intro for(u = box->head; u != nil; u = next){
510 6f4d00ee 2013-09-23 0intro next = u->next;
511 6f4d00ee 2013-09-23 0intro userFree(u);
512 6f4d00ee 2013-09-23 0intro }
513 4b576658 2013-09-23 0intro vtfree(box);
514 6f4d00ee 2013-09-23 0intro }
515 6f4d00ee 2013-09-23 0intro
516 6f4d00ee 2013-09-23 0intro static int
517 6f4d00ee 2013-09-23 0intro uboxInit(char* users, int len)
518 6f4d00ee 2013-09-23 0intro {
519 6f4d00ee 2013-09-23 0intro User *g, *u;
520 6f4d00ee 2013-09-23 0intro Ubox *box, *obox;
521 6f4d00ee 2013-09-23 0intro int blank, comment, i, nline, nuser;
522 6f4d00ee 2013-09-23 0intro char *buf, *f[5], **line, *p, *q, *s;
523 6f4d00ee 2013-09-23 0intro
524 6f4d00ee 2013-09-23 0intro /*
525 6f4d00ee 2013-09-23 0intro * Strip out whitespace and comments.
526 6f4d00ee 2013-09-23 0intro * Note that comments are pointless, they disappear
527 6f4d00ee 2013-09-23 0intro * when the server writes the database back out.
528 6f4d00ee 2013-09-23 0intro */
529 6f4d00ee 2013-09-23 0intro blank = 1;
530 6f4d00ee 2013-09-23 0intro comment = nline = 0;
531 6f4d00ee 2013-09-23 0intro
532 4b576658 2013-09-23 0intro s = p = buf = vtmalloc(len+1);
533 6f4d00ee 2013-09-23 0intro for(q = users; *q != '\0'; q++){
534 6f4d00ee 2013-09-23 0intro if(*q == '\r' || *q == '\t' || *q == ' ')
535 6f4d00ee 2013-09-23 0intro continue;
536 6f4d00ee 2013-09-23 0intro if(*q == '\n'){
537 6f4d00ee 2013-09-23 0intro if(!blank){
538 6f4d00ee 2013-09-23 0intro if(p != s){
539 6f4d00ee 2013-09-23 0intro *p++ = '\n';
540 6f4d00ee 2013-09-23 0intro nline++;
541 6f4d00ee 2013-09-23 0intro s = p;
542 6f4d00ee 2013-09-23 0intro }
543 6f4d00ee 2013-09-23 0intro blank = 1;
544 6f4d00ee 2013-09-23 0intro }
545 6f4d00ee 2013-09-23 0intro comment = 0;
546 6f4d00ee 2013-09-23 0intro continue;
547 6f4d00ee 2013-09-23 0intro }
548 6f4d00ee 2013-09-23 0intro if(*q == '#')
549 6f4d00ee 2013-09-23 0intro comment = 1;
550 6f4d00ee 2013-09-23 0intro blank = 0;
551 6f4d00ee 2013-09-23 0intro if(!comment)
552 6f4d00ee 2013-09-23 0intro *p++ = *q;
553 6f4d00ee 2013-09-23 0intro }
554 6f4d00ee 2013-09-23 0intro *p = '\0';
555 6f4d00ee 2013-09-23 0intro
556 4b576658 2013-09-23 0intro line = vtmallocz((nline+2)*sizeof(char*));
557 6f4d00ee 2013-09-23 0intro if((i = gettokens(buf, line, nline+2, "\n")) != nline){
558 6f4d00ee 2013-09-23 0intro fprint(2, "nline %d (%d) botch\n", nline, i);
559 4b576658 2013-09-23 0intro vtfree(line);
560 4b576658 2013-09-23 0intro vtfree(buf);
561 6f4d00ee 2013-09-23 0intro return 0;
562 6f4d00ee 2013-09-23 0intro }
563 6f4d00ee 2013-09-23 0intro
564 6f4d00ee 2013-09-23 0intro /*
565 6f4d00ee 2013-09-23 0intro * Everything is updated in a local Ubox until verified.
566 6f4d00ee 2013-09-23 0intro */
567 4b576658 2013-09-23 0intro box = vtmallocz(sizeof(Ubox));
568 6f4d00ee 2013-09-23 0intro
569 6f4d00ee 2013-09-23 0intro /*
570 6f4d00ee 2013-09-23 0intro * First pass - check format, check for duplicates
571 6f4d00ee 2013-09-23 0intro * and enter in hash buckets.
572 6f4d00ee 2013-09-23 0intro */
573 6f4d00ee 2013-09-23 0intro nuser = 0;
574 6f4d00ee 2013-09-23 0intro for(i = 0; i < nline; i++){
575 4b576658 2013-09-23 0intro s = vtstrdup(line[i]);
576 6f4d00ee 2013-09-23 0intro if(getfields(s, f, nelem(f), 0, ":") != 4){
577 6f4d00ee 2013-09-23 0intro fprint(2, "bad line '%s'\n", line[i]);
578 4b576658 2013-09-23 0intro vtfree(s);
579 6f4d00ee 2013-09-23 0intro continue;
580 6f4d00ee 2013-09-23 0intro }
581 6f4d00ee 2013-09-23 0intro if(*f[0] == '\0' || *f[1] == '\0'){
582 6f4d00ee 2013-09-23 0intro fprint(2, "bad line '%s'\n", line[i]);
583 4b576658 2013-09-23 0intro vtfree(s);
584 6f4d00ee 2013-09-23 0intro continue;
585 6f4d00ee 2013-09-23 0intro }
586 6f4d00ee 2013-09-23 0intro if(!validUserName(f[0])){
587 6f4d00ee 2013-09-23 0intro fprint(2, "invalid uid '%s'\n", f[0]);
588 4b576658 2013-09-23 0intro vtfree(s);
589 6f4d00ee 2013-09-23 0intro continue;
590 6f4d00ee 2013-09-23 0intro }
591 6f4d00ee 2013-09-23 0intro if(_userByUid(box, f[0]) != nil){
592 6f4d00ee 2013-09-23 0intro fprint(2, "duplicate uid '%s'\n", f[0]);
593 4b576658 2013-09-23 0intro vtfree(s);
594 6f4d00ee 2013-09-23 0intro continue;
595 6f4d00ee 2013-09-23 0intro }
596 6f4d00ee 2013-09-23 0intro if(!validUserName(f[1])){
597 6f4d00ee 2013-09-23 0intro fprint(2, "invalid uname '%s'\n", f[0]);
598 4b576658 2013-09-23 0intro vtfree(s);
599 6f4d00ee 2013-09-23 0intro continue;
600 6f4d00ee 2013-09-23 0intro }
601 6f4d00ee 2013-09-23 0intro if(_userByUname(box, f[1]) != nil){
602 6f4d00ee 2013-09-23 0intro fprint(2, "duplicate uname '%s'\n", f[1]);
603 4b576658 2013-09-23 0intro vtfree(s);
604 6f4d00ee 2013-09-23 0intro continue;
605 6f4d00ee 2013-09-23 0intro }
606 6f4d00ee 2013-09-23 0intro
607 6f4d00ee 2013-09-23 0intro u = userAlloc(f[0], f[1]);
608 6f4d00ee 2013-09-23 0intro uboxAddUser(box, u);
609 6f4d00ee 2013-09-23 0intro line[nuser] = line[i];
610 6f4d00ee 2013-09-23 0intro nuser++;
611 6f4d00ee 2013-09-23 0intro
612 4b576658 2013-09-23 0intro vtfree(s);
613 6f4d00ee 2013-09-23 0intro }
614 6f4d00ee 2013-09-23 0intro assert(box->nuser == nuser);
615 6f4d00ee 2013-09-23 0intro
616 6f4d00ee 2013-09-23 0intro /*
617 6f4d00ee 2013-09-23 0intro * Second pass - fill in leader and group information.
618 6f4d00ee 2013-09-23 0intro */
619 6f4d00ee 2013-09-23 0intro for(i = 0; i < nuser; i++){
620 4b576658 2013-09-23 0intro s = vtstrdup(line[i]);
621 6f4d00ee 2013-09-23 0intro getfields(s, f, nelem(f), 0, ":");
622 6f4d00ee 2013-09-23 0intro
623 6f4d00ee 2013-09-23 0intro assert(g = _userByUname(box, f[1]));
624 6f4d00ee 2013-09-23 0intro if(*f[2] != '\0'){
625 6f4d00ee 2013-09-23 0intro if((u = _userByUname(box, f[2])) == nil)
626 4b576658 2013-09-23 0intro g->leader = vtstrdup(g->uname);
627 6f4d00ee 2013-09-23 0intro else
628 4b576658 2013-09-23 0intro g->leader = vtstrdup(u->uname);
629 6f4d00ee 2013-09-23 0intro box->len += strlen(g->leader);
630 6f4d00ee 2013-09-23 0intro }
631 6f4d00ee 2013-09-23 0intro for(p = f[3]; p != nil; p = q){
632 6f4d00ee 2013-09-23 0intro if((q = utfrune(p, L',')) != nil)
633 6f4d00ee 2013-09-23 0intro *q++ = '\0';
634 6f4d00ee 2013-09-23 0intro if(!_groupAddMember(box, g, p)){
635 6f4d00ee 2013-09-23 0intro // print/log error here
636 6f4d00ee 2013-09-23 0intro }
637 6f4d00ee 2013-09-23 0intro }
638 6f4d00ee 2013-09-23 0intro
639 4b576658 2013-09-23 0intro vtfree(s);
640 6f4d00ee 2013-09-23 0intro }
641 6f4d00ee 2013-09-23 0intro
642 4b576658 2013-09-23 0intro vtfree(line);
643 4b576658 2013-09-23 0intro vtfree(buf);
644 6f4d00ee 2013-09-23 0intro
645 6f4d00ee 2013-09-23 0intro for(i = 0; usersMandatory[i] != nil; i++){
646 6f4d00ee 2013-09-23 0intro if((u = _userByUid(box, usersMandatory[i])) == nil){
647 4b576658 2013-09-23 0intro werrstr("user '%s' is mandatory", usersMandatory[i]);
648 6f4d00ee 2013-09-23 0intro uboxFree(box);
649 6f4d00ee 2013-09-23 0intro return 0;
650 6f4d00ee 2013-09-23 0intro }
651 6f4d00ee 2013-09-23 0intro if(strcmp(u->uid, u->uname) != 0){
652 4b576658 2013-09-23 0intro werrstr("uid/uname for user '%s' must match",
653 6f4d00ee 2013-09-23 0intro usersMandatory[i]);
654 6f4d00ee 2013-09-23 0intro uboxFree(box);
655 6f4d00ee 2013-09-23 0intro return 0;
656 6f4d00ee 2013-09-23 0intro }
657 6f4d00ee 2013-09-23 0intro }
658 6f4d00ee 2013-09-23 0intro
659 4b576658 2013-09-23 0intro wlock(&ubox.lock);
660 6f4d00ee 2013-09-23 0intro obox = ubox.box;
661 6f4d00ee 2013-09-23 0intro ubox.box = box;
662 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
663 6f4d00ee 2013-09-23 0intro
664 6f4d00ee 2013-09-23 0intro if(obox != nil)
665 6f4d00ee 2013-09-23 0intro uboxFree(obox);
666 6f4d00ee 2013-09-23 0intro
667 6f4d00ee 2013-09-23 0intro return 1;
668 6f4d00ee 2013-09-23 0intro }
669 6f4d00ee 2013-09-23 0intro
670 6f4d00ee 2013-09-23 0intro int
671 6f4d00ee 2013-09-23 0intro usersFileRead(char* path)
672 6f4d00ee 2013-09-23 0intro {
673 6f4d00ee 2013-09-23 0intro char *p;
674 6f4d00ee 2013-09-23 0intro File *file;
675 6f4d00ee 2013-09-23 0intro Fsys *fsys;
676 6f4d00ee 2013-09-23 0intro int len, r;
677 6f4d00ee 2013-09-23 0intro uvlong size;
678 6f4d00ee 2013-09-23 0intro
679 6f4d00ee 2013-09-23 0intro if((fsys = fsysGet("main")) == nil)
680 6f4d00ee 2013-09-23 0intro return 0;
681 6f4d00ee 2013-09-23 0intro fsysFsRlock(fsys);
682 6f4d00ee 2013-09-23 0intro
683 6f4d00ee 2013-09-23 0intro if(path == nil)
684 6f4d00ee 2013-09-23 0intro path = "/active/adm/users";
685 6f4d00ee 2013-09-23 0intro
686 6f4d00ee 2013-09-23 0intro r = 0;
687 6f4d00ee 2013-09-23 0intro if((file = fileOpen(fsysGetFs(fsys), path)) != nil){
688 6f4d00ee 2013-09-23 0intro if(fileGetSize(file, &size)){
689 6f4d00ee 2013-09-23 0intro len = size;
690 4b576658 2013-09-23 0intro p = vtmalloc(size+1);
691 6f4d00ee 2013-09-23 0intro if(fileRead(file, p, len, 0) == len){
692 6f4d00ee 2013-09-23 0intro p[len] = '\0';
693 6f4d00ee 2013-09-23 0intro r = uboxInit(p, len);
694 6f4d00ee 2013-09-23 0intro }
695 6f4d00ee 2013-09-23 0intro }
696 6f4d00ee 2013-09-23 0intro fileDecRef(file);
697 6f4d00ee 2013-09-23 0intro }
698 6f4d00ee 2013-09-23 0intro
699 6f4d00ee 2013-09-23 0intro fsysFsRUnlock(fsys);
700 6f4d00ee 2013-09-23 0intro fsysPut(fsys);
701 6f4d00ee 2013-09-23 0intro
702 6f4d00ee 2013-09-23 0intro return r;
703 6f4d00ee 2013-09-23 0intro }
704 6f4d00ee 2013-09-23 0intro
705 6f4d00ee 2013-09-23 0intro static int
706 6f4d00ee 2013-09-23 0intro cmdUname(int argc, char* argv[])
707 6f4d00ee 2013-09-23 0intro {
708 6f4d00ee 2013-09-23 0intro User *u, *up;
709 6f4d00ee 2013-09-23 0intro int d, dflag, i, r;
710 6f4d00ee 2013-09-23 0intro char *p, *uid, *uname;
711 6f4d00ee 2013-09-23 0intro char *createfmt = "fsys main create /active/usr/%s %s %s d775";
712 6f4d00ee 2013-09-23 0intro char *usage = "usage: uname [-d] uname [uid|:uid|%%newname|=leader|+member|-member]";
713 6f4d00ee 2013-09-23 0intro
714 6f4d00ee 2013-09-23 0intro dflag = 0;
715 6f4d00ee 2013-09-23 0intro
716 6f4d00ee 2013-09-23 0intro ARGBEGIN{
717 6f4d00ee 2013-09-23 0intro default:
718 6f4d00ee 2013-09-23 0intro return cliError(usage);
719 6f4d00ee 2013-09-23 0intro case 'd':
720 6f4d00ee 2013-09-23 0intro dflag = 1;
721 6f4d00ee 2013-09-23 0intro break;
722 6f4d00ee 2013-09-23 0intro }ARGEND
723 6f4d00ee 2013-09-23 0intro
724 6f4d00ee 2013-09-23 0intro if(argc < 1){
725 6f4d00ee 2013-09-23 0intro if(!dflag)
726 6f4d00ee 2013-09-23 0intro return cliError(usage);
727 4b576658 2013-09-23 0intro rlock(&ubox.lock);
728 6f4d00ee 2013-09-23 0intro uboxDump(ubox.box);
729 4b576658 2013-09-23 0intro runlock(&ubox.lock);
730 6f4d00ee 2013-09-23 0intro return 1;
731 6f4d00ee 2013-09-23 0intro }
732 6f4d00ee 2013-09-23 0intro
733 6f4d00ee 2013-09-23 0intro uname = argv[0];
734 6f4d00ee 2013-09-23 0intro argc--; argv++;
735 6f4d00ee 2013-09-23 0intro
736 6f4d00ee 2013-09-23 0intro if(argc == 0){
737 4b576658 2013-09-23 0intro rlock(&ubox.lock);
738 6f4d00ee 2013-09-23 0intro if((u = _userByUname(ubox.box, uname)) == nil){
739 4b576658 2013-09-23 0intro runlock(&ubox.lock);
740 6f4d00ee 2013-09-23 0intro return 0;
741 6f4d00ee 2013-09-23 0intro }
742 6f4d00ee 2013-09-23 0intro consPrint("\t%U\n", u);
743 4b576658 2013-09-23 0intro runlock(&ubox.lock);
744 6f4d00ee 2013-09-23 0intro return 1;
745 6f4d00ee 2013-09-23 0intro }
746 6f4d00ee 2013-09-23 0intro
747 4b576658 2013-09-23 0intro wlock(&ubox.lock);
748 6f4d00ee 2013-09-23 0intro u = _userByUname(ubox.box, uname);
749 6f4d00ee 2013-09-23 0intro while(argc--){
750 6f4d00ee 2013-09-23 0intro if(argv[0][0] == '%'){
751 6f4d00ee 2013-09-23 0intro if(u == nil){
752 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
753 6f4d00ee 2013-09-23 0intro return 0;
754 6f4d00ee 2013-09-23 0intro }
755 6f4d00ee 2013-09-23 0intro p = &argv[0][1];
756 6f4d00ee 2013-09-23 0intro if((up = _userByUname(ubox.box, p)) != nil){
757 4b576658 2013-09-23 0intro werrstr("uname: uname '%s' already exists",
758 6f4d00ee 2013-09-23 0intro up->uname);
759 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
760 6f4d00ee 2013-09-23 0intro return 0;
761 6f4d00ee 2013-09-23 0intro }
762 6f4d00ee 2013-09-23 0intro for(i = 0; usersMandatory[i] != nil; i++){
763 6f4d00ee 2013-09-23 0intro if(strcmp(usersMandatory[i], uname) != 0)
764 6f4d00ee 2013-09-23 0intro continue;
765 4b576658 2013-09-23 0intro werrstr("uname: uname '%s' is mandatory",
766 6f4d00ee 2013-09-23 0intro uname);
767 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
768 6f4d00ee 2013-09-23 0intro return 0;
769 6f4d00ee 2013-09-23 0intro }
770 6f4d00ee 2013-09-23 0intro
771 6f4d00ee 2013-09-23 0intro d = strlen(p) - strlen(u->uname);
772 6f4d00ee 2013-09-23 0intro for(up = ubox.box->head; up != nil; up = up->next){
773 6f4d00ee 2013-09-23 0intro if(up->leader != nil){
774 6f4d00ee 2013-09-23 0intro if(strcmp(up->leader, u->uname) == 0){
775 4b576658 2013-09-23 0intro vtfree(up->leader);
776 4b576658 2013-09-23 0intro up->leader = vtstrdup(p);
777 6f4d00ee 2013-09-23 0intro ubox.box->len += d;
778 6f4d00ee 2013-09-23 0intro }
779 6f4d00ee 2013-09-23 0intro }
780 6f4d00ee 2013-09-23 0intro for(i = 0; i < up->ngroup; i++){
781 6f4d00ee 2013-09-23 0intro if(strcmp(up->group[i], u->uname) != 0)
782 6f4d00ee 2013-09-23 0intro continue;
783 4b576658 2013-09-23 0intro vtfree(up->group[i]);
784 4b576658 2013-09-23 0intro up->group[i] = vtstrdup(p);
785 6f4d00ee 2013-09-23 0intro ubox.box->len += d;
786 6f4d00ee 2013-09-23 0intro break;
787 6f4d00ee 2013-09-23 0intro }
788 6f4d00ee 2013-09-23 0intro }
789 6f4d00ee 2013-09-23 0intro
790 6f4d00ee 2013-09-23 0intro uboxRemUser(ubox.box, u);
791 4b576658 2013-09-23 0intro vtfree(u->uname);
792 4b576658 2013-09-23 0intro u->uname = vtstrdup(p);
793 6f4d00ee 2013-09-23 0intro uboxAddUser(ubox.box, u);
794 6f4d00ee 2013-09-23 0intro }
795 6f4d00ee 2013-09-23 0intro else if(argv[0][0] == '='){
796 6f4d00ee 2013-09-23 0intro if(u == nil){
797 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
798 6f4d00ee 2013-09-23 0intro return 0;
799 6f4d00ee 2013-09-23 0intro }
800 6f4d00ee 2013-09-23 0intro if((up = _userByUname(ubox.box, &argv[0][1])) == nil){
801 6f4d00ee 2013-09-23 0intro if(argv[0][1] != '\0'){
802 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
803 6f4d00ee 2013-09-23 0intro return 0;
804 6f4d00ee 2013-09-23 0intro }
805 6f4d00ee 2013-09-23 0intro }
806 6f4d00ee 2013-09-23 0intro if(u->leader != nil){
807 6f4d00ee 2013-09-23 0intro ubox.box->len -= strlen(u->leader);
808 4b576658 2013-09-23 0intro vtfree(u->leader);
809 6f4d00ee 2013-09-23 0intro u->leader = nil;
810 6f4d00ee 2013-09-23 0intro }
811 6f4d00ee 2013-09-23 0intro if(up != nil){
812 4b576658 2013-09-23 0intro u->leader = vtstrdup(up->uname);
813 6f4d00ee 2013-09-23 0intro ubox.box->len += strlen(u->leader);
814 6f4d00ee 2013-09-23 0intro }
815 6f4d00ee 2013-09-23 0intro }
816 6f4d00ee 2013-09-23 0intro else if(argv[0][0] == '+'){
817 6f4d00ee 2013-09-23 0intro if(u == nil){
818 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
819 6f4d00ee 2013-09-23 0intro return 0;
820 6f4d00ee 2013-09-23 0intro }
821 6f4d00ee 2013-09-23 0intro if((up = _userByUname(ubox.box, &argv[0][1])) == nil){
822 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
823 6f4d00ee 2013-09-23 0intro return 0;
824 6f4d00ee 2013-09-23 0intro }
825 6f4d00ee 2013-09-23 0intro if(!_groupAddMember(ubox.box, u, up->uname)){
826 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
827 6f4d00ee 2013-09-23 0intro return 0;
828 6f4d00ee 2013-09-23 0intro }
829 6f4d00ee 2013-09-23 0intro }
830 6f4d00ee 2013-09-23 0intro else if(argv[0][0] == '-'){
831 6f4d00ee 2013-09-23 0intro if(u == nil){
832 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
833 6f4d00ee 2013-09-23 0intro return 0;
834 6f4d00ee 2013-09-23 0intro }
835 6f4d00ee 2013-09-23 0intro if((up = _userByUname(ubox.box, &argv[0][1])) == nil){
836 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
837 6f4d00ee 2013-09-23 0intro return 0;
838 6f4d00ee 2013-09-23 0intro }
839 6f4d00ee 2013-09-23 0intro if(!_groupRemMember(ubox.box, u, up->uname)){
840 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
841 6f4d00ee 2013-09-23 0intro return 0;
842 6f4d00ee 2013-09-23 0intro }
843 6f4d00ee 2013-09-23 0intro }
844 6f4d00ee 2013-09-23 0intro else{
845 6f4d00ee 2013-09-23 0intro if(u != nil){
846 4b576658 2013-09-23 0intro werrstr("uname: uname '%s' already exists",
847 6f4d00ee 2013-09-23 0intro u->uname);
848 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
849 6f4d00ee 2013-09-23 0intro return 0;
850 6f4d00ee 2013-09-23 0intro }
851 6f4d00ee 2013-09-23 0intro
852 6f4d00ee 2013-09-23 0intro uid = argv[0];
853 6f4d00ee 2013-09-23 0intro if(*uid == ':')
854 6f4d00ee 2013-09-23 0intro uid++;
855 6f4d00ee 2013-09-23 0intro if((u = _userByUid(ubox.box, uid)) != nil){
856 4b576658 2013-09-23 0intro werrstr("uname: uid '%s' already exists",
857 6f4d00ee 2013-09-23 0intro u->uid);
858 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
859 6f4d00ee 2013-09-23 0intro return 0;
860 6f4d00ee 2013-09-23 0intro }
861 6f4d00ee 2013-09-23 0intro
862 6f4d00ee 2013-09-23 0intro u = userAlloc(uid, uname);
863 6f4d00ee 2013-09-23 0intro uboxAddUser(ubox.box, u);
864 6f4d00ee 2013-09-23 0intro if(argv[0][0] != ':'){
865 6f4d00ee 2013-09-23 0intro // should have an option for the mode and gid
866 6f4d00ee 2013-09-23 0intro p = smprint(createfmt, uname, uname, uname);
867 6f4d00ee 2013-09-23 0intro r = cliExec(p);
868 4b576658 2013-09-23 0intro vtfree(p);
869 6f4d00ee 2013-09-23 0intro if(r == 0){
870 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
871 6f4d00ee 2013-09-23 0intro return 0;
872 6f4d00ee 2013-09-23 0intro }
873 6f4d00ee 2013-09-23 0intro }
874 6f4d00ee 2013-09-23 0intro }
875 6f4d00ee 2013-09-23 0intro argv++;
876 6f4d00ee 2013-09-23 0intro }
877 6f4d00ee 2013-09-23 0intro
878 6f4d00ee 2013-09-23 0intro if(usersFileWrite(ubox.box) == 0){
879 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
880 6f4d00ee 2013-09-23 0intro return 0;
881 6f4d00ee 2013-09-23 0intro }
882 6f4d00ee 2013-09-23 0intro if(dflag)
883 6f4d00ee 2013-09-23 0intro uboxDump(ubox.box);
884 4b576658 2013-09-23 0intro wunlock(&ubox.lock);
885 6f4d00ee 2013-09-23 0intro
886 6f4d00ee 2013-09-23 0intro return 1;
887 6f4d00ee 2013-09-23 0intro }
888 6f4d00ee 2013-09-23 0intro
889 6f4d00ee 2013-09-23 0intro static int
890 6f4d00ee 2013-09-23 0intro cmdUsers(int argc, char* argv[])
891 6f4d00ee 2013-09-23 0intro {
892 6f4d00ee 2013-09-23 0intro Ubox *box;
893 6f4d00ee 2013-09-23 0intro int dflag, r, wflag;
894 6f4d00ee 2013-09-23 0intro char *file;
895 6f4d00ee 2013-09-23 0intro char *usage = "usage: users [-d | -r file] [-w]";
896 6f4d00ee 2013-09-23 0intro
897 6f4d00ee 2013-09-23 0intro dflag = wflag = 0;
898 6f4d00ee 2013-09-23 0intro file = nil;
899 6f4d00ee 2013-09-23 0intro
900 6f4d00ee 2013-09-23 0intro ARGBEGIN{
901 6f4d00ee 2013-09-23 0intro default:
902 6f4d00ee 2013-09-23 0intro return cliError(usage);
903 6f4d00ee 2013-09-23 0intro case 'd':
904 6f4d00ee 2013-09-23 0intro dflag = 1;
905 6f4d00ee 2013-09-23 0intro break;
906 6f4d00ee 2013-09-23 0intro case 'r':
907 6f4d00ee 2013-09-23 0intro file = ARGF();
908 6f4d00ee 2013-09-23 0intro if(file == nil)
909 6f4d00ee 2013-09-23 0intro return cliError(usage);
910 6f4d00ee 2013-09-23 0intro break;
911 6f4d00ee 2013-09-23 0intro case 'w':
912 6f4d00ee 2013-09-23 0intro wflag = 1;
913 6f4d00ee 2013-09-23 0intro break;
914 6f4d00ee 2013-09-23 0intro }ARGEND
915 6f4d00ee 2013-09-23 0intro
916 6f4d00ee 2013-09-23 0intro if(argc)
917 6f4d00ee 2013-09-23 0intro return cliError(usage);
918 6f4d00ee 2013-09-23 0intro
919 6f4d00ee 2013-09-23 0intro if(dflag && file)
920 6f4d00ee 2013-09-23 0intro return cliError("cannot use -d and -r together");
921 6f4d00ee 2013-09-23 0intro
922 6f4d00ee 2013-09-23 0intro if(dflag)
923 6f4d00ee 2013-09-23 0intro uboxInit(usersDefault, sizeof(usersDefault));
924 6f4d00ee 2013-09-23 0intro else if(file){
925 6f4d00ee 2013-09-23 0intro if(usersFileRead(file) == 0)
926 6f4d00ee 2013-09-23 0intro return 0;
927 6f4d00ee 2013-09-23 0intro }
928 6f4d00ee 2013-09-23 0intro
929 4b576658 2013-09-23 0intro rlock(&ubox.lock);
930 6f4d00ee 2013-09-23 0intro box = ubox.box;
931 6f4d00ee 2013-09-23 0intro consPrint("\tnuser %d len %d\n", box->nuser, box->len);
932 6f4d00ee 2013-09-23 0intro
933 6f4d00ee 2013-09-23 0intro r = 1;
934 6f4d00ee 2013-09-23 0intro if(wflag)
935 6f4d00ee 2013-09-23 0intro r = usersFileWrite(box);
936 4b576658 2013-09-23 0intro runlock(&ubox.lock);
937 6f4d00ee 2013-09-23 0intro return r;
938 6f4d00ee 2013-09-23 0intro }
939 6f4d00ee 2013-09-23 0intro
940 6f4d00ee 2013-09-23 0intro int
941 6f4d00ee 2013-09-23 0intro usersInit(void)
942 6f4d00ee 2013-09-23 0intro {
943 6f4d00ee 2013-09-23 0intro fmtinstall('U', userFmt);
944 6f4d00ee 2013-09-23 0intro
945 6f4d00ee 2013-09-23 0intro uboxInit(usersDefault, sizeof(usersDefault));
946 6f4d00ee 2013-09-23 0intro
947 6f4d00ee 2013-09-23 0intro cliAddCmd("users", cmdUsers);
948 6f4d00ee 2013-09-23 0intro cliAddCmd("uname", cmdUname);
949 6f4d00ee 2013-09-23 0intro
950 6f4d00ee 2013-09-23 0intro return 1;
951 6f4d00ee 2013-09-23 0intro }