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
7 * chsh with no modifiers changes the shell of the user who is running
10 * If a commandline argument is given, it is taken to be the username
11 * of the user whose shell is to be changed.
13 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology
14 * For copying and distribution information, please see the file
18 #include <mit-copyright.h>
20 #include <moira_site.h>
27 #define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
32 int get_shell(int argc, char **argv, void *username);
33 int get_winshell(int argc, char **argv, void *username);
34 int get_fmodtime(int argc, char **argv, void *username);
35 void check_shell(char *shell);
36 #ifndef HAVE_GETUSERSHELL
37 char *getusershell(void);
43 int main(int argc, char *argv[])
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;
55 if ((whoami = strrchr(argv[0], '/')) == NULL)
60 /* parse our command line options */
61 while (++arg - argv < argc)
65 if (argis("w", "winshell"))
67 else if (argis("u", "unixshell"))
69 else if (argis("db", "database"))
71 if (arg - argv < argc - 1)
80 else if (username == NULL)
88 username = mrcl_krb_user();
93 if (!unixflg && !windowsflg)
96 if (unixflg && windowsflg)
99 if (mrcl_connect(server, "chsh", 12, 1) != MRCL_SUCCESS)
102 /* First, do an access check */
104 q_argv[USH_NAME] = username;
105 q_argv[USH_SHELL] = "junk";
108 if ((status = mr_access("update_user_shell", q_argc, q_argv)))
110 com_err(whoami, status, "; shell not\nchanged.");
114 printf("Changing login shell for %s.\n", username);
116 /* Display current information */
118 q_argv[NAME] = username;
121 if ((status = mr_query("get_finger_by_login", q_argc, q_argv,
122 get_fmodtime, username)))
124 com_err(whoami, status, "while getting user information.");
130 if ((status = mr_query("get_user_account_by_login", q_argc, q_argv,
131 get_shell, username)))
133 com_err(whoami, status, "while getting user information.");
137 /* Ask for new shell */
140 printf("New shell: ");
141 if (!fgets(shell, sizeof(shell), stdin))
143 got_one = (strlen(shell) > 1);
146 shell[strlen(shell) - 1] = 0; /* strip off newline */
148 /* Make sure we have a valid shell. This routine could exit */
153 printf("Changing shell to %s...\n", shell);
155 q_argv[USH_NAME] = username;
156 q_argv[USH_SHELL] = shell;
158 if ((status = mr_query("update_user_shell", q_argc, q_argv, NULL, NULL)))
160 com_err(whoami, status, "while changing shell.");
164 printf("Shell successfully changed.\n");
168 if ((status = mr_query("get_user_account_by_login", q_argc, q_argv,
169 get_winshell, username)))
171 com_err(whoami, status, "while getting user information.");
175 /* Ask for new Windows shell */
178 printf("New Windows shell: ");
179 if (!fgets(shell, sizeof(shell), stdin))
181 got_one = (strlen(shell) > 1);
184 shell[strlen(shell) - 1] = 0; /* strip off newline */
188 printf("Changing Windows shell to %s...\n", shell);
190 q_argv[USH_NAME] = username;
191 q_argv[USH_SHELL] = shell;
193 if ((status = mr_query("update_user_windows_shell", q_argc, q_argv,
196 com_err(whoami, status, "while changing Windows shell.");
200 printf("Windows shell successfully changed.\n");
208 int get_shell(int argc, char **argv, void *username)
210 /* We'll just take the first information we get since login names
211 cannot be duplicated in the database. */
213 if (argc < U_END || strcmp(argv[U_NAME], username))
215 fprintf(stderr, "Some internal error has occurred. Try again.\n");
219 printf("Current shell for %s is %s.\n", (char *)username, argv[U_SHELL]);
221 return MR_ABORT; /* Don't pay attention to other matches. */
224 int get_winshell(int argc, char **argv, void *username)
226 /* We'll just take the first information we get since login names
227 cannot be duplicated in the database. */
229 if (argc < U_END || strcmp(argv[U_NAME], username))
231 fprintf(stderr, "Some internal error has occurred. Try again.\n");
235 printf("Current Windows shell for %s is %s.\n", (char *)username,
236 argv[U_WINCONSOLESHELL]);
238 return MR_ABORT; /* Don't pay attention to other matches. */
241 int get_fmodtime(int argc, char **argv, void *username)
243 /* We'll just take the first information we get since login names
244 cannot be duplicated in the database. */
246 if (argc < F_END || strcmp(argv[F_NAME], username))
248 fprintf(stderr, "Some internal error has occurred. Try again.\n");
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]);
255 return MR_ABORT; /* Don't pay attention to other matches. */
258 void check_shell(char *shell)
263 while ((valid_shell = (char *)getusershell()))
265 if (!strcmp(shell, valid_shell))
270 else if (!strcmp(shell, 1 + strrchr(valid_shell, '/')))
273 strcpy(shell, valid_shell);
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");
288 else if (access(shell, X_OK))
290 fprintf(stderr, "%s is not available.\n", shell);
295 printf("%s exists but is an unusual choice.\n", shell);
296 printf("Try again if it is not what you wanted.\n");
303 fprintf(stderr, "Usage: %s [-w|-u] [user]\n", whoami);
307 #ifndef HAVE_GETUSERSHELL
308 #include <sys/param.h>
310 char *getusershell(void)
312 static FILE *shells = NULL;
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
318 static char buf[MAXPATHLEN];
323 shells = fopen("/etc/shells", "r");
326 fprintf(stderr, "%s: Can't open /etc/shells. Unable to determine if "
327 "this is a normal shell.\n\n", whoami);
334 if (!fgets(buf, sizeof(buf), shells))
344 p = strchr(buf, '\n');