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>
31 int leave(int status);
32 int chsh(char *uname);
33 int get_shell(int argc, char **argv, void *uname);
34 void check_shell(char *shell);
35 #ifndef HAVE_GETUSERSHELL
36 char *getusershell(void);
41 int main(int argc, char *argv[])
47 initialize_krb_error_table();
49 if ((whoami = strrchr(argv[0], '/')) == NULL)
61 /* Do it right; get name from kerberos ticket file rather than
64 if ((k_errno = tf_init(TKT_FILE, R_TKT_FIL)))
66 com_err(whoami, k_errno, "reading ticket file");
70 if ((k_errno = tf_get_pname(pname)))
72 com_err(whoami, k_errno, "getting kerberos principal name");
82 /* This should be called rather than exit once connection to moira server
83 has been established. */
92 int status; /* general purpose exit status */
93 int q_argc; /* argc for mr_query */
94 char *q_argv[U_END]; /* argv for mr_query */
95 char *motd; /* determine Moira server status */
97 int got_one = 0; /* have we got a new shell yet? */
98 char shell[BUFSIZ]; /* the new shell */
100 /* Try each query. If we ever fail, print error message and exit. */
102 status = mr_connect(NULL);
105 com_err(whoami, status, " while connecting to Moira");
109 status = mr_motd(&motd);
112 com_err(whoami, status, " unable to check server status");
117 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n",
122 status = mr_auth("chsh"); /* Don't use argv[0] - too easy to fake */
125 com_err(whoami, status,
126 " while authenticating -- run \"kinit\" and try again.");
130 /* First, do an access check */
132 q_argv[USH_NAME] = uname;
133 q_argv[USH_SHELL] = "junk";
136 if ((status = mr_access("update_user_shell", q_argc, q_argv)))
138 com_err(whoami, status, "; shell not\nchanged.");
142 printf("Changing login shell for %s.\n", uname);
144 /* Display current information */
146 q_argv[NAME] = uname;
149 if ((status = mr_query("get_user_account_by_login", q_argc, q_argv,
152 com_err(whoami, status, " while getting user information.");
156 /* Ask for new shell */
159 printf("New shell: ");
160 if (!fgets(shell, sizeof(shell), stdin))
162 got_one = (strlen(shell) > 1);
165 shell[strlen(shell) - 1] = 0; /* strip off newline */
167 /* Make sure we have a valid shell. This routine could exit */
172 printf("Changing shell to %s...\n", shell);
174 q_argv[USH_NAME] = uname;
175 q_argv[USH_SHELL] = shell;
177 if ((status = mr_query("update_user_shell", q_argc, q_argv, NULL, NULL)))
179 com_err(whoami, status, " while changing shell.");
183 printf("Shell successfully changed.\n");
189 int get_shell(int argc, char **argv, void *uname)
191 /* We'll just take the first information we get since login names
192 cannot be duplicated in the database. */
194 if (argc < U_END || strcmp(argv[U_NAME], uname))
196 fprintf(stderr, "Some internal error has occurred. Try again.\n");
200 printf("Account information last changed on %s\n", argv[U_MODTIME]);
201 printf("by user %s with %s.\n", argv[U_MODBY], argv[U_MODWITH]);
202 printf("Current shell for %s is %s.\n", (char *)uname, argv[U_SHELL]);
204 return MR_ABORT; /* Don't pay attention to other matches. */
207 void check_shell(char *shell)
212 while ((valid_shell = getusershell()))
214 if (!strcmp(shell, valid_shell))
219 else if (!strcmp(shell, 1 + strrchr(valid_shell, '/')))
222 strcpy(shell, valid_shell);
231 fprintf(stderr, "%s is not a standard shell. ", shell);
232 fprintf(stderr, "You may choose to use a nonstandard\n");
233 fprintf(stderr, "shell, but you must specify its complete ");
234 fprintf(stderr, "path name.\n");
237 else if (access(shell, X_OK))
239 fprintf(stderr, "%s is not available.\n", shell);
244 printf("%s exists but is an unusual choice.\n", shell);
245 printf("Try again if it is not what you wanted.\n");
252 fprintf(stderr, "Usage: %s [user]\n", whoami);
256 #ifndef HAVE_GETUSERSHELL
257 char *getusershell(void)
259 static int count = 1;
268 return "/bin/athena/tcsh";
273 return getusershell();