]> andersk Git - moira.git/blob - clients/moira/delete.c
a06f2b1fe5de7a03f13c59db81201d48e1cd63e3
[moira.git] / clients / moira / delete.c
1 #if (!defined(lint) && !defined(SABER))
2   static char rcsid_module_c[] = "$Header$";
3 #endif
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 CheckListForDeletion(char *name, Bool verbose)
42 {
43   struct qelem *elem = NULL;
44   int status;
45   char *args[2], buf[BUFSIZ], **info;
46
47   if ((status = do_mr_query("count_members_of_list", 1, &name, StoreInfo,
48                             (char *) &elem)))
49     {
50       com_err(program_name, status, " in DeleteList (count_members_of_list).");
51       return SUB_NORMAL;
52     }
53   info = (char **) elem->q_data;
54   if (!strcmp(info[NAME], "0"))
55     {
56       if (verbose)
57         {
58           sprintf(buf, "Delete the empty list %s? ", name);
59           switch (YesNoQuestion(buf, FALSE))
60             {
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 CheckAce(char *type, char *name, Bool verbose)
90 {
91   char *args[2], buf[BUFSIZ];
92   int status;
93
94   if (strcmp(type, "LIST"))
95     return;             /* If the ace is not a list the ignore it. */
96
97   args[0] = type;
98   args[1] = name;
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. */
103   if (verbose)
104     {
105       sprintf(buf, "Delete the unused Access Control Entity (ACE) %s? ", name);
106       if (YesNoQuestion(buf, FALSE) != TRUE)
107         {
108           Put_message("Aborting Deletion!");
109           return;
110         }
111     }
112   /*
113    * Delete the ACE.
114    *
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.
118    */
119   DeleteList(2, args);
120 }
121
122
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
127  *               succeed.
128  */
129
130 int CheckIfAce(char *name, char *type, Bool verbose)
131 {
132   char *args[2], buf[BUFSIZ], **info;
133   struct qelem *local, *elem;
134   int status;
135   elem = NULL;
136
137   args[0] = type;
138   args[1] = name;
139   switch ((status = do_mr_query("get_ace_use", 2, args,
140                                 StoreInfo, (char *) &elem)))
141     {
142     case MR_NO_MATCH:
143       return DM_NORMAL;
144     case MR_SUCCESS:
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))
150         {
151           FreeQueue(elem);
152           return DM_NORMAL;
153         }
154       if (verbose)
155         {
156           sprintf(buf, "%s %s %s", type, name,
157                   "is the ACE for the following data objects:");
158           Put_message(buf);
159           Put_message("");
160           for (; local != NULL; local = local->q_forw)
161             {
162               info = (char **) local->q_data;
163               if (!strcmp(info[0], "LIST") &&
164                   !strcmp(info[1], name))
165                 continue;
166               Print(CountArgs(info), info, NULL);
167             }
168           Put_message("");
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);
171           Put_message(buf);
172         }
173       break;
174     default:
175       com_err(program_name, status, " in CheckIfAce (get_ace_use).");
176       return SUB_ERROR;
177     }
178   FreeQueue(elem);
179   return SUB_ERROR;
180 }
181
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.
189  */
190
191 int RemoveItemFromLists(char *name, char *type, struct qelem **elem,
192                         int verbose)
193 {
194   struct qelem *local;
195   char *args[10], temp_buf[BUFSIZ];
196   int lists;
197   register int status;
198
199   args[0] = type;
200   args[1] = name;
201   *elem = NULL;
202
203   /*
204    * Get all list of which this item is a member, and store them in a queue.
205    */
206
207   status = do_mr_query("get_lists_of_member", 2, args, StoreInfo,
208                        (char *) elem);
209
210   if (status == MR_NO_MATCH)
211     return SUB_NORMAL;
212
213   if (status != MR_SUCCESS)
214     {
215       com_err(program_name, status, " in DeleteList (get_lists_of_member).");
216       return SUB_ERROR;
217     }
218
219   /*
220    * If verbose mode, ask user of we should remove our list from
221    * all these lists.
222    */
223
224   local = *elem = QueueTop(*elem);
225   lists = QueueCount(*elem);
226   if (lists == 0)
227     return SUB_NORMAL;
228   if (verbose)
229     {
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);
233       while (local)
234         {
235           char **info = (char **) local->q_data;
236           Print(1, &info[GLOM_NAME], (char *) NULL);
237             local = local->q_forw;
238         }
239         Put_message(" ");       /* Blank Line. */
240         sprintf(temp_buf, "Remove %s %s from these lists? ", type, name);
241         if (YesNoQuestion(temp_buf, FALSE) != TRUE)
242           {
243             Put_message("Aborting...");
244             FreeQueue(*elem);
245             *elem = NULL;
246             return SUB_ERROR;
247           }
248     }
249
250   /*
251    * Remove this list from all lists that it is a member of.
252    */
253
254   local = *elem;
255   args[DM_MEMBER] = name;
256   args[DM_TYPE] = type;
257   while (local)
258     {
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)))
263         {
264           com_err(program_name, status, " in delete_member\nAborting\n");
265           FreeQueue(*elem);
266           return SUB_ERROR;
267         }
268       local = local->q_forw;
269     }
270   return SUB_NORMAL;
271 }
272
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.
278  */
279
280 int RemoveMembersOfList(char *name, Bool verbose)
281 {
282   char buf[BUFSIZ], *args[10];
283   struct qelem *local, *elem = NULL;
284   int status, members;
285   /*
286    * Get the members of this list.
287    */
288   status = do_mr_query("get_members_of_list", 1, &name, StoreInfo,
289                        (char *) &elem);
290   if (status == MR_NO_MATCH)
291     return SUB_NORMAL;
292
293   if (status)
294     {
295       com_err(program_name, status, " in DeleteList (get_members_of_list).");
296       return SUB_ERROR;
297     }
298   /*
299    * If verbose mode, then ask the user if we should delete.
300    */
301   local = elem = QueueTop(elem);
302   if (!(members = QueueCount(elem)))
303     return SUB_NORMAL;
304   if (verbose)
305     {
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)
311         {
312           char **info = (char **) local->q_data;
313           Print(CountArgs(info), info, NULL);
314           local = local->q_forw;
315         }
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)
321         {
322           Put_message("Aborting...");
323           FreeQueue(elem);
324           return SUB_ERROR;
325         }
326     }
327   /*
328    * Perform The Removal.
329    */
330   local = elem;
331   args[0] = name;
332   while (local)
333     {
334       char **info = (char **) local->q_data;
335       args[1] = info[0];
336       args[2] = info[1];
337       if ((status = do_mr_query("delete_member_from_list",
338                                 3, args, Scream, NULL)))
339         {
340           com_err(program_name, status, " in delete_member\nAborting\n");
341           FreeQueue(elem);
342           return SUB_ERROR;
343         }
344       local = local->q_forw;
345     }
346   return SUB_NORMAL;
347 }
348
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.
356  */
357
358 int DeleteUserGroup(char *name, Bool verbose)
359 {
360   int status, ans;
361   char buf[BUFSIZ], *args[10];
362
363   status = do_mr_query("get_list_info", 1, &name, NullFunc, (char *) NULL);
364   if (!status)
365     {
366       if (verbose)
367         {
368           sprintf(buf, "There is also a list named %s, delete it?", name);
369           ans = YesNoQuestion(buf, FALSE);
370           if (ans == FALSE)
371             {
372               Put_message("Leaving group alone.");
373               return SUB_NORMAL;
374             }
375           if (ans < 0)
376             {
377               Put_message("Aborting...\n");
378               return SUB_ERROR;
379             }
380         }
381       /* ans == TRUE  || ~verbose */
382       args[0] = "foo";  /* not used. */
383       args[1] = name;
384       DeleteList(2, args);
385     }
386   else if (status != MR_NO_MATCH)
387     {
388       com_err(program_name, status, " Aborting Delete User.");
389       return SUB_ERROR;
390     }
391   return SUB_NORMAL;
392 }
393
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.
399  */
400
401 int DeleteHomeFilesys(char *name, Bool verbose)
402 {
403   int status;
404   char buf[BUFSIZ];
405
406   switch ((status = do_mr_query("get_filesys_by_label", 1, &name, NullFunc,
407                                 NULL)))
408     {
409     case MR_NO_MATCH:
410       break;
411     case MR_SUCCESS:
412       if (verbose)
413         {
414           sprintf(buf, "Delete the filesystem named %s (y/n)?", name);
415           switch (YesNoQuestion(buf, FALSE))
416             {
417             case FALSE:
418               Put_message("Filesystem Not Deleted, continuing...\n");
419               return SUB_NORMAL;
420             case TRUE:
421               break;
422             default:
423               Put_message("Filesystem Not Deleted, aborting...\n\n");
424               return SUB_ERROR;
425             }
426         }
427       if ((status = do_mr_query("delete_filesys", 1, &name, Scream,
428                                 NULL)) != MR_SUCCESS)
429         {
430           com_err(program_name, status, " in delete_filesys.");
431           return SUB_ERROR;
432         }
433       else
434         Put_message("Filesystem Successfully Deleted.");
435       break;
436     default:
437       com_err(program_name, status, " in get_filesystem_by_label).");
438       return SUB_ERROR;
439     }
440   return SUB_NORMAL;
441 }
442
443 #ifndef ATHENA
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.
448  */
449
450 static int RealDeleteUser(char *name)
451 {
452   char buf[BUFSIZ];
453   int status;
454
455   if ((status = do_mr_query("delete_user", 1, &name, Scream,
456                             NULL)) != MR_SUCCESS)
457     {
458       com_err(program_name, status, ": user not deleted");
459       return SUB_ERROR;
460     }
461   sprintf(buf, "User %s deleted.", name);
462   Put_message(buf);
463   return SUB_NORMAL;
464 }
465 #endif
466
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.
471  */
472
473 static int RealDeleteList(char *name)
474 {
475   char buf[BUFSIZ];
476   int status;
477
478   if ((status = do_mr_query("delete_list", 1, &name, Scream,
479                             NULL)) != MR_SUCCESS)
480     {
481       com_err(program_name, status, ": list not deleted");
482       return SUB_ERROR;
483     }
484   sprintf(buf, "List %s deleted.", name);
485   Put_message(buf);
486   Put_message("");
487   return SUB_NORMAL;
488 }
489
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,
497  *                             and cleaning up?
498  *      Returns: none - all is taken care of and error messages printed
499  *                      one way or the other.
500  */
501
502 void AttemptToDeleteList(char **list_info, Bool ask_first)
503 {
504   int status;
505   struct qelem *local, *member_of;
506   char *name = list_info[L_NAME];
507   member_of = NULL;
508
509   /*
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.
514    */
515
516   switch ((status = do_mr_query("delete_list", 1, &name, Scream, NULL)))
517     {
518     case MR_SUCCESS:
519       Put_message("List Sucessfully Deleted.");
520       CheckAce(list_info[L_ACE_TYPE], list_info[L_ACE_NAME], ask_first);
521       break;
522     case MR_IN_USE:
523       /*
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.
527        */
528
529       if ((CheckIfAce(name, "list", ask_first) != SUB_NORMAL) ||
530           (RemoveItemFromLists(name, "list",
531                                &member_of, ask_first) != SUB_NORMAL))
532         break;
533       /*
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
536        */
537       if (!strcmp(list_info[L_ACE_TYPE], "LIST") &&
538           !strcmp(list_info[L_ACE_NAME], list_info[L_NAME]))
539         {
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)
547             {
548               com_err(program_name, status, " while updating list owner");
549               Put_message("List may be only partly deleted.");
550             }
551         }
552       if ((RemoveMembersOfList(name, ask_first) == SUB_NORMAL) &&
553           (RealDeleteList(name) == SUB_NORMAL))
554         {               /* if... */
555           CheckAce(list_info[L_ACE_TYPE], list_info[L_ACE_NAME], ask_first);
556
557           local = QueueTop(member_of);
558           while (local)
559             {
560               char **info = (char **) local->q_data;
561               if (CheckListForDeletion(info[LM_LIST], ask_first) == SUB_ERROR)
562                 break;
563               local = local->q_forw;
564             }
565           FreeQueue(member_of);
566         }
567       break;
568     default:
569       com_err(program_name, status, " in DeleteList (delete_list).");
570       break;
571     }
572 }
573
574 /*      Function Name: DeleteList
575  *      Description: deletes a list
576  *      Arguments: argc, argv - standard MR argc and argv.
577  *      Returns: DM Status Code.
578  */
579
580 int DeleteList(int argc, 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     {
592     case MR_SUCCESS:
593       break;
594 #if 0
595     case MR_NO_WILDCARD:
596       Put_message("Wildcards are not accepted here.");
597       return DM_NORMAL;
598 #endif
599     case MR_NO_MATCH:
600     case MR_LIST:
601       Put_message("There is no list that matches that name.");
602       return DM_NORMAL;
603     default:
604       com_err(program_name, status, " in DeleteList (get_list_info).");
605       return DM_NORMAL;
606     }
607
608   top = list = QueueTop(list);
609   one_list = (QueueCount(list) == 1);
610   while (list)
611     {
612       char **info = (char **) list->q_data;
613       if (one_list)
614         {
615           sprintf(buf, "Are you sure that you want to delete the list %s",
616                   info[L_NAME]);
617           if (Confirm(buf))
618             AttemptToDeleteList(info, TRUE);
619         }
620       else
621         {
622           sprintf(buf, "Delete the list %s", info[L_NAME]);
623           switch (YesNoQuestion(buf, FALSE))
624             {
625             case TRUE:
626               AttemptToDeleteList(info, TRUE);
627               break;
628             case FALSE:
629               break;
630             default:
631               Put_message("Aborting...");
632               FreeQueue(top);
633               return DM_QUIT;
634             }
635         }
636       list = list->q_forw;
637     }
638   FreeQueue(top);
639   return DM_NORMAL;
640 }
641
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.
646  */
647
648 int DeleteUser(int argc, char **argv)
649 {
650   int status;
651   char buf[BUFSIZ];
652   char *name = argv[1]; /* name of the user we are deleting. */
653 #ifndef ATHENA
654   struct qelem *local, *member_of = NULL;
655 #endif
656
657   if (!ValidName(name))
658     return DM_NORMAL;
659
660   if (!Confirm("Are you sure that you want to delete this user?"))
661     return DM_NORMAL;
662
663   status = do_mr_query("delete_user", 1, &name, Scream, NULL);
664   if (status != MR_IN_USE && status != 0)
665     {
666       com_err(program_name, status, ": user not deleted");
667       return DM_NORMAL;
668     }
669   if (status == 0)
670     {
671       sprintf(buf, "User %s deleted.", name);
672       Put_message(buf);
673 #ifdef ATHENA
674       /* delete this return if the policy decision below is reversed */
675       return DM_NORMAL;
676 #endif
677     }
678 #ifdef ATHENA
679   /* Design decision not to allow registered users to be deleted.
680    */
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.");
683 #else
684   else if (status == MR_IN_USE)
685     {
686
687       /*
688        * Check:
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.
693        *
694        * If all these have been accomplished, then attempt to delete
695        * the user again.
696        */
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))
702         return DM_NORMAL;
703     }
704
705   /*
706    * Query - Delete all empty lists created by removing this user from them.
707    */
708
709   local = member_of;
710   while (local)
711     {
712       char **info = (char **) local->q_data;
713       if (CheckListForDeletion(info[0], TRUE) == SUB_ERROR)
714         break;
715       local = local->q_forw;
716     }
717
718   FreeQueue(member_of); /* Free memory and return. */
719 #endif
720   return DM_NORMAL;
721 }
This page took 2.92151 seconds and 3 git commands to generate.