source: trunk/third/moira/clients/chsh/chsh.c @ 24319

Revision 24319, 8.4 KB checked in by broder, 14 years ago (diff)
New Moira snapshot from SVN.
Line 
1/* $Id: chsh.c 3981 2010-02-16 21:13:05Z zacheiss $
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#include <sys/param.h>
27
28#define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
29
30RCSID("$HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/clients/chsh/chsh.c $ $Id: chsh.c 3981 2010-02-16 21:13:05Z zacheiss $");
31
32void usage(void);
33int get_shell(int argc, char **argv, void *username);
34int get_winshell(int argc, char **argv, void *username);
35int get_fmodtime(int argc, char **argv, void *username);
36void check_shell(char *shell);
37#ifndef HAVE_GETUSERSHELL
38char *getusershell(void);
39#endif
40
41char *whoami;
42char *username;
43
44int main(int argc, char *argv[])
45{
46  int status;                   /* general purpose exit status */
47  int q_argc;                   /* argc for mr_query */
48  char *q_argv[U_END];          /* argv for mr_query */
49  char *motd;                   /* determine Moira server status */
50  int got_one = 0;              /* Have we got a shell yet? */
51  int windowsflg = 0, unixflg = 0; 
52  char **arg = argv;
53  char *server = NULL, *shell = NULL;
54
55  if ((whoami = strrchr(argv[0], '/')) == NULL)
56    whoami = argv[0];
57  else
58    whoami++;
59
60  /* parse our command line options */
61  while (++arg - argv < argc)
62    {
63      if (**arg == '-')
64        {
65          if (argis("w", "winshell"))
66            windowsflg++;
67          else if (argis("u", "unixshell"))
68            unixflg++;
69          else if (argis("s", "shell"))
70            {
71              if (arg - argv < argc - 1)
72                {
73                  ++arg;
74                  shell = *arg;
75                }
76              else
77                usage();
78            }
79          else if (argis("db", "database"))
80            {
81              if (arg - argv < argc - 1)
82                {
83                  ++arg;
84                  server = *arg;
85                }
86              else
87                usage();
88            }
89        }
90      else if (username == NULL)
91        username = *arg;
92      else
93        usage();
94    }
95
96  if (!username)
97    {
98      username = mrcl_krb_user();
99      if (!username)
100        exit(1);
101    }
102
103  if (!unixflg && !windowsflg)
104    unixflg++;
105
106  if (unixflg && windowsflg)
107    usage();
108 
109  if (mrcl_connect(server, "chsh", 14, 1) != MRCL_SUCCESS)
110    exit(1);
111
112  /* First, do an access check */
113
114  q_argv[USH_NAME] = username;
115  q_argv[USH_SHELL] = "junk";
116  q_argc = USH_END;
117
118  if ((status = mr_access("update_user_shell", q_argc, q_argv)))
119    {
120      com_err(whoami, status, "; shell not\nchanged.");
121      exit(2);
122    }
123
124  printf("Changing login shell for %s.\n", username);
125
126  /* Display current information */
127 
128  q_argv[NAME] = username;
129  q_argc = NAME + 1;
130 
131  if ((status = mr_query("get_finger_by_login", q_argc, q_argv,
132                         get_fmodtime, username)))
133    {
134      com_err(whoami, status, "while getting user information.");
135      exit(2);
136    }
137
138  if (unixflg)
139    {
140      if ((status = mr_query("get_user_account_by_login", q_argc, q_argv,
141                             get_shell, username)))
142        {
143          com_err(whoami, status, "while getting user information.");
144          exit(2);
145        }
146
147
148      if (!shell)
149        {
150          /* Ask for new shell */
151          while (!got_one)
152            {
153              shell = malloc(MAXPATHLEN);
154              if (!shell)
155                exit(1);
156              printf("New shell: ");
157              if (!fgets(shell, MAXPATHLEN, stdin))
158                exit(0);
159              got_one = (strlen(shell) > 1);
160            }
161
162          shell[strlen(shell) - 1] = 0; /* trim newline */
163        }
164
165      /* Make sure we have a valid shell.  This routine could exit */
166      check_shell(shell);
167     
168      /* Change shell */
169     
170      printf("Changing shell to %s...\n", shell);
171     
172      q_argv[USH_NAME] = username;
173      q_argv[USH_SHELL] = shell;
174      q_argc = USH_END;
175      if ((status = mr_query("update_user_shell", q_argc, q_argv, NULL, NULL)))
176        {
177          com_err(whoami, status, "while changing shell.");
178          exit(2);
179        }
180     
181      printf("Shell successfully changed.\n");
182    }
183  else if (windowsflg)
184    {
185      if ((status = mr_query("get_user_account_by_login", q_argc, q_argv,
186                             get_winshell, username)))
187        {
188          com_err(whoami, status, "while getting user information.");
189          exit(2);
190        }
191
192      if (!shell)
193        {
194          /* Ask for new Windows shell */
195          while(!got_one)
196            {
197              shell = malloc(MAXPATHLEN);
198              if (!shell)
199                exit(1);
200              printf("New Windows shell: ");
201              if (!fgets(shell, MAXPATHLEN, stdin))
202                exit(0);
203              got_one = (strlen(shell) > 1);
204            }
205     
206          shell[strlen(shell) - 1] = 0; /* strip off newline */
207        }
208
209      /* Change shell */
210     
211      printf("Changing Windows shell to %s...\n", shell);
212     
213      q_argv[USH_NAME] = username;
214      q_argv[USH_SHELL] = shell;
215      q_argc = USH_END;
216      if ((status = mr_query("update_user_windows_shell", q_argc, q_argv,
217                             NULL, NULL)))
218        {
219          com_err(whoami, status, "while changing Windows shell.");
220          exit(2);
221        }
222     
223      printf("Windows shell successfully changed.\n");
224    }
225     
226  mr_disconnect();
227     
228  return 0;
229}
230
231int get_shell(int argc, char **argv, void *username)
232{
233  /* We'll just take the first information we get since login names
234     cannot be duplicated in the database. */
235
236  if (argc < U_END || strcmp(argv[U_NAME], username))
237    {
238      fprintf(stderr, "Some internal error has occurred.  Try again.\n");
239      exit(3);
240    }
241
242  printf("Current shell for %s is %s.\n", (char *)username, argv[U_SHELL]);
243
244  return MR_ABORT;              /* Don't pay attention to other matches. */
245}
246
247int get_winshell(int argc, char **argv, void *username)
248{
249  /* We'll just take the first information we get since login names
250     cannot be duplicated in the database. */
251
252  if (argc < U_END || strcmp(argv[U_NAME], username))
253    {
254      fprintf(stderr, "Some internal error has occurred.  Try again.\n");
255      exit(3);
256    }
257
258  printf("Current Windows shell for %s is %s.\n", (char *)username,
259         argv[U_WINCONSOLESHELL]);
260
261  return MR_ABORT;              /* Don't pay attention to other matches. */
262}
263
264int get_fmodtime(int argc, char **argv, void *username)
265{
266  /* We'll just take the first information we get since login names
267     cannot be duplicated in the database. */
268
269  if (argc < F_END || strcmp(argv[F_NAME], username))
270    {
271      fprintf(stderr, "Some internal error has occurred.  Try again.\n");
272      exit(3);
273    }
274
275  printf("Finger information last changed on %s\n", argv[F_MODTIME]);
276  printf("by user %s with %s.\n", argv[F_MODBY], argv[F_MODWITH]);
277
278  return MR_ABORT;              /* Don't pay attention to other matches. */
279}
280
281void check_shell(char *shell)
282{
283  char *valid_shell;
284  int ok = 0;
285
286  while ((valid_shell = (char *)getusershell()))
287    {
288      if (!strcmp(shell, valid_shell))
289        {
290          ok = 1;
291          break;
292        }
293      else if (!strcmp(shell, 1 + strrchr(valid_shell, '/')))
294        {
295          ok = 1;
296          strcpy(shell, valid_shell);
297          break;
298        }
299    }
300
301  if (!ok)
302    {
303      if (shell[0] != '/')
304        {
305          fprintf(stderr, "%s is not a standard shell.  ", shell);
306          fprintf(stderr, "You may choose to use a nonstandard\n");
307          fprintf(stderr, "shell, but you must specify its complete ");
308          fprintf(stderr, "path name.\n");
309          exit(2);
310        }
311      else if (access(shell, X_OK))
312        {
313          fprintf(stderr, "%s is not available.\n", shell);
314          exit(2);
315        }
316      else
317        {
318          printf("%s exists but is an unusual choice.\n", shell);
319          printf("Try again if it is not what you wanted.\n");
320        }
321    }
322}
323
324void usage(void)
325{
326  fprintf(stderr, "Usage: %s [-w|-u] [-s shell] [user]\n", whoami);
327  exit(1);
328}
329
330#ifndef HAVE_GETUSERSHELL
331#include <sys/param.h>
332
333char *getusershell(void)
334{
335  static FILE *shells = NULL;
336
337  /* In a sane universe, no shell will have a length longer than
338   * MAXPATHLEN. If any line in /etc/shells does, we'll lose, but
339   * not much. shrug.
340   */
341  static char buf[MAXPATHLEN];
342  char *p;
343
344  if (!shells)
345    {
346      shells = fopen("/etc/shells", "r");
347      if (!shells)
348        {
349          fprintf(stderr, "%s: Can't open /etc/shells. Unable to determine if "
350                  "this is a normal shell.\n\n", whoami);
351          return NULL;
352        }
353    }
354
355  while (1)
356    {
357      if (!fgets(buf, sizeof(buf), shells))
358        {
359          fclose(shells);
360          shells = NULL;
361          return NULL;
362        }
363
364      if (buf[0] != '/')
365        continue;
366
367      p = strchr(buf, '\n');
368      if (p)
369        *p = '\0';
370
371      return buf;
372    }
373}
374#endif
Note: See TracBrowser for help on using the repository browser.