* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
static char sccsid
[] = "@(#)su.c 5.4 (Berkeley) %G%";
#include <sys/resource.h>
char userbuf
[16] = "USER=";
char homebuf
[128] = "HOME=";
char shellbuf
[128] = "SHELL=";
char pathbuf
[128] = "PATH=:/usr/ucb:/bin:/usr/bin";
char *cleanenv
[] = { userbuf
, homebuf
, shellbuf
, pathbuf
, 0, 0 };
openlog("su", LOG_ODELAY
, LOG_AUTH
);
if (argc
> 1 && strcmp(argv
[1], "-f") == 0) {
if (argc
> 1 && strcmp(argv
[1], "-") == 0) {
if (argc
> 1 && argv
[1][0] != '-') {
if ((pwd
= getpwuid(getuid())) == NULL
) {
fprintf(stderr
, "Who are you?\n");
strcpy(buf
, pwd
->pw_name
);
if ((pwd
= getpwnam(user
)) == NULL
) {
fprintf(stderr
, "Unknown login: %s\n", user
);
* Only allow those in group zero to su to root.
if ((gr
= getgrgid(0)) != NULL
) {
for (i
= 0; gr
->gr_mem
[i
] != NULL
; i
++)
if (strcmp(buf
, gr
->gr_mem
[i
]) == 0)
fprintf(stderr
, "You do not have permission to su %s\n",
setpriority(PRIO_PROCESS
, 0, -2);
#define Getlogin() (((p = getlogin()) && *p) ? p : buf)
if (pwd
->pw_passwd
[0] == '\0' || getuid() == 0)
password
= getpass("Password:");
if (strcmp(pwd
->pw_passwd
, crypt(password
, pwd
->pw_passwd
)) != 0) {
fprintf(stderr
, "Sorry\n");
syslog(LOG_CRIT
, "BAD SU %s on %s",
syslog(LOG_NOTICE
, "%s on %s", Getlogin(), ttyname(2));
if (setgid(pwd
->pw_gid
) < 0) {
if (initgroups(user
, pwd
->pw_gid
)) {
fprintf(stderr
, "su: initgroups failed\n");
if (setuid(pwd
->pw_uid
) < 0) {
if (pwd
->pw_shell
&& *pwd
->pw_shell
)
cleanenv
[4] = getenv("TERM");
if (strcmp(user
, "root"))
setenv("USER", pwd
->pw_name
, userbuf
);
setenv("SHELL", shell
, shellbuf
);
setenv("HOME", pwd
->pw_dir
, homebuf
);
setpriority(PRIO_PROCESS
, 0, 0);
if (chdir(pwd
->pw_dir
) < 0) {
fprintf(stderr
, "No directory\n");
fprintf(stderr
, "No shell\n");
char *ename
, *eval
, *buf
;
register char **ep
= environ
;
* this assumes an environment variable "ename" already exists
for (cp
= ename
; *cp
== *dp
&& *cp
; cp
++, dp
++)
if (*cp
== 0 && (*dp
== '=' || *dp
== 0)) {
register char **ep
= environ
;
for (cp
= ename
; *cp
== *dp
&& *cp
; cp
++, dp
++)
if (*cp
== 0 && (*dp
== '=' || *dp
== 0))