]> andersk Git - moira.git/blob - clients/passwd/chsh.c
f0fee82152f667b4b16083e74df6ab6f29259f55
[moira.git] / clients / passwd / chsh.c
1 /*
2  * Copyright 1988 by the Massachusetts Institute of Technology. For copying
3  * and distribution information, see the file "mit-copyright.h". 
4  *
5  * $Source$
6  * $Header$
7  * $Author$
8  *
9  */
10
11 #ifndef lint
12 static char *rcsid_chsh_c = "$Header$";
13 #endif not lint
14
15 /*
16  * Talk to the SMS database to change a person's login shell.  The chosen
17  * shell must exist.  A warning will be issued if the shell is not in 
18  * /etc/shells.
19  * 
20  * chsh with no modifiers changes the shell of the user who is running
21  * the program.
22  * 
23  * If a commandline argument is given, it is taken to be the username
24  * of the user whose shell is to be changed.
25  *
26  */
27
28 #include <sys/types.h>
29 #include <stdio.h>
30 #include <strings.h>
31 #include <sys/file.h>
32 #include <krb.h>
33 #include <ctype.h>
34 #include <errno.h>
35
36 /* SMS includes */
37 #include <sms.h>
38 #include <sms_app.h>
39 #include "mit-copyright.h"
40
41 char *whoami;
42 char *getusershell();
43
44 extern char *krb_err_txt[];
45
46 main(argc, argv)
47     int argc;
48     char *argv[];
49 {
50     char pname[ANAME_SZ];
51     char *uname = pname;
52     int k_errno;
53     char *whoami;
54
55     if ((whoami = rindex(argv[0], '/')) == NULL)
56         whoami = argv[0];
57     else
58         whoami++;
59
60     if (argc > 2) {
61         usage();
62     }
63     
64     if (argc == 2)
65         uname = argv[1];
66     else
67     {
68         /* Do it right; get name from kerberos ticket file rather than 
69            from passord file. */
70         
71         if (k_errno = tf_init(TKT_FILE, R_TKT_FIL)) {
72             fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
73             exit(1);
74         }
75         
76         if (k_errno = tf_get_pname(pname)) {
77             fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
78             exit(1);
79         }
80
81         tf_close();
82     }
83     
84     exit(chsh(uname));
85 }
86
87 leave(status)
88   int status;
89   /* This should be called rather than exit once connection to sms server
90      has been established. */
91 {
92     sms_disconnect();
93     exit(status);
94 }
95
96 scream()
97 {
98     com_err(whoami, 0, "Unexpected return value from SMS -- programmer botch");
99     leave(1);
100 }
101
102 chsh(uname)
103   char *uname;
104 {
105     int status;                 /* general purpose exit status */
106     int q_argc;                 /* argc for sms_query */
107     char *q_argv[U_END];        /* argv for sms_query */
108
109     int got_one = 0;            /* have we got a new shell yet? */
110     char shell[BUFSIZ];         /* the new shell */
111     int get_shell();
112     void check_shell();         /* make sure new shell is valid */
113
114     /* Try each query.  If we ever fail, print error message and exit. */
115
116     status = sms_connect(SMS_SERVER);
117     if (status) {
118         com_err(whoami, status, " while connecting to SMS");
119         exit(1);
120     }
121
122     status = sms_auth("chsh");  /* Don't use argv[0] - too easy to fake */
123     if (status) {
124         com_err(whoami, status, 
125                 " while authenticating -- run \"kinit\" and try again.");
126         leave(1);
127     }
128
129     /* First, do an access check */
130
131     q_argv[USH_NAME] = uname;
132     q_argv[USH_SHELL] = "junk";
133     q_argc = USH_END;
134
135     if (status = sms_access("update_user_shell", q_argc, q_argv))
136     {
137         com_err(whoami, status, "; shell not\nchanged.");
138         leave(2);
139     }
140
141     printf("Changing login shell for %s.\n", uname);
142
143     /* Display current information */
144
145     q_argv[NAME] = uname;
146     q_argc = NAME + 1;
147
148     if ((status = sms_query("get_user_by_login", q_argc, q_argv, 
149                             get_shell, (char *) uname)))
150     {
151         com_err(whoami, status, " while getting user information.");
152         leave(2);
153     }
154
155     /* Ask for new shell */
156     while (!got_one)
157     {
158         printf("New shell: ");
159         if (fgets(shell, sizeof(shell), stdin) == NULL)
160           leave(0);
161         got_one = (strlen(shell) > 1);
162     }
163
164     shell[strlen(shell) - 1] = 0;       /* strip off newline */
165
166     /* Make sure we have a valid shell.  This routine could exit */
167     check_shell(shell);
168
169     /* Change shell */
170
171     printf("Changing shell to %s...\n", shell);
172
173     q_argv[USH_NAME] = uname;
174     q_argv[USH_SHELL] = shell;  
175     q_argc = USH_END;
176     if (status = sms_query("update_user_shell", q_argc, q_argv, 
177                            scream, (char *) NULL))
178     {
179         com_err(whoami, status, " while changing shell.");
180         leave(2);
181     }
182
183     printf("Shell successfully changed.\n");
184     sms_disconnect();
185
186     return(0);
187 }
188
189 get_shell(argc, argv, uname)
190   int argc;
191   char **argv;
192   char *uname;                  /* for sanity checking */
193 {
194     /* We'll just take the first information we get since login names 
195        cannot be duplicated in the database. */
196     
197     if (strcmp(argv[U_NAME], uname))
198     {
199         fprintf(stderr, "Some internal error has occurred.  Try again.\n");
200         leave(3);
201     }
202     
203     printf("Account information last changed on %s\n", argv[U_MODTIME]);
204     printf("by user %s with %s.\n", argv[U_MODBY], argv[U_MODWITH]);
205     printf("Current shell for %s is %s.\n", uname, argv[U_SHELL]); 
206     
207     return(SMS_ABORT);          /* Don't pay attention to other matches. */
208 }
209     
210 void check_shell(shell)
211   char *shell;
212 {
213     char *valid_shell;
214     int ok = 0;
215
216     while (valid_shell = getusershell()) {
217         if (strcmp(shell, valid_shell) == NULL) {
218             ok = 1;
219             break;
220         }
221         else if (strcmp(shell, 1+rindex(valid_shell, '/')) == NULL) {
222             ok = 1;
223             (void) strcpy(shell, valid_shell);
224             break;
225         }
226     }
227     
228     if (!ok) {
229         if (shell[0] != '/') {
230             fprintf(stderr, "%s it not a standard shell.  ", shell);
231             fprintf(stderr, "You may choose to use a nonstandard\n");
232             fprintf(stderr, "shell, but you must specify its complete ");
233             fprintf(stderr, "path name.\n");
234             leave(2);
235         }
236         else if (access(shell, X_OK)) {
237             fprintf(stderr, "%s is not available.\n", shell);
238             leave(2);
239         }
240         else {
241             printf("%s exists but is an unusual choice.\n", shell);
242             printf("Try again if it is not what you wanted.\n");
243         }
244     }
245 }       
246
247 usage()
248 {
249     fprintf(stderr, "Usage: %s [user]\n", whoami);
250     exit(1);
251 }
This page took 0.04822 seconds and 3 git commands to generate.