3 * Talk to the Moira database to change a person's GECOS information.
5 * chfn with no modifiers changes the information of the user who is
8 * If a commandline argument is given, it is taken to be the username
9 * of the user whose information is to be changed.
11 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology
12 * For copying and distribution information, please see the file
16 #include <mit-copyright.h>
18 #include <moira_site.h>
45 int leave(int status);
46 int chfn(char *uname);
47 int get_user_info(int argc, char *argv[], void *message);
48 char *ask(char *question, char *def_val, int phone_num);
49 void get_new_info(struct finger_info *old_info, struct finger_info *new_info);
51 int main(int argc, char *argv[])
57 initialize_krb_error_table();
59 if ((whoami = strrchr(argv[0], '/')) == NULL)
71 /* Do it right; get name from kerberos ticket file rather than
74 if ((k_errno = tf_init(TKT_FILE, R_TKT_FIL)))
76 com_err(whoami, k_errno, "reading ticket file");
80 if ((k_errno = tf_get_pname(pname)))
82 com_err(whoami, k_errno, "getting kerberos principal name");
92 /* This should be called rather than exit once connection to moira server
93 has been established. */
100 int chfn(char *uname)
102 int status; /* general purpose exit status */
103 int q_argc; /* argc for mr_query */
104 char *q_argv[F_END]; /* argv for mr_query */
105 char *motd; /* for Moira server status */
108 struct finger_info old_info;
109 struct finger_info new_info;
111 /* Try each query. If we ever fail, print error message and exit. */
113 status = mr_connect(NULL);
116 com_err(whoami, status, "while connecting to Moira");
120 status = mr_motd(&motd);
123 com_err(whoami, status, "unable to check server status");
128 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n",
133 status = mr_auth("chfn"); /* Don't use argv[0] - too easy to fake */
136 com_err(whoami, status,
137 "while authenticating -- run \"kinit\" and try again.");
141 /* First, do an access check. */
143 q_argv[F_NAME] = uname;
144 for (i = F_NAME + 1; i < F_MODTIME; i++)
146 q_argc = F_MODTIME; /* one more than the last updatable field */
148 if ((status = mr_access("update_finger_by_login", q_argc, q_argv)))
150 com_err(whoami, status, "; finger\ninformation not changed.");
154 printf("Changing finger information for %s.\n", uname);
156 /* Get information */
158 q_argv[NAME] = uname;
160 if ((status = mr_query("get_finger_by_login", q_argc, q_argv,
161 get_user_info, &old_info)))
163 com_err(whoami, status, "while getting user information.");
167 /* Get the new information from the user */
169 get_new_info(&old_info, &new_info);
173 printf("Changing finger information...\n");
175 q_argv[F_NAME] = uname;
176 q_argv[F_FULLNAME] = new_info.fullname;
177 q_argv[F_NICKNAME] = new_info.nickname;
178 q_argv[F_HOME_ADDR] = new_info.home_address;
179 q_argv[F_HOME_PHONE] = new_info.home_phone;
180 q_argv[F_OFFICE_ADDR] = new_info.office_address;
181 q_argv[F_OFFICE_PHONE] = new_info.office_phone;
182 q_argv[F_MIT_DEPT] = new_info.mit_department;
183 q_argv[F_MIT_AFFIL] = new_info.mit_year;
184 q_argc = F_MODTIME; /* First non-update query argument */
186 if ((status = mr_query("update_finger_by_login", q_argc, q_argv,
189 com_err(whoami, status, "while updating finger information.");
193 printf("Finger information updated succesfully.\n");
198 int get_user_info(int argc, char *argv[], void *message)
200 struct finger_info *old_info = message;
204 fprintf(stderr, "Some internal error occurred; try again.\n");
208 printf("Info last changed on %s by user %s with %s.\n",
209 argv[F_MODTIME], argv[F_MODBY], argv[F_MODWITH]);
211 old_info->fullname = strdup(argv[F_FULLNAME]);
212 old_info->nickname = strdup(argv[F_NICKNAME]);
213 old_info->home_address = strdup(argv[F_HOME_ADDR]);
214 old_info->home_phone = strdup(argv[F_HOME_PHONE]);
215 old_info->office_address = strdup(argv[F_OFFICE_ADDR]);
216 old_info->office_phone = strdup(argv[F_OFFICE_PHONE]);
217 old_info->mit_department = strdup(argv[F_MIT_DEPT]);
218 old_info->mit_year = strdup(argv[F_MIT_AFFIL]);
220 /* Only pay attention to the first match since login names are
221 unique in the database. */
225 char *ask(char *question, char *def_val, int phone_num)
227 static char buf[BUFSIZ];
238 printf("%s [%s]: ", question, def_val);
239 if (!fgets(buf, sizeof(buf), stdin))
241 buf[strlen(buf) - 1] = '\0';
242 if (strlen(buf) == 0)
244 else if (!strcasecmp(buf, BLANK))
249 for (i = 0; i < strlen(buf); i++)
254 printf("'\"' is not allowed.\n");
258 printf("',' is not allowed.\n");
262 printf("':' is not allowed.\n");
268 printf("Control characters are not allowed.\n");
279 for (i = 0; i < strlen(result); i++)
281 if (!isdigit(result[i]) && (result[i] != '-'))
283 printf("Phone numbers can contain only digits.\n");
287 if (result[i] == '-')
293 /* Remove dashes if necessary */
294 if (dashes && result == buf)
297 tmp1 = tmp2 = (char *)buf;
309 void get_new_info(struct finger_info *old_info, struct finger_info *new_info)
311 printf("Default values are printed inside of '[]'.\n");
312 printf("To accept the default, type <return>.\n");
313 printf("To have a blank entry, type the word '%s'.\n\n", BLANK);
315 #define GETINFO(m, v, n) new_info->v = strdup(ask(m, old_info->v, n))
317 GETINFO("Full name", fullname, FALSE);
318 GETINFO("Nickname", nickname, FALSE);
319 GETINFO("Home address (Ex: EC Bemis 514)", home_address, FALSE);
320 GETINFO("Home phone number (Ex: 3141592)", home_phone, TRUE);
321 GETINFO("Office address (Exs: E40-342 or 2-108)",
322 office_address, FALSE);
323 GETINFO("Office phone (Ex: 3-7619)", office_phone, TRUE);
324 GETINFO("MIT department (Exs: 9, Biology, Information Services)",
325 mit_department, FALSE);
326 GETINFO("MIT year (Exs: 1989, '91, Faculty, Grad)", mit_year, FALSE);
331 fprintf(stderr, "Usage: %s [user]\n", whoami);