]> andersk Git - moira.git/blame - clients/chsh/chsh.c
Trivial version update.
[moira.git] / clients / chsh / chsh.c
CommitLineData
f0c4fc06 1/* $Id$
2 *
3 * Talk to the Moira database to change a person's login shell. The chosen
4 * shell must exist. A warning will be issued if the shell is not in
5 * /etc/shells.
6 *
7 * chsh with no modifiers changes the shell of the user who is running
8 * the program.
9 *
10 * If a commandline argument is given, it is taken to be the username
11 * of the user whose shell is to be changed.
12 *
13 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology
14 * For copying and distribution information, please see the file
15 * <mit-copyright.h>.
16 */
17
18#include <mit-copyright.h>
19#include <moira.h>
20#include <moira_site.h>
21#include <mrclient.h>
22
23#include <stdio.h>
24#include <string.h>
25#include <unistd.h>
26
133344db 27#define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
28
f0c4fc06 29RCSID("$Header$");
30
31void usage(void);
7d869ec1 32int get_shell(int argc, char **argv, void *username);
33int get_winshell(int argc, char **argv, void *username);
34int get_fmodtime(int argc, char **argv, void *username);
f0c4fc06 35void check_shell(char *shell);
36#ifndef HAVE_GETUSERSHELL
37char *getusershell(void);
38#endif
39
40char *whoami;
7d869ec1 41char *username;
f0c4fc06 42
43int main(int argc, char *argv[])
44{
133344db 45 int status; /* general purpose exit status */
46 int q_argc; /* argc for mr_query */
47 char *q_argv[U_END]; /* argv for mr_query */
48 char *motd; /* determine Moira server status */
49 int got_one = 0; /* Have we got a shell yet? */
50 char shell[BUFSIZ]; /* Our new shell */
51 int windowsflg = 0, unixflg = 0;
52 char **arg = argv;
53 char *server = NULL;
f0c4fc06 54
55 if ((whoami = strrchr(argv[0], '/')) == NULL)
56 whoami = argv[0];
57 else
58 whoami++;
59
133344db 60 /* parse our command line options */
61 while (++arg - argv < argc)
62 {
63 if (**arg == '-')
64 {
65 if (argis("w", "winshell"))
66 windowsflg++;
67 else if (argis("u", "unixshell"))
68 unixflg++;
69 else if (argis("db", "database"))
70 {
71 if (arg - argv < argc - 1)
72 {
73 ++arg;
74 server = *arg;
75 }
76 else
77 usage();
78 }
79 }
7d869ec1 80 else if (username == NULL)
81 username = *arg;
133344db 82 else
83 usage();
84 }
f0c4fc06 85
7d869ec1 86 if (!username)
f0c4fc06 87 {
7d869ec1 88 username = mrcl_krb_user();
89 if (!username)
f0c4fc06 90 exit(1);
91 }
92
133344db 93 if (!unixflg && !windowsflg)
94 unixflg++;
f0c4fc06 95
133344db 96 if (unixflg && windowsflg)
97 usage();
98
d157e486 99 if (mrcl_connect(server, "chsh", 12, 1) != MRCL_SUCCESS)
f0c4fc06 100 exit(1);
101
102 /* First, do an access check */
103
7d869ec1 104 q_argv[USH_NAME] = username;
f0c4fc06 105 q_argv[USH_SHELL] = "junk";
106 q_argc = USH_END;
107
108 if ((status = mr_access("update_user_shell", q_argc, q_argv)))
109 {
110 com_err(whoami, status, "; shell not\nchanged.");
111 exit(2);
112 }
113
7d869ec1 114 printf("Changing login shell for %s.\n", username);
f0c4fc06 115
116 /* Display current information */
133344db 117
7d869ec1 118 q_argv[NAME] = username;
f0c4fc06 119 q_argc = NAME + 1;
133344db 120
f0c4fc06 121 if ((status = mr_query("get_finger_by_login", q_argc, q_argv,
7d869ec1 122 get_fmodtime, username)))
f0c4fc06 123 {
124 com_err(whoami, status, "while getting user information.");
125 exit(2);
126 }
127
133344db 128 if (unixflg)
f0c4fc06 129 {
133344db 130 if ((status = mr_query("get_user_account_by_login", q_argc, q_argv,
7d869ec1 131 get_shell, username)))
133344db 132 {
133 com_err(whoami, status, "while getting user information.");
134 exit(2);
135 }
136
137 /* Ask for new shell */
138 while (!got_one)
139 {
140 printf("New shell: ");
141 if (!fgets(shell, sizeof(shell), stdin))
142 exit(0);
143 got_one = (strlen(shell) > 1);
144 }
145
146 shell[strlen(shell) - 1] = 0; /* strip off newline */
147
148 /* Make sure we have a valid shell. This routine could exit */
149 check_shell(shell);
150
151 /* Change shell */
152
153 printf("Changing shell to %s...\n", shell);
154
7d869ec1 155 q_argv[USH_NAME] = username;
133344db 156 q_argv[USH_SHELL] = shell;
157 q_argc = USH_END;
158 if ((status = mr_query("update_user_shell", q_argc, q_argv, NULL, NULL)))
159 {
160 com_err(whoami, status, "while changing shell.");
161 exit(2);
162 }
163
164 printf("Shell successfully changed.\n");
f0c4fc06 165 }
133344db 166 else if (windowsflg)
f0c4fc06 167 {
133344db 168 if ((status = mr_query("get_user_account_by_login", q_argc, q_argv,
7d869ec1 169 get_winshell, username)))
133344db 170 {
171 com_err(whoami, status, "while getting user information.");
172 exit(2);
173 }
174
175 /* Ask for new Windows shell */
176 while(!got_one)
177 {
178 printf("New Windows shell: ");
179 if (!fgets(shell, sizeof(shell), stdin))
180 exit(0);
181 got_one = (strlen(shell) > 1);
182 }
183
184 shell[strlen(shell) - 1] = 0; /* strip off newline */
185
186 /* Change shell */
187
188 printf("Changing Windows shell to %s...\n", shell);
189
7d869ec1 190 q_argv[USH_NAME] = username;
133344db 191 q_argv[USH_SHELL] = shell;
192 q_argc = USH_END;
193 if ((status = mr_query("update_user_windows_shell", q_argc, q_argv,
194 NULL, NULL)))
195 {
196 com_err(whoami, status, "while changing Windows shell.");
197 exit(2);
198 }
199
200 printf("Windows shell successfully changed.\n");
f0c4fc06 201 }
133344db 202
203 mr_disconnect();
204
205 return 0;
206}
f0c4fc06 207
7d869ec1 208int get_shell(int argc, char **argv, void *username)
133344db 209{
210 /* We'll just take the first information we get since login names
211 cannot be duplicated in the database. */
f0c4fc06 212
7d869ec1 213 if (argc < U_END || strcmp(argv[U_NAME], username))
f0c4fc06 214 {
133344db 215 fprintf(stderr, "Some internal error has occurred. Try again.\n");
216 exit(3);
f0c4fc06 217 }
218
7d869ec1 219 printf("Current shell for %s is %s.\n", (char *)username, argv[U_SHELL]);
f0c4fc06 220
133344db 221 return MR_ABORT; /* Don't pay attention to other matches. */
f0c4fc06 222}
223
7d869ec1 224int get_winshell(int argc, char **argv, void *username)
f0c4fc06 225{
226 /* We'll just take the first information we get since login names
227 cannot be duplicated in the database. */
228
7d869ec1 229 if (argc < U_END || strcmp(argv[U_NAME], username))
f0c4fc06 230 {
231 fprintf(stderr, "Some internal error has occurred. Try again.\n");
232 exit(3);
233 }
234
7d869ec1 235 printf("Current Windows shell for %s is %s.\n", (char *)username,
133344db 236 argv[U_WINCONSOLESHELL]);
f0c4fc06 237
238 return MR_ABORT; /* Don't pay attention to other matches. */
239}
240
7d869ec1 241int get_fmodtime(int argc, char **argv, void *username)
f0c4fc06 242{
243 /* We'll just take the first information we get since login names
244 cannot be duplicated in the database. */
245
7d869ec1 246 if (argc < F_END || strcmp(argv[F_NAME], username))
f0c4fc06 247 {
248 fprintf(stderr, "Some internal error has occurred. Try again.\n");
249 exit(3);
250 }
251
252 printf("Finger information last changed on %s\n", argv[F_MODTIME]);
253 printf("by user %s with %s.\n", argv[F_MODBY], argv[F_MODWITH]);
254
255 return MR_ABORT; /* Don't pay attention to other matches. */
256}
257
258void check_shell(char *shell)
259{
260 char *valid_shell;
261 int ok = 0;
262
133344db 263 while ((valid_shell = (char *)getusershell()))
f0c4fc06 264 {
265 if (!strcmp(shell, valid_shell))
266 {
267 ok = 1;
268 break;
269 }
270 else if (!strcmp(shell, 1 + strrchr(valid_shell, '/')))
271 {
272 ok = 1;
273 strcpy(shell, valid_shell);
274 break;
275 }
276 }
277
278 if (!ok)
279 {
280 if (shell[0] != '/')
281 {
282 fprintf(stderr, "%s is not a standard shell. ", shell);
283 fprintf(stderr, "You may choose to use a nonstandard\n");
284 fprintf(stderr, "shell, but you must specify its complete ");
285 fprintf(stderr, "path name.\n");
286 exit(2);
287 }
288 else if (access(shell, X_OK))
289 {
290 fprintf(stderr, "%s is not available.\n", shell);
291 exit(2);
292 }
293 else
294 {
295 printf("%s exists but is an unusual choice.\n", shell);
296 printf("Try again if it is not what you wanted.\n");
297 }
298 }
299}
300
301void usage(void)
302{
133344db 303 fprintf(stderr, "Usage: %s [-w|-u] [user]\n", whoami);
f0c4fc06 304 exit(1);
305}
306
307#ifndef HAVE_GETUSERSHELL
308#include <sys/param.h>
309
310char *getusershell(void)
311{
312 static FILE *shells = NULL;
313
314 /* In a sane universe, no shell will have a length longer than
315 * MAXPATHLEN. If any line in /etc/shells does, we'll lose, but
316 * not much. shrug.
317 */
318 static char buf[MAXPATHLEN];
319 char *p;
320
321 if (!shells)
322 {
323 shells = fopen("/etc/shells", "r");
324 if (!shells)
325 {
326 fprintf(stderr, "%s: Can't open /etc/shells. Unable to determine if "
327 "this is a normal shell.\n\n", whoami);
328 return NULL;
329 }
330 }
331
332 while (1)
333 {
334 if (!fgets(buf, sizeof(buf), shells))
335 {
336 fclose(shells);
337 shells = NULL;
338 return NULL;
339 }
340
341 if (buf[0] != '/')
342 continue;
343
344 p = strchr(buf, '\n');
345 if (p)
346 *p = '\0';
347
348 return buf;
349 }
350}
351#endif
This page took 0.359329 seconds and 5 git commands to generate.