]>
git.saurik.com Git - apple/system_cmds.git/blob - system_cmds-597.1.1/newgrp.tproj/newgrp.c
d0004f7823b8cbe5372b31637669a021f06ed56b
2 * Copyright (c) 2002 Tim J. Robbins.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * newgrp -- change to a new group
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD: src/usr.bin/newgrp/newgrp.c,v 1.5 2009/12/13 03:14:06 delphij Exp $");
34 #include <sys/types.h>
42 #include <login_cap.h>
43 #endif /* !__APPLE__ */
45 #include <membership.h>
46 #endif /* __APPLE__ */
54 #endif /* __APPLE__ */
55 static void addgroup(const char *grpname
);
56 static void doshell(void);
57 static int inarray(gid_t
, const gid_t
[], int);
58 static void loginshell(void);
59 static void restoregrps(void);
60 static void usage(void);
62 static struct passwd
*pwd
;
65 extern char **environ
;
67 /* Manipulate effective user ID. */
68 #define PRIV_START do { \
69 if (seteuid(euid) < 0) \
72 #define PRIV_END do { \
73 if (seteuid(getuid()) < 0) \
78 main(int argc
, char *argv
[])
83 if (seteuid(getuid()) < 0)
86 if ((pwd
= getpwuid(getuid())) == NULL
)
87 errx(1, "unknown user");
90 while ((ch
= getopt(argc
, argv
, "-l")) != -1) {
92 case '-': /* Obsolescent */
114 if (seteuid(euid
) < 0)
116 if (setuid(getuid()) < 0)
132 fprintf(stderr
, "usage: newgrp [-l] [group]\n");
142 initres
= initgroups(pwd
->pw_name
, pwd
->pw_gid
);
143 setres
= setgid(pwd
->pw_gid
);
153 addgroup(const char *grpname
)
156 long lgid
, ngrps_max
;
157 int dbmember
, i
, ngrps
;
171 /* Try it as a group name, then a group id. */
172 if ((grp
= getgrnam(grpname
)) == NULL
)
173 if ((lgid
= strtol(grpname
, &ep
, 10)) <= 0 || *ep
!= '\0' ||
174 (grp
= getgrgid((gid_t
)lgid
)) == NULL
) {
175 warnx("%s: bad group name", grpname
);
180 status
= mbr_uid_to_uuid(pwd
->pw_uid
, user_uuid
);
182 errc(1, status
, "mbr_uid_to_uuid");
184 status
= mbr_gid_to_uuid(grp
->gr_gid
, group_uuid
);
186 errc(1, status
, "mbr_gid_to_uuid");
188 status
= mbr_check_membership(user_uuid
, group_uuid
, &dbmember
);
190 errc(1, status
, "mbr_check_membership");
193 * If the user is not a member of the requested group and the group
194 * has a password, prompt and check it.
197 if (pwd
->pw_gid
== grp
->gr_gid
)
199 for (p
= grp
->gr_mem
; *p
!= NULL
; p
++)
200 if (strcmp(*p
, pwd
->pw_name
) == 0) {
206 grp_passwd
= grp
->gr_passwd
;
207 if ((grp_passwd
== NULL
) || (grp_passwd
[0] == '\0'))
209 if (!dbmember
&& getuid() != 0) {
210 pass
= getpass("Password:");
212 strcmp(grp_passwd
, crypt(pass
, grp_passwd
)) != 0) {
213 fprintf(stderr
, "Sorry\n");
218 ngrps_max
= sysconf(_SC_NGROUPS_MAX
) + 1;
219 if ((grps
= malloc(sizeof(gid_t
) * ngrps_max
)) == NULL
)
221 if ((ngrps
= getgroups(ngrps_max
, (gid_t
*)grps
)) < 0) {
226 /* Remove requested gid from supp. list if it exists. */
227 if (grp
->gr_gid
!= egid
&& inarray(grp
->gr_gid
, grps
, ngrps
)) {
228 for (i
= 0; i
< ngrps
; i
++)
229 if (grps
[i
] == grp
->gr_gid
)
232 memmove(&grps
[i
], &grps
[i
+ 1], (ngrps
- i
) * sizeof(gid_t
));
234 if (setgroups(ngrps
, (const gid_t
*)grps
) < 0) {
243 if (setgid(grp
->gr_gid
)) {
249 grps
[0] = grp
->gr_gid
;
251 /* Add old effective gid to supp. list if it does not exist. */
252 if (egid
!= grp
->gr_gid
&& !inarray(egid
, grps
, ngrps
)) {
253 if (ngrps
+ 1 >= ngrps_max
)
254 warnx("too many groups");
256 grps
[ngrps
++] = egid
;
258 if (setgroups(ngrps
, (const gid_t
*)grps
)) {
272 inarray(gid_t gid
, const gid_t grps
[], int ngrps
)
276 for (i
= 0; i
< ngrps
; i
++)
283 * Set the environment to what would be expected if the user logged in
284 * again; this performs the same steps as su(1)'s -l option.
289 char *args
[2], **cleanenv
, *term
, *ticket
;
291 char *prog
, progbuf
[PATH_MAX
];
294 #endif /* !__APPLE__ */
295 shell
= pwd
->pw_shell
;
297 shell
= _PATH_BSHELL
;
298 if (chdir(pwd
->pw_dir
) < 0) {
299 warn("%s", pwd
->pw_dir
);
303 term
= getenv("TERM");
304 ticket
= getenv("KRBTKFILE");
306 if ((cleanenv
= calloc(20, sizeof(char *))) == NULL
)
311 lc
= login_getpwclass(pwd
);
312 setusercontext(lc
, pwd
, pwd
->pw_uid
,
313 LOGIN_SETPATH
|LOGIN_SETUMASK
|LOGIN_SETENV
);
315 #endif /* !__APPLE__ */
316 setenv("USER", pwd
->pw_name
, 1);
317 setenv("SHELL", shell
, 1);
318 setenv("HOME", pwd
->pw_dir
, 1);
320 setenv("TERM", term
, 1);
322 setenv("KRBTKFILE", ticket
, 1);
324 strlcpy(progbuf
, shell
, sizeof(progbuf
));
325 prog
= basename(progbuf
);
327 if (asprintf(args
, "-%s", prog
) < 0)
339 char *prog
, progbuf
[PATH_MAX
];
341 shell
= pwd
->pw_shell
;
343 shell
= _PATH_BSHELL
;
345 strlcpy(progbuf
, shell
, sizeof(progbuf
));
346 prog
= basename(progbuf
);
348 execl(shell
, prog
, (char *)NULL
);