2 static char rcsid_module_c[] = "$Header$";
5 /* This is the file user.c for allmaint, the SMS client that allows
6 * a user to maintaint most important parts of the SMS database.
7 * It Contains: the functions for usermaint.
10 * By: Chris D. Peterson
16 * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
18 * For further information on copyright and distribution
19 * see the file mit-copyright.h
28 #include "mit-copyright.h"
30 #include "allmaint_funcs.h"
40 static void PrintQuota(); /* prints Quota info. */
41 static void PrintUserInfo(); /* prints User info. */
42 static int PrintPOBoxes(); /* prints PO Box information. */
44 /* Function Name: AskUserInfo.
45 * Description: This function askes the user for information about a
46 * machine and saves it into a structure.
47 * Arguments: info - a pointer the the structure to put the info into.
48 * flags - Flags asking us which info we want.
49 * Returns: the args to pass to the query.
50 * NOTES: the return args are not necessarily in the correct order to
51 * use the #defined names (e.g args[UID] is not the uid anymore).
55 AskUserInfo(info, name)
59 char temp_buf[BUFSIZ], *newname;
61 sprintf(temp_buf,"\nChanging Attributes of user %s.\n",info[NAME]);
62 Put_message(temp_buf);
65 newname = Strsave(info[U_NAME]);
66 GetValueFromUser("The new login name for this user.", &newname);
68 GetValueFromUser("User's UID:", &info[U_UID]);
69 GetValueFromUser("User's shell:", &info[U_SHELL]);
70 GetValueFromUser("User's last name:", &info[U_LAST]);
71 GetValueFromUser("User's first name:", &info[U_FIRST]);
72 GetValueFromUser("User's middle name:", &info[U_MIDDLE]);
73 GetValueFromUser("User's status:", &info[U_STATE]);
74 GetValueFromUser("User's MIT ID number:", &info[U_MITID]);
75 RemoveHyphens(info[U_MITID]); /* zap'em */
76 GetValueFromUser("User's MIT Year (class):", &info[U_CLASS]);
78 FreeAndClear(&info[U_MODTIME], TRUE);
79 FreeAndClear(&info[U_MODBY], TRUE);
80 FreeAndClear(&info[U_MODWITH], TRUE);
83 * Slide the newname into the #2 slot, this screws up all future references
84 * to this list, since we slip the pointer into a info list it gets freed
85 * when the rest of the list gets freed.
88 SlipInNewName(info, newname);
93 /* Function Name: GetUserInfo
94 * Description: Stores the user information in a queue.
95 * Arguments: type - type of field given to get info, one of:
96 * LOGIN, UID, NAME, CLASS.
97 * name1 - name of thing specified by type (wildcards okay)
98 * name2 - other name, only used in get user by first and last.
100 * Returns: the first element of the queue containing the user info.
104 GetUserInfo(type, name1, name2)
110 struct qelem * elem = NULL;
115 if ( (status = sms_query("get_user_by_login", 1, args,
116 StoreInfo, (char *) &elem)) != 0) {
117 com_err(program_name, status, " when attempting to get_use_by_login.");
123 if ( (status = sms_query("get_user_by_uid", 1, args,
124 StoreInfo, (char *) &elem)) != 0) {
125 com_err(program_name, status,
126 " when attempting to get_use_by_uid.");
133 if ( (status = sms_query("get_user_by_name", 1, args,
134 StoreInfo, (char *) &elem)) != 0) {
135 com_err(program_name, status,
136 " when attempting to get_use_by_name.");
142 if ( (status = sms_query("get_user_by_class", 1, args,
143 StoreInfo, (char *) &elem)) != 0) {
144 com_err(program_name, status,
145 " when attempting to get_use_by_class.");
151 if ( (status = sms_query("get_nquotas_by_user", 1, args,
152 StoreInfo, (char *) &elem)) != 0) {
153 com_err(program_name, status, " in get_nfs_quotas_by_user");
158 return( QueueTop(elem) );
161 /* -------------------------- Change Menu -------------------------- */
163 /* Function Name: ModifyUser
164 * Description: Modify some of the information about a user.
165 * Arguments: argc, argv - login name of the user in argv[1].
166 * Returns: DM_NORMAL.
171 ModifyUser(argc, argv)
176 char *temp_buf, error_buf[BUFSIZ];
177 struct qelem * elem, * local;
179 local = elem = GetUserInfo(LOGIN, argv[1], (char *) NULL);
181 while (local != NULL) {
182 char ** info = (char **) local->q_data;
183 char ** args = AskUserInfo(info, TRUE);
185 if ( (status = sms_query("update_user", CountArgs(args),
186 args, Scream, NULL)) != 0) {
187 com_err(program_name, status, " in ModifyFields");
188 if (local->q_forw == NULL)
191 temp_buf = ", Continuing to next user";
192 sprintf(error_buf,"User %s not updated due to error%s.",
193 info[NAME], temp_buf);
194 Put_message(error_buf);
196 local = local->q_forw;
203 /* Function Name: POType
204 * Description: Asks the SMS server if it is of type pop, of
205 * of type local. If neither, we assume that it's
207 * Arguments: machine - a canonicalized machine name,
208 * Returns: the PO Type, one of: pop, local, foreign.
217 struct qelem *top, *elem = NULL;
220 status = sms_query("get_server_locations", 1, &type,
222 if (status && (status != SMS_NO_MATCH)) {
223 com_err(program_name, status, (char *) NULL);
224 return( (char *) NULL);
228 while (elem != NULL) {
229 char ** info = (char **) elem->q_data;
230 if (strcmp (info[1], machine) == 0) {
232 return( Strsave("POP") );
237 return ( Strsave("SMTP") );
240 /* Function Name: ChangeUserPOBox
241 * Description: Changes The P.O. Box for a user.
242 * Arguments: argc, argv - the login name of the user in argv[1].
243 * Returns: DM_NORMAL.
248 ChangeUserPOBox(argc, argv)
253 struct qelem * poqueue, *local;
254 char *type, buf[BUFSIZ], *pohost;
258 sprintf(buf,"Current pobox for user %s: \n", argv[1]);
260 status = sms_query("get_pobox", 1, argv + 1, PrintPOBoxes, NULL);
261 if (status != SMS_NO_MATCH && status != 0) {
262 com_err(program_name, status, "in ChangeUserPOBox.");
265 else if (status == SMS_NO_MATCH)
266 Put_message("This user has no P.O. Box.");
268 if (YesNoQuestion("Shall we use the least loaded Post Office?", TRUE)) {
271 if ( status = sms_query ("get_server_host_info", 2, po,
272 StoreInfo, (char *) &poqueue) != 0) {
273 com_err(program_name, status,
274 " in ChangeUserPOBox (get_server_host_info).");
278 while (local != NULL) {
279 char ** args = (char **) local->q_data;
280 int new_space, old_space = -1 ;
281 if ( !isdigit(*args[6]) || !isdigit(*args[7]) )
283 "non-digit value in server_host_info, this is a bug.");
285 new_space = atoi(argv[7]) - atoi(args[6]);
286 if ( (new_space < old_space) || (old_space == -1) ) {
287 old_space = new_space;
288 strcpy(buf, args[1]);
291 local = local->q_forw;
293 pohost = Strsave(buf);
296 (void) sprintf(buf, "The Post Office %s was chosen.",
300 else if( (Prompt_input("Which Machine for Post Office?",
302 if ( (pohost = CanonicalizeHostname(buf)) == NULL) {
303 Put_message("\nNameserver doesn't know that machine, sorry.");
306 type = POType(pohost);
309 sprintf(buf, "%s %s's %s %s?", "Are you sure that you want to replace all",
310 argv[1], "P.O. Boxes\n with ** ONE ** on the machine", pohost);
317 if (status = sms_query("set_pobox", 4, po, Scream, NULL) != 0 )
318 com_err(program_name, status, " in ChangeUserPOBox");
320 Put_message("Operation Aborted.");
325 /* ------------------------- Top Menu ------------------------- */
327 /* delete user in delete.c */
329 /* Function Name: DeleteUserByUid
330 * Description: Deletes the user given a uid number.
331 * Arguments: argc, argv - uid if user in argv[1].
332 * Returns: DM_NORMAL.
337 DeleteUserByUid(argc, argv)
343 if (Confirm("Are you sure you want to remove this user"))
344 if ( (status = sms_query("delete_user_by_uid", 1, argv+1, Scream,
345 (char * ) NULL)) != 0)
346 com_err(program_name, status, " in DeleteUserByUid");
351 /* ------------------------- Show Quota Info ------------------------- */
353 /* Function Name: ShowDefaultQuota
354 * Description: This prints out a default quota for the system.
356 * Returns: DM_NORMAL.
363 static char *val[] = {"def_quota"};
365 if (status = sms_query("get_value", 1, val, Print, (char *) NULL) != 0)
366 com_err(program_name, status, " in ShowDefaultQuota");
371 /* Function Name: ShowUserQuota
372 * Description: Shows the quota of a user.
373 * Arguments: argc, argv - users login name is argv[1].
379 ShowUserQuota(argc, argv)
383 struct qelem *elem, *top;
384 top = elem = GetUserInfo(QUOTA, argv[1], (char *) NULL);
386 while (elem != NULL) {
387 char ** info = (char **) elem->q_data;
395 /* Function Name: ChangeDefaultQuota
396 * Description: Changes the System Wide default quota.
397 * Arguments: argc, argv - New quota in argv[1].
398 * Returns: DM_NORMAL.
403 ChangeDefaultQuota(argc, argv)
409 static char *newval[] = {
410 "update_value", "def_quota", NULL,
414 "Are you sure that you want to change the default quota\n"
415 "for all new users? (y/n) ");
418 if (status = sms_query("update_value", 3, newval, Scream, NULL) != 0)
419 com_err(program_name, status, " in update_value");
422 Put_message("Quota not changed.");
427 /* ---------------------- User Locker Manipultation -------------------- */
429 /* Function Name: AddUserLocker
430 * Description: Add a new locker for a user.
431 * Arguments: arc, argv -
432 * argv[1] login name of user.
433 * argv[2] server host name.
434 * argv[3] Directory on host.
435 * argv[4] quota in Kb.
436 * Returns: DM_NORMAL.
441 AddUserLocker(argc, argv)
452 args[1] = CanonicalizeHostname(argv[2]);
453 if (args[1] == (char *)NULL) {
454 Put_message("Could not canonicalize hostname; continuing..");
458 if (status = sms_query("add_locker", 4, args, Scream, NULL) != 0)
459 com_err(program_name, status, " in add_user_locker");
464 /* needs to be fixed - CDP 6/10/88 */
466 /* Function Name: DeleteUserLocker
467 * Description: Deletes a locker - BOOM.
468 * Arguments: arc, argv - the name of the locker in argv[1]/
469 * Returns: DM_NORMAL.
474 DeleteUserLocker(argc, argv)
479 if (status = sms_query("delete_locker", 1, argv + 1,
480 Scream, (char *)NULL) != 0)
481 com_err(program_name, status, " in delete_locker");
486 /* Function Name: ChangeUserQuota
487 * Description: This function allows all quotas to be updated for a user.
488 * Arguments: arg, argv - the name of the user in argv[1].
489 * Returns: DM_NORMAL.
494 ChangeUserQuota(argc, argv)
499 char error_buf[BUFSIZ];
500 struct qelem *elem, *local;
502 elem = GetUserInfo(QUOTA, argv[1], (char *) NULL);
505 while (local != NULL) {
507 info = (char **) local->q_data;
509 GetValueFromUser("New quota (in KB): ", &info[Q_QUOTA]);
511 if (status = sms_query("update_nfs_quota", 3, info,
512 Scream, (char *) NULL) != 0) {
513 com_err(program_name, status, " in update_nfs_quota");
514 sprintf(error_buf,"Could not perform quota change on %s",
516 Put_message(error_buf);
518 local = local->q_forw;
524 /* Function Name: ShowUserByLogin
525 * Description: Shows user information given a login name.
526 * Arguments: argc, argv - login name in argv[1].
532 ShowUserByLogin(argc, argv)
536 struct qelem *top, *elem;
538 elem = top = GetUserInfo(LOGIN, argv[1], (char *) NULL);
539 while (elem != NULL) {
540 PrintUserInfo( (char **) elem->q_data, FALSE);
548 /* Function Name: RetrieveUserByName
549 * Description: Show information on a user give fist and/or last name.
550 * Arguments: argc, argv - argv[1] - first name.
551 * argv[2] - last name.
552 * Returns: DM_NORMAL.
557 ShowUserByName(argc, argv)
561 struct qelem *top, *elem;
564 elem = top = GetUserInfo(NAME, argv[1], argv[2]);
566 if (!PromptWithDefault("Print full information, or just the names (F/N)?",
570 while (elem != NULL) {
574 PrintUserInfo( (char **) elem->q_data, FALSE);
578 PrintUserInfo( (char **) elem->q_data, TRUE);
588 /* Function Name: ShowUserByClass
589 * Description: Shows real and login names of all users in class.
590 * Arguments: argc, argv - argv[1] contains the class.
595 ShowUserByClass(argc, argv)
599 struct qelem *top, *elem;
601 elem = top = GetUserInfo(CLASS, argv[1], (char *) NULL);
603 while (elem != NULL) {
604 PrintUserInfo( (char **) elem->q_data, TRUE);
613 /* Function Name: PrintQuota
614 * Description: Prints a users quota information.
615 * Arguments: info - a pointer to the quota information:
625 sprintf(buf, "Machine: %s\t\tDirectory: %s\t\tQuota: %s",
626 info[Q_MACHINE], info[Q_DIRECTORY], info[Q_QUOTA]);
630 /* Function Name: PrintPOBoxes
631 * Description: Yet another specialized print function.
632 * Arguments: argc, argv -
633 * argv[0] - login name.
636 * argv[3] - box name.
643 PrintPOBoxes(argc, argv, junk)
649 /* no newline 'cause Put_message adds one */
651 (void) sprintf(buf, "Address: %s@%s\t\tType: %s", argv[PO_BOX],
652 argv[PO_MACHINE], argv[PO_TYPE]);
653 (void) Put_message(buf);
658 /* Function Name: PrintUserInfo
659 * Description: Prints Information about a user.
660 * Arguments: info - an argument list with the user information
662 * name_only - if TRUE then print only the users name.
667 PrintUserInfo(info, name_only)
674 sprintf(buf, "%s, %s %s", info[U_LAST],
675 info[U_FIRST], info[U_MIDDLE]);
676 sprintf(buf, "%-40s/tUser Name: %s", buf, info[U_NAME]);
681 "Login name: %-10s/tUser id: %-10s\tLogin shell %s",
682 info[U_NAME], info[U_UID], info[U_SHELL]);
683 (void) Put_message(buf);
684 (void) sprintf(buf, "Full name: %s %s %s\tClass: %s",
685 info[U_FIRST], info[U_MIDDLE],
686 info[U_LAST], info[U_CLASS]);
687 (void) Put_message(buf);
689 "Account status: %s\tEncrypted MIT ID number: %s",
690 atoi(info[U_STATE]) ? "active" : "inactive",
692 (void) Put_message(buf);
693 (void) sprintf(buf, "Last Modification by %s at %s with %s.",
694 info[U_MODBY], info[U_MODTIME], info[U_MODWITH]);
695 (void) Put_message(buf);
703 * c-continued-statement-offset: 4
705 * c-argdecl-indent: 4