1 #if (!defined(lint) && !defined(SABER))
2 static char rcsid_module_c[] = "$Header$";
5 /* This is the file delete.c for the MOIRA Client, which allows a nieve
6 * user to quickly and easily maintain most parts of the MOIRA database.
7 * It Contains: functions for deleting users and lists.
10 * By: Chris D. Peterson
16 * Copyright 1988 by the Massachusetts Institute of Technology.
18 * For further information on copyright and distribution
19 * see the file mit-copyright.h
25 #include <moira_site.h>
28 #include "mit-copyright.h"
33 /* Function Name: CheckListForDeletion
34 * Description: Check one of the lists in which we just removed a member.
35 * if the list is empty then it will delete it.
36 * Arguments: name - name of the list to check.
37 * verbose - verbose mode?
41 int CheckListForDeletion(char *name, Bool verbose)
43 struct qelem *elem = NULL;
45 char *args[2], buf[BUFSIZ], **info;
47 if ((status = do_mr_query("count_members_of_list", 1, &name, StoreInfo,
50 com_err(program_name, status, " in DeleteList (count_members_of_list).");
53 info = (char **) elem->q_data;
54 if (!strcmp(info[NAME], "0"))
58 sprintf(buf, "Delete the empty list %s? ", name);
59 switch (YesNoQuestion(buf, FALSE))
64 Put_message("Not deleting this list.");
68 Put_message("Aborting Deletion!");
73 args[0] = "foo"; /* not used. */
81 /* Function Name: CheckAce
82 * Description: Checks an ace to see of we should delete it.
83 * Arguments: type - the type of this ace.
84 * name - the name of the ace.
85 * verbose - query user?
89 void CheckAce(char *type, char *name, Bool verbose)
91 char *args[2], buf[BUFSIZ];
94 if (strcmp(type, "LIST"))
95 return; /* If the ace is not a list the ignore it. */
99 status = do_mr_query("get_ace_use", 2, args, NullFunc, NULL);
100 if (status != MR_NO_MATCH)
101 return; /* If this query fails the ace will
102 not be deleted even if it is empty. */
105 sprintf(buf, "Delete the unused Access Control Entity (ACE) %s? ", name);
106 if (YesNoQuestion(buf, FALSE) != TRUE)
108 Put_message("Aborting Deletion!");
115 * NOTE: Delete list expects only the name of the list to delete in argv[1].
116 * since, 'args' already satisfies this, there is no need to create
117 * a special argument list.
123 /* Function Name: CheckIfAce
124 * Description: Checks to see if this is an ace of another data object.
125 * Arguments: name - name of the object.
126 * Returns: SUB_ERROR if this list is an ace, or if the query did not
130 int CheckIfAce(char *name, char *type, Bool verbose)
132 char *args[2], buf[BUFSIZ], **info;
133 struct qelem *local, *elem;
139 switch ((status = do_mr_query("get_ace_use", 2, args,
140 StoreInfo, (char *) &elem)))
145 local = elem = QueueTop(elem);
146 info = (char **) local->q_data;
147 if (QueueCount(elem) == 1 &&
148 !strcmp(info[0], "LIST") &&
149 !strcmp(info[1], name))
156 sprintf(buf, "%s %s %s", type, name,
157 "is the ACE for the following data objects:");
160 for (; local != NULL; local = local->q_forw)
162 info = (char **) local->q_data;
163 if (!strcmp(info[0], "LIST") &&
164 !strcmp(info[1], name))
166 Print(CountArgs(info), info, NULL);
169 Put_message("The ACE for each of these items must be changed before");
170 sprintf(buf, "the %s %s can be deleted.\n", type, name);
175 com_err(program_name, status, " in CheckIfAce (get_ace_use).");
182 /* Function Name: RemoveItemFromLists
183 * Description: this function removes a list from all other lists of
184 * which it is a member.
185 * Arguments: name - name of the item
186 * elem - a pointer to a queue element. RETURNED
187 * verbose - verbose mode.
188 * Returns: SUB_ERROR if there is an error.
191 int RemoveItemFromLists(char *name, char *type, struct qelem **elem,
195 char *args[10], temp_buf[BUFSIZ];
204 * Get all list of which this item is a member, and store them in a queue.
207 status = do_mr_query("get_lists_of_member", 2, args, StoreInfo,
210 if (status == MR_NO_MATCH)
213 if (status != MR_SUCCESS)
215 com_err(program_name, status, " in DeleteList (get_lists_of_member).");
220 * If verbose mode, ask user of we should remove our list from
224 local = *elem = QueueTop(*elem);
225 lists = QueueCount(*elem);
230 sprintf(temp_buf, "%s %s is a member of %d other list%s.\n", type,
231 name, lists, ((lists == 1) ? "" : "s"));
232 Put_message(temp_buf);
235 char **info = (char **) local->q_data;
236 Print(1, &info[GLOM_NAME], (char *) NULL);
237 local = local->q_forw;
239 Put_message(" "); /* Blank Line. */
240 sprintf(temp_buf, "Remove %s %s from these lists? ", type, name);
241 if (YesNoQuestion(temp_buf, FALSE) != TRUE)
243 Put_message("Aborting...");
251 * Remove this list from all lists that it is a member of.
255 args[DM_MEMBER] = name;
256 args[DM_TYPE] = type;
259 char **info = (char **) local->q_data;
260 args[DM_LIST] = info[GLOM_NAME];
261 if ((status = do_mr_query("delete_member_from_list",
262 3, args, Scream, NULL)))
264 com_err(program_name, status, " in delete_member\nAborting\n");
268 local = local->q_forw;
273 /* Function Name: RemoveMembersOfList
274 * Description: Deletes the members of the list.
275 * Arguments: name - name of the list.
276 * verbose - query user, about deletion?
277 * Returns: SUB_ERROR - if we could not delete, or the user abouted.
280 int RemoveMembersOfList(char *name, Bool verbose)
282 char buf[BUFSIZ], *args[10];
283 struct qelem *local, *elem = NULL;
286 * Get the members of this list.
288 status = do_mr_query("get_members_of_list", 1, &name, StoreInfo,
290 if (status == MR_NO_MATCH)
295 com_err(program_name, status, " in DeleteList (get_members_of_list).");
299 * If verbose mode, then ask the user if we should delete.
301 local = elem = QueueTop(elem);
302 if (!(members = QueueCount(elem)))
306 sprintf(buf, "List %s has %d member%s:", name, QueueCount(elem),
307 ((members == 1) ? "" : "s"));
309 Put_message(" "); /* Blank Line. */
312 char **info = (char **) local->q_data;
313 Print(CountArgs(info), info, NULL);
314 local = local->q_forw;
316 Put_message(" "); /* Blank Line. */
317 sprintf(buf, "Remove th%s member%s from list %s? ",
318 ((members == 1) ? "is" : "ese"),
319 ((members == 1) ? "" : "s"), name);
320 if (YesNoQuestion(buf, FALSE) != TRUE)
322 Put_message("Aborting...");
328 * Perform The Removal.
334 char **info = (char **) local->q_data;
337 if ((status = do_mr_query("delete_member_from_list",
338 3, args, Scream, NULL)))
340 com_err(program_name, status, " in delete_member\nAborting\n");
344 local = local->q_forw;
349 /* Function Name: DeleteUserGroup
350 * Description: Deletes the list given by name if it exists.
351 * intended to be used to delete user groups
352 * Arguments: name - the name of the list to delete.
353 * verbose - flag that if TRUE queries the user to
354 * ask if list should be deleted.
355 * Returns: MR_ERROR if there is an error.
358 int DeleteUserGroup(char *name, Bool verbose)
361 char buf[BUFSIZ], *args[10];
363 status = do_mr_query("get_list_info", 1, &name, NullFunc, (char *) NULL);
368 sprintf(buf, "There is also a list named %s, delete it?", name);
369 ans = YesNoQuestion(buf, FALSE);
372 Put_message("Leaving group alone.");
377 Put_message("Aborting...\n");
381 /* ans == TRUE || ~verbose */
382 args[0] = "foo"; /* not used. */
386 else if (status != MR_NO_MATCH)
388 com_err(program_name, status, " Aborting Delete User.");
394 /* Function Name: DeleteHomeFilesys
395 * Description: Delete the home filesystem for the named user.
396 * Arguments: name - name of the user (and filsystem) to delete.
397 * verbose - if TRUE query user.
398 * Returns: SUB_NORMAL if home filesystem deleted, or nonexistant.
401 int DeleteHomeFilesys(char *name, Bool verbose)
406 switch ((status = do_mr_query("get_filesys_by_label", 1, &name, NullFunc,
414 sprintf(buf, "Delete the filesystem named %s (y/n)?", name);
415 switch (YesNoQuestion(buf, FALSE))
418 Put_message("Filesystem Not Deleted, continuing...\n");
423 Put_message("Filesystem Not Deleted, aborting...\n\n");
427 if ((status = do_mr_query("delete_filesys", 1, &name, Scream,
428 NULL)) != MR_SUCCESS)
430 com_err(program_name, status, " in delete_filesys.");
434 Put_message("Filesystem Successfully Deleted.");
437 com_err(program_name, status, " in get_filesystem_by_label).");
444 /* Function Name: RealDeleteUser
445 * Description: Just Deletes the user.
446 * Arguments: name - name of User to delete
447 * Returns: SUB_ERROR if the deletion failed.
450 static int RealDeleteUser(char *name)
455 if ((status = do_mr_query("delete_user", 1, &name, Scream,
456 NULL)) != MR_SUCCESS)
458 com_err(program_name, status, ": user not deleted");
461 sprintf(buf, "User %s deleted.", name);
467 /* Function Name: RealDeleteList
468 * Description: Just Deletes the list.
469 * Arguments: name - name of list to delete
470 * Returns: SUB_ERROR if the deletion failed.
473 static int RealDeleteList(char *name)
478 if ((status = do_mr_query("delete_list", 1, &name, Scream,
479 NULL)) != MR_SUCCESS)
481 com_err(program_name, status, ": list not deleted");
484 sprintf(buf, "List %s deleted.", name);
490 /* Function Name: AttemptToDeleteList
491 * Description: Atempts to delete list, in the following manner:
492 * 1) try to delet it, if this fails in a known error then
493 * a) try to clean up each of those known methods, or
494 * at least explain why we failed.
495 * Arguments: list_info - info about this list.
496 * ask_first - (T/F) query user before preparing for deletion,
498 * Returns: none - all is taken care of and error messages printed
499 * one way or the other.
502 void AttemptToDeleteList(char **list_info, Bool ask_first)
505 struct qelem *local, *member_of;
506 char *name = list_info[L_NAME];
510 * Attempt delete. - will only work if:
511 * 1) This list has no members.
512 * 2) This list in a member of no other lists.
513 * 3) This list is not an ace of another object.
516 switch ((status = do_mr_query("delete_list", 1, &name, Scream, NULL)))
519 Put_message("List Sucessfully Deleted.");
520 CheckAce(list_info[L_ACE_TYPE], list_info[L_ACE_NAME], ask_first);
524 * This list is in use. Try to find out why,
525 * and for the cases where we have a good idea of
526 * what to do we will query and then do it.
529 if ((CheckIfAce(name, "list", ask_first) != SUB_NORMAL) ||
530 (RemoveItemFromLists(name, "list",
531 &member_of, ask_first) != SUB_NORMAL))
534 * If the list is it's own ACL, then make the person performing
535 * the delete the owner before removing this person from the list
537 if (!strcmp(list_info[L_ACE_TYPE], "LIST") &&
538 !strcmp(list_info[L_ACE_NAME], list_info[L_NAME]))
540 free(list_info[L_ACE_TYPE]);
541 free(list_info[L_ACE_NAME]);
542 list_info[L_ACE_TYPE] = Strsave("USER");
543 list_info[L_ACE_NAME] = Strsave(user);
544 SlipInNewName(list_info, Strsave(list_info[L_NAME]));
545 if ((status = do_mr_query("update_list", CountArgs(list_info) - 3,
546 list_info, Scream, NULL)) != MR_SUCCESS)
548 com_err(program_name, status, " while updating list owner");
549 Put_message("List may be only partly deleted.");
552 if ((RemoveMembersOfList(name, ask_first) == SUB_NORMAL) &&
553 (RealDeleteList(name) == SUB_NORMAL))
555 CheckAce(list_info[L_ACE_TYPE], list_info[L_ACE_NAME], ask_first);
557 local = QueueTop(member_of);
560 char **info = (char **) local->q_data;
561 if (CheckListForDeletion(info[LM_LIST], ask_first) == SUB_ERROR)
563 local = local->q_forw;
565 FreeQueue(member_of);
569 com_err(program_name, status, " in DeleteList (delete_list).");
574 /* Function Name: DeleteList
575 * Description: deletes a list
576 * Arguments: argc, argv - standard MR argc and argv.
577 * Returns: DM Status Code.
580 int DeleteList(int argc, char *argv[])
583 struct qelem *top, *list;
589 switch ((status = do_mr_query("get_list_info", 1, argv + 1,
590 StoreInfo, (char *) &list)))
596 Put_message("Wildcards are not accepted here.");
601 Put_message("There is no list that matches that name.");
604 com_err(program_name, status, " in DeleteList (get_list_info).");
608 top = list = QueueTop(list);
609 one_list = (QueueCount(list) == 1);
612 char **info = (char **) list->q_data;
615 sprintf(buf, "Are you sure that you want to delete the list %s",
618 AttemptToDeleteList(info, TRUE);
622 sprintf(buf, "Delete the list %s", info[L_NAME]);
623 switch (YesNoQuestion(buf, FALSE))
626 AttemptToDeleteList(info, TRUE);
631 Put_message("Aborting...");
642 /* Function Name: DeleteUser
643 * Description: Deletes a user from the database.
644 * Arguments: argc, argv - name of the user in argv[1].
645 * Returns: DM_NORMAL.
648 int DeleteUser(int argc, char **argv)
652 char *name = argv[1]; /* name of the user we are deleting. */
654 struct qelem *local, *member_of = NULL;
657 if (!ValidName(name))
660 if (!Confirm("Are you sure that you want to delete this user?"))
663 status = do_mr_query("delete_user", 1, &name, Scream, NULL);
664 if (status != MR_IN_USE && status != 0)
666 com_err(program_name, status, ": user not deleted");
671 sprintf(buf, "User %s deleted.", name);
674 /* delete this return if the policy decision below is reversed */
679 /* Design decision not to allow registered users to be deleted.
681 Put_message("Sorry, registered users cannot be deleted from the database.");
682 Put_message("Deactivate the user now, and the system manager will expunge later.");
684 else if (status == MR_IN_USE)
689 * 1) Query - Delete home filesytem.
690 * 2) Query - Delete user Group.
691 * 2) Is the user an ACE of any object in the database?
692 * 3) Query - Remove user from all list of which he is a member.
694 * If all these have been accomplished, then attempt to delete
697 if ((DeleteHomeFilesys(name, TRUE) == SUB_ERROR) ||
698 (DeleteUserGroup(name, TRUE) == SUB_ERROR) ||
699 (CheckIfAce(name, "user", TRUE) == SUB_ERROR) ||
700 (RemoveItemFromLists(name, "user", &member_of, TRUE) == SUB_ERROR) ||
701 (RealDeleteUser(name) == SUB_ERROR))
706 * Query - Delete all empty lists created by removing this user from them.
712 char **info = (char **) local->q_data;
713 if (CheckListForDeletion(info[0], TRUE) == SUB_ERROR)
715 local = local->q_forw;
718 FreeQueue(member_of); /* Free memory and return. */