Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libcmd/id.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1992-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* *
20
***********************************************************************/
21
#pragma prototyped
22
/*
23
* David Korn
24
* Glenn Fowler
25
* AT&T Research
26
*
27
* id
28
*/
29
30
static const char usage[] =
31
"[-?\n@(#)$Id: id (AT&T Research) 2004-06-11 $\n]"
32
USAGE_LICENSE
33
"[+NAME?id - return user identity]"
34
"[+DESCRIPTION?If no \auser\a operand is specified \bid\b writes user and "
35
"group IDs and the corresponding user and group names of the "
36
"invoking process to standard output. If the effective and "
37
"real IDs do not match, both are written. Any supplementary "
38
"groups the current process belongs to will also be written.]"
39
"[+?If a \auser\a operand is specified and the process has permission, "
40
"the user and group IDs and any supplementary group IDs of the "
41
"selected user will be written to standard output.]"
42
"[+?If any options are specified, then only a portion of the information "
43
"is written.]"
44
"[n:name?Write the name instead of the numeric ID.]"
45
"[r:real?Writes real ID instead of the effective ID.]"
46
"[[a?This option is ignored.]"
47
"[g:group?Writes only the group ID.]"
48
"[u:user?Writes only the user ID.]"
49
"[G:groups?Writes only the supplementary group IDs.]"
50
"[s:fair-share?Writes fair share scheduler IDs and groups on systems that "
51
"support fair share scheduling.]"
52
"\n"
53
"\n[user]\n"
54
"\n"
55
"[+EXIT STATUS?]{"
56
"[+0?Successful completion.]"
57
"[+>0?An error occurred.]"
58
"}"
59
"[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2)]"
60
;
61
62
#include <cmd.h>
63
64
#include "FEATURE/ids"
65
66
#include <grp.h>
67
#include <pwd.h>
68
69
#if _lib_fsid
70
#if _lib_getfsgid && ( _sys_fss || _hdr_fsg )
71
#define fss_grp fs_grp
72
#define fss_id fs_id
73
#define fss_mem fs_mem
74
#define fss_passwd fs_passwd
75
#define fss_shares fs_shares
76
#if _sys_fss
77
#include <sys/fss.h>
78
#endif
79
#if _hdr_fsg
80
#include <fsg.h>
81
#endif
82
#if !_lib_isfsg && !defined(isfsg)
83
#define isfsg(p) (!(p)->fs_id&&!(p)->fs_shares&&(!(p)->fs_passwd||!*(p)->fs_passwd))
84
#endif
85
#else
86
#undef _lib_fsid
87
#endif
88
#endif
89
90
#define power2(n) (!((n)&((n)-1)))
91
92
#define GG_FLAG (1<<0)
93
#define G_FLAG (1<<1)
94
#define N_FLAG (1<<2)
95
#define R_FLAG (1<<3)
96
#define U_FLAG (1<<4)
97
#define S_FLAG (1<<5)
98
#define O_FLAG (1<<6)
99
#define X_FLAG (1<<7)
100
101
#if _lib_fsid
102
static void
103
getfsids(Sfio_t* sp, const char* name, int flags, register int lastchar)
104
{
105
register struct fsg* fs;
106
register char* s;
107
register char** p;
108
char** x;
109
110
if (lastchar)
111
{
112
if (flags & O_FLAG) flags = 1;
113
else flags = 0;
114
}
115
else if (flags & N_FLAG) flags = 1;
116
else flags = -1;
117
setfsgent();
118
while (fs = getfsgnam(name))
119
if (!isfsg(fs))
120
{
121
if (p = fs->fs_mem)
122
{
123
if (flags > 0) x = 0;
124
else
125
{
126
register char** q;
127
register char* t;
128
register int n;
129
130
n = 0;
131
q = p;
132
while (s = *q++)
133
n += strlen(s) + 1;
134
if (!(x = newof(0, char*, q - p, n)))
135
break;
136
s = (char*)(x + (q - p));
137
q = x;
138
while (t = *p++)
139
{
140
*q++ = s;
141
while (*s++ = *t++);
142
}
143
*q = 0;
144
p = x;
145
}
146
while (s = *p++)
147
{
148
if (lastchar == '=')
149
{
150
lastchar = ',';
151
sfputr(sp, " fsid=", -1);
152
}
153
else if (!lastchar) lastchar = ' ';
154
else sfputc(sp, lastchar);
155
if (flags > 0) sfprintf(sp, "%s", s);
156
else
157
{
158
setfsgent();
159
while (fs = getfsgnam(s))
160
if (isfsg(fs))
161
{
162
if (flags < 0) sfprintf(sp, "%u", fs->fs_id);
163
else sfprintf(sp, "%u(%s)", fs->fs_id, s);
164
break;
165
}
166
}
167
}
168
if (x) free(x);
169
}
170
break;
171
}
172
endfsgent();
173
if (lastchar == ' ') sfputc(sp, '\n');
174
}
175
#endif
176
177
static void
178
putid(Sfio_t* sp, int flags, const char* label, const char* name, long number)
179
{
180
sfprintf(sp, "%s=", label);
181
if (flags & O_FLAG)
182
{
183
if (name) sfputr(sp, name, -1);
184
else sfprintf(sp, "%lu", number);
185
}
186
else
187
{
188
sfprintf(sp, "%u", number);
189
if (name) sfprintf(sp, "(%s)", name);
190
}
191
}
192
193
static int
194
getids(Sfio_t* sp, const char* name, register int flags)
195
{
196
register struct passwd* pw;
197
register struct group* grp;
198
register int i;
199
register int j;
200
register int k;
201
#if _lib_fsid
202
register struct fsg* fs;
203
const char* fs_name;
204
int fs_id;
205
#endif
206
char** p;
207
char* s;
208
int lastchar;
209
int ngroups = 0;
210
const char* gname;
211
uid_t user;
212
uid_t euid;
213
gid_t group;
214
gid_t egid;
215
216
static gid_t* groups;
217
218
if (flags & GG_FLAG)
219
{
220
static int maxgroups;
221
222
/*
223
* get supplemental groups if required
224
*/
225
226
if (!maxgroups)
227
{
228
/*
229
* first time
230
*/
231
232
if ((maxgroups = getgroups(0, groups)) <= 0)
233
maxgroups = NGROUPS_MAX;
234
if (!(groups = newof(0, gid_t, maxgroups + 1, 0)))
235
error(ERROR_exit(1), "out of space [group array]");
236
}
237
ngroups = getgroups(maxgroups, groups);
238
for (i = j = 0; i < ngroups; i++)
239
{
240
for (k = 0; k < j && groups[k] != groups[i]; k++);
241
if (k >= j) groups[j++] = groups[i];
242
}
243
ngroups = j;
244
}
245
if (name)
246
{
247
flags |= X_FLAG;
248
if (!(flags & N_FLAG) || (flags & (G_FLAG|GG_FLAG)))
249
{
250
if (!(pw = getpwnam(name)))
251
{
252
user = strtol(name, &s, 0);
253
if (*s || !(pw = getpwuid(user)))
254
error(ERROR_exit(1), "%s: name not found", name);
255
name = pw->pw_name;
256
}
257
user = pw->pw_uid;
258
group = pw->pw_gid;
259
}
260
#if _lib_fsid
261
if (!(flags & N_FLAG) || (flags & S_FLAG))
262
{
263
setfsgent();
264
do
265
{
266
if (!(fs = getfsgnam(name)))
267
error(ERROR_exit(1), "%u: fss name not found", name);
268
} while (isfsg(fs));
269
fs_id = fs->fs_id;
270
}
271
#endif
272
}
273
else
274
{
275
if (flags & G_FLAG)
276
group = (flags & R_FLAG) ? getgid() : getegid();
277
if (flags & (GG_FLAG|N_FLAG|U_FLAG))
278
user = (flags & R_FLAG) ? getuid() : geteuid();
279
#if _lib_fsid
280
if (flags & S_FLAG)
281
fs_id = fsid(0);
282
#endif
283
if (flags & N_FLAG)
284
name = (pw = getpwuid(user)) ? pw->pw_name : (char*)0;
285
}
286
if (ngroups == 1 && groups[0] == group)
287
ngroups = 0;
288
if ((flags & N_FLAG) && (flags & G_FLAG))
289
gname = (grp = getgrgid(group)) ? grp->gr_name : (char*)0;
290
#if _lib_fsid
291
if ((flags & N_FLAG) && (flags & S_FLAG))
292
{
293
setfsgent();
294
fs_name = (fs = getfsgid(fs_id)) ? fs->fs_grp : (char*)0;
295
}
296
#endif
297
if ((flags & (U_FLAG|G_FLAG|S_FLAG)) == (U_FLAG|G_FLAG|S_FLAG))
298
{
299
putid(sp, flags, "uid", name, user);
300
putid(sp, flags, " gid", gname, group);
301
if ((flags & X_FLAG) && name)
302
{
303
#if _lib_getgrent
304
#if _lib_setgrent
305
setgrent();
306
#endif
307
lastchar = '=';
308
while (grp = getgrent())
309
if (p = grp->gr_mem)
310
while (s = *p++)
311
if (streq(s, name))
312
{
313
if (lastchar == '=')
314
sfputr(sp, " groups", -1);
315
sfputc(sp, lastchar);
316
lastchar = ',';
317
if (flags & O_FLAG)
318
sfprintf(sp, "%s", grp->gr_name);
319
else sfprintf(sp, "%u(%s)", grp->gr_gid, grp->gr_name);
320
}
321
#if _lib_endgrent
322
endgrent();
323
#endif
324
#endif
325
#if _lib_fsid
326
getfsids(sp, name, flags, '=');
327
#endif
328
}
329
else
330
{
331
if ((euid = geteuid()) != user)
332
putid(sp, flags, " euid", (pw = getpwuid(euid)) ? pw->pw_name : (char*)0, euid);
333
if ((egid = getegid()) != group)
334
putid(sp, flags, " egid", (grp = getgrgid(egid)) ? grp->gr_name : (char*)0, egid);
335
if (ngroups > 0)
336
{
337
sfputr(sp, " groups", -1);
338
lastchar = '=';
339
for (i = 0; i < ngroups; i++)
340
{
341
group = groups[i];
342
sfputc(sp, lastchar);
343
if (grp = getgrgid(group))
344
{
345
if (flags & O_FLAG) sfprintf(sp, "%s", grp->gr_name);
346
else sfprintf(sp, "%u(%s)", group, grp->gr_name);
347
}
348
else sfprintf(sp, "%u", group);
349
lastchar = ',';
350
}
351
}
352
#if _lib_fsid
353
putid(sp, flags, " fsid", fs_name, fs_id);
354
#endif
355
}
356
sfputc(sp,'\n');
357
return(0);
358
}
359
if (flags & U_FLAG)
360
{
361
if ((flags & N_FLAG) && name) sfputr(sp, name, '\n');
362
else sfprintf(sp, "%u\n", user);
363
}
364
else if (flags & G_FLAG)
365
{
366
if ((flags & N_FLAG) && gname) sfputr(sp, gname, '\n');
367
else sfprintf(sp, "%u\n", group);
368
}
369
else if (flags & GG_FLAG)
370
{
371
if ((flags & X_FLAG) && name)
372
{
373
#if _lib_getgrent
374
#if _lib_setgrent
375
setgrent();
376
#endif
377
i = 0;
378
while (grp = getgrent())
379
if (p = grp->gr_mem)
380
while (s = *p++)
381
if (streq(s, name))
382
{
383
if (i++) sfputc(sp, ' ');
384
if (flags & N_FLAG) sfprintf(sp, "%s", grp->gr_name);
385
else sfprintf(sp, "%u", grp->gr_gid);
386
}
387
#if _lib_endgrent
388
endgrent();
389
#endif
390
if (i) sfputc(sp, '\n');
391
#endif
392
}
393
else if (ngroups > 0)
394
{
395
for (i = 0;;)
396
{
397
group = groups[i];
398
if ((flags & N_FLAG) && (grp = getgrgid(group)))
399
sfprintf(sp, "%s", grp->gr_name);
400
else sfprintf(sp, "%u", group);
401
if (++i >= ngroups) break;
402
sfputc(sp, ' ');
403
}
404
sfputc(sp, '\n');
405
}
406
}
407
#if _lib_fsid
408
else if (flags & S_FLAG)
409
{
410
if ((flags & X_FLAG) && name) getfsids(sp, name, flags, 0);
411
else if ((flags & N_FLAG) && fs_name) sfputr(sp, fs_name, '\n');
412
else sfprintf(sp, "%u\n", fs_id);
413
}
414
#endif
415
return(0);
416
}
417
418
int
419
b_id(int argc, char** argv, Shbltin_t* context)
420
{
421
register int flags = 0;
422
register int n;
423
424
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
425
for (;;)
426
{
427
switch (optget(argv, usage))
428
{
429
case 'a':
430
continue;
431
case 'G':
432
flags |= GG_FLAG;
433
continue;
434
case 'g':
435
flags |= G_FLAG;
436
continue;
437
case 'n':
438
flags |= N_FLAG;
439
continue;
440
case 'r':
441
flags |= R_FLAG;
442
continue;
443
case 's':
444
flags |= S_FLAG;
445
continue;
446
case 'u':
447
flags |= U_FLAG;
448
continue;
449
case ':':
450
error(2, "%s", opt_info.arg);
451
break;
452
case '?':
453
error(ERROR_usage(2), "%s", opt_info.arg);
454
break;
455
}
456
break;
457
}
458
argv += opt_info.index;
459
argc -= opt_info.index;
460
n = (flags & (GG_FLAG|G_FLAG|S_FLAG|U_FLAG));
461
if (!power2(n))
462
error(2, "incompatible options selected");
463
if (error_info.errors || argc > 1)
464
error(ERROR_usage(2), "%s", optusage(NiL));
465
if (!(flags & ~(N_FLAG|R_FLAG)))
466
{
467
if (flags & N_FLAG) flags |= O_FLAG;
468
flags |= (U_FLAG|G_FLAG|N_FLAG|R_FLAG|S_FLAG|GG_FLAG);
469
}
470
error_info.errors = getids(sfstdout, *argv, flags);
471
return(error_info.errors);
472
}
473
474