]> andersk Git - moira.git/blob - clients/moira/delete.c
sms -> moira
[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 <strings.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 void
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;
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             if (YesNoQuestion(buf, FALSE) != TRUE) {
61                 Put_message("Aborting Deletion!");
62                 FreeQueue(elem);
63                 return; 
64             }
65         }
66         args[0] = "foo";                /* not used. */
67         args[1] = name;
68         DeleteList(2, args);
69     }
70     FreeQueue(elem);
71 }
72
73 /*      Function Name: CheckAce
74  *      Description: Checks an ace to see of we should delete it.
75  *      Arguments: type - the type of this ace.
76  *                 name - the name of the ace.
77  *                 verbose - query user?
78  *      Returns: none.
79  */
80
81 void
82 CheckAce(type, name, verbose)
83 char * type, *name;
84 Bool verbose;
85 {
86     char *args[2], buf[BUFSIZ];
87     int status;
88
89     if ( strcmp(type, "LIST") != 0 ) 
90         return;         /* If the ace is not a list the ignore it. */
91  
92     args[0] = type;
93     args[1] = name;
94     status = do_mr_query("get_ace_use", 2, args, NullFunc, (char *) NULL);
95     if (status != MR_NO_MATCH)
96         return;                 /* If this query fails the ace will
97                                    not be deleted even if it is empty. */
98     if (verbose) {
99         sprintf(buf, "Delete the unused Access Control Entity (ACE) %s? ",
100                 name);
101         if ( YesNoQuestion(buf, FALSE) != TRUE) {
102             Put_message("Aborting Deletion!");
103             return;
104         }
105     }
106 /*
107  * Delete the ACE.
108  *
109  * NOTE: Delete list expects only the name of the list to delete in argv[1].
110  *       since, 'args' already satisfies this, there is no need to create
111  *       a special argument list.
112  */
113     DeleteList(2, args);
114 }
115         
116
117 /*      Function Name: CheckIfAce
118  *      Description: Checks to see if this is an ace of another data object.
119  *      Arguments: name - name of the object.
120  *      Returns: SUB_ERROR if this list is an ace, or if the query did not
121  *               succeed.
122  */
123
124 int
125 CheckIfAce(name, type, verbose)
126 char * name, * type;
127 Bool verbose;
128 {
129     char * args[2], buf[BUFSIZ], **info;
130     struct qelem *local, *elem;
131     int status;
132     elem = NULL;
133
134     args[0] = type;
135     args[1] = name;
136     switch (status = do_mr_query("get_ace_use", 2, args,
137                                   StoreInfo, (char *) &elem)) {
138     case MR_NO_MATCH:
139         return(DM_NORMAL);
140     case MR_SUCCESS:
141         local = elem = QueueTop(elem);
142         info = (char **) local->q_data;
143         if (QueueCount(elem) == 1 &&
144             !strcmp(info[0], "LIST") &&
145             !strcmp(info[1], name)) {
146             FreeQueue(elem);
147             return(DM_NORMAL);
148         }
149         if (verbose) {
150             sprintf(buf, "%s %s %s", type, name,
151                     "is the ACE for the following data objects:");
152             Put_message(buf);
153             Put_message("");
154             while (local != NULL) {
155                 info = (char **) local->q_data;
156                 if (!strcmp(info[0], "LIST") &&
157                     !strcmp(info[1], name))
158                     continue;
159                 Print(CountArgs(info), info, NULL);
160                 local = local->q_forw;
161             }
162             Put_message("");
163             Put_message(
164                  "The ACE for each of these items must be changed before");
165             sprintf(buf,"the %s %s can be deleted.\n", type, name);
166             Put_message(buf);
167         }
168         break;
169     default:
170         com_err(program_name, status, " in CheckIfAce (get_ace_use).");
171         return(SUB_ERROR);
172     }
173     FreeQueue(elem);
174     return(SUB_ERROR);
175 }
176
177 /*      Function Name: RemoveItemFromLists
178  *      Description: this function removes a list from all other lists of
179  *                   which it is a member.
180  *      Arguments: name - name of the item
181  *                 elem - a pointer to a queue element. RETURNED
182  *                 verbose - verbose mode.
183  *      Returns: SUB_ERROR if there is an error.
184  */
185
186 int
187 RemoveItemFromLists(name, type, elem, verbose)
188 char * name, *type;
189 struct qelem ** elem;
190 int verbose;
191 {
192     struct qelem *local;
193     char *args[10], temp_buf[BUFSIZ];
194     int lists;
195     register int status;
196     
197     args[0] = type;
198     args[1] = name;
199     *elem = NULL;
200
201 /* 
202  * Get all list of which this item is a member, and store them in a queue.
203  */
204
205     status = do_mr_query("get_lists_of_member", 2, args, StoreInfo,
206                           (char *) elem);
207
208     if (status == MR_NO_MATCH)
209         return(SUB_NORMAL);
210
211     if (status != MR_SUCCESS) { 
212         com_err(program_name, status, " in DeleteList (get_lists_of_member).");
213         return(SUB_ERROR);
214     }
215
216 /*
217  * If verbose mode, ask user of we should remove our list from 
218  * all these lists.
219  */
220
221     local = *elem = QueueTop(*elem);
222     lists = QueueCount(*elem);
223     if (lists == 0)
224         return(SUB_NORMAL);
225     if (verbose) {
226         sprintf(temp_buf, "%s %s is a member of %d other list%s.\n", type,
227                 name, lists, ((lists == 1) ? "" : "s") );
228         Put_message(temp_buf);
229         while (local != NULL) {
230             char ** info = (char **) local->q_data;
231             Print( 1, &info[GLOM_NAME], (char *) NULL);
232             local = local->q_forw;
233         }
234         Put_message(" ");       /* Blank Line. */
235         sprintf(temp_buf,"Remove %s %s from these lists? ", type, name);
236         if (YesNoQuestion(temp_buf, FALSE) != TRUE) {
237             Put_message("Aborting...");
238             FreeQueue(*elem);
239             *elem = NULL;
240             return(SUB_ERROR);
241         }
242     }
243
244 /*
245  * Remove this list from all lists that it is a member of.
246  */
247
248     local = *elem;
249     args[DM_MEMBER] = name;
250     args[DM_TYPE] = type;
251     while (local != NULL) {
252         char ** info = (char **) local->q_data;
253         args[DM_LIST] = info[GLOM_NAME];
254         if ( (status = do_mr_query("delete_member_from_list",
255                                     3, args, Scream, NULL)) != 0) {
256             com_err(program_name, status, " in delete_member\nAborting\n");
257             FreeQueue(*elem);
258             return(SUB_ERROR);
259         }
260         local = local->q_forw;
261     }
262     return(SUB_NORMAL);
263 }
264
265 /*      Function Name: RemoveMembersOfList
266  *      Description: Deletes the members of the list.
267  *      Arguments: name - name of the list.
268  *                 verbose - query user, about deletion?
269  *      Returns: SUB_ERROR - if we could not delete, or the user abouted.
270  */
271
272 int
273 RemoveMembersOfList(name, verbose)
274 char * name;
275 Bool verbose;
276 {
277     char buf[BUFSIZ], *args[10];
278     struct qelem *local, *elem = NULL;
279     int status, members;
280 /* 
281  * Get the members of this list.
282  */
283     status = do_mr_query("get_members_of_list", 1, &name, StoreInfo,
284                           (char *) &elem);
285     if (status == MR_NO_MATCH) 
286         return(SUB_NORMAL);
287
288     if (status != 0) {  
289         com_err(program_name, status, " in DeleteList (get_members_of_list).");
290         return(SUB_ERROR);
291     }
292 /*
293  * If verbose mode, then ask the user if we should delete.
294  */
295     local = elem = QueueTop(elem);
296     if ( (members = QueueCount(elem)) == 0)
297         return(SUB_NORMAL);
298     if (verbose) {
299         sprintf(buf, "List %s has %d member%s:", name, QueueCount(elem),
300                 ((members == 1) ? "" : "s") );
301         Put_message(buf);
302         Put_message(" ");       /* Blank Line. */
303         while (local != NULL) {
304             char ** info = (char **) local->q_data;
305             Print( CountArgs(info), info, NULL);
306             local = local->q_forw;
307         }
308         Put_message(" ");       /* Blank Line. */
309         sprintf(buf, "Remove th%s member%s from list %s? ", 
310                 ((members == 1) ? "is" : "ese"), 
311                 ((members == 1) ? "" : "s"), name );
312         if ( YesNoQuestion(buf, FALSE) != TRUE) {
313             Put_message("Aborting...");
314             FreeQueue(elem);
315             return(SUB_ERROR);
316         }
317     }
318 /*
319  * Perform The Removal.
320  */
321     local = elem;
322     args[0] = name; 
323     while (local != NULL) {
324         char ** info = (char **) local->q_data;
325         args[1] = info[0];
326         args[2] = info[1];
327         if ( (status = do_mr_query("delete_member_from_list",
328                                     3, args, Scream, NULL)) != 0) {
329             com_err(program_name, status, " in delete_member\nAborting\n");
330             FreeQueue(elem);
331             return(SUB_ERROR);
332         }
333         local = local->q_forw;
334     }
335     return(SUB_NORMAL);
336 }
337
338 /*      Function Name: DeleteUserGroup
339  *      Description: Deletes the list given by name if it exists.
340  *                   intended to be used to delete user groups
341  *      Arguments: name - the name of the list to delete.
342  *                 verbose - flag that if TRUE queries the user to
343  *                           ask if list should be deleted.
344  *      Returns: MR_ERROR if there is an error.
345  */
346
347 int
348 DeleteUserGroup(name, verbose)
349 char * name;
350 Bool verbose;
351 {
352     int status, ans;
353     char buf[BUFSIZ], *args[10];
354
355     status = do_mr_query("get_list_info", 1, &name, NullFunc, (char *) NULL);
356     if (status == 0) {
357         if (verbose) {
358             sprintf(buf, "There is also a list named %s, delete it?", name);
359             ans = YesNoQuestion(buf, FALSE);
360             if (ans == FALSE) {
361                 Put_message("Leaving group alone.");
362                 return(SUB_NORMAL);
363             }
364             if (ans < 0) {
365                 Put_message("Aborting...\n");
366                 return(SUB_ERROR);
367             }
368         }
369         /* ans == TRUE  || ~verbose */
370             args[0] = "foo";    /* not used. */
371             args[1] = name;
372             DeleteList(2, args);
373     }
374     else if (status != MR_NO_MATCH) {
375         com_err(program_name, status, " Aborting Delete User.");        
376         return(SUB_ERROR);
377     }
378     return(SUB_NORMAL);
379 }
380
381 /*      Function Name: DeleteHomeFilesys
382  *      Description: Delete the home filesystem for the named user.
383  *      Arguments: name - name of the user (and filsystem) to delete.
384  *                 verbose - if TRUE query user.
385  *      Returns: SUB_NORMAL if home filesystem deleted, or nonexistant.
386  */
387
388 int
389 DeleteHomeFilesys(name, verbose)
390 char * name;
391 Bool verbose;
392 {
393     int status;
394     char buf[BUFSIZ];
395     
396     switch (status = do_mr_query("get_filesys_by_label", 1, &name, NullFunc, 
397                                   (char *) NULL)) {
398     case MR_NO_MATCH:
399         break;
400     case MR_SUCCESS:
401         if (verbose) {
402             sprintf(buf, "Delete the filesystem named %s (y/n)?", name);
403             switch (YesNoQuestion(buf, FALSE)) {
404             case FALSE:
405                 Put_message("Filesystem Not Deleted, continuing...\n");
406                 return(SUB_NORMAL);
407             case TRUE:
408                 break;
409             default:
410                 Put_message("Filesystem Not Deleted, aborting...\n\n");
411                 return(SUB_ERROR);
412             }
413         }
414         if ( (status = do_mr_query("delete_filesys", 1, &name, Scream,
415                                     (char *) NULL) ) != MR_SUCCESS) {
416             com_err(program_name, status, " in delete_filesys.");
417             return(SUB_ERROR);
418         }
419         else 
420             Put_message("Filesystem Successfully Deleted.");
421         break;
422     default:
423         com_err(program_name, status, " in get_filesystem_by_label).");
424         return(SUB_ERROR);
425     }
426     return(SUB_NORMAL);
427 }
428
429 /*      Function Name: RealDeleteUser
430  *      Description: Just Deletes the user.
431  *      Arguments: name - name of User to delete
432  *      Returns: SUB_ERROR if the deletion failed.
433  */
434
435 static int
436 RealDeleteUser(name)
437 char * name;
438 {
439     char buf[BUFSIZ];
440     int status;
441
442     if ( (status = do_mr_query("delete_user", 1, &name, Scream, 
443                                 (char *) NULL)) != MR_SUCCESS) {
444         com_err(program_name, status, ": user not deleted");
445         return(SUB_ERROR);
446     }
447     (void) sprintf(buf, "User %s deleted.", name);
448     Put_message(buf);
449     return(SUB_NORMAL);
450 }
451
452 /*      Function Name: RealDeleteList
453  *      Description: Just Deletes the list.
454  *      Arguments: name - name of list to delete
455  *      Returns: SUB_ERROR if the deletion failed.
456  */
457
458 static int
459 RealDeleteList(name)
460 char * name;
461 {
462     char buf[BUFSIZ];
463     int status;
464
465     if ( (status = do_mr_query("delete_list", 1, &name, Scream, 
466                                 (char *) NULL)) != MR_SUCCESS) {
467         com_err(program_name, status, ": list not deleted");
468         return(SUB_ERROR);
469     }
470     (void) sprintf(buf, "List %s deleted.", name);
471     Put_message(buf);
472     Put_message("");
473     return(SUB_NORMAL);
474 }
475
476 /*      Function Name: AttemptToDeleteList
477  *      Description: Atempts to delete list, in the following manner:
478  *                   1) try to delet it, if this fails in a known error then
479  *                      a) try to clean up each of those known methods, or
480  *                         at least explain why we failed.
481  *      Arguments: list_info - info about this list.
482  *                 ask_first - (T/F) query user before preparing for deletion,
483  *                             and cleaning up?
484  *      Returns: none - all is taken care of and error messages printed
485  *                      one way or the other.
486  */
487
488 void
489 AttemptToDeleteList(list_info, ask_first)
490 char ** list_info;
491 Bool ask_first;
492 {
493     int status;
494     struct qelem *local, *member_of;
495     char *name = list_info[L_NAME];
496     member_of = NULL;
497     
498     /*
499      * Attempt delete. - will only work if:
500      * 1) This list has no members.
501      * 2) This list in a member of no other lists.
502      * 3) This list is not an ace of another object.
503      */
504     
505     switch (status = do_mr_query("delete_list", 1, &name,
506                                   Scream, (char *) NULL)) {
507     case MR_SUCCESS:
508         Put_message("List Sucessfully Deleted.");
509         CheckAce(list_info[L_ACE_TYPE], list_info[L_ACE_NAME], ask_first);
510         break;
511     case MR_IN_USE:
512         /* 
513          * This list is in use.  Try to find out why, 
514          * and for the cases where we have a good idea of 
515          * what to do we will query and then do it.
516          */
517         
518         if ((CheckIfAce(name, "list", ask_first) != SUB_NORMAL) ||
519             (RemoveItemFromLists(name, "list",
520                                  &member_of, ask_first) != SUB_NORMAL))
521           break;
522         /*
523          * If the list is it's own ACL, then make the person performing
524          * the delete the owner before removing this person from the list
525          */
526         if (!strcmp(list_info[L_ACE_TYPE], "LIST") &&
527             !strcmp(list_info[L_ACE_NAME], list_info[L_NAME])) {
528               free(list_info[L_ACE_TYPE]);
529               free(list_info[L_ACE_NAME]);
530               list_info[L_ACE_TYPE] = Strsave("USER");
531               list_info[L_ACE_NAME] = Strsave(user);
532               SlipInNewName(list_info, Strsave(list_info[L_NAME]));
533               if ((status = do_mr_query("update_list", CountArgs(list_info)-3,
534                                        list_info, Scream, (char *) NULL))
535                     != MR_SUCCESS) {
536                   com_err(program_name, status, " while updating list owner");
537                   Put_message("List may be only partly deleted.");
538               }
539         }
540         if ((RemoveMembersOfList(name, ask_first) == SUB_NORMAL) &&
541             (RealDeleteList(name) == SUB_NORMAL) ) 
542         {               /* if... */
543             CheckAce(list_info[L_ACE_TYPE], list_info[L_ACE_NAME], ask_first);
544             
545             local = QueueTop(member_of);
546             while (local != NULL) {
547                 char ** info = (char **) local->q_data;
548                 CheckListForDeletion(info[LM_LIST], ask_first);
549                 local = local->q_forw;
550             }
551             FreeQueue(member_of);
552         }
553         break;
554     default:
555         com_err(program_name, status, " in DeleteList (delete_list).");
556         break;
557     }
558 }
559
560 /*      Function Name: DeleteList
561  *      Description: deletes a list
562  *      Arguments: argc, argv - standard MR argc and argv.
563  *      Returns: DM Status Code.
564  */
565
566 /* ARGSUSED */
567 int
568 DeleteList(argc, argv)
569 int argc;
570 char *argv[];
571 {
572     char buf[BUFSIZ];
573     struct qelem *top, *list;
574     register int status;
575     Bool one_list;
576
577     list = NULL;
578     
579     switch(status = do_mr_query("get_list_info", 1, argv + 1,
580                                  StoreInfo, (char *) &list)){
581     case MR_SUCCESS:
582         break;
583 /*    case MR_NO_WILDCARD:
584         Put_message("Wildcards are not accepted here.");
585         return(DM_NORMAL);
586 */  case MR_NO_MATCH:
587     case MR_LIST:
588         Put_message("There is no list that matches that name.");
589         return(DM_NORMAL);
590     default:
591         com_err(program_name, status,   " in DeleteList (get_list_info).");
592         return(DM_NORMAL);
593     }
594     
595     top = list = QueueTop(list);
596     one_list = (QueueCount(list) == 1);
597     while (list != NULL) {
598         char ** info = (char**) list->q_data;
599         if (one_list) {
600             sprintf( buf, "Are you sure that you want to delete the list %s",
601                     info[L_NAME]);
602             if ( Confirm(buf) ) AttemptToDeleteList(info, TRUE);
603         }
604         else {
605             sprintf(buf, "Delete the list %s", info[L_NAME]);
606             switch( YesNoQuestion( buf, FALSE ) ) {
607             case TRUE:
608                 AttemptToDeleteList(info, TRUE);
609                 break;
610             case FALSE:
611                 break;
612             default:
613                 Put_message ("Aborting...");
614                 FreeQueue(top);
615                 return(DM_NORMAL);
616             }
617         }
618         list = list->q_forw;
619     }
620     FreeQueue(top);
621     return(DM_NORMAL);
622 }
623
624 /*      Function Name: DeleteUser
625  *      Description: Deletes a user from the database.
626  *      Arguments: argc, argv - name of the user in argv[1].
627  *      Returns: DM_NORMAL.
628  */
629
630 /* ARGSUSED */
631 int
632 DeleteUser(argc, argv)
633 int argc;
634 char ** argv;
635 {
636     int status;
637     char buf[BUFSIZ];
638     char * name = argv[1];      /* name of the user we are deleting. */
639     struct qelem *local, *member_of = NULL;
640
641     if (!ValidName(name))
642         return(DM_NORMAL);
643
644     if (!Confirm("Are you sure that you want to delete this user?"))
645         return(DM_NORMAL);
646
647     status = do_mr_query("delete_user", 1, &name, Scream, (char *) NULL);
648     if (status != MR_IN_USE && status != 0) {
649         com_err(program_name, status, ": user not deleted");    
650         return(DM_NORMAL);
651     }
652     if (status == 0) {
653         sprintf(buf,"User %s deleted.", name);
654         Put_message(buf);
655         /* delete this return if the policy decision below is reversed */
656         return(DM_NORMAL);
657     }
658 /* Design decision not to allow registered users to be deleted.
659  */
660     Put_message("Sorry, registered users cannot be deleted from the database.");
661     Put_message("Deactivate the user now, and the system manager will expunge later.");
662 #ifdef notdef
663     else if (status == MR_IN_USE) {
664
665 /*
666  * Check:
667  * 1) Query - Delete home filesytem.
668  * 2) Query - Delete user Group.
669  * 2) Is the user an ACE of any object in the database?
670  * 3) Query - Remove user from all list of which he is a member.
671  *
672  * If all these have been accomplished, then attempt to delete the user again.
673  */
674         if ( (DeleteHomeFilesys(name, TRUE) == SUB_ERROR) ||
675              (DeleteUserGroup(name, TRUE) == SUB_ERROR)  ||
676              (CheckIfAce(name, "user", TRUE) == SUB_ERROR) ||
677              (RemoveItemFromLists(name, "user",
678                                   &member_of, TRUE) == SUB_ERROR) ||
679              (RealDeleteUser(name) == SUB_ERROR) ) {
680             return(DM_NORMAL);
681         }
682     }
683
684 /*
685  * Query - Delete all empty lists created by removing this user from them.
686  */
687
688     local = member_of;
689     while (local != NULL) {
690         char ** info = (char **) local->q_data;
691         CheckListForDeletion(info[0], TRUE);
692         local = local->q_forw;
693     }
694
695     FreeQueue(member_of);       /* Free memory and return. */
696 #endif
697     return(DM_NORMAL);
698 }
This page took 0.20344 seconds and 5 git commands to generate.