]>
Commit | Line | Data |
---|---|---|
7283d000 | 1 | /* |
2 | * Copyright 1988 by the Massachusetts Institute of Technology. For copying | |
3 | * and distribution information, see the file "mit-copyright.h". | |
4 | * | |
5 | * $Source$ | |
6 | * $Header$ | |
7 | * $Author$ | |
8 | * | |
9 | */ | |
10 | ||
11 | #ifndef lint | |
12 | static char *rcsid_chsh_c = "$Header$"; | |
13 | #endif not lint | |
14 | ||
15 | /* | |
8defc06b | 16 | * Talk to the MOIRA database to change a person's login shell. The chosen |
7283d000 | 17 | * shell must exist. A warning will be issued if the shell is not in |
18 | * /etc/shells. | |
19 | * | |
20 | * chsh with no modifiers changes the shell of the user who is running | |
21 | * the program. | |
22 | * | |
23 | * If a commandline argument is given, it is taken to be the username | |
24 | * of the user whose shell is to be changed. | |
25 | * | |
26 | */ | |
27 | ||
b687d789 | 28 | #ifdef POSIX |
29 | #include <unistd.h> | |
30 | #endif | |
7283d000 | 31 | #include <sys/types.h> |
32 | #include <stdio.h> | |
f071d8a7 | 33 | #include <string.h> |
7283d000 | 34 | #include <sys/file.h> |
35 | #include <krb.h> | |
36 | #include <ctype.h> | |
37 | #include <errno.h> | |
38 | ||
8defc06b | 39 | /* MOIRA includes */ |
40 | #include <moira.h> | |
41 | #include <moira_site.h> | |
7283d000 | 42 | #include "mit-copyright.h" |
43 | ||
44 | char *whoami; | |
45 | char *getusershell(); | |
46 | ||
7283d000 | 47 | main(argc, argv) |
48 | int argc; | |
49 | char *argv[]; | |
50 | { | |
51 | char pname[ANAME_SZ]; | |
52 | char *uname = pname; | |
53 | int k_errno; | |
54 | char *whoami; | |
55 | ||
f071d8a7 | 56 | if ((whoami = strrchr(argv[0], '/')) == NULL) |
7283d000 | 57 | whoami = argv[0]; |
58 | else | |
59 | whoami++; | |
60 | ||
61 | if (argc > 2) { | |
62 | usage(); | |
63 | } | |
64 | ||
65 | if (argc == 2) | |
66 | uname = argv[1]; | |
67 | else | |
68 | { | |
69 | /* Do it right; get name from kerberos ticket file rather than | |
70 | from passord file. */ | |
71 | ||
72 | if (k_errno = tf_init(TKT_FILE, R_TKT_FIL)) { | |
73 | fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]); | |
74 | exit(1); | |
75 | } | |
76 | ||
77 | if (k_errno = tf_get_pname(pname)) { | |
78 | fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]); | |
79 | exit(1); | |
80 | } | |
81 | ||
82 | tf_close(); | |
83 | } | |
84 | ||
85 | exit(chsh(uname)); | |
86 | } | |
87 | ||
88 | leave(status) | |
89 | int status; | |
8defc06b | 90 | /* This should be called rather than exit once connection to moira server |
7283d000 | 91 | has been established. */ |
92 | { | |
8defc06b | 93 | mr_disconnect(); |
7283d000 | 94 | exit(status); |
95 | } | |
96 | ||
97 | scream() | |
98 | { | |
95cd286e | 99 | com_err(whoami, 0, "Unexpected return value from Moira -- programmer botch"); |
7283d000 | 100 | leave(1); |
101 | } | |
102 | ||
103 | chsh(uname) | |
104 | char *uname; | |
105 | { | |
106 | int status; /* general purpose exit status */ | |
8defc06b | 107 | int q_argc; /* argc for mr_query */ |
108 | char *q_argv[U_END]; /* argv for mr_query */ | |
109 | char *motd; /* determine MR server status */ | |
7283d000 | 110 | |
111 | int got_one = 0; /* have we got a new shell yet? */ | |
112 | char shell[BUFSIZ]; /* the new shell */ | |
113 | int get_shell(); | |
114 | void check_shell(); /* make sure new shell is valid */ | |
115 | ||
116 | /* Try each query. If we ever fail, print error message and exit. */ | |
117 | ||
8defc06b | 118 | status = mr_connect(NULL); |
7283d000 | 119 | if (status) { |
95cd286e | 120 | com_err(whoami, status, " while connecting to Moira"); |
7283d000 | 121 | exit(1); |
122 | } | |
123 | ||
8defc06b | 124 | status = mr_motd(&motd); |
262ca740 | 125 | if (status) { |
126 | com_err(whoami, status, " unable to check server status"); | |
127 | leave(1); | |
128 | } | |
129 | if (motd) { | |
95cd286e | 130 | fprintf(stderr, "The Moira server is currently unavailable:\n%s\n", motd); |
262ca740 | 131 | leave(1); |
132 | } | |
133 | ||
8defc06b | 134 | status = mr_auth("chsh"); /* Don't use argv[0] - too easy to fake */ |
7283d000 | 135 | if (status) { |
136 | com_err(whoami, status, | |
137 | " while authenticating -- run \"kinit\" and try again."); | |
138 | leave(1); | |
139 | } | |
140 | ||
141 | /* First, do an access check */ | |
142 | ||
143 | q_argv[USH_NAME] = uname; | |
144 | q_argv[USH_SHELL] = "junk"; | |
145 | q_argc = USH_END; | |
146 | ||
8defc06b | 147 | if (status = mr_access("update_user_shell", q_argc, q_argv)) |
7283d000 | 148 | { |
149 | com_err(whoami, status, "; shell not\nchanged."); | |
150 | leave(2); | |
151 | } | |
152 | ||
153 | printf("Changing login shell for %s.\n", uname); | |
154 | ||
155 | /* Display current information */ | |
156 | ||
157 | q_argv[NAME] = uname; | |
158 | q_argc = NAME + 1; | |
159 | ||
7be7e273 | 160 | if ((status = mr_query("get_user_account_by_login", q_argc, q_argv, |
7283d000 | 161 | get_shell, (char *) uname))) |
162 | { | |
163 | com_err(whoami, status, " while getting user information."); | |
164 | leave(2); | |
165 | } | |
166 | ||
167 | /* Ask for new shell */ | |
168 | while (!got_one) | |
169 | { | |
170 | printf("New shell: "); | |
5bd0a4c4 | 171 | if (fgets(shell, sizeof(shell), stdin) == NULL) |
172 | leave(0); | |
7283d000 | 173 | got_one = (strlen(shell) > 1); |
174 | } | |
175 | ||
176 | shell[strlen(shell) - 1] = 0; /* strip off newline */ | |
177 | ||
178 | /* Make sure we have a valid shell. This routine could exit */ | |
179 | check_shell(shell); | |
180 | ||
181 | /* Change shell */ | |
182 | ||
183 | printf("Changing shell to %s...\n", shell); | |
184 | ||
185 | q_argv[USH_NAME] = uname; | |
186 | q_argv[USH_SHELL] = shell; | |
187 | q_argc = USH_END; | |
8defc06b | 188 | if (status = mr_query("update_user_shell", q_argc, q_argv, |
7283d000 | 189 | scream, (char *) NULL)) |
190 | { | |
191 | com_err(whoami, status, " while changing shell."); | |
192 | leave(2); | |
193 | } | |
194 | ||
195 | printf("Shell successfully changed.\n"); | |
8defc06b | 196 | mr_disconnect(); |
7283d000 | 197 | |
198 | return(0); | |
199 | } | |
200 | ||
201 | get_shell(argc, argv, uname) | |
202 | int argc; | |
203 | char **argv; | |
204 | char *uname; /* for sanity checking */ | |
205 | { | |
206 | /* We'll just take the first information we get since login names | |
207 | cannot be duplicated in the database. */ | |
208 | ||
b687d789 | 209 | if (argc < U_END || strcmp(argv[U_NAME], uname)) |
7283d000 | 210 | { |
211 | fprintf(stderr, "Some internal error has occurred. Try again.\n"); | |
212 | leave(3); | |
213 | } | |
214 | ||
215 | printf("Account information last changed on %s\n", argv[U_MODTIME]); | |
216 | printf("by user %s with %s.\n", argv[U_MODBY], argv[U_MODWITH]); | |
217 | printf("Current shell for %s is %s.\n", uname, argv[U_SHELL]); | |
218 | ||
8defc06b | 219 | return(MR_ABORT); /* Don't pay attention to other matches. */ |
7283d000 | 220 | } |
221 | ||
222 | void check_shell(shell) | |
223 | char *shell; | |
224 | { | |
225 | char *valid_shell; | |
226 | int ok = 0; | |
227 | ||
228 | while (valid_shell = getusershell()) { | |
229 | if (strcmp(shell, valid_shell) == NULL) { | |
230 | ok = 1; | |
231 | break; | |
232 | } | |
f071d8a7 | 233 | else if (strcmp(shell, 1+strrchr(valid_shell, '/')) == NULL) { |
7283d000 | 234 | ok = 1; |
235 | (void) strcpy(shell, valid_shell); | |
236 | break; | |
237 | } | |
238 | } | |
239 | ||
240 | if (!ok) { | |
241 | if (shell[0] != '/') { | |
242 | fprintf(stderr, "%s it not a standard shell. ", shell); | |
243 | fprintf(stderr, "You may choose to use a nonstandard\n"); | |
244 | fprintf(stderr, "shell, but you must specify its complete "); | |
245 | fprintf(stderr, "path name.\n"); | |
246 | leave(2); | |
247 | } | |
248 | else if (access(shell, X_OK)) { | |
249 | fprintf(stderr, "%s is not available.\n", shell); | |
250 | leave(2); | |
251 | } | |
252 | else { | |
253 | printf("%s exists but is an unusual choice.\n", shell); | |
254 | printf("Try again if it is not what you wanted.\n"); | |
255 | } | |
256 | } | |
257 | } | |
258 | ||
259 | usage() | |
260 | { | |
261 | fprintf(stderr, "Usage: %s [user]\n", whoami); | |
262 | exit(1); | |
263 | } | |
fa00aa12 | 264 | |
0ffa8026 | 265 | #if defined(ultrix) || defined(_AIX) || defined(sgi) |
fa00aa12 | 266 | char *getusershell() |
267 | { | |
268 | static int count = 1; | |
269 | ||
270 | switch (count++) { | |
271 | case 1: | |
272 | return("/bin/sh"); | |
273 | case 2: | |
274 | return("/bin/csh"); | |
275 | case 3: | |
0ffa8026 | 276 | return("/bin/athena/tcsh"); |
277 | case 4: | |
fa00aa12 | 278 | return(NULL); |
279 | default: | |
280 | count = 1; | |
281 | return(getusershell()); | |
282 | } | |
283 | } | |
a2ff3b56 | 284 | #endif |