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