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