]> andersk Git - moira.git/blob - clients/moira/delete.c
Diane Delgado's changes for a fixed table-locking order
[moira.git] / clients / moira / delete.c
1 #if (!defined(lint) && !defined(SABER))
2   static char rcsid_module_c[] = "$Header$";
3 #endif lint
4
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.
8  *      
9  *      Created:        5/18/88
10  *      By:             Chris D. Peterson
11  *
12  *      $Source$
13  *      $Author$
14  *      $Header$
15  *      
16  *      Copyright 1988 by the Massachusetts Institute of Technology.
17  *
18  *      For further information on copyright and distribution 
19  *      see the file mit-copyright.h
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <moira.h>
25 #include <moira_site.h>
26 #include <menu.h>
27
28 #include "mit-copyright.h"
29 #include "defs.h"
30 #include "f_defs.h"
31 #include "globals.h"
32
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?
38  *      Returns: none.
39  */
40
41 int
42 CheckListForDeletion(name, verbose)
43 char * name;
44 Bool verbose;
45 {
46     struct qelem *elem = NULL;
47     int status;
48     char *args[2], buf[BUFSIZ], **info;
49
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).");
54         return(SUB_NORMAL);
55     }
56     info = (char **) elem->q_data;
57     if ( strcmp(info[NAME],"0") == 0) {
58         if (verbose) {
59             sprintf(buf, "Delete the empty list %s? ", name);
60             switch (YesNoQuestion(buf, FALSE)) {
61             case TRUE:
62                 break;
63             case FALSE:
64                 Put_message("Not deleting this list.");
65                 FreeQueue(elem);
66                 return(SUB_NORMAL);
67             default:
68                 Put_message("Aborting Deletion!");
69                 FreeQueue(elem);
70                 return(SUB_ERROR);
71             }
72         }
73         args[0] = "foo";                /* not used. */
74         args[1] = name;
75         DeleteList(2, args);
76     }
77     FreeQueue(elem);
78     return(SUB_NORMAL);
79 }
80
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?
86  *      Returns: none.
87  */
88
89 void
90 CheckAce(type, name, verbose)
91 char * type, *name;
92 Bool verbose;
93 {
94     char *args[2], buf[BUFSIZ];
95     int status;
96
97     if ( strcmp(type, "LIST") != 0 ) 
98         return;         /* If the ace is not a list the ignore it. */
99  
100     args[0] = type;
101     args[1] = name;
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. */
106     if (verbose) {
107         sprintf(buf, "Delete the unused Access Control Entity (ACE) %s? ",
108                 name);
109         if ( YesNoQuestion(buf, FALSE) != TRUE) {
110             Put_message("Aborting Deletion!");
111             return;
112         }
113     }
114 /*
115  * Delete the ACE.
116  *
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.
120  */
121     DeleteList(2, args);
122 }
123         
124
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
129  *               succeed.
130  */
131
132 int
133 CheckIfAce(name, type, verbose)
134 char * name, * type;
135 Bool verbose;
136 {
137     char * args[2], buf[BUFSIZ], **info;
138     struct qelem *local, *elem;
139     int status;
140     elem = NULL;
141
142     args[0] = type;
143     args[1] = name;
144     switch (status = do_mr_query("get_ace_use", 2, args,
145                                   StoreInfo, (char *) &elem)) {
146     case MR_NO_MATCH:
147         return(DM_NORMAL);
148     case MR_SUCCESS:
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)) {
154             FreeQueue(elem);
155             return(DM_NORMAL);
156         }
157         if (verbose) {
158             sprintf(buf, "%s %s %s", type, name,
159                     "is the ACE for the following data objects:");
160             Put_message(buf);
161             Put_message("");
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))
166                     continue;
167                 Print(CountArgs(info), info, NULL);
168             }
169             Put_message("");
170             Put_message(
171                  "The ACE for each of these items must be changed before");
172             sprintf(buf,"the %s %s can be deleted.\n", type, name);
173             Put_message(buf);
174         }
175         break;
176     default:
177         com_err(program_name, status, " in CheckIfAce (get_ace_use).");
178         return(SUB_ERROR);
179     }
180     FreeQueue(elem);
181     return(SUB_ERROR);
182 }
183
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.
191  */
192
193 int
194 RemoveItemFromLists(name, type, elem, verbose)
195 char * name, *type;
196 struct qelem ** elem;
197 int verbose;
198 {
199     struct qelem *local;
200     char *args[10], temp_buf[BUFSIZ];
201     int lists;
202     register int status;
203     
204     args[0] = type;
205     args[1] = name;
206     *elem = NULL;
207
208 /* 
209  * Get all list of which this item is a member, and store them in a queue.
210  */
211
212     status = do_mr_query("get_lists_of_member", 2, args, StoreInfo,
213                           (char *) elem);
214
215     if (status == MR_NO_MATCH)
216         return(SUB_NORMAL);
217
218     if (status != MR_SUCCESS) { 
219         com_err(program_name, status, " in DeleteList (get_lists_of_member).");
220         return(SUB_ERROR);
221     }
222
223 /*
224  * If verbose mode, ask user of we should remove our list from 
225  * all these lists.
226  */
227
228     local = *elem = QueueTop(*elem);
229     lists = QueueCount(*elem);
230     if (lists == 0)
231         return(SUB_NORMAL);
232     if (verbose) {
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;
240         }
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...");
245             FreeQueue(*elem);
246             *elem = NULL;
247             return(SUB_ERROR);
248         }
249     }
250
251 /*
252  * Remove this list from all lists that it is a member of.
253  */
254
255     local = *elem;
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");
264             FreeQueue(*elem);
265             return(SUB_ERROR);
266         }
267         local = local->q_forw;
268     }
269     return(SUB_NORMAL);
270 }
271
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.
277  */
278
279 int
280 RemoveMembersOfList(name, verbose)
281 char * name;
282 Bool verbose;
283 {
284     char buf[BUFSIZ], *args[10];
285     struct qelem *local, *elem = NULL;
286     int status, members;
287 /* 
288  * Get the members of this list.
289  */
290     status = do_mr_query("get_members_of_list", 1, &name, StoreInfo,
291                           (char *) &elem);
292     if (status == MR_NO_MATCH) 
293         return(SUB_NORMAL);
294
295     if (status != 0) {  
296         com_err(program_name, status, " in DeleteList (get_members_of_list).");
297         return(SUB_ERROR);
298     }
299 /*
300  * If verbose mode, then ask the user if we should delete.
301  */
302     local = elem = QueueTop(elem);
303     if ( (members = QueueCount(elem)) == 0)
304         return(SUB_NORMAL);
305     if (verbose) {
306         sprintf(buf, "List %s has %d member%s:", name, QueueCount(elem),
307                 ((members == 1) ? "" : "s") );
308         Put_message(buf);
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;
314         }
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...");
321             FreeQueue(elem);
322             return(SUB_ERROR);
323         }
324     }
325 /*
326  * Perform The Removal.
327  */
328     local = elem;
329     args[0] = name; 
330     while (local != NULL) {
331         char ** info = (char **) local->q_data;
332         args[1] = info[0];
333         args[2] = info[1];
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");
337             FreeQueue(elem);
338             return(SUB_ERROR);
339         }
340         local = local->q_forw;
341     }
342     return(SUB_NORMAL);
343 }
344
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.
352  */
353
354 int
355 DeleteUserGroup(name, verbose)
356 char * name;
357 Bool verbose;
358 {
359     int status, ans;
360     char buf[BUFSIZ], *args[10];
361
362     status = do_mr_query("get_list_info", 1, &name, NullFunc, (char *) NULL);
363     if (status == 0) {
364         if (verbose) {
365             sprintf(buf, "There is also a list named %s, delete it?", name);
366             ans = YesNoQuestion(buf, FALSE);
367             if (ans == FALSE) {
368                 Put_message("Leaving group alone.");
369                 return(SUB_NORMAL);
370             }
371             if (ans < 0) {
372                 Put_message("Aborting...\n");
373                 return(SUB_ERROR);
374             }
375         }
376         /* ans == TRUE  || ~verbose */
377             args[0] = "foo";    /* not used. */
378             args[1] = name;
379             DeleteList(2, args);
380     }
381     else if (status != MR_NO_MATCH) {
382         com_err(program_name, status, " Aborting Delete User.");        
383         return(SUB_ERROR);
384     }
385     return(SUB_NORMAL);
386 }
387
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.
393  */
394
395 int
396 DeleteHomeFilesys(name, verbose)
397 char * name;
398 Bool verbose;
399 {
400     int status;
401     char buf[BUFSIZ];
402     
403     switch (status = do_mr_query("get_filesys_by_label", 1, &name, NullFunc, 
404                                   (char *) NULL)) {
405     case MR_NO_MATCH:
406         break;
407     case MR_SUCCESS:
408         if (verbose) {
409             sprintf(buf, "Delete the filesystem named %s (y/n)?", name);
410             switch (YesNoQuestion(buf, FALSE)) {
411             case FALSE:
412                 Put_message("Filesystem Not Deleted, continuing...\n");
413                 return(SUB_NORMAL);
414             case TRUE:
415                 break;
416             default:
417                 Put_message("Filesystem Not Deleted, aborting...\n\n");
418                 return(SUB_ERROR);
419             }
420         }
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.");
424             return(SUB_ERROR);
425         }
426         else 
427             Put_message("Filesystem Successfully Deleted.");
428         break;
429     default:
430         com_err(program_name, status, " in get_filesystem_by_label).");
431         return(SUB_ERROR);
432     }
433     return(SUB_NORMAL);
434 }
435
436 #ifndef ATHENA
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.
441  */
442
443 static int
444 RealDeleteUser(name)
445 char * name;
446 {
447     char buf[BUFSIZ];
448     int status;
449
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");
453         return(SUB_ERROR);
454     }
455     (void) sprintf(buf, "User %s deleted.", name);
456     Put_message(buf);
457     return(SUB_NORMAL);
458 }
459 #endif
460
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.
465  */
466
467 static int
468 RealDeleteList(name)
469 char * name;
470 {
471     char buf[BUFSIZ];
472     int status;
473
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");
477         return(SUB_ERROR);
478     }
479     (void) sprintf(buf, "List %s deleted.", name);
480     Put_message(buf);
481     Put_message("");
482     return(SUB_NORMAL);
483 }
484
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,
492  *                             and cleaning up?
493  *      Returns: none - all is taken care of and error messages printed
494  *                      one way or the other.
495  */
496
497 void
498 AttemptToDeleteList(list_info, ask_first)
499 char ** list_info;
500 Bool ask_first;
501 {
502     int status;
503     struct qelem *local, *member_of;
504     char *name = list_info[L_NAME];
505     member_of = NULL;
506     
507     /*
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.
512      */
513     
514     switch (status = do_mr_query("delete_list", 1, &name,
515                                   Scream, (char *) NULL)) {
516     case MR_SUCCESS:
517         Put_message("List Sucessfully Deleted.");
518         CheckAce(list_info[L_ACE_TYPE], list_info[L_ACE_NAME], ask_first);
519         break;
520     case MR_IN_USE:
521         /* 
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.
525          */
526         
527         if ((CheckIfAce(name, "list", ask_first) != SUB_NORMAL) ||
528             (RemoveItemFromLists(name, "list",
529                                  &member_of, ask_first) != SUB_NORMAL))
530           break;
531         /*
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
534          */
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))
544                     != MR_SUCCESS) {
545                   com_err(program_name, status, " while updating list owner");
546                   Put_message("List may be only partly deleted.");
547               }
548         }
549         if ((RemoveMembersOfList(name, ask_first) == SUB_NORMAL) &&
550             (RealDeleteList(name) == SUB_NORMAL) ) 
551         {               /* if... */
552             CheckAce(list_info[L_ACE_TYPE], list_info[L_ACE_NAME], ask_first);
553             
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)
558                   break;
559                 local = local->q_forw;
560             }
561             FreeQueue(member_of);
562         }
563         break;
564     default:
565         com_err(program_name, status, " in DeleteList (delete_list).");
566         break;
567     }
568 }
569
570 /*      Function Name: DeleteList
571  *      Description: deletes a list
572  *      Arguments: argc, argv - standard MR argc and argv.
573  *      Returns: DM Status Code.
574  */
575
576 /* ARGSUSED */
577 int
578 DeleteList(argc, argv)
579 int argc;
580 char *argv[];
581 {
582     char buf[BUFSIZ];
583     struct qelem *top, *list;
584     register int status;
585     Bool one_list;
586
587     list = NULL;
588     
589     switch(status = do_mr_query("get_list_info", 1, argv + 1,
590                                  StoreInfo, (char *) &list)){
591     case MR_SUCCESS:
592         break;
593 /*    case MR_NO_WILDCARD:
594         Put_message("Wildcards are not accepted here.");
595         return(DM_NORMAL);
596 */  case MR_NO_MATCH:
597     case MR_LIST:
598         Put_message("There is no list that matches that name.");
599         return(DM_NORMAL);
600     default:
601         com_err(program_name, status,   " in DeleteList (get_list_info).");
602         return(DM_NORMAL);
603     }
604     
605     top = list = QueueTop(list);
606     one_list = (QueueCount(list) == 1);
607     while (list != NULL) {
608         char ** info = (char**) list->q_data;
609         if (one_list) {
610             sprintf( buf, "Are you sure that you want to delete the list %s",
611                     info[L_NAME]);
612             if ( Confirm(buf) ) AttemptToDeleteList(info, TRUE);
613         }
614         else {
615             sprintf(buf, "Delete the list %s", info[L_NAME]);
616             switch( YesNoQuestion( buf, FALSE ) ) {
617             case TRUE:
618                 AttemptToDeleteList(info, TRUE);
619                 break;
620             case FALSE:
621                 break;
622             default:
623                 Put_message ("Aborting...");
624                 FreeQueue(top);
625                 return(DM_QUIT);
626             }
627         }
628         list = list->q_forw;
629     }
630     FreeQueue(top);
631     return(DM_NORMAL);
632 }
633
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.
638  */
639
640 /* ARGSUSED */
641 int
642 DeleteUser(argc, argv)
643 int argc;
644 char ** argv;
645 {
646     int status;
647     char buf[BUFSIZ];
648     char * name = argv[1];      /* name of the user we are deleting. */
649 #ifndef ATHENA
650     struct qelem *local, *member_of = NULL;
651 #endif
652
653     if (!ValidName(name))
654         return(DM_NORMAL);
655
656     if (!Confirm("Are you sure that you want to delete this user?"))
657         return(DM_NORMAL);
658
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");    
662         return(DM_NORMAL);
663     }
664     if (status == 0) {
665         sprintf(buf,"User %s deleted.", name);
666         Put_message(buf);
667 #ifdef ATHENA
668         /* delete this return if the policy decision below is reversed */
669         return(DM_NORMAL);
670 #endif
671     }
672 #ifdef ATHENA
673 /* Design decision not to allow registered users to be deleted.
674  */
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.");
677 #else
678     else if (status == MR_IN_USE) {
679
680 /*
681  * Check:
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.
686  *
687  * If all these have been accomplished, then attempt to delete the user again.
688  */
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) ) {
695             return(DM_NORMAL);
696         }
697     }
698
699 /*
700  * Query - Delete all empty lists created by removing this user from them.
701  */
702
703     local = member_of;
704     while (local != NULL) {
705         char ** info = (char **) local->q_data;
706         if (CheckListForDeletion(info[0], TRUE) == SUB_ERROR)
707           break;
708         local = local->q_forw;
709     }
710
711     FreeQueue(member_of);       /* Free memory and return. */
712 #endif
713     return(DM_NORMAL);
714 }
This page took 0.08914 seconds and 5 git commands to generate.