2 * Copyright 1988 by the Massachusetts Institute of Technology. For copying
3 * and distribution information, see the file "mit-copyright.h".
12 static char *rcsid_chfn_c = "$Header$";
16 * Talk to the MOIRA database to change a person's GECOS information.
18 * chfn with no modifiers changes the information of the user who is
19 * running the program.
21 * If a commandline argument is given, it is taken to be the username
22 * of the user whose information is to be changed.
29 #include <sys/types.h>
39 #include <moira_site.h>
40 #include "mit-copyright.h"
44 extern char *krb_err_txt[];
66 if ((whoami = strrchr(argv[0], '/')) == NULL)
79 /* Do it right; get name from kerberos ticket file rather than
82 if (k_errno = tf_init(TKT_FILE, R_TKT_FIL)) {
83 fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
87 if (k_errno = tf_get_pname(pname)) {
88 fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
100 /* This should be called rather than exit once connection to moira server
101 has been established. */
109 com_err(whoami, 0, "Unexpected return value from Moira -- programmer botch");
116 int status; /* general purpose exit status */
117 int q_argc; /* argc for mr_query */
118 char *q_argv[F_END]; /* argv for mr_query */
119 char *motd; /* for MR server status */
125 struct finger_info old_info;
126 struct finger_info new_info;
128 /* Try each query. If we ever fail, print error message and exit. */
130 status = mr_connect(NULL);
132 com_err(whoami, status, "while connecting to Moira");
136 status = mr_motd(&motd);
138 com_err(whoami, status, "unable to check server status");
142 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n", motd);
146 status = mr_auth("chfn"); /* Don't use argv[0] - too easy to fake */
148 com_err(whoami, status,
149 "while authenticating -- run \"kinit\" and try again.");
153 /* First, do an access check. */
155 q_argv[F_NAME] = uname;
156 for (i = F_NAME + 1; i < F_MODTIME; i++)
158 q_argc = F_MODTIME; /* one more than the last updatable field */
160 if (status = mr_access("update_finger_by_login", q_argc, q_argv)) {
161 com_err(whoami, status, "; finger\ninformation not changed.");
165 printf("Changing finger information for %s.\n", uname);
167 /* Get information */
169 q_argv[NAME] = uname;
171 if (status = mr_query("get_finger_by_login", q_argc, q_argv,
172 get_user_info, (char *) &old_info))
174 com_err(whoami, status, "while getting user information.");
178 /* Get the new information from the user */
180 get_new_info(&old_info, &new_info);
184 printf("Changing finger information...\n");
186 q_argv[F_NAME] = uname;
187 q_argv[F_FULLNAME] = new_info.fullname;
188 q_argv[F_NICKNAME] = new_info.nickname;
189 q_argv[F_HOME_ADDR] = new_info.home_address;
190 q_argv[F_HOME_PHONE] = new_info.home_phone;
191 q_argv[F_OFFICE_ADDR] = new_info.office_address;
192 q_argv[F_OFFICE_PHONE] = new_info.office_phone;
193 q_argv[F_MIT_DEPT] = new_info.mit_department;
194 q_argv[F_MIT_AFFIL] = new_info.mit_year;
195 q_argc = F_MODTIME; /* First non-update query argument */
197 if (status = mr_query("update_finger_by_login", q_argc, q_argv,
198 scream, (char *)NULL))
200 com_err(whoami, status, "while updating finger information.");
204 printf("Finger information updated succesfully.\n");
209 get_user_info(argc, argv, message)
214 struct finger_info *old_info = (struct finger_info *) message;
217 fprintf(stderr, "Some internal error occurred; try again.\n");
221 printf("Info last changed on %s by user %s with %s.\n",
222 argv[F_MODTIME], argv[F_MODBY], argv[F_MODWITH]);
224 old_info->fullname = strsave(argv[F_FULLNAME]);
225 old_info->nickname = strsave(argv[F_NICKNAME]);
226 old_info->home_address = strsave(argv[F_HOME_ADDR]);
227 old_info->home_phone = strsave(argv[F_HOME_PHONE]);
228 old_info->office_address = strsave(argv[F_OFFICE_ADDR]);
229 old_info->office_phone = strsave(argv[F_OFFICE_PHONE]);
230 old_info->mit_department = strsave(argv[F_MIT_DEPT]);
231 old_info->mit_year = strsave(argv[F_MIT_AFFIL]);
233 /* Only pay attention to the first match since login names are
234 unique in the database. */
238 char *ask(question, def_val, phone_num)
241 int phone_num; /* True if this must contain only digits */
243 static char buf[BUFSIZ];
254 printf("%s [%s]: ", question, def_val);
255 if (fgets(buf, sizeof(buf), stdin) == NULL)
257 buf[strlen(buf) - 1] = NULL;
258 if (strlen(buf) == 0)
260 else if (strcasecmp(buf, BLANK) == NULL)
265 for (i = 0; i < strlen(buf); i++)
270 printf("'\"' is not allowed.\n");
274 printf("',' is not allowed.\n");
278 printf("':' is not allowed.\n");
282 if (iscntrl(buf[i])) {
283 printf("Control characters are not allowed.\n");
292 if (phone_num && ok) {
293 for (i = 0; i < strlen(result); i++) {
294 if (!isdigit(result[i]) && (result[i] != '-')) {
295 printf("Phone numbers can contain only digits.\n");
299 if (result[i] == '-')
305 /* Remove dashes if necessary */
306 if (dashes && result == buf) {
308 tmp1 = tmp2 = (char *)buf;
319 void get_new_info(old_info, new_info)
320 struct finger_info *old_info;
321 struct finger_info *new_info;
323 printf("Default values are printed inside of '[]'.\n");
324 printf("To accept the default, type <return>.\n");
325 printf("To have a blank entry, type the word '%s'.\n\n", BLANK);
327 #define GETINFO(m,v,n) \
328 new_info->v = strsave(ask(m, old_info->v, n))
330 GETINFO("Full name", fullname, FALSE);
331 GETINFO("Nickname", nickname, FALSE);
332 GETINFO("Home address (Ex: Atkinson 304)", home_address, FALSE);
333 GETINFO("Home phone number (Ex: 3141592)", home_phone, TRUE);
334 GETINFO("Office address (Exs: E40-342 or 2-108)",
335 office_address, FALSE);
336 GETINFO("Office phone (Ex: 3-1300)", office_phone, TRUE);
337 GETINFO("MIT department (Exs: 9, Biology, Information Services)",
338 mit_department, FALSE);
339 GETINFO("MIT year (Exs: 1989, '91, Faculty, Grad)", mit_year, FALSE);
344 fprintf(stderr, "Usage: %s [user]\n", whoami);