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