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.
8 * By: Chris D. Peterson
10 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
11 * For copying and distribution information, please see the file
15 #include <mit-copyright.h>
18 #include <moira_site.h>
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);
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
53 /* globals only for this file. */
55 static char current_list[BUFSIZ];
58 /* Function Name: PrintListAce
59 * Description: This function prints the list ace information.
60 * Arguments: info - an info structure.
64 static void PrintListAce(char **info)
68 sprintf(buf, "Item: %-20s Name: %s", info[ACE_TYPE], info[ACE_NAME]);
72 /* Function Name: PrintListInfo
73 * Description: This function Prints out the List info in a coherent form.
74 * Arguments: info - the List info.
78 static void PrintListInfo(char **info)
83 sprintf(buf, "%20sList: %s", "", info[L_NAME]);
85 sprintf(buf, "Description: %s", info[L_DESC]);
87 if (atoi(info[L_MAILLIST]))
88 Put_message("This list is a mailing list.");
90 Put_message("This list is NOT a mailing list.");
91 if (atoi(info[L_GROUP]))
93 sprintf(buf, "This list is a Group%s and its ID number is %s",
94 atoi(info[L_NFSGROUP]) ? " and an NFS Group," : "",
99 Put_message("This list is NOT a Group.");
101 if (!strcmp(info[L_ACE_TYPE], "NONE"))
102 Put_message("This list has no Administrator, how strange?!");
105 sprintf(buf, "The Administrator of this list is the %s: %s",
106 info[L_ACE_TYPE], info[L_ACE_NAME]);
110 if (strcmp(info[L_MEMACE_TYPE], "NONE"))
112 sprintf(buf, "The Membership Administrator of this list is the %s: %s",
113 info[L_MEMACE_TYPE], info[L_MEMACE_NAME]);
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");
122 sprintf(buf, MOD_FORMAT, info[L_MODBY], info[L_MODTIME], info[L_MODWITH]);
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.
133 struct mqelem *GetListInfo(int type, char *name1, char *name2)
136 struct mqelem *elem = NULL;
143 if ((status = do_mr_query("get_list_info", 1, args, StoreInfo, &elem)))
145 com_err(program_name, status, " in get_list_info");
151 if ((status = do_mr_query("get_members_of_list", 1, args,
154 com_err(program_name, status, " in get_members_of_list");
161 if (!strcmp(name1, "MACHINE"))
162 args[1] = canonicalize_hostname(strdup(name2));
163 if ((status = do_mr_query("get_lists_of_member", 2, args,
166 com_err(program_name, status, " in get_list_of_members");
173 if ((status = do_mr_query("get_ace_use", 2, args, StoreInfo, &elem)))
175 com_err(program_name, status, " in get_ace_use");
180 return QueueTop(elem);
183 /* Function Name: AskListInfo.
184 * Description: This function askes the user for information about a
185 * machine and saves it into a structure.
186 * Arguments: info - a pointer the the structure to put the
188 * name - add a newname field? (T/F)
189 * Returns: SUB_ERROR or SUB_NORMAL.
192 char **AskListInfo(char **info, Bool name)
194 char temp_buf[BUFSIZ], *newname;
197 sprintf(temp_buf, "Setting information of list %s.", info[L_NAME]);
198 Put_message(temp_buf);
205 newname = strdup(info[L_NAME]);
206 if (GetValueFromUser("The new name for this list", &newname) ==
209 if (ValidName(newname))
213 if (GetYesNoValueFromUser("Is this an active list", &info[L_ACTIVE]) ==
216 if (GetYesNoValueFromUser("Is this a public list", &info[L_PUBLIC]) ==
219 if (GetYesNoValueFromUser("Is this a hidden list", &info[L_HIDDEN]) ==
222 if (GetYesNoValueFromUser("Is this a maillist", &info[L_MAILLIST]) ==
225 if (GetYesNoValueFromUser("Is this a group", &info[L_GROUP]) == SUB_ERROR)
227 if (atoi(info[L_GROUP]))
229 if (GetYesNoValueFromUser("Is this an NFS group", &info[L_NFSGROUP]) ==
232 if (GetValueFromUser("What is the GID for this group.", &info[L_GID]) ==
238 if (GetTypeFromUser("What Type of Administrator", "ace_type",
239 &info[L_ACE_TYPE]) == SUB_ERROR)
241 if (strcasecmp(info[L_ACE_TYPE], "none"))
243 sprintf(temp_buf, "Which %s will be the administrator of this list: ",
245 if (GetValueFromUser(temp_buf, &info[L_ACE_NAME]) == SUB_ERROR)
250 Put_message("Setting the administrator of this list to 'NONE'");
251 Put_message("will make you unable to further modify the list.");
252 if (YesNoQuestion("Do you really want to do this?", FALSE) == TRUE)
255 } while (!strcasecmp(info[L_ACE_TYPE], "none"));
257 if (!strcasecmp(info[L_ACE_TYPE], "kerberos"))
261 mrcl_validate_kerberos_member(info[L_ACE_NAME], &canon);
262 if (mrcl_get_message())
263 Put_message(mrcl_get_message());
264 free(info[L_ACE_NAME]);
265 info[L_ACE_NAME] = canon;
267 if (GetTypeFromUser("What Type of Membership Administrator", "ace_type",
268 &info[L_MEMACE_TYPE]) == SUB_ERROR)
270 if (strcasecmp(info[L_MEMACE_TYPE], "none"))
272 sprintf(temp_buf, "Which %s will be the membership administrator of this list: ",
273 info[L_MEMACE_TYPE]);
274 if (GetValueFromUser(temp_buf, &info[L_MEMACE_NAME]) == SUB_ERROR)
277 if (!strcasecmp(info[L_MEMACE_TYPE], "kerberos"))
281 mrcl_validate_kerberos_member(info[L_MEMACE_NAME], &canon);
282 if (mrcl_get_message())
283 Put_message(mrcl_get_message());
284 free(info[L_MEMACE_NAME]);
285 info[L_MEMACE_NAME] = canon;
287 if (GetValueFromUser("Description: ", &info[L_DESC]) == SUB_ERROR)
290 FreeAndClear(&info[L_MODTIME], TRUE);
291 FreeAndClear(&info[L_MODBY], TRUE);
292 FreeAndClear(&info[L_MODWITH], TRUE);
294 * Slide the newname into the #2 slot, this screws up all future references
297 if (name) /* slide the newname into the #2 slot. */
298 SlipInNewName(info, newname);
303 /* -------------- List functions. -------------- */
305 /* Function Name: ShowListInfo.
306 * Description: shows info on a list.
307 * Arguments: argc, argv - name of list in argv[1].
308 * Returns: DM status code.
311 int ShowListInfo(int argc, char **argv)
313 struct mqelem *top, *list;
315 top = list = GetListInfo(LIST, argv[1], NULL);
318 PrintListInfo(list->q_data);
326 /* Function Name: RealUpdateList
327 * Description: performs the actual update of the list.
328 * Arguments: info - all information needed to update the list.
329 * junk - an UNUSED boolean.
333 static void RealUpdateList(char **info, Bool junk)
337 struct mqelem *elem = NULL;
339 if (!(args = AskListInfo(info, TRUE)))
341 Put_message("Aborted.");
346 * If the new list name is less than 8 characters, make sure it doesn't
347 * collide with a username.
349 if ((strlen(args[2]) <= 8) &&
350 do_mr_query("get_user_account_by_login", 1, args + 1,
351 StoreInfo, &elem) != MR_NO_MATCH)
355 sprintf(buf, "\nA user by the name `%s' already exists in the database.",
358 Loop(QueueTop(elem), FreeInfo);
360 if (YesNoQuestion("Do you still want to rename this list to that name",
363 Put_message("List ** NOT ** Updated.");
368 if ((stat = do_mr_query("update_list", CountArgs(args), args,
369 NULL, NULL)) != MR_SUCCESS)
371 com_err(program_name, stat, " in UpdateList.");
372 Put_message("List ** NOT ** Updated.");
375 Put_message("List successfully updated.");
378 /* Function Name: UpdateList
379 * Description: updates the information on a list.
380 * Arguments: argc, argv - name of list in argv[1].
381 * Returns: DM Status code.
384 int UpdateList(int argc, char **argv)
388 top = GetListInfo(LIST, argv[1], (char *) NULL);
389 QueryLoop(top, NullPrint, RealUpdateList, "Update the list");
395 /* Function Name: SetDefaults
396 * Description: sets defaults for AddList function
397 * Arguments: info - the array to add them to.
398 * name - name of the program to add.
399 * Returns: defaults - the default information.
402 static char **SetDefaults(char **info, char *name)
404 info[L_NAME] = strdup(name);
405 info[L_ACTIVE] = strdup(DEFAULT_ACTIVE);
406 info[L_PUBLIC] = strdup(DEFAULT_PUBLIC);
407 info[L_HIDDEN] = strdup(DEFAULT_HIDDEN);
408 info[L_MAILLIST] = strdup(DEFAULT_MAILLIST);
409 info[L_GROUP] = strdup(DEFAULT_GROUP);
410 info[L_GID] = strdup(DEFAULT_GID);
411 info[L_NFSGROUP] = strdup(DEFAULT_NFSGROUP);
412 info[L_ACE_TYPE] = strdup(DEFAULT_ACE_TYPE);
413 info[L_ACE_NAME] = strdup(DEFAULT_ACE_NAME);
414 info[L_MEMACE_TYPE] = strdup(DEFAULT_MEMACE_TYPE);
415 info[L_MEMACE_NAME] = strdup(DEFAULT_MEMACE_NAME);
416 info[L_DESC] = strdup(DEFAULT_DESCRIPTION);
417 info[L_MODTIME] = info[L_MODBY] = info[L_MODWITH] = info[L_END] = NULL;
421 /* Function Name: AddList
423 * Arguments: argc, argv - name of list in argv[1].
424 * Returns: SUB_ERROR if list not created.
427 int AddList(int argc, char **argv)
429 static char *info[MAX_ARGS_SIZE], **add_args;
430 int status, ret_code = SUB_NORMAL;
431 struct mqelem *elem = NULL;
433 if (!ValidName(argv[1]))
435 status = do_mr_query("get_list_info", 1, argv + 1, NULL, NULL);
436 if (status != MR_NO_MATCH)
438 if (status == MR_SUCCESS)
439 Put_message("This list already exists.");
441 com_err(program_name, status, " in AddList.");
445 if (status = mr_access("add_list", L_MODTIME, SetDefaults(info, argv[1])))
447 com_err(program_name, status, " in AddList.");
452 * If the listname is less than 8 characters, make sure it doesn't
453 * collide with a username.
455 if ((strlen(argv[1]) <= 8) &&
456 do_mr_query("get_user_account_by_login", 1, argv + 1,
457 StoreInfo, &elem) != MR_NO_MATCH)
461 sprintf(buf, "\nA user by the name `%s' already exists in the database.",
464 Loop(QueueTop(elem), FreeInfo);
466 if (YesNoQuestion("Create a list with the same name", FALSE) != TRUE)
470 if (!(add_args = AskListInfo(SetDefaults(info, argv[1]), FALSE)))
472 Put_message("Aborted.");
476 if ((status = do_mr_query("add_list", CountArgs(add_args), add_args,
477 NULL, NULL)) != MR_SUCCESS)
479 com_err(program_name, status, " in AddList.");
480 Put_message("List Not Created.");
481 ret_code = SUB_ERROR;
488 /* Function Name: Instructions
489 * Description: This func prints out instruction on manipulating lists.
491 * Returns: DM Status Code.
494 int ListHelp(int argc, char **argv)
496 static char *message[] = {
497 "Listmaint handles the creation, deletion, and updating of lists.",
498 "A list can be a mailing list, a group list, or both.",
499 "The concept behind lists is that a list has an owner",
500 "- administrator - and members.",
501 "The administrator of a list may be another list.",
502 "The members of a list can be users (login names), other lists,",
503 "or address strings.",
504 "You can use certain keys to do the following:",
505 " Refresh the screen - Type ctrl-L.",
506 " Escape from a function - Type ctrl-C.",
507 " Suspend the program (temporarily) - Type ctrl-Z.",
511 return PrintHelp(message);
514 /*-*-* LISTMAINT UPDATE MENU *-*-*/
516 /* Function Name: ListmaintMemberMenuEntry
517 * Description: entry routine into the listmaint member menu.
518 * Arguments: m - the member menu.
519 * argc, argv - name of the list in argv[1].
523 int ListmaintMemberMenuEntry(Menu *m, int argc, char **argv)
525 char temp_buf[BUFSIZ];
526 char *list_name = argv[1];
529 if (!ValidName(list_name))
534 if (AddList(argc, argv) == SUB_ERROR)
536 sprintf(temp_buf, "List '%s' created. Do you want to %s", list_name,
537 "change its membership (y/n)? ");
538 if (YesNoQuestion(temp_buf, TRUE) != TRUE)
542 /* All we want to know is if it exists. */
543 switch ((stat = do_mr_query("count_members_of_list", 1, argv + 1,
549 Put_message("This list does not exist.");
552 Put_message("You are not allowed to view this list.");
555 com_err(program_name, stat, " in get_list_info");
559 sprintf(temp_buf, "Change/Display membership of '%s'", list_name);
560 m->m_title = strdup(temp_buf);
561 strcpy(current_list, list_name);
565 /* Function Name: ListmaintMemberMenuExit
566 * Description: This is the function called when the member menu is
567 * exited, it frees the memory that is storing the name.
568 * Arguments: m - the menu
572 int ListmaintMemberMenuExit(Menu *m)
575 strcpy(current_list, "");
579 /* Function Name: ListMembersByType
580 * Description: This function lists the users of a list by type.
581 * Arguments: type - the type of the list "USER", "LIST", or "STRING".
582 * tags - whether or not to display tags
584 * NOTE: if type is NULL, all lists members are listed.
587 void ListMembersByType(char *type, int tags)
589 char temp_buf[BUFSIZ];
593 args[0] = current_list;
597 if ((status = do_mr_query(tags ? "get_tagged_members_of_list" :
598 "get_members_of_list", CountArgs(args),
599 args, PrintByType, type)))
600 com_err(program_name, status, " in ListMembersByType");
604 Put_message("List is empty (no members).");
607 sprintf(temp_buf, "No %s Members", type);
608 Put_message(temp_buf);
613 /* Function Name: ListAllMembers
614 * Description: lists all members of the current list.
619 int ListAllMembers(int argc, char **argv)
621 ListMembersByType(NULL, 0);
625 /* Function Name: ListUserMembers
626 * Description: This function lists all members of a list of type "USER".
628 * Returns: DM_NORMAL.
631 int ListUserMembers(int argc, char **argv)
633 ListMembersByType("USER", 0);
637 /* Function Name: ListListMembers
638 * Description: This function lists all members of a list of type "LIST".
640 * Returns: DM_NORMAL.
643 int ListListMembers(int argc, char **argv)
645 ListMembersByType("LIST", 0);
649 /* Function Name: ListStringMembers
650 * Description:This function lists all members of a list of type "STRING".
652 * Returns: DM_NORMAL.
655 int ListStringMembers(int argc, char **argv)
657 ListMembersByType("STRING", 0);
661 /* Function Name: GetMemberInfo
662 * Description: This function gets the information needed to
663 * add or delete a user from a list.
664 * Arguments: argc, argv - standard.
665 * action - name of the action to be performed either
667 * ret_argc, ret_argv - the returned value of argc and argv.
668 * Returns: SUB_ERROR or SUB_NORMAL.
671 int GetMemberInfo(char *action, char **ret_argv)
673 char temp_buf[BUFSIZ];
675 ret_argv[LM_LIST] = strdup(current_list);
677 ret_argv[LM_TYPE] = strdup("user");
678 if (GetTypeFromUser("Type of member", "member", &ret_argv[LM_TYPE]) ==
682 sprintf(temp_buf, "Name of %s to %s", ret_argv[LM_TYPE], action);
683 ret_argv[LM_MEMBER] = strdup(user);
684 if (GetValueFromUser(temp_buf, &ret_argv[LM_MEMBER]) == SUB_ERROR)
686 ret_argv[LM_END] = NULL; /* NULL terminate this list. */
688 if (strcasecmp(ret_argv[LM_TYPE], "string") &&
689 !ValidName(ret_argv[LM_MEMBER]))
697 /* Function Name: AddMember
698 * Description: This function adds a member to a list.
700 * Returns: DM_NORMAL.
703 int AddMember(int argc, char **argv)
705 char *args[10], temp_buf[BUFSIZ], *p;
707 struct mqelem *mailhubs, *elem;
709 if (GetMemberInfo("add", args) == SUB_ERROR)
712 if (!strcmp(args[LM_TYPE], "STRING"))
714 status = mrcl_validate_string_member(args[LM_MEMBER]);
715 if (status != MRCL_SUCCESS)
716 Put_message(mrcl_get_message());
717 if (status == MRCL_REJECT)
720 else if (!strcmp(args[LM_TYPE], "KERBEROS"))
724 mrcl_validate_kerberos_member(args[LM_MEMBER], &canon);
725 if (mrcl_get_message())
726 Put_message(mrcl_get_message());
727 free(args[LM_MEMBER]);
728 args[LM_MEMBER] = canon;
730 else if (!strcmp(args[LM_TYPE], "MACHINE"))
733 canon = canonicalize_hostname(strdup(args[LM_MEMBER]));
734 free(args[LM_MEMBER]);
735 args[LM_MEMBER] = canon;
738 if ((status = do_mr_query("add_member_to_list", CountArgs(args), args,
739 NULL, NULL)) != MR_SUCCESS)
741 if (status == MR_EXISTS)
743 sprintf(temp_buf, "The %s %s is already a member of LIST %s.",
744 args[LM_TYPE], args[LM_MEMBER], args[LM_LIST]);
745 Put_message(temp_buf);
748 com_err(program_name, status, " in AddMember");
755 /* Function Name: DeleteMember
756 * Description: This function deletes a member from a list.
761 int DeleteMember(int argc, char **argv)
766 if (GetMemberInfo("delete", args) == SUB_ERROR)
769 if (Confirm("Are you sure you want to delete this member?"))
771 if ((status = do_mr_query("delete_member_from_list", CountArgs(args),
774 if ((status == MR_STRING || status == MR_NO_MATCH) &&
775 !strcmp(args[LM_TYPE], "KERBEROS"))
778 mrcl_validate_kerberos_member(args[LM_MEMBER], &canon);
779 if (mrcl_get_message())
781 free(args[LM_MEMBER]);
782 args[LM_MEMBER] = canon;
783 if (do_mr_query("delete_member_from_list", CountArgs(args),
784 args, NULL, NULL) == MR_SUCCESS)
786 Put_message(mrcl_get_message());
791 else if ((status == MR_MACHINE || status == MR_NO_MATCH) &&
792 !strcmp(args[LM_TYPE], "MACHINE"))
795 canon = canonicalize_hostname(args[LM_MEMBER]);
796 free(args[LM_MEMBER]);
797 args[LM_MEMBER] = canon;
798 if (do_mr_query("delete_member_from_list", CountArgs(args),
799 args, NULL, NULL) == MR_SUCCESS)
804 com_err(program_name, status, " in DeleteMember");
806 Put_message("Deletion Completed.");
809 Put_message("Deletion has been Aborted.");
815 /* Function Name: TagMember
816 * Description: Add a tag to a list member
821 int TagMember(int argc, char **argv)
826 if (GetMemberInfo("tag", args) == SUB_ERROR)
829 args[LM_TAG] = strdup("");
830 if (GetValueFromUser("Tag" , &args[LM_TAG]) == SUB_ERROR)
832 Put_message("Aborted.");
835 args[LM_TAG_END] = NULL; /* NULL terminate this list. */
837 if ((status = do_mr_query("tag_member_of_list", CountArgs(args),
839 com_err(program_name, status, " in TagMember");
845 /* Function Name: ListAllMembers
846 * Description: lists all members of the current list.
851 int ListMembersWithTags(int argc, char **argv)
853 ListMembersByType(NULL, 1);
857 /* Function Name: InterRemoveItemFromLists
858 * Description: This function allows interactive removal of an item
859 * (user, string, list) for all list that it is on.
861 * Returns: DM_NORMAL.
862 * NOTES: QueryLoop() does not work here because info does not have
863 * enough information in it to delete the member from the list.
866 int InterRemoveItemFromLists(int argc, char **argv)
869 char *type, *name, *args[10], buf[BUFSIZ];
870 struct mqelem *top, *elem;
872 type = strdup("USER");
873 if (GetTypeFromUser("Type of member", "member", &type) == SUB_ERROR)
876 sprintf(buf, "Name of %s", type);
878 if (GetValueFromUser(buf, &name) == SUB_ERROR)
881 if (!ValidName(name))
884 top = elem = GetListInfo(GLOM, type, name);
889 char **info = elem->q_data;
890 sprintf(line, "Delete %s %s from the list \"%s\" (y/n/q)? ", type,
891 name, info[GLOM_NAME]);
892 switch (YesNoQuitQuestion(line, FALSE))
895 Put_message("deleting...");
896 args[DM_LIST] = info[GLOM_NAME];
897 args[DM_TYPE] = type;
898 args[DM_MEMBER] = name;
899 if (!strcmp("MACHINE", type))
900 args[DM_MEMBER] = canonicalize_hostname(strdup(name));
901 if ((status = do_mr_query("delete_member_from_list", 3, args,
904 /* should probabally check to delete list. */
905 com_err(program_name, status, " in delete_member");
911 Put_message("Aborting...");
921 /*-*-* LIST MENU *-*-*/
923 /* Function Name: ListByMember
924 * Description: This gets all lists that a given member is a member of.
926 * Returns: DM_NORMAL.
929 int ListByMember(int argc, char **argv)
931 char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name, **info;
932 Bool maillist, group, neither;
933 struct mqelem *top, *elem;
935 type = strdup("USER");
936 if (GetTypeFromUser("Type of member", "member", &type) == SUB_ERROR)
939 sprintf(buf, "Name of %s", type);
941 if (GetValueFromUser(buf, &name) == SUB_ERROR)
944 switch (YesNoQuestion("Do you want a recursive search (y/n)", TRUE))
947 sprintf(temp_buf, "R%s", type); /* "USER" to "RUSER" etc. */
949 type = strdup(temp_buf);
957 if ((maillist = YesNoQuestion("Show Lists that are Maillists (y/n) ?",
960 if ((group = YesNoQuestion("Show Lists that are Groups (y/n) ?",
964 if ((neither = YesNoQuestion("Show Lists that are neither Maillists nor Groups (y/n) ?",
968 elem = top = GetListInfo(GLOM, type, name);
973 if ((maillist == TRUE && !strcmp(info[GLOM_MAILLIST], "1")) ||
974 (group == TRUE && !strcmp(info[GLOM_GROUP], "1")))
975 Put_message(info[GLOM_NAME]);
976 if (neither == TRUE && !strcmp(info[GLOM_MAILLIST], "0") &&
977 !strcmp(info[GLOM_GROUP], "0"))
978 Put_message(info[GLOM_NAME]);
985 /* Function Name: ListByAdministrator
986 * Description: This function prints all lists which a given user or
989 * Returns: DM_NORMAL.
992 int ListByAdministrator(int argc, char **argv)
994 char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
997 type = strdup("USER");
998 if (GetTypeFromUser("Type of member", "member", &type) == SUB_ERROR)
1001 sprintf(buf, "Name of %s", type);
1002 name = strdup(user);
1003 if (GetValueFromUser(buf, &name) == SUB_ERROR)
1006 switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE))
1009 sprintf(temp_buf, "R%s", type); /* "USER" to "RUSER" etc. */
1011 type = strdup(temp_buf);
1019 top = GetListInfo(ACE_USE, type, name);
1020 Loop(top, PrintListAce);
1026 /* Function Name: ListAllPublicMailLists
1027 * Description: This function lists all public mailing lists.
1029 * Returns: DM_NORMAL.
1032 int ListAllPublicMailLists(int argc, char **argv)
1035 static char *args[] = {
1036 "TRUE", /* active */
1037 "TRUE", /* public */
1038 "FALSE", /* hidden */
1039 "TRUE", /* maillist */
1040 "DONTCARE", /* group. */
1043 if (YesNoQuestion("This query will take a while. Do you wish to continue?",
1046 if ((status = do_mr_query("qualified_get_lists", 5, args,
1047 Print, NULL)) != MR_SUCCESS)
1048 com_err(program_name, status, " in ListAllGroups");