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