]> andersk Git - moira.git/blobdiff - clients/moira/lists.c
Need to distinguish MRCL_WARN and MRCL_REJECT when validating string
[moira.git] / clients / moira / lists.c
index b663333bcd6fa72a5134f4b7e3711110289994b4..b839836fb6a5f09908d636b3395d8b5f646dab77 100644 (file)
@@ -1,35 +1,37 @@
-#if (!defined(lint) && !defined(SABER))
-  static char rcsid_module_c[] = "$Header$";
-#endif lint
-
-/*     This is the file lists.c for the SMS Client, which allows a nieve
- *      user to quickly and easily maintain most parts of the SMS database.
+/* $Id$
+ *
+ *     This is the file lists.c for the Moira Client, which allows users
+ *      to quickly and easily maintain most parts of the Moira database.
  *     It Contains: All list manipulation functions, except delete.
- *     
+ *
  *     Created:        4/12/88
  *     By:             Chris D. Peterson
  *
- *      $Source$
- *      $Author$
- *      $Header$
- *     
- *     Copyright 1988 by the Massachusetts Institute of Technology.
- *
- *     For further information on copyright and distribution 
- *     see the file mit-copyright.h
+ * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
  */
 
-#include <stdio.h>
-#include <strings.h>
-#include <sms.h>
-#include <sms_app.h>
-#include <menu.h>
-
-#include "mit-copyright.h"
+#include <mit-copyright.h>
+#include <moira.h>
+#include <mrclient.h>
+#include <moira_site.h>
 #include "defs.h"
 #include "f_defs.h"
 #include "globals.h"
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+RCSID("$Header$");
+
+struct mqelem *GetListInfo(int type, char *name1, char *name2);
+char **AskListInfo(char **info, Bool name);
+int AddList(int argc, char **argv);
+void ListMembersByType(char *type, int tags);
+int GetMemberInfo(char *action, char **ret_argv);
+
 #define LIST    0
 #define MEMBERS 1
 #define GLOM    2
 #define DEFAULT_MAILLIST    DEFAULT_YES
 #define DEFAULT_GROUP       DEFAULT_NO
 #define DEFAULT_GID         UNIQUE_GID
+#define DEFAULT_NFSGROUP    DEFAULT_NO
 #define DEFAULT_ACE_TYPE    "user"
 #define DEFAULT_ACE_NAME    (user)
+#define DEFAULT_MEMACE_TYPE "NONE"
+#define DEFAULT_MEMACE_NAME "NONE"
 #define DEFAULT_DESCRIPTION DEFAULT_COMMENT
 
 /* globals only for this file. */
 
 static char current_list[BUFSIZ];
 
+
 /*     Function Name: PrintListAce
  *     Description: This function prints the list ace information.
  *     Arguments: info - an info structure.
  *     Returns: none.
  */
 
-static void
-PrintListAce(info)
-char ** info;
+static void PrintListAce(char **info)
 {
-    char buf[BUFSIZ];
+  char buf[BUFSIZ];
 
-    sprintf(buf, "Item: %-20s Name: %s", info[ACE_TYPE], 
-           info[ACE_NAME]);
-    Put_message(buf);
+  sprintf(buf, "Item: %-20s Name: %s", info[ACE_TYPE], info[ACE_NAME]);
+  Put_message(buf);
 }
 
 /*     Function Name: PrintListInfo
@@ -72,44 +75,52 @@ char ** info;
  *     Returns: none.
  */
 
