Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / cmd / newgrp / newgrp.c
blob8523c71130ac8e53d051e592cbb7c6bc388ab66c
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
33 * newgrp [-l | -] [group]
35 * rules
36 * if no arg, group id in password file is used
37 * else if group id == id in password file
38 * else if login name is in member list
39 * else if password is present and user knows it
40 * else too bad
42 #include <stdio.h>
43 #include <sys/types.h>
44 #include <pwd.h>
45 #include <grp.h>
46 #include <crypt.h>
47 #include <string.h>
48 #include <stdlib.h>
49 #include <locale.h>
50 #include <syslog.h>
51 #include <unistd.h>
53 #define SHELL "/usr/bin/sh"
55 #define PATH "PATH=:/usr/bin:"
56 #define SUPATH "PATH=:/usr/sbin:/usr/bin"
57 #define ELIM 128
59 char PW[] = "newgrp: Password: ";
60 char NG[] = "newgrp: Sorry";
61 char PD[] = "newgrp: Permission denied";
62 char UG[] = "newgrp: Unknown group";
63 char NS[] = "newgrp: You have no shell";
65 char *homedir;
66 char *logname;
68 char *envinit[ELIM];
69 extern char **environ;
70 char *path = PATH;
71 char *supath = SUPATH;
73 void error(char *s) __NORETURN;
74 static void warn(char *s);
75 void usage(void);
77 int
78 main(int argc, char *argv[])
80 struct passwd *p;
81 gid_t chkgrp();
82 int eflag = 0;
83 int flag;
84 uid_t uid;
85 char *shell, *dir, *name;
86 size_t len;
88 #ifdef DEBUG
89 chroot(".");
90 #endif
92 (void) setlocale(LC_ALL, "");
93 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
94 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
95 #endif
96 (void) textdomain(TEXT_DOMAIN);
98 if ((p = getpwuid(getuid())) == NULL)
99 error(NG);
100 endpwent();
102 while ((flag = getopt(argc, argv, "l")) != EOF) {
103 switch (flag) {
104 case 'l':
105 eflag++;
106 break;
108 default:
109 usage();
110 break;
114 argc -= optind;
115 argv = &argv[optind];
117 if (argc > 0 && *argv[0] == '-') {
118 if (eflag)
119 usage();
120 eflag++;
121 argv++;
122 --argc;
125 if (argc > 0)
126 p->pw_gid = chkgrp(argv[0], p);
128 uid = p->pw_uid;
130 len = strlen(p->pw_dir) + 1;
131 if ((dir = (char *)malloc(len)) == NULL)
132 error("newgrp: Memory request failed");
133 (void) strncpy(dir, p->pw_dir, len);
134 len = strlen(p->pw_name) + 1;
135 if ((name = (char *)malloc(len)) == NULL)
136 error("newgrp: Memory request failed");
137 (void) strncpy(name, p->pw_name, len);
139 if (setgid(p->pw_gid) < 0 || setuid(getuid()) < 0)
140 error(NG);
142 if (!*p->pw_shell) {
143 if ((shell = getenv("SHELL")) != NULL) {
144 p->pw_shell = shell;
145 } else {
146 p->pw_shell = SHELL;
150 if (eflag) {
151 char *simple;
153 len = strlen(dir) + 6;
154 if ((homedir = (char *)malloc(len)) == NULL)
155 error("newgrp: Memory request failed");
156 (void) snprintf(homedir, len, "HOME=%s", dir);
157 len = strlen(name) + 9;
158 if ((logname = (char *)malloc(len)) == NULL)
159 error("newgrp: Memory request failed");
160 (void) snprintf(logname, len, "LOGNAME=%s", name);
163 envinit[2] = logname;
164 (void) chdir(dir);
165 envinit[0] = homedir;
166 if (uid == 0)
167 envinit[1] = supath;
168 else
169 envinit[1] = path;
170 envinit[3] = NULL;
171 environ = envinit;
173 len = strlen(p->pw_shell) + 2;
174 if ((shell = (char *)malloc(len)) == NULL)
175 error("newgrp: Memory request failed");
176 (void) snprintf(shell, len, "-%s", p->pw_shell);
177 simple = strrchr(shell, '/');
178 if (simple) {
179 *(shell+1) = '\0';
180 shell = strcat(shell, ++simple);
183 else
184 shell = p->pw_shell;
186 (void) execl(p->pw_shell, shell, NULL);
187 warn(NS);
188 return (1);
191 static void
192 warn(char *s)
194 (void) fprintf(stderr, "%s\n", gettext(s));
197 void
198 error(char *s)
200 warn(s);
201 exit(1);
204 gid_t
205 chkgrp(gname, p)
206 char *gname;
207 struct passwd *p;
209 char **t;
210 struct group *g;
212 g = getgrnam(gname);
213 endgrent();
214 if (g == NULL) {
215 warn(UG);
216 return (getgid());
218 if (p->pw_gid == g->gr_gid || getuid() == 0) {
219 return (g->gr_gid);
221 for (t = g->gr_mem; *t; ++t) {
222 if (strcmp(p->pw_name, *t) == 0) {
223 return (g->gr_gid);
226 if (*g->gr_passwd) {
227 if (!isatty(fileno(stdin))) {
228 error(PD);
230 if (strcmp(g->gr_passwd,
231 crypt(getpassphrase(PW), g->gr_passwd)) == 0) {
232 return (g->gr_gid);
235 warn(NG);
236 return (getgid());
239 void
240 usage(void)
242 (void) fprintf(stderr, gettext(
243 "usage: newgrp [-l | -] [group]\n"));
244 exit(2);