forget difference between big and small commands - obsolete with vm.
[minix.git] / commands / simple / su.c
blob91d620b2618c646638a326f020e140d295dbbcaa
1 /* su - become super-user Author: Patrick van Kleef */
3 #include <sys/types.h>
4 #include <pwd.h>
5 #include <grp.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <limits.h>
11 #include <fcntl.h>
12 #include <time.h>
13 #if __minix_vmd
14 #include <sys/syslog.h>
15 #endif
16 #include <minix/minlib.h>
18 _PROTOTYPE(int main, (int argc, char **argv));
20 int main(argc, argv)
21 int argc;
22 char *argv[];
24 register char *name, *password;
25 char *shell, sh0[100];
26 char from_user[8+1], from_shell[100];
27 register struct passwd *pwd;
28 char USER[20], LOGNAME[25], HOME[100], SHELL[100];
29 char *envv[20], **envp;
30 int smallenv;
31 char *p;
32 int super;
33 int loginshell;
34 gid_t groups[NGROUPS_MAX];
35 int ngroups;
36 int g;
38 smallenv = 0;
39 loginshell = 0;
40 if (argc > 1 && (strcmp(argv[1], "-") == 0 || strcmp(argv[1], "-e") == 0)) {
41 if (argv[1][1] == 0)
42 loginshell= 1; /* 'su -' reads .profile */
43 argv[1] = argv[0];
44 argv++;
45 argc--;
46 smallenv = 1; /* Use small environment. */
48 if (argc > 1) {
49 if (argv[1][0] == '-') {
50 fprintf(stderr,
51 "Usage: su [-[e]] [user [shell-arguments ...]]\n");
52 exit(1);
54 name = argv[1];
55 argv[1] = argv[0];
56 argv++;
57 } else {
58 name = "root";
61 if ((pwd = getpwuid(getuid())) == 0) {
62 fprintf(stderr, "You do not exist\n");
63 exit(1);
65 strncpy(from_user, pwd->pw_name, 8);
66 from_user[8]= 0;
67 strncpy(from_shell, pwd->pw_shell[0] == '\0' ? "/bin/sh" : pwd->pw_shell,
68 sizeof(from_shell)-1);
69 from_shell[sizeof(from_shell)-1]= 0;
71 if ((pwd = getpwnam(name)) == 0) {
72 fprintf(stderr, "Unknown id: %s\n", name);
73 exit(1);
75 super = 0;
76 if (getgid() == 0) super = 1;
77 ngroups = getgroups(NGROUPS_MAX, groups);
78 for (g = 0; g < ngroups; g++) if (groups[g] == 0) super = 1;
80 if (!super && strcmp(pwd->pw_passwd, crypt("", pwd->pw_passwd)) != 0) {
81 #if __minix_vmd
82 openlog("su", 0, LOG_AUTH);
83 #endif
84 password = getpass("Password:");
85 if (password == 0
86 || strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
87 if (password != 0 && *password != 0) {
88 #if __minix_vmd
89 syslog(LOG_WARNING, "su %s failed for %s",
90 name, from_user);
91 #endif
93 fprintf(stderr, "Sorry\n");
94 exit(2);
96 #if __minix_vmd
97 syslog(LOG_NOTICE, "su %s succeeded for %s", name, from_user);
98 closelog();
99 #endif
102 initgroups(pwd->pw_name, pwd->pw_gid);
103 setgid(pwd->pw_gid);
104 setuid(pwd->pw_uid);
105 if (loginshell) {
106 shell = pwd->pw_shell[0] == '\0' ? "/bin/sh" : pwd->pw_shell;
107 } else {
108 if ((shell = getenv("SHELL")) == NULL) shell = from_shell;
110 if ((p= strrchr(shell, '/')) == 0) p= shell; else p++;
111 sh0[0]= '-';
112 strcpy(loginshell ? sh0+1 : sh0, p);
113 argv[0]= sh0;
115 if (smallenv) {
116 envp = envv;
117 *envp++ = "PATH=:/bin:/usr/bin",
118 strcpy(USER, "USER=");
119 strcpy(USER + 5, name);
120 *envp++ = USER;
121 strcpy(LOGNAME, "LOGNAME=");
122 strcpy(LOGNAME + 8, name);
123 *envp++ = LOGNAME;
124 strcpy(SHELL, "SHELL=");
125 strcpy(SHELL + 6, shell);
126 *envp++ = SHELL;
127 strcpy(HOME, "HOME=");
128 strcpy(HOME + 5, pwd->pw_dir);
129 *envp++ = HOME;
130 if ((p = getenv("TERM")) != NULL) {
131 *envp++ = p - 5;
133 if ((p = getenv("TERMCAP")) != NULL) {
134 *envp++ = p - 8;
136 if ((p = getenv("TZ")) != NULL) {
137 *envp++ = p - 3;
139 *envp = NULL;
140 (void) chdir(pwd->pw_dir);
141 execve(shell, argv, envv);
142 perror(shell);
143 } else {
144 execv(shell, argv);
145 perror(shell);
147 fprintf(stderr, "No shell\n");
148 return(3);