-static void
-PrintListInfo(info)
-char ** info;
+static void PrintListInfo(char **info)
 {
-    char buf[BUFSIZ];
-
-    Put_message(" ");
-    (void) sprintf(buf, "%20sList: %s", "", info[L_NAME]);
-    (void) Put_message(buf);
-    (void) sprintf(buf, "Description: %s", info[L_DESC]);
-    (void) Put_message(buf);
-    if ( atoi(info[L_MAILLIST]))
-       Put_message("This list is a mailing list.");
-    else
-       Put_message("This list is NOT a mailing list.");
-    if ( atoi(info[L_GROUP]) ) {
-       (void) sprintf(buf,"This list is a Group and its ID number is %s",
-                      info[L_GID]);
-       Put_message(buf);
+  char buf[BUFSIZ];
+
+  Put_message(" ");
+  sprintf(buf, "%20sList: %s", "", info[L_NAME]);
+  Put_message(buf);
+  sprintf(buf, "Description: %s", info[L_DESC]);
+  Put_message(buf);
+  if (atoi(info[L_MAILLIST]))
+    Put_message("This list is a mailing list.");
+  else
+    Put_message("This list is NOT a mailing list.");
+  if (atoi(info[L_GROUP]))
+    {
+      sprintf(buf, "This list is a Group%s and its ID number is %s",
+             atoi(info[L_NFSGROUP]) ? " and an NFS Group," : "",
+             info[L_GID]);
+      Put_message(buf);
     }
-    else
-       Put_message("This list is NOT a Group.");
-
-    if (strcmp(info[L_ACE_TYPE],"NONE") == 0)
-       Put_message("This list has no Administrator, how strange?!");
-    else {
-       sprintf(buf, "The Administrator of this list is the %s: %s",
-               info[L_ACE_TYPE], info[L_ACE_NAME]);
-       Put_message(buf);
+  else
+    Put_message("This list is NOT a Group.");
+
+  if (!strcmp(info[L_ACE_TYPE], "NONE"))
+    Put_message("This list has no Administrator, how strange?!");
+  else
+    {
+      sprintf(buf, "The Administrator of this list is the %s: %s",
+             info[L_ACE_TYPE], info[L_ACE_NAME]);
+      Put_message(buf);
     }
 
-    (void) sprintf(buf, "This list is: %s, %s, and %s",
-                  atoi(info[L_ACTIVE]) ? "active" : "inactive",
-                  atoi(info[L_PUBLIC]) ? "public" : "private",
-                  atoi(info[L_HIDDEN]) ? "hidden" : "visible");
-    (void) Put_message(buf);
-    sprintf(buf, MOD_FORMAT, info[L_MODBY], info[L_MODTIME], info[L_MODWITH]);
-    (void) Put_message(buf);
+  if (strcmp(info[L_MEMACE_TYPE], "NONE"))
+    {
+      sprintf(buf, "The Membership Administrator of this list is the %s: %s",
+             info[L_MEMACE_TYPE], info[L_MEMACE_NAME]);
+      Put_message(buf);
+    }
+
+  sprintf(buf, "This list is: %s, %s, and %s",
+         atoi(info[L_ACTIVE]) ? "active" : "inactive",
+         atoi(info[L_PUBLIC]) ? "public" : "private",
+         atoi(info[L_HIDDEN]) ? "hidden" : "visible");
+  Put_message(buf);
+  sprintf(buf, MOD_FORMAT, info[L_MODBY], info[L_MODTIME], info[L_MODWITH]);
+  Put_message(buf);
 }
 
 /*     Function Name: GetListInfo
@@ -119,57 +130,56 @@ char ** info;
  *     Returns: the first element in the queue.
  */
 
-/* ARGSUSED */
-struct qelem *
-GetListInfo(type, name1, name2)
-int type;
-char * name1, *name2;
+struct mqelem *GetListInfo(int type, char *name1, char *name2)
 {
-    char *args[2];
-    struct qelem * elem = NULL;
-    register int status;
+  char *args[2];
+  struct mqelem *elem = NULL;
+  int status;
 
-    switch(type) {
+  switch (type)
+    {
     case LIST:
-       args[0] = name1;
-       if ( (status = do_sms_query("get_list_info", 1, args,
-                              StoreInfo, (char *) &elem)) != 0) {
-           com_err(program_name, status, " in get_list_info");
-           return (NULL);
+      args[0] = name1;
+      if ((status = do_mr_query("get_list_info", 1, args, StoreInfo, &elem)))
+       {
+         com_err(program_name, status, " in get_list_info");
+         return NULL;
        }
-       break;
+      break;
     case MEMBERS:
-       args[0] = name1;
-       if ( (status = do_sms_query("get_members_of_list", 1, args,
-                              StoreInfo, (char *) &elem)) != 0) {
-           com_err(program_name, status, " in get_members_of_list");
-           return (NULL);
+      args[0] = name1;
+      if ((status = do_mr_query("get_members_of_list", 1, args,
+                               StoreInfo, &elem)))
+       {
+         com_err(program_name, status, " in get_members_of_list");
+         return NULL;
        }
-       break;
+      break;
     case GLOM:
-       args[0] = name1;        
-       args[1] = name2;        
-       if ( (status =  do_sms_query("get_lists_of_member", 2, args,
-                              StoreInfo, (char *) &elem)) != 0) {
-           com_err(program_name, status, " in get_list_of_members");
-           return (NULL);
+      args[0] = name1;
+      args[1] = name2;
+      if ((status = do_mr_query("get_lists_of_member", 2, args,
+                               StoreInfo, &elem)))
+       {
+         com_err(program_name, status, " in get_list_of_members");
+         return NULL;
        }
-       break;
+      break;
     case ACE_USE:
-       args[0] = name1;        
-       args[1] = name2;        
-       if ( (status =  do_sms_query("get_ace_use", 2, args,
-                              StoreInfo, (char *) &elem)) != 0) {
-           com_err(program_name, status, " in get_ace_use");
-           return (NULL);
+      args[0] = name1;
+      args[1] = name2;
+      if ((status = do_mr_query("get_ace_use", 2, args, StoreInfo, &elem)))
+       {
+         com_err(program_name, status, " in get_ace_use");
+         return NULL;
        }
-       break;
+      break;
     }
-    return( QueueTop(elem) );
-}      
+  return QueueTop(elem);
+}
 
 /*     Function Name: AskListInfo.
- *     Description: This function askes the user for information about a 
+ *     Description: This function askes the user for information about a
  *                   machine and saves it into a structure.
  *     Arguments: info - a pointer the the structure to put the
  *                             info into.
@@ -177,54 +187,115 @@ char * name1, *name2;
  *     Returns: SUB_ERROR or SUB_NORMAL.
  */
 
-char **
-AskListInfo(info, name)
-char ** info;
-Bool name;
+char **AskListInfo(char **info, Bool name)
 {
-    char temp_buf[BUFSIZ], *newname;
-
-    Put_message(" ");
-    sprintf(temp_buf,"Setting information of list %s.",info[L_NAME]);
-    Put_message(temp_buf);
-    Put_message(" ");
-
-    if (name) {
-       while (1) {
-           newname = Strsave(info[L_NAME]);
-           GetValueFromUser("The new name for this list", &newname);
-           if (ValidName(newname))
-             break;
+  char temp_buf[BUFSIZ], *newname;
+
+  Put_message(" ");
+  sprintf(temp_buf, "Setting information of list %s.", info[L_NAME]);
+  Put_message(temp_buf);
+  Put_message(" ");
+
+  if (name)
+    {
+      while (1)
+       {
+         newname = strdup(info[L_NAME]);
+         if (GetValueFromUser("The new name for this list", &newname) ==
+             SUB_ERROR)
+           return NULL;
+         if (ValidName(newname))
+           break;
        }
     }
-    GetYesNoValueFromUser("Is this an active list", &info[L_ACTIVE]);
-    GetYesNoValueFromUser("Is this a public list", &info[L_PUBLIC]);
-    GetYesNoValueFromUser("Is this a hidden list", &info[L_HIDDEN]);
-    GetYesNoValueFromUser("Is this a maillist", &info[L_MAILLIST]);
-    GetYesNoValueFromUser("Is this a group", &info[L_GROUP]);
-    if (atoi(info[L_GROUP]))
-       GetValueFromUser("What is the GID for this group.", &info[L_GID]);
-
-    GetTypeFromUser("What Type of Administrator", "ace_type",&info[L_ACE_TYPE]);
-    if ((strcasecmp(info[L_ACE_TYPE], "NONE") != 0) &&
-       (strcasecmp(info[L_ACE_TYPE], "none") != 0)) {
+  if (GetYesNoValueFromUser("Is this an active list", &info[L_ACTIVE]) ==
+      SUB_ERROR)
+    return NULL;
+  if (GetYesNoValueFromUser("Is this a public list", &info[L_PUBLIC]) ==
+      SUB_ERROR)
+    return NULL;
+  if (GetYesNoValueFromUser("Is this a hidden list", &info[L_HIDDEN]) ==
+      SUB_ERROR)
+    return NULL;
+  if (GetYesNoValueFromUser("Is this a maillist", &info[L_MAILLIST]) ==
+      SUB_ERROR)
+    return NULL;
+  if (GetYesNoValueFromUser("Is this a group", &info[L_GROUP]) == SUB_ERROR)
+    return NULL;
+  if (atoi(info[L_GROUP]))
+    {
+      if (GetYesNoValueFromUser("Is this an NFS group", &info[L_NFSGROUP]) == 
+         SUB_ERROR)
+       return NULL;
+      if (GetValueFromUser("What is the GID for this group.", &info[L_GID]) ==
+         SUB_ERROR)
+       return NULL;
+    }
+
+  do {
+    if (GetTypeFromUser("What Type of Administrator", "ace_type",
+                       &info[L_ACE_TYPE]) == SUB_ERROR)
+      return NULL;
+    if (strcasecmp(info[L_ACE_TYPE], "none"))
+      {
        sprintf(temp_buf, "Which %s will be the administrator of this list: ",
                info[L_ACE_TYPE]);
-       GetValueFromUser(temp_buf, &info[L_ACE_NAME]);
+       if (GetValueFromUser(temp_buf, &info[L_ACE_NAME]) == SUB_ERROR)
+         return NULL;
+      }
+    else
+      {
+       Put_message("Setting the administrator of this list to 'NONE'");
+       Put_message("will make you unable to further modify the list.");
+       if (YesNoQuestion("Do you really want to do this?", FALSE) == TRUE)
+         break;
+      }
+  } while (!strcasecmp(info[L_ACE_TYPE], "none"));
+       
+  if (!strcasecmp(info[L_ACE_TYPE], "kerberos"))
+    {
+      char *canon;
+      
+      mrcl_validate_kerberos_member(info[L_ACE_NAME], &canon);
+      if (mrcl_get_message())
+       Put_message(mrcl_get_message());
+      free(info[L_ACE_NAME]);
+      info[L_ACE_NAME] = canon;
     }
-    GetValueFromUser("Description: ", &info[L_DESC]);
-
-    FreeAndClear(&info[L_MODTIME], TRUE);
-    FreeAndClear(&info[L_MODBY], TRUE);
-    FreeAndClear(&info[L_MODWITH], TRUE);
-/* 
- * Slide the newname into the #2 slot, this screws up all future references 
- * to this list.
- */
-    if (name)                  /* slide the newname into the #2 slot. */
-       SlipInNewName(info, newname);
-
-    return(info);
+  if (GetTypeFromUser("What Type of Membership Administrator", "ace_type",
+                     &info[L_MEMACE_TYPE]) == SUB_ERROR)
+    return NULL;
+  if (strcasecmp(info[L_MEMACE_TYPE], "none"))
+    {
+      sprintf(temp_buf, "Which %s will be the membership administrator of this list: ",
+             info[L_MEMACE_TYPE]);
+      if (GetValueFromUser(temp_buf, &info[L_MEMACE_NAME]) == SUB_ERROR)
+       return NULL;
+    }
+  if (!strcasecmp(info[L_MEMACE_TYPE], "kerberos"))
+    {
+      char *canon;
+
+      mrcl_validate_kerberos_member(info[L_MEMACE_NAME], &canon);
+      if (mrcl_get_message())
+       Put_message(mrcl_get_message());
+      free(info[L_MEMACE_NAME]);
+      info[L_MEMACE_NAME] = canon;
+    }
+  if (GetValueFromUser("Description: ", &info[L_DESC]) == SUB_ERROR)
+    return NULL;
+
+  FreeAndClear(&info[L_MODTIME], TRUE);
+  FreeAndClear(&info[L_MODBY], TRUE);
+  FreeAndClear(&info[L_MODWITH], TRUE);
+  /*
+   * Slide the newname into the #2 slot, this screws up all future references
+   * to this list.
+   */
+  if (name)                    /* slide the newname into the #2 slot. */
+    SlipInNewName(info, newname);
+
+  return info;
 }
 
 /* -------------- List functions. -------------- */
@@ -235,22 +306,19 @@ Bool name;
  *     Returns: DM status code.
  */
 
-/* ARGSUSED */
-int
-ShowListInfo(argc, argv)
-int argc;
-char **argv;
+int ShowListInfo(int argc, char **argv)
 {
-    struct qelem *top, *list;
+  struct mqelem *top, *list;
 
-    top = list = GetListInfo(LIST, argv[1], (char *) NULL);
-    while (list != NULL) {
-       PrintListInfo( (char **) list->q_data);
-       list = list->q_forw;
+  top = list = GetListInfo(LIST, argv[1], NULL);
+  while (list)
+    {
+      PrintListInfo(list->q_data);
+      list = list->q_forw;
     }
-    
-    FreeQueue(top);
-    return(DM_NORMAL);
+
+  FreeQueue(top);
+  return DM_NORMAL;
 }
 
 /*     Function Name: RealUpdateList
@@ -259,24 +327,50 @@ char **argv;
  *                 junk - an UNUSED boolean.
  *     Returns: none.
  */
-/* ARGSUSED */   
-static void
-RealUpdateList(info, junk)
-char ** info;
-Bool junk;
+
+static void RealUpdateList(char **info, Bool junk)
 {
-    register int stat;
-    char ** args;
-    
-    args = AskListInfo(info, TRUE);
-    if ( (stat = do_sms_query("update_list", CountArgs(args), args, 
-                          Scream, (char *) NULL)) != SMS_SUCCESS) {
-       com_err(program_name, stat, " in UpdateList."); 
-       Put_message("List ** NOT ** Updated.");
+  int stat;
+  char **args;
+  struct mqelem *elem = NULL;
+
+  if (!(args = AskListInfo(info, TRUE)))
+    {
+      Put_message("Aborted.");
+      return;
     }
-    else
-       Put_message("List successfully updated.");
+
+  /*
+   * If the new list name is less than 8 characters, make sure it doesn't
+   * collide with a username.
+   */
+  if ((strlen(args[2]) <= 8) &&
+      do_mr_query("get_user_account_by_login", 1, args + 1,
+                 StoreInfo, &elem) != MR_NO_MATCH)
+    {
+      char buf[256];
+
+      sprintf(buf, "\nA user by the name `%s' already exists in the database.",
+             args[1]);
+      Put_message(buf);
+      Loop(QueueTop(elem), FreeInfo);
+      FreeQueue(elem);
+      if (YesNoQuestion("Do you still want to rename this list to that name",
+                       FALSE) != TRUE)
+       {
+         Put_message("List ** NOT ** Updated.");
+         return;
+       }
+    }
+
+  if ((stat = do_mr_query("update_list", CountArgs(args), args,
+                         NULL, NULL)) != MR_SUCCESS)
+    {
+      com_err(program_name, stat, " in UpdateList.");
+      Put_message("List ** NOT ** Updated.");
+    }
+  else
+    Put_message("List successfully updated.");
 }
 
 /*     Function Name: UpdateList
@@ -285,19 +379,15 @@ Bool junk;
  *     Returns: DM Status code.
  */
 
-/* ARGSUSED */
-int
-UpdateList(argc, argv)
-int argc;
-char **argv;
+int UpdateList(int argc, char **argv)
 {
-    struct qelem *top;
+  struct mqelem *top;
 
-    top = GetListInfo(LIST, argv[1], (char *) NULL);
-    QueryLoop(top, NullPrint, RealUpdateList, "Update the list");
+  top = GetListInfo(LIST, argv[1], (char *) NULL);
+  QueryLoop(top, NullPrint, RealUpdateList, "Update the list");
 
-    FreeQueue(top);
-    return(DM_NORMAL);
+  FreeQueue(top);
+  return DM_NORMAL;
 }
 
 /*     Function Name: SetDefaults
@@ -307,63 +397,84 @@ char **argv;
  *     Returns: defaults - the default information.
  */
 
-static char **
-SetDefaults(info, name)
-char ** info;
-char * name;
+static char **SetDefaults(char **info, char *name)
 {
-   info[L_NAME] =     Strsave(name);
-   info[L_ACTIVE] =   Strsave(DEFAULT_ACTIVE);
-   info[L_PUBLIC] =   Strsave(DEFAULT_PUBLIC);
-   info[L_HIDDEN] =   Strsave(DEFAULT_HIDDEN);
-   info[L_MAILLIST] = Strsave(DEFAULT_MAILLIST);
-   info[L_GROUP] =    Strsave(DEFAULT_GROUP);
-   info[L_GID] =      Strsave(DEFAULT_GID);
-   info[L_ACE_TYPE] = Strsave(DEFAULT_ACE_TYPE);
-   info[L_ACE_NAME] = Strsave(DEFAULT_ACE_NAME);
-   info[L_DESC] =     Strsave(DEFAULT_DESCRIPTION);
-   info[L_MODTIME] = info[L_MODBY] = info[L_MODWITH] = info[L_END] = NULL;
-   return(info);
+  info[L_NAME] =     strdup(name);
+  info[L_ACTIVE] =   strdup(DEFAULT_ACTIVE);
+  info[L_PUBLIC] =   strdup(DEFAULT_PUBLIC);
+  info[L_HIDDEN] =   strdup(DEFAULT_HIDDEN);
+  info[L_MAILLIST] = strdup(DEFAULT_MAILLIST);
+  info[L_GROUP] =    strdup(DEFAULT_GROUP);
+  info[L_GID] =      strdup(DEFAULT_GID);
+  info[L_NFSGROUP] = strdup(DEFAULT_NFSGROUP);
+  info[L_ACE_TYPE] = strdup(DEFAULT_ACE_TYPE);
+  info[L_ACE_NAME] = strdup(DEFAULT_ACE_NAME);
+  info[L_MEMACE_TYPE] = strdup(DEFAULT_MEMACE_TYPE);
+  info[L_MEMACE_NAME] = strdup(DEFAULT_MEMACE_NAME);
+  info[L_DESC] =     strdup(DEFAULT_DESCRIPTION);
+  info[L_MODTIME] = info[L_MODBY] = info[L_MODWITH] = info[L_END] = NULL;
+  return info;
 }
 
 /*     Function Name: AddList
- *     Description: 
+ *     Description:
  *     Arguments: argc, argv - name of list in argv[1].
  *     Returns: SUB_ERROR if list not created.
  */
 
-/* ARGSUSED */
-int
-AddList(argc, argv)
-int argc;
-char **argv;
+int AddList(int argc, char **argv)
 {
-    static char *info[MAX_ARGS_SIZE], **add_args;
-    int status, ret_code = SUB_NORMAL;
-
-    if (!ValidName(argv[1]))
-      return(DM_NORMAL);
-    status = do_sms_query("get_list_info", 1, argv + 1, NullFunc, 
-                      (char *) NULL);
-    if (status != SMS_NO_MATCH) {
-       if (status == SMS_SUCCESS)
-           Put_message("This list already exists.");
-       else
-           com_err(program_name, status, " in AddList.");      
-       return(SUB_ERROR);
+  static char *info[MAX_ARGS_SIZE], **add_args;
+  int status, ret_code = SUB_NORMAL;
+  struct mqelem *elem = NULL;
+
+  if (!ValidName(argv[1]))
+    return DM_NORMAL;
+  status = do_mr_query("get_list_info", 1, argv + 1, NULL, NULL);
+  if (status != MR_NO_MATCH)
+    {
+      if (status == MR_SUCCESS)
+       Put_message("This list already exists.");
+      else
+       com_err(program_name, status, " in AddList.");
+      return SUB_ERROR;
     }
 
-    add_args = AskListInfo(SetDefaults(info,argv[1]), FALSE);
+  /*
+   * If the listname is less than 8 characters, make sure it doesn't
+   * collide with a username.
+   */
+  if ((strlen(argv[1]) <= 8) &&
+      do_mr_query("get_user_account_by_login", 1, argv + 1,
+                 StoreInfo, &elem) != MR_NO_MATCH)
+    {
+      char buf[256];
+
+      sprintf(buf, "\nA user by the name `%s' already exists in the database.",
+             argv[1]);
+      Put_message(buf);
+      Loop(QueueTop(elem), FreeInfo);
+      FreeQueue(elem);
+      if (YesNoQuestion("Create a list with the same name", FALSE) != TRUE)
+       return SUB_ERROR;
+    }
+
+  if (!(add_args = AskListInfo(SetDefaults(info, argv[1]), FALSE)))
+    {
+      Put_message("Aborted.");
+      return SUB_ERROR;
+    }
 
-    if ( (status = do_sms_query("add_list", CountArgs(add_args), add_args,
-                            Scream, (char *) NULL)) != SMS_SUCCESS) {
-       com_err(program_name, status, " in AddList.");  
-       Put_message("List Not Created.");
-       ret_code = SUB_ERROR;
+  if ((status = do_mr_query("add_list", CountArgs(add_args), add_args,
+                           NULL, NULL)) != MR_SUCCESS)
+    {
+      com_err(program_name, status, " in AddList.");
+      Put_message("List Not Created.");
+      ret_code = SUB_ERROR;
     }
 
-    FreeInfo(info);
-    return(ret_code);
+  FreeInfo(info);
+  return ret_code;
 }
 
 /*     Function Name: Instructions
@@ -372,25 +483,24 @@ char **argv;
  *     Returns: DM Status Code.
  */
 
-int
-ListHelp()
+int ListHelp(int argc, char **argv)
 {
-    static char * message[] = {
-       "Listmaint handles the creation, deletion, and updating of lists.",
-       "A list can be a mailing list, a group list, or both.",
-       "The concept behind lists is that a list has an owner",
-       "- administrator -  and members.",
-       "The administrator of a list may be another list.",
-       "The members of a list can be users (login names), other lists,",
-       "or address strings.",
-       "You can use certain keys to do the following:",
-       "    Refresh the screen - Type ctrl-L.",
-       "    Escape from a function - Type ctrl-C.",
-       "    Suspend the program (temporarily) - Type ctrl-Z.",
-       NULL,
-    };
-
-    return(PrintHelp(message));
+  static char *message[] = {
+    "Listmaint handles the creation, deletion, and updating of lists.",
+    "A list can be a mailing list, a group list, or both.",
+    "The concept behind lists is that a list has an owner",
+    "- administrator -  and members.",
+    "The administrator of a list may be another list.",
+    "The members of a list can be users (login names), other lists,",
+    "or address strings.",
+    "You can use certain keys to do the following:",
+    "    Refresh the screen - Type ctrl-L.",
+    "    Escape from a function - Type ctrl-C.",
+    "    Suspend the program (temporarily) - Type ctrl-Z.",
+    NULL,
+  };
+
+  return PrintHelp(message);
 }
 
 /*-*-* LISTMAINT UPDATE MENU *-*-*/
@@ -402,113 +512,106 @@ ListHelp()
  *     Returns: none.
  */
 
-/* ARGSUSED */
-int
-ListmaintMemberMenuEntry(m, argc, argv)
-Menu *m;
-int argc;
-char **argv;
+int ListmaintMemberMenuEntry(Menu *m, int argc, char **argv)
 {
-    char temp_buf[BUFSIZ];
-    char *list_name = argv[1];
-    register int stat;    
-
-    if (!ValidName(list_name))
-       return(DM_QUIT);
-
-    if (*argv[0] == 'a') {     /* add_list */
-       if (AddList(argc, argv) == SUB_ERROR)
-           return(DM_QUIT);
-       (void) sprintf(temp_buf, "List '%s' created. Do you want to %s",
-                      list_name, "change its membership (y/n)? ");
-       if (YesNoQuestion(temp_buf, TRUE) != TRUE )
-           return(DM_QUIT);
+  char temp_buf[BUFSIZ];
+  char *list_name = argv[1];
+  int stat;
+
+  if (!ValidName(list_name))
+    return DM_QUIT;
+
+  if (*argv[0] == 'a')
+    {  /* add_list */
+      if (AddList(argc, argv) == SUB_ERROR)
+       return DM_QUIT;
+      sprintf(temp_buf, "List '%s' created. Do you want to %s", list_name,
+             "change its membership (y/n)? ");
+      if (YesNoQuestion(temp_buf, TRUE) != TRUE)
+       return DM_QUIT;
     }
-    else 
-       /* All we want to know is if it exists. */
-       switch( (stat = do_sms_query("count_members_of_list", 1, argv + 1,
-                                  NullFunc, (char *) NULL))) {
-       case SMS_SUCCESS:
-           break;
-       case SMS_LIST:
-           Put_message("This list does not exist.");
-           return(DM_QUIT);
-       case SMS_PERM:
-           Put_message("You are not allowed to view this list.");
-           break;
-       default:
-           com_err(program_name, stat, " in get_list_info");
-           return(DM_QUIT);
-       }
-
-    (void) sprintf(temp_buf, 
-                  "Change/Display membership of '%s'", list_name);
-    m->m_title = Strsave(temp_buf);
-    strcpy(current_list, list_name);
-    return(DM_NORMAL);
+  else
+    /* All we want to know is if it exists. */
+    switch ((stat = do_mr_query("count_members_of_list", 1, argv + 1,
+                               NULL, NULL)))
+      {
+      case MR_SUCCESS:
+       break;
+      case MR_LIST:
+       Put_message("This list does not exist.");
+       return DM_QUIT;
+      case MR_PERM:
+       Put_message("You are not allowed to view this list.");
+       break;
+      default:
+       com_err(program_name, stat, " in get_list_info");
+       return DM_QUIT;
+      }
+
+  sprintf(temp_buf, "Change/Display membership of '%s'", list_name);
+  m->m_title = strdup(temp_buf);
+  strcpy(current_list, list_name);
+  return DM_NORMAL;
 }
 
 /*     Function Name: ListmaintMemberMenuExit
  *     Description: This is the function called when the member menu is
  *                   exited, it frees the memory that is storing the name.
  *     Arguments: m - the menu
- *     Returns: DM_NORMAL 
+ *     Returns: DM_NORMAL
  */
 
-int
-ListmaintMemberMenuExit(m)
-Menu *m;
+int ListmaintMemberMenuExit(Menu *m)
 {
-    free(m->m_title);
-    strcpy(current_list, "");
-    return(DM_NORMAL);
+  free(m->m_title);
+  strcpy(current_list, "");
+  return DM_NORMAL;
 }
 
 /*     Function Name: ListMembersByType
  *     Description: This function lists the users of a list by type.
  *     Arguments: type - the type of the list "USER", "LIST", or "STRING".
+ *                tags - whether or not to display tags
  *     Returns: none.
  *      NOTE: if type is NULL, all lists members are listed.
  */
 
-int
-ListMembersByType(type)
-char * type;
+void ListMembersByType(char *type, int tags)
 {
-    char temp_buf[BUFSIZ];
-    register int status;
-    char * args[10];
-
-    args[0] = current_list;
-    args[1] = NULL;
-
-    found_some = FALSE;
-    if ( (status = do_sms_query("get_members_of_list", CountArgs(args), args, 
-                            PrintByType, type)) != 0) {
-       com_err(program_name, status, " in ListMembersByType");
-       return(DM_NORMAL);
-    }
-    if (!found_some) {
-       if (type == NULL)
-           Put_message("List is empty (no members).");
-       else {
-           sprintf(temp_buf,"No %s Members",type);
-           Put_message(temp_buf);
+  char temp_buf[BUFSIZ];
+  int status;
+  char *args[10];
+
+  args[0] = current_list;
+  args[1] = NULL;
+
+  found_some = FALSE;
+  if ((status = do_mr_query(tags ? "get_tagged_members_of_list" :
+                           "get_members_of_list", CountArgs(args),
+                           args, PrintByType, type)))
+    com_err(program_name, status, " in ListMembersByType");
+  if (!found_some)
+    {
+      if (!type)
+       Put_message("List is empty (no members).");
+      else
+       {
+         sprintf(temp_buf, "No %s Members", type);
+         Put_message(temp_buf);
        }
     }
 }
 
 /*     Function Name: ListAllMembers
  *     Description: lists all members of the current list.
- *     Arguments: 
+ *     Arguments:
  *     Returns: DM_NORMAL
  */
 
-int
-ListAllMembers()
+int ListAllMembers(int argc, char **argv)
 {
-    ListMembersByType(NULL);
-    return (DM_NORMAL);
+  ListMembersByType(NULL, 0);
+  return DM_NORMAL;
 }
 
 /*     Function Name: ListUserMembers
@@ -517,10 +620,10 @@ ListAllMembers()
  *     Returns: DM_NORMAL.
  */
 
-ListUserMembers()
+int ListUserMembers(int argc, char **argv)
 {
-    ListMembersByType("USER");
-    return(DM_NORMAL);
+  ListMembersByType("USER", 0);
+  return DM_NORMAL;
 }
 
 /*     Function Name: ListListMembers
@@ -529,10 +632,10 @@ ListUserMembers()
  *     Returns: DM_NORMAL.
  */
 
-ListListMembers()
+int ListListMembers(int argc, char **argv)
 {
-    ListMembersByType("LIST");
-    return(DM_NORMAL);
+  ListMembersByType("LIST", 0);
+  return DM_NORMAL;
 }
 
 /*     Function Name: ListStringMembers
@@ -541,10 +644,10 @@ ListListMembers()
  *     Returns: DM_NORMAL.
  */
 
-ListStringMembers()
+int ListStringMembers(int argc, char **argv)
 {
-    ListMembersByType("STRING");
-    return(DM_NORMAL);
+  ListMembersByType("STRING", 0);
+  return DM_NORMAL;
 }
 
 /*     Function Name: GetMemberInfo
@@ -557,28 +660,30 @@ ListStringMembers()
  *     Returns: SUB_ERROR or SUB_NORMAL.
  */
 
-int
-GetMemberInfo(action, ret_argv)
-char *action, **ret_argv;
+int GetMemberInfo(char *action, char **ret_argv)
 {
-    char temp_buf[BUFSIZ], ret_buf[BUFSIZ];
-
-    ret_argv[LM_LIST] = Strsave(current_list);
-
-    ret_argv[LM_TYPE] = Strsave("user");
-    GetTypeFromUser("Type of member", "member", &ret_argv[LM_TYPE]);
-
-    sprintf(temp_buf,"Name of %s to %s", ret_argv[LM_TYPE], action);
-    ret_argv[LM_MEMBER] = Strsave(user);
-    GetValueFromUser(temp_buf, &ret_argv[LM_MEMBER]);
-    ret_argv[LM_END] = NULL;           /* NULL terminate this list. */
-
-    if (strcasecmp(ret_argv[LM_TYPE], "string") &&
-       !ValidName( ret_argv[LM_MEMBER] ) ) {
-       FreeInfo(ret_argv);
-       return(SUB_ERROR);
+  char temp_buf[BUFSIZ];
+
+  ret_argv[LM_LIST] = strdup(current_list);
+
+  ret_argv[LM_TYPE] = strdup("user");
+  if (GetTypeFromUser("Type of member", "member", &ret_argv[LM_TYPE]) ==
+      SUB_ERROR)
+    return SUB_ERROR;
+
+  sprintf(temp_buf, "Name of %s to %s", ret_argv[LM_TYPE], action);
+  ret_argv[LM_MEMBER] = strdup(user);
+  if (GetValueFromUser(temp_buf, &ret_argv[LM_MEMBER]) == SUB_ERROR)
+    return SUB_ERROR;
+  ret_argv[LM_END] = NULL;             /* NULL terminate this list. */
+
+  if (strcasecmp(ret_argv[LM_TYPE], "string") &&
+      !ValidName(ret_argv[LM_MEMBER]))
+    {
+      FreeInfo(ret_argv);
+      return SUB_ERROR;
     }
-    return(SUB_NORMAL);
+  return SUB_NORMAL;
 }
 
 /*     Function Name: AddMember
@@ -587,28 +692,49 @@ char *action, **ret_argv;
  *     Returns: DM_NORMAL.
  */
 
-int
-AddMember()
+int AddMember(int argc, char **argv)
 {
-    char *args[10], temp_buf[BUFSIZ];
-    register int status;
-
-    if ( GetMemberInfo("add", args) == SUB_ERROR )
-       return(DM_NORMAL);
-
-    if ( (status = do_sms_query("add_member_to_list", CountArgs(args), args,
-                          Scream, NULL)) != SMS_SUCCESS) {
-       if (status == SMS_EXISTS) {
-           sprintf(temp_buf, "The %s %s is already a member of LIST %s.",
-                   args[LM_TYPE], args[LM_MEMBER], args[LM_LIST]);
-           Put_message(temp_buf);
+  char *args[10], temp_buf[BUFSIZ], *p;
+  int status;
+  struct mqelem *mailhubs, *elem;
+
+  if (GetMemberInfo("add", args) == SUB_ERROR)
+    return DM_NORMAL;
+
+  if (!strcmp(args[LM_TYPE], "STRING"))
+    {
+      status = mrcl_validate_string_member(args[LM_MEMBER]);
+      if (status != MRCL_SUCCESS)
+       Put_message(mrcl_get_message());
+      if (status == MRCL_REJECT)
+       return DM_NORMAL;
+    }
+  else if (!strcmp(args[LM_TYPE], "KERBEROS"))
+    {
+      char *canon;
+
+      mrcl_validate_kerberos_member(args[LM_MEMBER], &canon);
+      if (mrcl_get_message())
+       Put_message(mrcl_get_message());
+      free(args[LM_MEMBER]);
+      args[LM_MEMBER] = canon;
+    }
+
+  if ((status = do_mr_query("add_member_to_list", CountArgs(args), args,
+                           NULL, NULL)) != MR_SUCCESS)
+    {
+      if (status == MR_EXISTS)
+       {
+         sprintf(temp_buf, "The %s %s is already a member of LIST %s.",
+                 args[LM_TYPE], args[LM_MEMBER], args[LM_LIST]);
+         Put_message(temp_buf);
        }
-       else 
-           com_err(program_name, status, " in AddMember");
+      else
+       com_err(program_name, status, " in AddMember");
     }
 
-    FreeInfo(args);
-    return(DM_NORMAL);
+  FreeInfo(args);
+  return DM_NORMAL;
 }
 
 /*     Function Name: DeleteMember
@@ -617,27 +743,89 @@ AddMember()
  *     Returns: DM_NORMAL
  */
 
-int
-DeleteMember()
+int DeleteMember(int argc, char **argv)
+{
+  char *args[10];
+  int status;
+
+  if (GetMemberInfo("delete", args) == SUB_ERROR)
+    return DM_NORMAL;
+
+  if (Confirm("Are you sure you want to delete this member?"))
+    {
+      if ((status = do_mr_query("delete_member_from_list", CountArgs(args),
+                               args, NULL, NULL)))
+       {
+         if ((status == MR_STRING || status == MR_NO_MATCH) &&
+             !strcmp(args[LM_TYPE], "KERBEROS"))
+           {
+             char *canon;
+             mrcl_validate_kerberos_member(args[LM_MEMBER], &canon);
+             if (mrcl_get_message())
+               {
+                 free(args[LM_MEMBER]);
+                 args[LM_MEMBER] = canon;
+                 if (do_mr_query("delete_member_from_list", CountArgs(args),
+                                 args, NULL, NULL) == MR_SUCCESS)
+                   {
+                     Put_message(mrcl_get_message());
+                     status = MR_SUCCESS;
+                   }
+               }
+           }
+       }
+      if (status)
+       com_err(program_name, status, " in DeleteMember");
+      else
+       Put_message("Deletion Completed.");
+    }
+  else
+    Put_message("Deletion has been Aborted.");
+
+  FreeInfo(args);
+  return DM_NORMAL;
+}
+
+/*     Function Name: TagMember
+ *     Description: Add a tag to a list member
+ *     Arguments:
+ *     Returns: DM_NORMAL
+ */
+
+int TagMember(int argc, char **argv)
 {
-    char *args[10];
-    register int status;
-
-    if( GetMemberInfo("delete", args) == SUB_ERROR )
-       return(DM_NORMAL);
-
-    if (Confirm("Are you sure you want to delete this member?") ) {
-       if (status = do_sms_query("delete_member_from_list", CountArgs(args),
-                              args, Scream, NULL))
-           com_err(program_name, status, " in DeleteMember");
-       else
-           Put_message("Deletion Completed.");
+  char *args[10];
+  int status;
+
+  if (GetMemberInfo("tag", args) == SUB_ERROR)
+    return DM_NORMAL;
+
+  args[LM_TAG] = strdup("");
+  if (GetValueFromUser("Tag" , &args[LM_TAG]) == SUB_ERROR)
+    {
+      Put_message("Aborted.");
+      return DM_NORMAL;
     }
-    else 
-       Put_message("Deletion has been Aborted.");
+  args[LM_TAG_END] = NULL;             /* NULL terminate this list. */
 
-    FreeInfo(args);
-    return(DM_NORMAL);
+  if ((status = do_mr_query("tag_member_of_list", CountArgs(args),
+                           args, NULL, NULL)))
+    com_err(program_name, status, " in TagMember");
+
+  FreeInfo(args);
+  return DM_NORMAL;
+}
+
+/*     Function Name: ListAllMembers
+ *     Description: lists all members of the current list.
+ *     Arguments:
+ *     Returns: DM_NORMAL
+ */
+
+int ListMembersWithTags(int argc, char **argv)
+{
+  ListMembersByType(NULL, 1);
+  return DM_NORMAL;
 }
 
 /*     Function Name: InterRemoveItemFromLists
@@ -649,54 +837,57 @@ DeleteMember()
  *             enough information in it to delete the member from the list.
  */
 
-int
-InterRemoveItemFromLists()
+int InterRemoveItemFromLists(int argc, char **argv)
 {
-    register int status;
-    char type[BUFSIZ], name[BUFSIZ], *args[10], buf[BUFSIZ];
-    struct qelem *top, *elem;
-
-    if ( !(PromptWithDefault("Type of member (user, list, string)", type, 
-                           BUFSIZ, "user")) )
-       return(DM_NORMAL);
-    
-    sprintf(buf, "Name of %s", type);
-    if ( !(PromptWithDefault(buf, name, BUFSIZ, user)) ) {
-       return(DM_NORMAL);
-    }
-
-    if (!ValidName(name))
-       return(DM_NORMAL);
-
-    top = elem = GetListInfo(GLOM, type, name);
-
-    while(elem != NULL) {
-       char line[BUFSIZ];
-       char ** info = (char **) elem->q_data;
-       sprintf(line, "Delete %s %s from the list \"%s\" (y/n/q)? ", type,
-               name, info[GLOM_NAME]);
-       switch (YesNoQuitQuestion(line, FALSE)) {
+  int status;
+  char *type, *name, *args[10], buf[BUFSIZ];
+  struct mqelem *top, *elem;
+
+  type = strdup("USER");
+  if (GetTypeFromUser("Type of member", "member", &type) == SUB_ERROR)
+    return DM_NORMAL;
+
+  sprintf(buf, "Name of %s", type);
+  name = strdup(user);
+  if (GetValueFromUser(buf, &name) == SUB_ERROR)
+    return DM_NORMAL;
+
+  if (!ValidName(name))
+    return DM_NORMAL;
+
+  top = elem = GetListInfo(GLOM, type, name);
+
+  while (elem)
+    {
+      char line[BUFSIZ];
+      char **info = elem->q_data;
+      sprintf(line, "Delete %s %s from the list \"%s\" (y/n/q)? ", type,
+             name, info[GLOM_NAME]);
+      switch (YesNoQuitQuestion(line, FALSE))
+       {
        case TRUE:
-           Put_message("deleting...");
-           args[DM_LIST] = info[GLOM_NAME];
-           args[DM_TYPE] = type;
-           args[DM_MEMBER] = name;
-           if ( (status = do_sms_query("delete_member_from_list", 3, args,
-                              Scream, (char *) NULL)) != 0)
-               /* should probabally check to delete list. */
-               com_err(program_name, status, " in delete_member");
-           break;
+         Put_message("deleting...");
+         args[DM_LIST] = info[GLOM_NAME];
+         args[DM_TYPE] = type;
+         args[DM_MEMBER] = name;
+         if ((status = do_mr_query("delete_member_from_list", 3, args,
+                                   NULL, NULL)))
+           {
+             /* should probabally check to delete list. */
+             com_err(program_name, status, " in delete_member");
+           }
+         break;
        case FALSE:
-           break;
+         break;
        default:
-           Put_message("Aborting...");
-           FreeQueue(top);
-           return(DM_NORMAL);
+         Put_message("Aborting...");
+         FreeQueue(top);
+         return DM_NORMAL;
        }
-       elem = elem->q_forw;
+      elem = elem->q_forw;
     }
-    FreeQueue(top);
-    return(DM_NORMAL);
+  FreeQueue(top);
+  return DM_NORMAL;
 }
 
 /*-*-* LIST MENU *-*-*/
@@ -707,43 +898,60 @@ InterRemoveItemFromLists()
  *     Returns: DM_NORMAL.
  */
 
-int
-ListByMember()
+int ListByMember(int argc, char **argv)
 {
-    char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name, **info;
-    Bool maillist, group;
-    struct qelem *top, *elem;
-
-    if ( !(PromptWithDefault("Type of member (user, list, string)", buf, 
-                           BUFSIZ, "user")) )
-       return(DM_NORMAL);
-
-    /* What we really want is a recursive search */
-    sprintf(temp_buf, "R%s", buf); 
-    type = Strsave(temp_buf);
-
-    sprintf(temp_buf, "Name of %s", buf);
-    if ( !(PromptWithDefault(temp_buf, buf, BUFSIZ, user)) ) {
-       free(type);
-       return(DM_NORMAL);
+  char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name, **info;
+  Bool maillist, group, neither;
+  struct mqelem *top, *elem;
+
+  type = strdup("USER");
+  if (GetTypeFromUser("Type of member", "member", &type) == SUB_ERROR)
+    return DM_NORMAL;
+
+  sprintf(buf, "Name of %s", type);
+  name = strdup(user);
+  if (GetValueFromUser(buf, &name) == SUB_ERROR)
+    return DM_NORMAL;
+
+  switch (YesNoQuestion("Do you want a recursive search (y/n)", TRUE))
+    {
+    case TRUE:
+      sprintf(temp_buf, "R%s", type);  /* "USER" to "RUSER" etc. */
+      free(type);
+      type = strdup(temp_buf);
+      break;
+    case FALSE:
+      break;
+    default:
+      return DM_NORMAL;
     }
-    name = Strsave(buf);
 
-    maillist = YesNoQuestion("Show Lists that are Maillists (y/n) ?",
-                            TRUE);
-    group = YesNoQuestion("Show Lists that are Groups (y/n) ?", TRUE);
-
-    elem = top = GetListInfo(GLOM, type, name);
-
-    while (elem != NULL) {
-       info = (char**) elem->q_data;
-       if ((maillist == TRUE && !strcmp(info[GLOM_MAILLIST], "1")) ||
-           (group == TRUE && !strcmp(info[GLOM_GROUP], "1")))
-               Put_message(info[GLOM_NAME]);
-       elem = elem->q_forw;
+  if ((maillist = YesNoQuestion("Show Lists that are Maillists (y/n) ?",
+                               TRUE)) == -1)
+    return DM_NORMAL;
+  if ((group = YesNoQuestion("Show Lists that are Groups (y/n) ?",
+                            TRUE)) == -1)
+    return DM_NORMAL;
+
+  if ((neither = YesNoQuestion("Show Lists that are neither Maillists nor Groups (y/n) ?",
+                              TRUE)) == -1)
+    return DM_NORMAL;
+
+  elem = top = GetListInfo(GLOM, type, name);
+
+  while (elem)
+    {
+      info = elem->q_data;
+      if ((maillist == TRUE && !strcmp(info[GLOM_MAILLIST], "1")) ||
+         (group == TRUE && !strcmp(info[GLOM_GROUP], "1")))
+       Put_message(info[GLOM_NAME]);
+      if (neither == TRUE && !strcmp(info[GLOM_MAILLIST], "0") &&
+          !strcmp(info[GLOM_GROUP], "0"))
+       Put_message(info[GLOM_NAME]);
+      elem = elem->q_forw;
     }
-    FreeQueue(top);
-    return (DM_NORMAL);
+  FreeQueue(top);
+  return DM_NORMAL;
 }
 
 /*     Function Name: ListByAdministrator
@@ -753,86 +961,38 @@ ListByMember()
  *     Returns: DM_NORMAL.
  */
 
-int
-ListByAdministrator()
+int ListByAdministrator(int argc, char **argv)
 {
-    char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
-    struct qelem *top;
-
-    if ( !(PromptWithDefault("Type of member (user, list, string)", buf, 
-                           BUFSIZ, "user")) )
-       return(DM_NORMAL);
-
-    if ( YesNoQuestion("Do you want a recursive search (y/n)", FALSE) == 1 ) {
-       sprintf(temp_buf, "R%s", buf);  /* "USER" to "RUSER" etc. */
-       type = Strsave(temp_buf);
-    }
-    else 
-       type = Strsave(buf);
-    
-    sprintf(temp_buf, "Name of %s", buf);
-    if ( !(PromptWithDefault(temp_buf, buf, BUFSIZ, user)) ) {
-       free(type);
-       return(DM_NORMAL);
+  char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
+  struct mqelem *top;
+
+  type = strdup("USER");
+  if (GetTypeFromUser("Type of member", "member", &type) == SUB_ERROR)
+    return DM_NORMAL;
+
+  sprintf(buf, "Name of %s", type);
+  name = strdup(user);
+  if (GetValueFromUser(buf, &name) == SUB_ERROR)
+    return DM_NORMAL;
+
+  switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE))
+    {
+    case TRUE:
+      sprintf(temp_buf, "R%s", type);  /* "USER" to "RUSER" etc. */
+      free(type);
+      type = strdup(temp_buf);
+      break;
+    case FALSE:
+      break;
+    default:
+      return DM_NORMAL;
     }
-    name = Strsave(buf);
 
-    top = GetListInfo(ACE_USE, type, name);
-    Loop(top, PrintListAce);
+  top = GetListInfo(ACE_USE, type, name);
+  Loop(top, PrintListAce);
 
-    FreeQueue(top);
-    return (DM_NORMAL);
-}
-
-/*     Function Name: ListAllGroups
- *     Description: This function lists all visable groups.
- *     Arguments: none.
- *     Returns: DM_NORMAL.
- */
-
-ListAllGroups()
-{
-    register int status;
-    static char * args[] = {
-       "TRUE",                 /* active */
-       "DONTCARE",             /* public */
-       "FALSE",                /* hidden */
-       "DONTCARE",             /* maillist */
-       "TRUE",                 /* group. */
-    };
-
-    if (YesNoQuestion("This query will take a while, Do you wish to continue?",
-                      TRUE) == TRUE )
-       if (status = do_sms_query("qualified_get_lists", 5, args,
-                              Print, (char *) NULL) != 0)
-           com_err(program_name, status, " in ListAllGroups");
-    return (DM_NORMAL);
-}
-
-/*     Function Name: ListAllMailLists
- *     Description: This function lists all visable maillists.
- *     Arguments: none
- *     Returns: DM_NORMAL.
- */
-
-ListAllMailLists()
-{
-    register int status;
-    static char * args[] = {
-       "TRUE",                 /* active */
-       "DONTCARE",             /* public */
-       "FALSE",                /* hidden */
-       "TRUE",                 /* maillist */
-       "DONTCARE",             /* group. */
-    };
-
-    if (YesNoQuestion("This query will take a while. Do you wish to continue?",
-                      TRUE) == TRUE )
-       if (status = do_sms_query("qualified_get_lists", 5, args,
-                              Print, (char *) NULL) != 0)
-           com_err(program_name, status, " in ListAllGroups");
-
-    return (DM_NORMAL);        
+  FreeQueue(top);
+  return DM_NORMAL;
 }
 
 /*     Function Name: ListAllPublicMailLists
@@ -841,22 +1001,24 @@ ListAllMailLists()
  *     Returns: DM_NORMAL.
  */
 
-ListAllPublicMailLists()
+int ListAllPublicMailLists(int argc, char **argv)
 {
-    register int status;
-    static char * args[] = {
-       "TRUE",                 /* active */
-       "TRUE",                 /* public */
-       "FALSE",                /* hidden */
-       "TRUE",                 /* maillist */
-       "DONTCARE",             /* group. */
-    };
-
-    if (YesNoQuestion("This query will take a while. Do you wish to continue?",
-                      TRUE) == TRUE )
-       if (status = do_sms_query("qualified_get_lists", 5, args,
-                              Print, (char *) NULL) != 0)
-           com_err(program_name, status, " in ListAllGroups");
-
-    return (DM_NORMAL);        
+  int status;
+  static char *args[] = {
+    "TRUE",                    /* active */
+    "TRUE",                    /* public */
+    "FALSE",                   /* hidden */
+    "TRUE",                    /* maillist */
+    "DONTCARE",                        /* group. */
+  };
+
+  if (YesNoQuestion("This query will take a while. Do you wish to continue?",
+                   TRUE) == TRUE)
+    {
+      if ((status = do_mr_query("qualified_get_lists", 5, args,
+                               Print, NULL)) != MR_SUCCESS)
+       com_err(program_name, status, " in ListAllGroups");
+    }
+
+  return DM_NORMAL;
 }
This page took 0.098107 seconds and 4 git commands to generate.