]> andersk Git - moira.git/blame - clients/chsh/chsh.c
moved from clients/passwd to clients/chsh
[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
27RCSID("$Header$");
28
29void usage(void);
30int chsh(char *uname);
31int get_shell(int argc, char **argv, void *uname);
32int get_fmodtime(int argc, char **argv, void *uname);
33void check_shell(char *shell);
34#ifndef HAVE_GETUSERSHELL
35char *getusershell(void);
36#endif
37
38char *whoami;
39
40int main(int argc, char *argv[])
41{
42 char *uname;
43
44 if ((whoami = strrchr(argv[0], '/')) == NULL)
45 whoami = argv[0];
46 else
47 whoami++;
48
49 if (argc > 2)
50 usage();
51
52 if (argc == 2)
53 uname = argv[1];
54 else
55 {
56 uname = mrcl_krb_user();
57 if (!uname)
58 exit(1);
59 }
60
61 exit(chsh(uname));
62}
63
64int chsh(char *uname)
65{
66 int status; /* general purpose exit status */
67 int q_argc; /* argc for mr_query */
68 char *q_argv[U_END]; /* argv for mr_query */
69 char *motd; /* determine Moira server status */
70
71 int got_one = 0; /* have we got a new shell yet? */
72 char shell[BUFSIZ]; /* the new shell */
73
74 if (mrcl_connect(NULL, "chsh", 2, 1) != MRCL_SUCCESS)
75 exit(1);
76
77 /* First, do an access check */
78
79 q_argv[USH_NAME] = uname;
80 q_argv[USH_SHELL] = "junk";
81 q_argc = USH_END;
82
83 if ((status = mr_access("update_user_shell", q_argc, q_argv)))
84 {
85 com_err(whoami, status, "; shell not\nchanged.");
86 exit(2);
87 }
88
89 printf("Changing login shell for %s.\n", uname);
90
91 /* Display current information */
92
93 q_argv[NAME] = uname;
94 q_argc = NAME + 1;
95
96 if ((status = mr_query("get_finger_by_login", q_argc, q_argv,
97 get_fmodtime, uname)))
98 {
99 com_err(whoami, status, "while getting user information.");
100 exit(2);
101 }
102
103 if ((status = mr_query("get_user_account_by_login", q_argc, q_argv,
104 get_shell, uname)))
105 {
106 com_err(whoami, status, "while getting user information.");
107 exit(2);
108 }
109
110 /* Ask for new shell */
111 while (!got_one)
112 {
113 printf("New shell: ");
114 if (!fgets(shell, sizeof(shell), stdin))
115 exit(0);
116 got_one = (strlen(shell) > 1);
117 }
118
119 shell[strlen(shell) - 1] = 0; /* strip off newline */
120
121 /* Make sure we have a valid shell. This routine could exit */
122 check_shell(shell);
123
124 /* Change shell */
125
126 printf("Changing shell to %s...\n", shell);
127
128 q_argv[USH_NAME] = uname;
129 q_argv[USH_SHELL] = shell;
130 q_argc = USH_END;
131 if ((status = mr_query("update_user_shell", q_argc, q_argv, NULL, NULL)))
132 {
133 com_err(whoami, status, "while changing shell.");
134 exit(2);
135 }
136
137 printf("Shell successfully changed.\n");
138 mr_disconnect();
139
140 return 0;
141}
142
143int get_shell(int argc, char **argv, void *uname)
144{
145 /* We'll just take the first information we get since login names
146 cannot be duplicated in the database. */
147
148 if (argc < U_END || strcmp(argv[U_NAME], uname))
149 {
150 fprintf(stderr, "Some internal error has occurred. Try again.\n");
151 exit(3);
152 }
153
154 printf("Current shell for %s is %s.\n", (char *)uname, argv[U_SHELL]);
155
156 return MR_ABORT; /* Don't pay attention to other matches. */
157}
158
159int get_fmodtime(int argc, char **argv, void *uname)
160{
161 /* We'll just take the first information we get since login names
162 cannot be duplicated in the database. */
163
164 if (argc < F_END || strcmp(argv[F_NAME], uname))
165 {
166 fprintf(stderr, "Some internal error has occurred. Try again.\n");
167 exit(3);
168 }
169
170 printf("Finger information last changed on %s\n", argv[F_MODTIME]);
171 printf("by user %s with %s.\n", argv[F_MODBY], argv[F_MODWITH]);
172
173 return MR_ABORT; /* Don't pay attention to other matches. */
174}
175
176void check_shell(char *shell)
177{
178 char *valid_shell;
179 int ok = 0;
180
181 while ((valid_shell = getusershell()))
182 {
183 if (!strcmp(shell, valid_shell))
184 {
185 ok = 1;
186 break;
187 }
188 else if (!strcmp(shell, 1 + strrchr(valid_shell, '/')))
189 {
190 ok = 1;
191 strcpy(shell, valid_shell);
192 break;
193 }
194 }
195
196 if (!ok)
197 {
198 if (shell[0] != '/')
199 {
200 fprintf(stderr, "%s is not a standard shell. ", shell);
201 fprintf(stderr, "You may choose to use a nonstandard\n");
202 fprintf(stderr, "shell, but you must specify its complete ");
203 fprintf(stderr, "path name.\n");
204 exit(2);
205 }
206 else if (access(shell, X_OK))
207 {
208 fprintf(stderr, "%s is not available.\n", shell);
209 exit(2);
210 }
211 else
212 {
213 printf("%s exists but is an unusual choice.\n", shell);
214 printf("Try again if it is not what you wanted.\n");
215 }
216 }
217}
218
219void usage(void)
220{
221 fprintf(stderr, "Usage: %s [user]\n", whoami);
222 exit(1);
223}
224
225#ifndef HAVE_GETUSERSHELL
226#include <sys/param.h>
227
228char *getusershell(void)
229{
230 static FILE *shells = NULL;
231
232 /* In a sane universe, no shell will have a length longer than
233 * MAXPATHLEN. If any line in /etc/shells does, we'll lose, but
234 * not much. shrug.
235 */
236 static char buf[MAXPATHLEN];
237 char *p;
238
239 if (!shells)
240 {
241 shells = fopen("/etc/shells", "r");
242 if (!shells)
243 {
244 fprintf(stderr, "%s: Can't open /etc/shells. Unable to determine if "
245 "this is a normal shell.\n\n", whoami);
246 return NULL;
247 }
248 }
249
250 while (1)
251 {
252 if (!fgets(buf, sizeof(buf), shells))
253 {
254 fclose(shells);
255 shells = NULL;
256 return NULL;
257 }
258
259 if (buf[0] != '/')
260 continue;
261
262 p = strchr(buf, '\n');
263 if (p)
264 *p = '\0';
265
266 return buf;
267 }
268}
269#endif
This page took 0.07997 seconds and 5 git commands to generate.