1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#define FOR_useradd
30#include "toys.h"
31
32GLOBALS(
33 char *dir;
34 char *gecos;
35 char *shell;
36 char *u_grp;
37 long uid;
38
39 long gid;
40)
41
42void useradd_main(void)
43{
44 char *s = *toys.optargs, *entry;
45 struct passwd pwd;
46
47
48 if (toys.optc == 2) {
49 if (toys.optflags) help_exit("options with USER GROUP");
50 xexec((char *[]){"groupadd", toys.optargs[0], toys.optargs[1], 0});
51 }
52
53
54 if (s[strcspn(s, ":/\n")] || strlen(s) > LOGIN_NAME_MAX)
55 error_exit("bad username");
56
57 if (getpwnam(s)) error_exit("'%s' in use", s);
58
59
60
61
62
63
64 pwd.pw_name = s;
65 pwd.pw_passwd = "x";
66 pwd.pw_gecos = TT.gecos ? TT.gecos : "Linux User,";
67 pwd.pw_dir = TT.dir ? TT.dir : xmprintf("/home/%s", *toys.optargs);
68
69 if (!TT.shell) {
70 TT.shell = getenv("SHELL");
71
72 if (!TT.shell) {
73 struct passwd *pw = getpwuid(getuid());
74
75 if (pw && pw->pw_shell && *pw->pw_shell) TT.shell = xstrdup(pw->pw_shell);
76 else TT.shell = "/bin/sh";
77 }
78 }
79 pwd.pw_shell = TT.shell;
80
81 if (toys.optflags & FLAG_u) {
82 if (TT.uid > INT_MAX) error_exit("bad uid");
83 if (getpwuid(TT.uid)) error_exit("uid '%ld' in use", TT.uid);
84 } else {
85 if (toys.optflags & FLAG_S) TT.uid = CFG_TOYBOX_UID_SYS;
86 else TT.uid = CFG_TOYBOX_UID_USR;
87
88 while (getpwuid(TT.uid)) TT.uid++;
89 }
90 pwd.pw_uid = TT.uid;
91
92 if (toys.optflags & FLAG_G) TT.gid = xgetgrnam(TT.u_grp)->gr_gid;
93 else {
94
95 if (toys.optflags & FLAG_S) TT.gid = CFG_TOYBOX_UID_SYS;
96 else TT.gid = CFG_TOYBOX_UID_USR;
97 if (getgrnam(pwd.pw_name)) error_exit("group '%s' in use", pwd.pw_name);
98
99 while (getgrgid(TT.gid)) TT.gid++;
100 }
101 pwd.pw_gid = TT.gid;
102
103
104 if (!(toys.optflags & FLAG_G)) {
105 char *s = xmprintf("-g%ld", (long)pwd.pw_gid);
106
107 if (xrun((char *[]){"groupadd", *toys.optargs, s, 0}))
108 error_msg("addgroup -g%ld fail", (long)pwd.pw_gid);
109 free(s);
110 }
111
112
113
114
115
116
117
118
119 entry = xmprintf("%s:%s:%ld:%ld:%s:%s:%s", pwd.pw_name, pwd.pw_passwd,
120 (long)pwd.pw_uid, (long)pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir,
121 pwd.pw_shell);
122 if (update_password("/etc/passwd", pwd.pw_name, entry)) error_exit("updating passwd file failed");
123 free(entry);
124
125 if (toys.optflags & FLAG_S)
126 entry = xmprintf("%s:!!:%u::::::", pwd.pw_name,
127 (unsigned)(time(NULL))/(24*60*60));
128 else entry = xmprintf("%s:!!:%u:0:99999:7:::", pwd.pw_name,
129 (unsigned)(time(0))/(24*60*60));
130 update_password("/etc/shadow", pwd.pw_name, entry);
131 free(entry);
132
133
134 if (!(toys.optflags & (FLAG_S|FLAG_H))) {
135 char *skel = "/etc/skel", *p = pwd.pw_dir;
136
137
138 if (access(p, F_OK)) {
139 if (!access(skel, R_OK))
140 toys.exitval = xrun((char *[]){"cp", "-R", skel, p, 0});
141 else toys.exitval = xrun((char *[]){"mkdir", "-p", p, 0});
142 if (!toys.exitval)
143 toys.exitval |= xrun((char *[]){"chown", "-R",
144 xmprintf("%lu:%lu", TT.uid, TT.gid), p, 0});
145 wfchmodat(AT_FDCWD, p, 0700);
146 } else fprintf(stderr, "'%s' exists, not copying '%s'", p, skel);
147 }
148
149
150 if (!(toys.optflags & FLAG_D))
151 if (xrun((char *[]){"passwd", pwd.pw_name, 0})) error_exit("passwd");
152
153 if (toys.optflags & FLAG_G) {
154
155 if (xrun((char *[]){"groupadd", *toys.optargs, TT.u_grp, 0}))
156 error_exit("groupadd");
157 }
158}
159