]> andersk Git - moira.git/blob - clients/moira/lists.c
e3295f8d329c44fb8eb99c0c843fd46639c2ee1c
[moira.git] / clients / moira / lists.c
1 /* $Id$
2  *
3  *      This is the file lists.c for the Moira Client, which allows users
4  *      to quickly and easily maintain most parts of the Moira database.
5  *      It Contains: All list manipulation functions, except delete.
6  *
7  *      Created:        4/12/88
8  *      By:             Chris D. Peterson
9  *
10  * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
11  * For copying and distribution information, please see the file
12  * <mit-copyright.h>.
13  */
14
15 #include <mit-copyright.h>
16 #include <moira.h>
17 #include <mrclient.h>
18 #include <moira_site.h>
19 #include "defs.h"
20 #include "f_defs.h"
21 #include "globals.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 RCSID("$Header$");
28
29 struct mqelem *GetListInfo(int type, char *name1, char *name2);
30 char **AskListInfo(char **info, Bool name);
31 int AddList(int argc, char **argv);
32 void ListMembersByType(char *type, int tags);
33 int GetMemberInfo(char *action, char **ret_argv);
34
35 #define LIST    0
36 #define MEMBERS 1
37 #define GLOM    2
38 #define ACE_USE 3
39
40 #define DEFAULT_ACTIVE      DEFAULT_YES
41 #define DEFAULT_PUBLIC      DEFAULT_YES
42 #define DEFAULT_HIDDEN      DEFAULT_NO
43 #define DEFAULT_MAILLIST    DEFAULT_YES
44 #define DEFAULT_GROUP       DEFAULT_NO
45 #define DEFAULT_GID         UNIQUE_GID
46 #define DEFAULT_NFSGROUP    DEFAULT_NO
47 #define DEFAULT_ACE_TYPE    "user"
48 #define DEFAULT_ACE_NAME    (user)
49 #define DEFAULT_MEMACE_TYPE "NONE"
50 #define DEFAULT_MEMACE_NAME "NONE"
51 #define DEFAULT_DESCRIPTION DEFAULT_COMMENT
52
53 /* globals only for this file. */
54
55 static char current_list[BUFSIZ];
56
57
58 /*      Function Name: PrintListAce
59  *      Description: This function prints the list ace information.
60  *      Arguments: info - an info structure.
61  *      Returns: none.
62  */
63
64 static void PrintListAce(char **info)
65 {
66   char buf[BUFSIZ];
67
68   sprintf(buf, "Item: %-20s Name: %s", info[ACE_TYPE], info[ACE_NAME]);
69   Put_message(buf);
70 }
71
72 /*      Function Name: PrintListInfo
73  *      Description: This function Prints out the List info in a coherent form.
74  *      Arguments: info - the List info.
75  *      Returns: none.
76  */
77
78 static void PrintListInfo(char **info)
79 {
80   char buf[BUFSIZ];
81
82   Put_message(" ");
83   sprintf(buf, "%20sList: %s", "", info[L_NAME]);
84   Put_message(buf);
85   sprintf(buf, "Description: %s", info[L_DESC]);
86   Put_message(buf);
87   if (atoi(info[L_MAILLIST]))
88     Put_message("This list is a mailing list.");
89   else
90     Put_message("This list is NOT a mailing list.");
91   if (atoi(info[L_GROUP]))
92     {
93       sprintf(buf, "This list is a Group%s and its ID number is %s",
94               atoi(info[L_NFSGROUP]) ? " and an NFS Group," : "",
95               info[L_GID]);
96       Put_message(buf);
97     }
98   else
99     Put_message("This list is NOT a Group.");
100
101   if (!strcmp(info[L_ACE_TYPE], "NONE"))
102     Put_message("This list has no Administrator, how strange?!");
103   else
104     {
105       sprintf(buf, "The Administrator of this list is the %s: %s",
106               info[L_ACE_TYPE], info[L_ACE_NAME]);
107       Put_message(buf);
108     }
109
110   if (strcmp(info[L_MEMACE_TYPE], "NONE"))
111     {
112       sprintf(buf, "The Membership Administrator of this list is the %s: %s",
113               info[L_MEMACE_TYPE], info[L_MEMACE_NAME]);
114       Put_message(buf);
115     }
116
117   sprintf(buf, "This list is: %s, %s, and %s",
118           atoi(info[L_ACTIVE]) ? "active" : "inactive",
119           atoi(info[L_PUBLIC]) ? "public" : "private",
120           atoi(info[L_HIDDEN]) ? "hidden" : "visible");
121   Put_message(buf);
122   sprintf(buf, MOD_FORMAT, info[L_MODBY], info[L_MODTIME], info[L_MODWITH]);
123   Put_message(buf);
124 }
125
126 /*      Function Name: GetListInfo
127  *      Description: Stores all info about a group of lists in a queue.
128  *      Arguments: type - type of info to store.
129  *                 name - name of the info.
130  *      Returns: the first element in the queue.
131  */
132
133 struct mqelem *GetListInfo(int type, char *name1, char *name2)
134 {
135   char *args[2];
136   struct mqelem *elem = NULL;
137   int status;
138
139   switch (type)
140     {
141     case LIST:
142       args[0] = name1;
143       if ((status = do_mr_query("get_list_info", 1, args, StoreInfo, &elem)))
144         {
145           com_err(program_name, status, " in get_list_info");
146           return NULL;
147         }
148       break;
149     case MEMBERS:
150       args[0] = name1;
151       if ((status = do_mr_query("get_members_of_list", 1, args,
152                                 StoreInfo, &elem)))
153         {
154           com_err(program_name, status, " in get_members_of_list");
155           return NULL;
156         }
157       break;
158     case GLOM:
159       args[0] = name1;
160       args[1] = name2;
161       if ((status = do_mr_query("get_lists_of_member", 2, args,
162                                 StoreInfo, &elem)))
163         {
164           com_err(program_name, status, " in get_list_of_members");
165           return NULL;
166         }
167       break;
168     case ACE_USE:
169       args[0] = name1;
170       args[1] = name2;
171       if ((status = do_mr_query("get_ace_use", 2, args, StoreInfo, &elem)))
172         {
173           com_err(program_name, status, " in get_ace_use");
174           return NULL;
175         }
176       break;
177     }
178   return QueueTop(elem);
179 }
180
181 /*      Function Name: AskListInfo.
182  *      Description: This function askes the user for information about a
183  *                   machine and saves it into a structure.
184  *      Arguments: info - a pointer the the structure to put the
185  *                             info into.
186  *                 name - add a newname field? (T/F)
187  *      Returns: SUB_ERROR or SUB_NORMAL.
188  */
189
190 char **AskListInfo(char **info, Bool name)
191 {
192   char temp_buf[BUFSIZ], *newname;
193
194   Put_message(" ");
195   sprintf(temp_buf, "Setting information of list %s.", info[L_NAME]);
196   Put_message(temp_buf);
197   Put_message(" ");
198
199   if (name)
200     {
201       while (1)
202         {
203           newname = strdup(info[L_NAME]);
204           if (GetValueFromUser("The new name for this list", &newname) ==
205               SUB_ERROR)
206             return NULL;
207           if (ValidName(newname))
208             break;
209         }
210     }
211   if (GetYesNoValueFromUser("Is this an active list", &info[L_ACTIVE]) ==
212       SUB_ERROR)
213     return NULL;
214   if (GetYesNoValueFromUser("Is this a public list", &info[L_PUBLIC]) ==
215       SUB_ERROR)
216     return NULL;
217   if (GetYesNoValueFromUser("Is this a hidden list", &info[L_HIDDEN]) ==
218       SUB_ERROR)
219     return NULL;
220   if (GetYesNoValueFromUser("Is this a maillist", &info[L_MAILLIST]) ==
221       SUB_ERROR)
222     return NULL;
223   if (GetYesNoValueFromUser("Is this a group", &info[L_GROUP]) == SUB_ERROR)
224     return NULL;
225   if (atoi(info[L_GROUP]))
226     {
227       if (GetYesNoValueFromUser("Is this an NFS group", &info[L_NFSGROUP]) == 
228           SUB_ERROR)
229         return NULL;
230       if (GetValueFromUser("What is the GID for this group.", &info[L_GID]) ==
231           SUB_ERROR)
232         return NULL;
233     }
234
235   if (GetTypeFromUser("What Type of Administrator", "ace_type",
236                       &info[L_ACE_TYPE]) == SUB_ERROR)
237     return NULL;
238   if (strcasecmp(info[L_ACE_TYPE], "NONE") &&
239       strcasecmp(info[L_ACE_TYPE], "none"))
240     {
241       sprintf(temp_buf, "Which %s will be the administrator of this list: ",
242               info[L_ACE_TYPE]);
243       if (GetValueFromUser(temp_buf, &info[L_ACE_NAME]) == SUB_ERROR)
244         return NULL;
245     }
246   if (!strcasecmp(info[L_ACE_TYPE], "kerberos"))
247     {
248       char *canon;
249       
250       mrcl_validate_kerberos_member(info[L_ACE_NAME], &canon);
251       if (mrcl_get_message())
252         Put_message(mrcl_get_message());
253       free(info[L_ACE_NAME]);
254       info[L_ACE_NAME] = canon;
255     }
256   if (GetTypeFromUser("What Type of Membership Administrator", "ace_type",
257                       &info[L_MEMACE_TYPE]) == SUB_ERROR)
258     return NULL;
259   if (strcasecmp(info[L_MEMACE_TYPE], "NONE") &&
260       strcasecmp(info[L_MEMACE_TYPE], "none"))
261     {
262       sprintf(temp_buf, "Which %s will be the membership administrator of this list: ",
263               info[L_MEMACE_TYPE]);
264       if (GetValueFromUser(temp_buf, &info[L_MEMACE_NAME]) == SUB_ERROR)
265         return NULL;
266     }
267   if (!strcasecmp(info[L_MEMACE_TYPE], "kerberos"))
268     {
269       char *canon;
270
271       mrcl_validate_kerberos_member(info[L_MEMACE_NAME], &canon);
272       if (mrcl_get_message())
273         Put_message(mrcl_get_message());
274       free(info[L_MEMACE_NAME]);
275       info[L_MEMACE_NAME] = canon;
276     }
277   if (GetValueFromUser("Description: ", &info[L_DESC]) == SUB_ERROR)
278     return NULL;
279
280   FreeAndClear(&info[L_MODTIME], TRUE);
281   FreeAndClear(&info[L_MODBY], TRUE);
282   FreeAndClear(&info[L_MODWITH], TRUE);
283   /*
284    * Slide the newname into the #2 slot, this screws up all future references
285    * to this list.
286    */
287   if (name)                     /* slide the newname into the #2 slot. */
288     SlipInNewName(info, newname);
289
290   return info;
291 }
292
293 /* -------------- List functions. -------------- */
294
295 /*      Function Name: ShowListInfo.
296  *      Description: shows info on a list.
297  *      Arguments: argc, argv - name of list in argv[1].
298  *      Returns: DM status code.
299  */
300
301 int ShowListInfo(int argc, char **argv)
302 {
303   struct mqelem *top, *list;
304
305   top = list = GetListInfo(LIST, argv[1], NULL);
306   while (list)
307     {
308       PrintListInfo(list->q_data);
309       list = list->q_forw;
310     }
311
312   FreeQueue(top);
313   return DM_NORMAL;
314 }
315
316 /*      Function Name: RealUpdateList
317  *      Description: performs the actual update of the list.
318  *      Arguments: info - all information needed to update the list.
319  *                 junk - an UNUSED boolean.
320  *      Returns: none.
321  */
322
323 static void RealUpdateList(char **info, Bool junk)
324 {
325   int stat;
326   char **args;
327   struct mqelem *elem = NULL;
328
329   if (!(args = AskListInfo(info, TRUE)))
330     {
331       Put_message("Aborted.");
332       return;
333     }
334
335   /*
336    * If the new list name is less than 8 characters, make sure it doesn't
337    * collide with a username.
338    */
339   if ((strlen(args[2]) <= 8) &&
340       do_mr_query("get_user_account_by_login", 1, args + 1,
341                   StoreInfo, &elem) != MR_NO_MATCH)
342     {
343       char buf[256];
344
345       sprintf(buf, "\nA user by the name `%s' already exists in the database.",
346               args[1]);
347       Put_message(buf);
348       Loop(QueueTop(elem), FreeInfo);
349       FreeQueue(elem);
350       if (YesNoQuestion("Do you still want to rename this list to that name",
351                         FALSE) != TRUE)
352         {
353           Put_message("List ** NOT ** Updated.");
354           return;
355         }
356     }
357
358   if ((stat = do_mr_query("update_list", CountArgs(args), args,
359                           NULL, NULL)) != MR_SUCCESS)
360     {
361       com_err(program_name, stat, " in UpdateList.");
362       Put_message("List ** NOT ** Updated.");
363     }
364   else
365     Put_message("List successfully updated.");
366 }
367
368 /*      Function Name: UpdateList
369  *      Description: updates the information on a list.
370  *      Arguments: argc, argv - name of list in argv[1].
371  *      Returns: DM Status code.
372  */
373
374 int UpdateList(int argc, char **argv)
375 {
376   struct mqelem *top;
377
378   top = GetListInfo(LIST, argv[1], (char *) NULL);
379   QueryLoop(top, NullPrint, RealUpdateList, "Update the list");
380
381   FreeQueue(top);
382   return DM_NORMAL;
383 }
384
385 /*      Function Name: SetDefaults
386  *      Description: sets defaults for AddList function
387  *      Arguments: info - the array to add them to.
388  *                 name - name of the program to add.
389  *      Returns: defaults - the default information.
390  */
391
392 static char **SetDefaults(char **info, char *name)
393 {
394   info[L_NAME] =     strdup(name);
395   info[L_ACTIVE] =   strdup(DEFAULT_ACTIVE);
396   info[L_PUBLIC] =   strdup(DEFAULT_PUBLIC);
397   info[L_HIDDEN] =   strdup(DEFAULT_HIDDEN);
398   info[L_MAILLIST] = strdup(DEFAULT_MAILLIST);
399   info[L_GROUP] =    strdup(DEFAULT_GROUP);
400   info[L_GID] =      strdup(DEFAULT_GID);
401   info[L_NFSGROUP] = strdup(DEFAULT_NFSGROUP);
402   info[L_ACE_TYPE] = strdup(DEFAULT_ACE_TYPE);
403   info[L_ACE_NAME] = strdup(DEFAULT_ACE_NAME);
404   info[L_MEMACE_TYPE] = strdup(DEFAULT_MEMACE_TYPE);
405   info[L_MEMACE_NAME] = strdup(DEFAULT_MEMACE_NAME);
406   info[L_DESC] =     strdup(DEFAULT_DESCRIPTION);
407   info[L_MODTIME] = info[L_MODBY] = info[L_MODWITH] = info[L_END] = NULL;
408   return info;
409 }
410
411 /*      Function Name: AddList
412  *      Description:
413  *      Arguments: argc, argv - name of list in argv[1].
414  *      Returns: SUB_ERROR if list not created.
415  */
416
417 int AddList(int argc, char **argv)
418 {
419   static char *info[MAX_ARGS_SIZE], **add_args;
420   int status, ret_code = SUB_NORMAL;
421   struct mqelem *elem = NULL;
422
423   if (!ValidName(argv[1]))
424     return DM_NORMAL;
425   status = do_mr_query("get_list_info", 1, argv + 1, NULL, NULL);
426   if (status != MR_NO_MATCH)
427     {
428       if (status == MR_SUCCESS)
429         Put_message("This list already exists.");
430       else
431         com_err(program_name, status, " in AddList.");
432       return SUB_ERROR;
433     }
434
435   /*
436    * If the listname is less than 8 characters, make sure it doesn't
437    * collide with a username.
438    */
439   if ((strlen(argv[1]) <= 8) &&
440       do_mr_query("get_user_account_by_login", 1, argv + 1,
441                   StoreInfo, &elem) != MR_NO_MATCH)
442     {
443       char buf[256];
444
445       sprintf(buf, "\nA user by the name `%s' already exists in the database.",
446               argv[1]);
447       Put_message(buf);
448       Loop(QueueTop(elem), FreeInfo);
449       FreeQueue(elem);
450       if (YesNoQuestion("Create a list with the same name", FALSE) != TRUE)
451         return SUB_ERROR;
452     }
453
454   if (!(add_args = AskListInfo(SetDefaults(info, argv[1]), FALSE)))
455     {
456       Put_message("Aborted.");
457       return SUB_ERROR;
458     }
459
460   if ((status = do_mr_query("add_list", CountArgs(add_args), add_args,
461                             NULL, NULL)) != MR_SUCCESS)
462     {
463       com_err(program_name, status, " in AddList.");
464       Put_message("List Not Created.");
465       ret_code = SUB_ERROR;
466     }
467
468   FreeInfo(info);
469   return ret_code;
470 }
471
472 /*      Function Name: Instructions
473  *      Description: This func prints out instruction on manipulating lists.
474  *      Arguments: none
475  *      Returns: DM Status Code.
476  */
477
478 int ListHelp(int argc, char **argv)
479 {
480   static char *message[] = {
481     "Listmaint handles the creation, deletion, and updating of lists.",
482     "A list can be a mailing list, a group list, or both.",
483     "The concept behind lists is that a list has an owner",
484     "- administrator -  and members.",
485     "The administrator of a list may be another list.",
486     "The members of a list can be users (login names), other lists,",
487     "or address strings.",
488     "You can use certain keys to do the following:",
489     "    Refresh the screen - Type ctrl-L.",
490     "    Escape from a function - Type ctrl-C.",
491     "    Suspend the program (temporarily) - Type ctrl-Z.",
492     NULL,
493   };
494
495   return PrintHelp(message);
496 }
497
498 /*-*-* LISTMAINT UPDATE MENU *-*-*/
499
500 /*      Function Name: ListmaintMemberMenuEntry
501  *      Description: entry routine into the listmaint member menu.
502  *      Arguments: m - the member menu.
503  *                 argc, argv - name of the list in argv[1].
504  *      Returns: none.
505  */
506
507 int ListmaintMemberMenuEntry(Menu *m, int argc, char **argv)
508 {
509   char temp_buf[BUFSIZ];
510   char *list_name = argv[1];
511   int stat;
512
513   if (!ValidName(list_name))
514     return DM_QUIT;
515
516   if (*argv[0] == 'a')
517     {   /* add_list */
518       if (AddList(argc, argv) == SUB_ERROR)
519         return DM_QUIT;
520       sprintf(temp_buf, "List '%s' created. Do you want to %s", list_name,
521               "change its membership (y/n)? ");
522       if (YesNoQuestion(temp_buf, TRUE) != TRUE)
523         return DM_QUIT;
524     }
525   else
526     /* All we want to know is if it exists. */
527     switch ((stat = do_mr_query("count_members_of_list", 1, argv + 1,
528                                 NULL, NULL)))
529       {
530       case MR_SUCCESS:
531         break;
532       case MR_LIST:
533         Put_message("This list does not exist.");
534         return DM_QUIT;
535       case MR_PERM:
536         Put_message("You are not allowed to view this list.");
537         break;
538       default:
539         com_err(program_name, stat, " in get_list_info");
540         return DM_QUIT;
541       }
542
543   sprintf(temp_buf, "Change/Display membership of '%s'", list_name);
544   m->m_title = strdup(temp_buf);
545   strcpy(current_list, list_name);
546   return DM_NORMAL;
547 }
548
549 /*      Function Name: ListmaintMemberMenuExit
550  *      Description: This is the function called when the member menu is
551  *                   exited, it frees the memory that is storing the name.
552  *      Arguments: m - the menu
553  *      Returns: DM_NORMAL
554  */
555
556 int ListmaintMemberMenuExit(Menu *m)
557 {
558   free(m->m_title);
559   strcpy(current_list, "");
560   return DM_NORMAL;
561 }
562
563 /*      Function Name: ListMembersByType
564  *      Description: This function lists the users of a list by type.
565  *      Arguments: type - the type of the list "USER", "LIST", or "STRING".
566  *                 tags - whether or not to display tags
567  *      Returns: none.
568  *      NOTE: if type is NULL, all lists members are listed.
569  */
570
571 void ListMembersByType(char *type, int tags)
572 {
573   char temp_buf[BUFSIZ];
574   int status;
575   char *args[10];
576
577   args[0] = current_list;
578   args[1] = NULL;
579
580   found_some = FALSE;
581   if ((status = do_mr_query(tags ? "get_tagged_members_of_list" :
582                             "get_members_of_list", CountArgs(args),
583                             args, PrintByType, type)))
584     com_err(program_name, status, " in ListMembersByType");
585   if (!found_some)
586     {
587       if (!type)
588         Put_message("List is empty (no members).");
589       else
590         {
591           sprintf(temp_buf, "No %s Members", type);
592           Put_message(temp_buf);
593         }
594     }
595 }
596
597 /*      Function Name: ListAllMembers
598  *      Description: lists all members of the current list.
599  *      Arguments:
600  *      Returns: DM_NORMAL
601  */
602
603 int ListAllMembers(int argc, char **argv)
604 {
605   ListMembersByType(NULL, 0);
606   return DM_NORMAL;
607 }
608
609 /*      Function Name: ListUserMembers
610  *      Description: This function lists all members of a list of type "USER".
611  *      Arguments: none
612  *      Returns: DM_NORMAL.
613  */
614
615 int ListUserMembers(int argc, char **argv)
616 {
617   ListMembersByType("USER", 0);
618   return DM_NORMAL;
619 }
620
621 /*      Function Name: ListListMembers
622  *      Description: This function lists all members of a list of type "LIST".
623  *      Arguments: none
624  *      Returns: DM_NORMAL.
625  */
626
627 int ListListMembers(int argc, char **argv)
628 {
629   ListMembersByType("LIST", 0);
630   return DM_NORMAL;
631 }
632
633 /*      Function Name: ListStringMembers
634  *      Description:This function lists all members of a list of type "STRING".
635  *      Arguments: none
636  *      Returns: DM_NORMAL.
637  */
638
639 int ListStringMembers(int argc, char **argv)
640 {
641   ListMembersByType("STRING", 0);
642   return DM_NORMAL;
643 }
644
645 /*      Function Name: GetMemberInfo
646  *      Description: This function gets the information needed to
647  *                   add or delete a user from a list.
648  *      Arguments: argc, argv - standard.
649  *                 action - name of the action to be performed either
650  *                          "add" or "delete".
651  *                 ret_argc, ret_argv - the returned value of argc and argv.
652  *      Returns: SUB_ERROR or SUB_NORMAL.
653  */
654
655 int GetMemberInfo(char *action, char **ret_argv)
656 {
657   char temp_buf[BUFSIZ];
658
659   ret_argv[LM_LIST] = strdup(current_list);
660
661   ret_argv[LM_TYPE] = strdup("user");
662   if (GetTypeFromUser("Type of member", "member", &ret_argv[LM_TYPE]) ==
663       SUB_ERROR)
664     return SUB_ERROR;
665
666   sprintf(temp_buf, "Name of %s to %s", ret_argv[LM_TYPE], action);
667   ret_argv[LM_MEMBER] = strdup(user);
668   if (GetValueFromUser(temp_buf, &ret_argv[LM_MEMBER]) == SUB_ERROR)
669     return SUB_ERROR;
670   ret_argv[LM_END] = NULL;              /* NULL terminate this list. */
671
672   if (strcasecmp(ret_argv[LM_TYPE], "string") &&
673       !ValidName(ret_argv[LM_MEMBER]))
674     {
675       FreeInfo(ret_argv);
676       return SUB_ERROR;
677     }
678   return SUB_NORMAL;
679 }
680
681 /*      Function Name: AddMember
682  *      Description: This function adds a member to a list.
683  *      Arguments: none.
684  *      Returns: DM_NORMAL.
685  */
686
687 int AddMember(int argc, char **argv)
688 {
689   char *args[10], temp_buf[BUFSIZ], *p;
690   int status;
691   struct mqelem *mailhubs, *elem;
692
693   if (GetMemberInfo("add", args) == SUB_ERROR)
694     return DM_NORMAL;
695
696   if (!strcmp(args[LM_TYPE], "STRING"))
697     {
698       if (mrcl_validate_string_member(args[LM_MEMBER]) != MRCL_SUCCESS)
699         {
700           Put_message(mrcl_get_message());
701           return DM_NORMAL;
702         }
703     }
704   else if (!strcmp(args[LM_TYPE], "KERBEROS"))
705     {
706       char *canon;
707
708       mrcl_validate_kerberos_member(args[LM_MEMBER], &canon);
709       if (mrcl_get_message())
710         Put_message(mrcl_get_message());
711       free(args[LM_MEMBER]);
712       args[LM_MEMBER] = canon;
713     }
714
715   if ((status = do_mr_query("add_member_to_list", CountArgs(args), args,
716                             NULL, NULL)) != MR_SUCCESS)
717     {
718       if (status == MR_EXISTS)
719         {
720           sprintf(temp_buf, "The %s %s is already a member of LIST %s.",
721                   args[LM_TYPE], args[LM_MEMBER], args[LM_LIST]);
722           Put_message(temp_buf);
723         }
724       else
725         com_err(program_name, status, " in AddMember");
726     }
727
728   FreeInfo(args);
729   return DM_NORMAL;
730 }
731
732 /*      Function Name: DeleteMember
733  *      Description: This function deletes a member from a list.
734  *      Arguments: none.
735  *      Returns: DM_NORMAL
736  */
737
738 int DeleteMember(int argc, char **argv)
739 {
740   char *args[10];
741   int status;
742
743   if (GetMemberInfo("delete", args) == SUB_ERROR)
744     return DM_NORMAL;
745
746   if (Confirm("Are you sure you want to delete this member?"))
747     {
748       if ((status = do_mr_query("delete_member_from_list", CountArgs(args),
749                                 args, NULL, NULL)))
750         {
751           if ((status == MR_STRING || status == MR_NO_MATCH) &&
752               !strcmp(args[LM_TYPE], "KERBEROS"))
753             {
754               char *canon;
755               mrcl_validate_kerberos_member(args[LM_MEMBER], &canon);
756               if (mrcl_get_message())
757                 {
758                   free(args[LM_MEMBER]);
759                   args[LM_MEMBER] = canon;
760                   if (do_mr_query("delete_member_from_list", CountArgs(args),
761                                   args, NULL, NULL) == MR_SUCCESS)
762                     {
763                       Put_message(mrcl_get_message());
764                       status = MR_SUCCESS;
765                     }
766                 }
767             }
768         }
769       if (status)
770         com_err(program_name, status, " in DeleteMember");
771       else
772         Put_message("Deletion Completed.");
773     }
774   else
775     Put_message("Deletion has been Aborted.");
776
777   FreeInfo(args);
778   return DM_NORMAL;
779 }
780
781 /*      Function Name: TagMember
782  *      Description: Add a tag to a list member
783  *      Arguments:
784  *      Returns: DM_NORMAL
785  */
786
787 int TagMember(int argc, char **argv)
788 {
789   char *args[10];
790   int status;
791
792   if (GetMemberInfo("tag", args) == SUB_ERROR)
793     return DM_NORMAL;
794
795   args[LM_TAG] = strdup("");
796   if (GetValueFromUser("Tag" , &args[LM_TAG]) == SUB_ERROR)
797     {
798       Put_message("Aborted.");
799       return DM_NORMAL;
800     }
801   args[LM_TAG_END] = NULL;              /* NULL terminate this list. */
802
803   if ((status = do_mr_query("tag_member_of_list", CountArgs(args),
804                             args, NULL, NULL)))
805     com_err(program_name, status, " in TagMember");
806
807   FreeInfo(args);
808   return DM_NORMAL;
809 }
810
811 /*      Function Name: ListAllMembers
812  *      Description: lists all members of the current list.
813  *      Arguments:
814  *      Returns: DM_NORMAL
815  */
816
817 int ListMembersWithTags(int argc, char **argv)
818 {
819   ListMembersByType(NULL, 1);
820   return DM_NORMAL;
821 }
822
823 /*      Function Name: InterRemoveItemFromLists
824  *      Description: This function allows interactive removal of an item
825  *                   (user, string, list) for all list  that it is on.
826  *      Arguments: none.
827  *      Returns: DM_NORMAL.
828  *      NOTES: QueryLoop() does not work here because info does not have
829  *             enough information in it to delete the member from the list.
830  */
831
832 int InterRemoveItemFromLists(int argc, char **argv)
833 {
834   int status;
835   char *type, *name, *args[10], buf[BUFSIZ];
836   struct mqelem *top, *elem;
837
838   type = strdup("USER");
839   if (GetTypeFromUser("Type of member", "member", &type) == SUB_ERROR)
840     return DM_NORMAL;
841
842   sprintf(buf, "Name of %s", type);
843   name = strdup(user);
844   if (GetValueFromUser(buf, &name) == SUB_ERROR)
845     return DM_NORMAL;
846
847   if (!ValidName(name))
848     return DM_NORMAL;
849
850   top = elem = GetListInfo(GLOM, type, name);
851
852   while (elem)
853     {
854       char line[BUFSIZ];
855       char **info = elem->q_data;
856       sprintf(line, "Delete %s %s from the list \"%s\" (y/n/q)? ", type,
857               name, info[GLOM_NAME]);
858       switch (YesNoQuitQuestion(line, FALSE))
859         {
860         case TRUE:
861           Put_message("deleting...");
862           args[DM_LIST] = info[GLOM_NAME];
863           args[DM_TYPE] = type;
864           args[DM_MEMBER] = name;
865           if ((status = do_mr_query("delete_member_from_list", 3, args,
866                                     NULL, NULL)))
867             {
868               /* should probabally check to delete list. */
869               com_err(program_name, status, " in delete_member");
870             }
871           break;
872         case FALSE:
873           break;
874         default:
875           Put_message("Aborting...");
876           FreeQueue(top);
877           return DM_NORMAL;
878         }
879       elem = elem->q_forw;
880     }
881   FreeQueue(top);
882   return DM_NORMAL;
883 }
884
885 /*-*-* LIST MENU *-*-*/
886
887 /*      Function Name: ListByMember
888  *      Description: This gets all lists that a given member is a member of.
889  *      Arguments: none.
890  *      Returns: DM_NORMAL.
891  */
892
893 int ListByMember(int argc, char **argv)
894 {
895   char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name, **info;
896   Bool maillist, group, neither;
897   struct mqelem *top, *elem;
898
899   type = strdup("USER");
900   if (GetTypeFromUser("Type of member", "member", &type) == SUB_ERROR)
901     return DM_NORMAL;
902
903   sprintf(buf, "Name of %s", type);
904   name = strdup(user);
905   if (GetValueFromUser(buf, &name) == SUB_ERROR)
906     return DM_NORMAL;
907
908   switch (YesNoQuestion("Do you want a recursive search (y/n)", TRUE))
909     {
910     case TRUE:
911       sprintf(temp_buf, "R%s", type);   /* "USER" to "RUSER" etc. */
912       free(type);
913       type = strdup(temp_buf);
914       break;
915     case FALSE:
916       break;
917     default:
918       return DM_NORMAL;
919     }
920
921   if ((maillist = YesNoQuestion("Show Lists that are Maillists (y/n) ?",
922                                 TRUE)) == -1)
923     return DM_NORMAL;
924   if ((group = YesNoQuestion("Show Lists that are Groups (y/n) ?",
925                              TRUE)) == -1)
926     return DM_NORMAL;
927
928   if ((neither = YesNoQuestion("Show Lists that are neither Maillists nor Groups (y/n) ?",
929                                TRUE)) == -1)
930     return DM_NORMAL;
931
932   elem = top = GetListInfo(GLOM, type, name);
933
934   while (elem)
935     {
936       info = elem->q_data;
937       if ((maillist == TRUE && !strcmp(info[GLOM_MAILLIST], "1")) ||
938           (group == TRUE && !strcmp(info[GLOM_GROUP], "1")))
939         Put_message(info[GLOM_NAME]);
940       if (neither == TRUE && !strcmp(info[GLOM_MAILLIST], "0") &&
941            !strcmp(info[GLOM_GROUP], "0"))
942         Put_message(info[GLOM_NAME]);
943       elem = elem->q_forw;
944     }
945   FreeQueue(top);
946   return DM_NORMAL;
947 }
948
949 /*      Function Name: ListByAdministrator
950  *      Description: This function prints all lists which a given user or
951  *                   group administers.
952  *      Arguments: none.
953  *      Returns: DM_NORMAL.
954  */
955
956 int ListByAdministrator(int argc, char **argv)
957 {
958   char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
959   struct mqelem *top;
960
961   type = strdup("USER");
962   if (GetTypeFromUser("Type of member", "member", &type) == SUB_ERROR)
963     return DM_NORMAL;
964
965   sprintf(buf, "Name of %s", type);
966   name = strdup(user);
967   if (GetValueFromUser(buf, &name) == SUB_ERROR)
968     return DM_NORMAL;
969
970   switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE))
971     {
972     case TRUE:
973       sprintf(temp_buf, "R%s", type);   /* "USER" to "RUSER" etc. */
974       free(type);
975       type = strdup(temp_buf);
976       break;
977     case FALSE:
978       break;
979     default:
980       return DM_NORMAL;
981     }
982
983   top = GetListInfo(ACE_USE, type, name);
984   Loop(top, PrintListAce);
985
986   FreeQueue(top);
987   return DM_NORMAL;
988 }
989
990 /*      Function Name: ListAllPublicMailLists
991  *      Description: This function lists all public mailing lists.
992  *      Arguments: none
993  *      Returns: DM_NORMAL.
994  */
995
996 int ListAllPublicMailLists(int argc, char **argv)
997 {
998   int status;
999   static char *args[] = {
1000     "TRUE",                     /* active */
1001     "TRUE",                     /* public */
1002     "FALSE",                    /* hidden */
1003     "TRUE",                     /* maillist */
1004     "DONTCARE",                 /* group. */
1005   };
1006
1007   if (YesNoQuestion("This query will take a while. Do you wish to continue?",
1008                     TRUE) == TRUE)
1009     {
1010       if ((status = do_mr_query("qualified_get_lists", 5, args,
1011                                 Print, NULL)) != MR_SUCCESS)
1012         com_err(program_name, status, " in ListAllGroups");
1013     }
1014
1015   return DM_NORMAL;
1016 }
This page took 0.102381 seconds and 3 git commands to generate.