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?
42 CheckListForDeletion(name, verbose)
46 struct qelem *elem = NULL;
48 char *args[2], buf[BUFSIZ], **info;
50 if ( (status = do_mr_query("count_members_of_list", 1, &name, StoreInfo,
51 (char *) &elem)) != 0) {
52 com_err(program_name, status,
53 " in DeleteList (count_members_of_list).");
56 info = (char **) elem->q_data;
57 if ( strcmp(info[NAME],"0") == 0) {
59 sprintf(buf, "Delete the empty list %s? ", name);
60 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?
90 CheckAce(type, name, verbose)
94 char *args[2], buf[BUFSIZ];
97 if ( strcmp(type, "LIST") != 0 )
98 return; /* If the ace is not a list the ignore it. */
102 status = do_mr_query("get_ace_use", 2, args, NullFunc, (char *) NULL);
103 if (status != MR_NO_MATCH)
104 return; /* If this query fails the ace will
105 not be deleted even if it is empty. */
107 sprintf(buf, "Delete the unused Access Control Entity (ACE) %s? ",
109 if ( YesNoQuestion(buf, FALSE) != TRUE) {
110 Put_message("Aborting Deletion!");
117 * NOTE: Delete list expects only the name of the list to delete in argv[1].
118 * since, 'args' already satisfies this, there is no need to create
119 * a special argument list.
125 /* Function Name: CheckIfAce
126 * Description: Checks to see if this is an ace of another data object.
127 * Arguments: name - name of the object.
128 * Returns: SUB_ERROR if this list is an ace, or if the query did not
133 CheckIfAce(name, type, verbose)
137 char * args[2], buf[BUFSIZ], **info;
138 struct qelem *local, *elem;
144 switch (status = do_mr_query("get_ace_use", 2, args,
145 StoreInfo, (char *) &elem)) {
149 local = elem = QueueTop(elem);
150 info = (char **) local->q_data;
151 if (QueueCount(elem) == 1 &&
152 !strcmp(info[0], "LIST") &&
153 !strcmp(info[1], name)) {
158 sprintf(buf, "%s %s %s", type, name,
159 "is the ACE for the following data objects:");
162 for (; local != NULL; local = local->q_forw) {
163 info = (char **) local->q_data;
164 if (!strcmp(info[0], "LIST") &&
165 !strcmp(info[1], name))
167 Print(CountArgs(info), info, NULL);
171 "The ACE for each of these items must be changed before");
172 sprintf(buf,"the %s %s can be deleted.\n", type, name);
177 com_err(program_name, status, " in CheckIfAce (get_ace_use).");
184 /* Function Name: RemoveItemFromLists
185 * Description: this function removes a list from all other lists of
186 * which it is a member.
187 * Arguments: name - name of the item
188 * elem - a pointer to a queue element. RETURNED
189 * verbose - verbose mode.
190 * Returns: SUB_ERROR if there is an error.
194 RemoveItemFromLists(name, type, elem, verbose)
196 struct qelem ** elem;
200 char *args[10], temp_buf[BUFSIZ];
209 * Get all list of which this item is a member, and store them in a queue.
212 status = do_mr_query("get_lists_of_member", 2, args, StoreInfo,
215 if (status == MR_NO_MATCH)
218 if (status != MR_SUCCESS) {
219 com_err(program_name, status, " in DeleteList (get_lists_of_member).");
224 * If verbose mode, ask user of we should remove our list from
228 local = *elem = QueueTop(*elem);
229 lists = QueueCount(*elem);
233 sprintf(temp_buf, "%s %s is a member of %d other list%s.\n", type,
234 name, lists, ((lists == 1) ? "" : "s") );
235 Put_message(temp_buf);
236 while (local != NULL) {
237 char ** info = (char **) local->q_data;
238 Print( 1, &info[GLOM_NAME], (char *) NULL);
239 local = local->q_forw;
241 Put_message(" "); /* Blank Line. */
242 sprintf(temp_buf,"Remove %s %s from these lists? ", type, name);
243 if (YesNoQuestion(temp_buf, FALSE) != TRUE) {
244 Put_message("Aborting...");
252 * Remove this list from all lists that it is a member of.
256 args[DM_MEMBER] = name;
257 args[DM_TYPE] = type;
258 while (local != NULL) {
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)) != 0) {
263 com_err(program_name, status, " in delete_member\nAborting\n");
267 local = local->q_forw;
272 /* Function Name: RemoveMembersOfList
273 * Description: Deletes the members of the list.
274 * Arguments: name - name of the list.
275 * verbose - query user, about deletion?
276 * Returns: SUB_ERROR - if we could not delete, or the user abouted.
280 RemoveMembersOfList(name, verbose)
284 char buf[BUFSIZ], *args[10];
285 struct qelem *local, *elem = NULL;
288 * Get the members of this list.
290 status = do_mr_query("get_members_of_list", 1, &name, StoreInfo,
292 if (status == MR_NO_MATCH)
296 com_err(program_name, status, " in DeleteList (get_members_of_list).");
300 * If verbose mode, then ask the user if we should delete.
302 local = elem = QueueTop(elem);
303 if ( (members = QueueCount(elem)) == 0)
306 sprintf(buf, "List %s has %d member%s:", name, QueueCount(elem),
307 ((members == 1) ? "" : "s") );
309 Put_message(" "); /* Blank Line. */
310 while (local != NULL) {
311 char ** info = (char **) local->q_data;
312 Print( CountArgs(info), info, NULL);
313 local = local->q_forw;
315 Put_message(" "); /* Blank Line. */
316 sprintf(buf, "Remove th%s member%s from list %s? ",
317 ((members == 1) ? "is" : "ese"),
318 ((members == 1) ? "" : "s"), name );
319 if ( YesNoQuestion(buf, FALSE) != TRUE) {
320 Put_message("Aborting...");
326 * Perform The Removal.
330 while (local != NULL) {
331 char ** info = (char **) local->q_data;
334 if ( (status = do_mr_query("delete_member_from_list",
335 3, args, Scream, NULL)) != 0) {
336 com_err(program_name, status, " in delete_member\nAborting\n");
340 local = local->q_forw;
345 /* Function Name: DeleteUserGroup
346 * Description: Deletes the list given by name if it exists.
347 * intended to be used to delete user groups
348 * Arguments: name - the name of the list to delete.
349 * verbose - flag that if TRUE queries the user to
350 * ask if list should be deleted.
351 * Returns: MR_ERROR if there is an error.
355 DeleteUserGroup(name, verbose)
360 char buf[BUFSIZ], *args[10];
362 status = do_mr_query("get_list_info", 1, &name, NullFunc, (char *) NULL);
365 sprintf(buf, "There is also a list named %s, delete it?", name);
366 ans = YesNoQuestion(buf, FALSE);
368 Put_message("Leaving group alone.");
372 Put_message("Aborting...\n");
376 /* ans == TRUE || ~verbose */
377 args[0] = "foo"; /* not used. */
381 else if (status != MR_NO_MATCH) {
382 com_err(program_name, status, " Aborting Delete User.");
388 /* Function Name: DeleteHomeFilesys
389 * Description: Delete the home filesystem for the named user.
390 * Arguments: name - name of the user (and filsystem) to delete.
391 * verbose - if TRUE query user.
392 * Returns: SUB_NORMAL if home filesystem deleted, or nonexistant.
396 DeleteHomeFilesys(name, verbose)
403 switch (status = do_mr_query("get_filesys_by_label", 1, &name, NullFunc,
409 sprintf(buf, "Delete the filesystem named %s (y/n)?", name);
410 switch (YesNoQuestion(buf, FALSE)) {
412 Put_message("Filesystem Not Deleted, continuing...\n");
417 Put_message("Filesystem Not Deleted, aborting...\n\n");
421 if ( (status = do_mr_query("delete_filesys", 1, &name, Scream,
422 (char *) NULL) ) != MR_SUCCESS) {
423 com_err(program_name, status, " in delete_filesys.");
427 Put_message("Filesystem Successfully Deleted.");
430 com_err(program_name, status, " in get_filesystem_by_label).");
437 /* Function Name: RealDeleteUser
438 * Description: Just Deletes the user.
439 * Arguments: name - name of User to delete
440 * Returns: SUB_ERROR if the deletion failed.
450 if ( (status = do_mr_query("delete_user", 1, &name, Scream,
451 (char *) NULL)) != MR_SUCCESS) {
452 com_err(program_name, status, ": user not deleted");
455 (void) sprintf(buf, "User %s deleted.", name);
461 /* Function Name: RealDeleteList
462 * Description: Just Deletes the list.
463 * Arguments: name - name of list to delete
464 * Returns: SUB_ERROR if the deletion failed.
474 if ( (status = do_mr_query("delete_list", 1, &name, Scream,
475 (char *) NULL)) != MR_SUCCESS) {
476 com_err(program_name, status, ": list not deleted");
479 (void) sprintf(buf, "List %s deleted.", name);
485 /* Function Name: AttemptToDeleteList
486 * Description: Atempts to delete list, in the following manner:
487 * 1) try to delet it, if this fails in a known error then
488 * a) try to clean up each of those known methods, or
489 * at least explain why we failed.
490 * Arguments: list_info - info about this list.
491 * ask_first - (T/F) query user before preparing for deletion,
493 * Returns: none - all is taken care of and error messages printed
494 * one way or the other.
498 AttemptToDeleteList(list_info, ask_first)
503 struct qelem *local, *member_of;
504 char *name = list_info[L_NAME];
508 * Attempt delete. - will only work if:
509 * 1) This list has no members.
510 * 2) This list in a member of no other lists.
511 * 3) This list is not an ace of another object.
514 switch (status = do_mr_query("delete_list", 1, &name,
515 Scream, (char *) NULL)) {
517 Put_message("List Sucessfully Deleted.");
518 CheckAce(list_info[L_ACE_TYPE], list_info[L_ACE_NAME], ask_first);
522 * This list is in use. Try to find out why,
523 * and for the cases where we have a good idea of
524 * what to do we will query and then do it.
527 if ((CheckIfAce(name, "list", ask_first) != SUB_NORMAL) ||
528 (RemoveItemFromLists(name, "list",
529 &member_of, ask_first) != SUB_NORMAL))
532 * If the list is it's own ACL, then make the person performing
533 * the delete the owner before removing this person from the list
535 if (!strcmp(list_info[L_ACE_TYPE], "LIST") &&
536 !strcmp(list_info[L_ACE_NAME], list_info[L_NAME])) {
537 free(list_info[L_ACE_TYPE]);
538 free(list_info[L_ACE_NAME]);
539 list_info[L_ACE_TYPE] = Strsave("USER");
540 list_info[L_ACE_NAME] = Strsave(user);
541 SlipInNewName(list_info, Strsave(list_info[L_NAME]));
542 if ((status = do_mr_query("update_list", CountArgs(list_info)-3,
543 list_info, Scream, (char *) NULL))
545 com_err(program_name, status, " while updating list owner");
546 Put_message("List may be only partly deleted.");
549 if ((RemoveMembersOfList(name, ask_first) == SUB_NORMAL) &&
550 (RealDeleteList(name) == SUB_NORMAL) )
552 CheckAce(list_info[L_ACE_TYPE], list_info[L_ACE_NAME], ask_first);
554 local = QueueTop(member_of);
555 while (local != NULL) {
556 char ** info = (char **) local->q_data;
557 if (CheckListForDeletion(info[LM_LIST], ask_first) == SUB_ERROR)
559 local = local->q_forw;
561 FreeQueue(member_of);
565 com_err(program_name, status, " in DeleteList (delete_list).");
570 /* Function Name: DeleteList
571 * Description: deletes a list
572 * Arguments: argc, argv - standard MR argc and argv.
573 * Returns: DM Status Code.
578 DeleteList(argc, argv)
583 struct qelem *top, *list;
589 switch(status = do_mr_query("get_list_info", 1, argv + 1,
590 StoreInfo, (char *) &list)){
593 /* case MR_NO_WILDCARD:
594 Put_message("Wildcards are not accepted here.");
598 Put_message("There is no list that matches that name.");
601 com_err(program_name, status, " in DeleteList (get_list_info).");
605 top = list = QueueTop(list);
606 one_list = (QueueCount(list) == 1);
607 while (list != NULL) {
608 char ** info = (char**) list->q_data;
610 sprintf( buf, "Are you sure that you want to delete the list %s",
612 if ( Confirm(buf) ) AttemptToDeleteList(info, TRUE);
615 sprintf(buf, "Delete the list %s", info[L_NAME]);
616 switch( YesNoQuestion( buf, FALSE ) ) {
618 AttemptToDeleteList(info, TRUE);
623 Put_message ("Aborting...");
634 /* Function Name: DeleteUser
635 * Description: Deletes a user from the database.
636 * Arguments: argc, argv - name of the user in argv[1].
637 * Returns: DM_NORMAL.
642 DeleteUser(argc, argv)
648 char * name = argv[1]; /* name of the user we are deleting. */
650 struct qelem *local, *member_of = NULL;
653 if (!ValidName(name))
656 if (!Confirm("Are you sure that you want to delete this user?"))
659 status = do_mr_query("delete_user", 1, &name, Scream, (char *) NULL);
660 if (status != MR_IN_USE && status != 0) {
661 com_err(program_name, status, ": user not deleted");
665 sprintf(buf,"User %s deleted.", name);
668 /* delete this return if the policy decision below is reversed */
673 /* Design decision not to allow registered users to be deleted.
675 Put_message("Sorry, registered users cannot be deleted from the database.");
676 Put_message("Deactivate the user now, and the system manager will expunge later.");
678 else if (status == MR_IN_USE) {
682 * 1) Query - Delete home filesytem.
683 * 2) Query - Delete user Group.
684 * 2) Is the user an ACE of any object in the database?
685 * 3) Query - Remove user from all list of which he is a member.
687 * If all these have been accomplished, then attempt to delete the user again.
689 if ( (DeleteHomeFilesys(name, TRUE) == SUB_ERROR) ||
690 (DeleteUserGroup(name, TRUE) == SUB_ERROR) ||
691 (CheckIfAce(name, "user", TRUE) == SUB_ERROR) ||
692 (RemoveItemFromLists(name, "user",
693 &member_of, TRUE) == SUB_ERROR) ||
694 (RealDeleteUser(name) == SUB_ERROR) ) {
700 * Query - Delete all empty lists created by removing this user from them.
704 while (local != NULL) {
705 char ** info = (char **) local->q_data;
706 if (CheckListForDeletion(info[0], TRUE) == SUB_ERROR)
708 local = local->q_forw;
711 FreeQueue(member_of); /* Free memory and return. */