Skip to content

Commit 61052c0

Browse files
committed
id: Add id.py
1 parent 6159754 commit 61052c0

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

src/id.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/python3
2+
3+
import grp
4+
import pwd
5+
import os
6+
import sys
7+
from optparse import OptionParser
8+
9+
10+
def _id(opts, users: list[str]):
11+
process_uid = os.getuid() if opts.real else os.geteuid()
12+
process_gid = os.getgid() if opts.real else os.getegid()
13+
14+
failed = False
15+
16+
for user in users or [str(process_uid)]:
17+
try:
18+
passwd = pwd.getpwnam(user)
19+
except KeyError as e:
20+
try:
21+
passwd = pwd.getpwuid(int(user))
22+
except (KeyError, ValueError):
23+
failed = True
24+
print(e, file=sys.stderr)
25+
continue
26+
27+
if opts.user:
28+
print(
29+
passwd.pw_name if opts.name else passwd.pw_uid,
30+
end="\0" if opts.zero else "\n",
31+
)
32+
continue
33+
34+
gid = process_gid if passwd.pw_uid == process_uid else passwd.pw_gid
35+
36+
if opts.group:
37+
print(
38+
grp.getgrgid(gid) if opts.name else gid,
39+
end="\0" if opts.zero else "\n",
40+
)
41+
continue
42+
43+
if opts.groups:
44+
print(
45+
("\0" if opts.zero else "\n").join(
46+
map(str, os.getgrouplist(passwd.pw_name, gid))
47+
),
48+
end="\0" if opts.zero else "\n",
49+
)
50+
continue
51+
52+
print(
53+
f"uid={passwd.pw_uid}({passwd.pw_name})"
54+
+ f" gid={passwd.pw_gid}({grp.getgrgid(passwd.pw_gid).gr_name})"
55+
+ " groups="
56+
+ ",".join(
57+
[
58+
f"{id}({grp.getgrgid(id).gr_name})"
59+
for id in os.getgrouplist(passwd.pw_name, passwd.pw_gid)
60+
]
61+
),
62+
)
63+
64+
if failed:
65+
sys.exit(1)
66+
67+
68+
if __name__ == "__main__":
69+
parser = OptionParser(
70+
usage="Usage: %prog [OPTION]... [USER]...",
71+
description="Print user and group information for each USER or the current user.",
72+
add_help_option=False,
73+
)
74+
parser.add_option("--help", action="help", help="show usage information and exit")
75+
76+
parser.add_option(
77+
"-u", "--user", action="store_true", help="print only the effective user ID"
78+
)
79+
parser.add_option(
80+
"-g", "--group", action="store_true", help="print only the effective group ID"
81+
)
82+
parser.add_option("-G", "--groups", action="store_true", help="print all group IDs")
83+
84+
parser.add_option(
85+
"-n",
86+
"--name",
87+
action="store_true",
88+
help="print names instead of numbers (for -ugG)",
89+
)
90+
parser.add_option(
91+
"-r",
92+
"--real",
93+
action="store_true",
94+
help="print the real ID instead of the effective ID (for -ugG)",
95+
)
96+
parser.add_option(
97+
"-z",
98+
"--zero",
99+
action="store_true",
100+
help="delimit entries with NUL instead of whitespace (for -ugG)",
101+
)
102+
103+
parser.add_option(
104+
"-a", action="store_true", help="(ignored; present for compatibility)"
105+
)
106+
parser.add_option("-Z", "--context", action="store_true", help="(unimplemented)")
107+
108+
opts, args = parser.parse_args()
109+
110+
if opts.context:
111+
parser.error("--context (-Z) is not supported")
112+
113+
if (ugG := (opts.user, opts.group, opts.groups)).count(True) > 1:
114+
parser.error("cannot print more than one of -ugG")
115+
116+
if opts.name or opts.real and not any(ugG):
117+
parser.error("cannot print only names or real IDs in default format")
118+
119+
if opts.zero and not any(ugG):
120+
parser.error("option --zero not permitted in default format")
121+
122+
_id(opts, args)

0 commit comments

Comments
 (0)