source: trunk/third/moira/clients/moira/lists.c @ 24319

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