3 * Command line oriented Moira List tool.
5 * by Mark Rosenstein, September 1988.
7 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
8 * For copying and distribution information, please see the file
12 #include <mit-copyright.h>
14 #include <moira_site.h>
30 /* It is important to membercmp that M_USER < M_LIST < M_STRING */
37 /* argument parsing macro */
38 #define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
40 /* flags from command line */
41 int infoflg, verbose, syncflg, memberflg, recursflg, noauth;
42 int showusers, showstrings, showkerberos, showlists, showtags;
43 int createflag, setinfo, active, public, hidden, maillist, grouplist;
48 /* various member lists */
49 struct save_queue *addlist, *dellist, *memberlist, *synclist, *taglist;
51 char *listname, *whoami;
53 void usage(char **argv);
54 void show_list_member(struct member *memberstruct);
55 int show_list_info(int argc, char **argv, void *hint);
56 int save_list_info(int argc, char **argv, void *hint);
57 int show_list_count(int argc, char **argv, void *hint);
58 void recursive_display_list_members(void);
59 void unique_add_member(struct save_queue *q, struct member *m);
60 int get_list_members(int argc, char **argv, void *sq);
61 void get_members_from_file(char *filename, struct save_queue *queue);
62 int collect(int argc, char **argv, void *l);
63 struct member *parse_member(char *s);
64 int membercmp(const void *mem1, const void *mem2);
65 int sq_count_elts(struct save_queue *q);
66 char *get_username(void);
68 int main(int argc, char **argv)
73 struct member *memberstruct;
74 char *server = NULL, *p;
76 /* clear all flags & lists */
77 infoflg = verbose = syncflg = memberflg = recursflg = 0;
78 noauth = showusers = showstrings = showkerberos = showlists = 0;
79 createflag = setinfo = 0;
80 active = public = hidden = maillist = grouplist = nfsgroup = -1;
81 listname = newname = desc = NULL;
83 addlist = sq_create();
84 dellist = sq_create();
85 memberlist = sq_create();
86 synclist = sq_create();
87 taglist = sq_create();
92 /* parse args, building addlist, dellist, & synclist */
93 while (++arg - argv < argc)
97 if (argis("m", "members"))
99 else if (argis("u", "users"))
101 else if (argis("s", "strings"))
103 else if (argis("l", "lists"))
105 else if (argis("k", "kerberos"))
107 else if (argis("t", "tags"))
109 else if (argis("i", "info"))
111 else if (argis("n", "noauth"))
113 else if (argis("v", "verbose"))
115 else if (argis("r", "recursive"))
117 else if (argis("S", "server") || argis("db", "database"))
119 if (arg - argv < argc - 1)
127 else if (argis("a", "add"))
129 if (arg - argv < argc - 1)
132 if ((memberstruct = parse_member(*arg)))
133 sq_save_data(addlist, memberstruct);
138 else if (argis("at", "addtagged"))
140 if (arg - argv < argc - 2)
143 if ((memberstruct = parse_member(*arg)))
144 sq_save_data(addlist, memberstruct);
145 memberstruct->tag = *++arg;
150 else if (argis("al", "addlist"))
152 if (arg - argv < argc - 1)
155 get_members_from_file(*arg, addlist);
160 else if (argis("d", "delete"))
162 if (arg - argv < argc - 1)
165 if ((memberstruct = parse_member(*arg)))
166 sq_save_data(dellist, memberstruct);
171 else if (argis("dl", "deletelist"))
173 if (arg - argv < argc - 1)
176 get_members_from_file(*arg, dellist);
181 else if (argis("f", "file"))
183 if (arg - argv < argc - 1)
187 get_members_from_file(*arg, synclist);
192 else if (argis("ct", "changetag"))
194 if (arg - argv < argc - 2)
197 if ((memberstruct = parse_member(*arg)))
198 sq_save_data(taglist, memberstruct);
199 memberstruct->tag = *++arg;
204 else if (argis("C", "create"))
206 else if (argis("P", "public"))
211 else if (argis("NP", "private"))
216 else if (argis("A", "active"))
221 else if (argis("I", "inactive"))
226 else if (argis("V", "visible"))
231 else if (argis("H", "hidden"))
236 else if (argis("M", "mail"))
241 else if (argis("NM", "notmail"))
246 else if (argis("G", "group"))
251 else if (argis("NG", "notgroup"))
256 else if (argis("N", "nfs"))
261 else if (argis("NN", "notnfs"))
266 else if (argis("D", "desc"))
268 if (arg - argv < argc - 1)
277 else if (argis("O", "owner"))
279 if (arg - argv < argc - 1)
283 owner = parse_member(*arg);
288 else if (argis("R", "rename"))
290 if (arg - argv < argc - 1)
302 else if (listname == NULL)
307 if (listname == NULL)
310 /* if no other options specified, turn on list members flag */
311 if (!(infoflg || syncflg || createflag || setinfo ||
312 addlist->q_next != addlist || dellist->q_next != dellist ||
313 taglist->q_next != taglist))
316 /* If none of {users,strings,lists,kerberos} specified, turn them all on */
317 if (!(showusers || showstrings || showlists || showkerberos))
318 showusers = showstrings = showlists = showkerberos = 1;
321 status = mrcl_connect(server, "blanche", 3, !noauth);
322 if (status == MRCL_AUTH_ERROR)
324 com_err(whoami, 0, "Try the -noauth flag if you don't "
325 "need authentication.");
330 /* check for username/listname clash */
331 if (createflag || (setinfo && newname && strcmp(newname, listname)))
333 status = mr_query("get_user_account_by_login", 1,
334 createflag ? &listname : &newname,
336 if (status != MR_NO_MATCH)
337 fprintf(stderr, "WARNING: A user by that name already exists.\n");
340 /* create if needed */
345 argv[L_NAME] = listname;
346 argv[L_ACTIVE] = (active == 0) ? "0" : "1";
347 argv[L_PUBLIC] = (public == 1) ? "1" : "0";
348 argv[L_HIDDEN] = (hidden == 1) ? "1" : "0";
349 argv[L_MAILLIST] = (maillist == 0) ? "0" : "1";
350 argv[L_GROUP] = (grouplist == 1) ? "1" : "0";
351 argv[L_GID] = UNIQUE_GID;
352 argv[L_NFSGROUP] = (nfsgroup == 1) ? "1" : "0";
353 argv[L_DESC] = desc ? desc : "none";
357 argv[L_ACE_NAME] = owner->name;
362 argv[L_ACE_TYPE] = "USER";
363 status = mr_query("add_list", 11, argv, NULL, NULL);
364 if (owner->type != M_ANY || status != MR_USER)
368 argv[L_ACE_TYPE] = "LIST";
369 status = mr_query("add_list", 11, argv, NULL, NULL);
373 argv[L_ACE_TYPE] = "KERBEROS";
374 status = mr_query("add_list", 11, argv, NULL, NULL);
380 argv[L_ACE_TYPE] = "USER";
381 argv[L_ACE_NAME] = get_username();
383 status = mr_query("add_list", 11, argv, NULL, NULL);
388 com_err(whoami, status, "while creating list.");
396 status = mr_query("get_list_info", 1, &listname,
397 save_list_info, argv);
400 com_err(whoami, status, "while getting list information");
406 argv[L_NAME + 1] = newname;
408 argv[L_ACTIVE + 1] = active ? "1" : "0";
410 argv[L_PUBLIC + 1] = public ? "1" : "0";
412 argv[L_HIDDEN + 1] = hidden ? "1" : "0";
414 argv[L_MAILLIST + 1] = maillist ? "1" : "0";
416 argv[L_GROUP + 1] = grouplist ? "1" : "0";
418 argv[L_NFSGROUP + 1] = nfsgroup ? "1" : "0";
420 argv[L_DESC + 1] = desc;
424 argv[L_ACE_NAME + 1] = owner->name;
429 argv[L_ACE_TYPE + 1] = "USER";
430 status = mr_query("update_list", 12, argv, NULL, NULL);
431 if (owner->type != M_ANY || status != MR_USER)
435 argv[L_ACE_TYPE + 1] = "LIST";
436 status = mr_query("update_list", 12, argv, NULL, NULL);
440 argv[L_ACE_TYPE + 1] = "KERBEROS";
441 status = mr_query("update_list", 12, argv, NULL, NULL);
446 status = mr_query("update_list", 12, argv, NULL, NULL);
450 com_err(whoami, status, "while updating list.");
457 /* display list info if requested to */
460 status = mr_query("get_list_info", 1, &listname, show_list_info, NULL);
463 com_err(whoami, status, "while getting list information");
466 if (verbose && !memberflg)
468 status = mr_query("count_members_of_list", 1, &listname,
469 show_list_count, NULL);
472 com_err(whoami, status, "while getting list count");
478 /* if we're synchronizing to a file, we need to:
479 * get the current members of the list
480 * for each member of the sync file
481 * if they are on the list, remove them from the in-memory copy
482 * if they're not on the list, add them to add-list
483 * if anyone is left on the in-memory copy, put them on the delete-list
484 * lastly, reset memberlist so we can use it again later
488 status = mr_query("get_members_of_list", 1, &listname,
489 get_list_members, memberlist);
492 com_err(whoami, status, "getting members of list %s", listname);
495 while (sq_get_data(synclist, &memberstruct))
497 struct save_queue *q;
500 for (q = memberlist->q_next; q != memberlist; q = q->q_next)
502 if (membercmp(q->q_data, memberstruct) == 0)
504 q->q_prev->q_next = q->q_next;
505 q->q_next->q_prev = q->q_prev;
511 sq_save_data(addlist, memberstruct);
513 while (sq_get_data(memberlist, &memberstruct))
514 sq_save_data(dellist, memberstruct);
515 sq_destroy(memberlist);
516 memberlist = sq_create();
519 /* Process the add list */
520 while (sq_get_data(addlist, &memberstruct))
522 /* canonicalize string if necessary */
523 if (memberstruct->type != M_KERBEROS &&
524 (p = strchr(memberstruct->name, '@')))
526 char *host = canonicalize_hostname(strdup(++p));
527 static char **mailhubs = NULL;
536 mailhubs = malloc(sizeof(char *));
538 status = mr_query("get_alias", 3, argv, collect,
540 if (status != MR_SUCCESS && status != MR_NO_MATCH)
542 com_err(whoami, status,
543 " while reading list of MAILHUB servers");
547 for (i = 0; (p = mailhubs[i]); i++)
549 if (!strcasecmp(p, host))
551 host = strdup(memberstruct->name);
552 *(strchr(memberstruct->name, '@')) = 0;
553 if (memberstruct->type == M_STRING)
554 memberstruct->type = M_ANY;
555 fprintf(stderr, "Warning: \"%s\" converted to "
556 "\"%s\" because it is a local name.\n",
557 host, memberstruct->name);
563 /* now continue adding member */
564 membervec[0] = listname;
565 membervec[2] = memberstruct->name;
566 membervec[3] = memberstruct->tag;
569 printf("Adding member ");
570 show_list_member(memberstruct);
572 switch (memberstruct->type)
576 membervec[1] = "USER";
577 status = mr_query("add_tagged_member_to_list", 4, membervec,
579 if (status == MR_SUCCESS)
581 else if (status != MR_USER || memberstruct->type != M_ANY)
583 com_err(whoami, status, "while adding member %s to %s",
584 memberstruct->name, listname);
589 membervec[1] = "LIST";
590 status = mr_query("add_tagged_member_to_list", 4, membervec,
592 if (status == MR_SUCCESS)
594 if (!strcmp(membervec[0], get_username()))
596 fprintf(stderr, "\nWARNING: \"LIST:%s\" was just added "
597 "to list \"%s\".\n", membervec[2], membervec[0]);
598 fprintf(stderr, "If you meant to add yourself to the list "
599 "\"%s\", type:\n", membervec[2]);
600 fprintf(stderr, "\tblanche %s -d %s\t(to undo this)\n",
601 membervec[0], membervec[2]);
602 fprintf(stderr, "\tblanche %s -a %s\t(to add yourself to "
603 "that list)\n", membervec[2], membervec[0]);
607 else if (status != MR_LIST || memberstruct->type != M_ANY)
609 com_err(whoami, status, "while adding member %s to %s",
610 memberstruct->name, listname);
615 status = mrcl_validate_string_member(memberstruct->name);
616 if (status == MRCL_REJECT)
618 mrcl_com_err(whoami);
622 else if (memberstruct->type == M_ANY && status != MR_SUCCESS)
624 /* if user is trying to add something which isn't a
625 remote string, or a list, or a user, and didn't
626 explicitly specify `STRING:', it's probably a typo */
627 com_err(whoami, MR_NO_MATCH, "while adding member %s to %s",
628 memberstruct->name, listname);
633 membervec[1] = "STRING";
634 status = mr_query("add_tagged_member_to_list", 4, membervec,
636 if (status != MR_SUCCESS)
638 com_err(whoami, status, "while adding member %s to %s",
639 memberstruct->name, listname);
644 membervec[1] = "KERBEROS";
645 status = mrcl_validate_kerberos_member(membervec[2], &membervec[2]);
646 if (mrcl_get_message())
647 mrcl_com_err(whoami);
648 status = mr_query("add_tagged_member_to_list", 4, membervec,
650 if (status != MR_SUCCESS)
652 com_err(whoami, status, "while adding member %s to %s",
653 memberstruct->name, listname);
660 /* Process the delete list */
661 while (sq_get_data(dellist, &memberstruct))
663 membervec[0] = listname;
664 membervec[2] = memberstruct->name;
667 printf("Deleting member ");
668 show_list_member(memberstruct);
670 switch (memberstruct->type)
674 membervec[1] = "USER";
675 status = mr_query("delete_member_from_list", 3, membervec,
677 if (status == MR_SUCCESS)
679 else if ((status != MR_USER && status != MR_NO_MATCH) ||
680 memberstruct->type != M_ANY)
682 com_err(whoami, status, "while deleting member %s from %s",
683 memberstruct->name, listname);
688 membervec[1] = "LIST";
689 status = mr_query("delete_member_from_list", 3, membervec,
691 if (status == MR_SUCCESS)
693 else if ((status != MR_LIST && status != MR_NO_MATCH) ||
694 memberstruct->type != M_ANY)
696 if (status == MR_PERM && memberstruct->type == M_ANY &&
697 !strcmp(membervec[2], get_username()))
699 /* M_ANY means we've fallen through from the user
700 * case. The user is trying to remove himself from
701 * a list, but we got MR_USER or MR_NO_MATCH above,
702 * meaning he's not really on it, and we got MR_PERM
703 * when trying to remove LIST:$USER because he's not
704 * on the acl. That error is useless, so return
705 * MR_NO_MATCH instead. However, this will generate the
706 * wrong error if the user was trying to remove the list
707 * with his username from a list he doesn't administrate
708 * without explicitly specifying "list:".
710 status = MR_NO_MATCH;
712 com_err(whoami, status, "while deleting member %s from %s",
713 memberstruct->name, listname);
718 membervec[1] = "STRING";
719 status = mr_query("delete_member_from_list", 3, membervec,
721 if (status == MR_STRING && memberstruct->type == M_ANY)
723 com_err(whoami, 0, " Unable to find member %s to delete from %s",
724 memberstruct->name, listname);
726 if (!strcmp(membervec[0], get_username()))
728 fprintf(stderr, "(If you were trying to remove yourself "
729 "from the list \"%s\",\n", membervec[2]);
730 fprintf(stderr, "the correct command is \"blanche %s -d "
731 "%s\".)\n", membervec[2], membervec[0]);
734 else if (status != MR_SUCCESS)
736 com_err(whoami, status, "while deleting member %s from %s",
737 memberstruct->name, listname);
742 membervec[1] = "KERBEROS";
743 status = mr_query("delete_member_from_list", 3, membervec,
745 if (status == MR_STRING || status == MR_NO_MATCH)
747 /* Try canonicalizing the Kerberos principal and trying
748 * again. If we succeed, print the message from mrcl.
749 * Otherwise, just pretend we never did this and print
750 * the original error message.
752 mrcl_validate_kerberos_member(membervec[2], &membervec[2]);
753 if (mrcl_get_message())
755 if (mr_query("delete_member_from_list", 3, membervec,
756 NULL, NULL) == MR_SUCCESS)
757 mrcl_com_err(whoami);
761 if (status != MR_SUCCESS)
763 com_err(whoami, status, "while deleting member %s from %s",
764 memberstruct->name, listname);
770 /* Process the tag list */
771 while (sq_get_data(taglist, &memberstruct))
773 membervec[0] = listname;
774 membervec[2] = memberstruct->name;
775 membervec[3] = memberstruct->tag;
778 printf("Tagging member ");
779 show_list_member(memberstruct);
781 switch (memberstruct->type)
785 membervec[1] = "USER";
786 status = mr_query("tag_member_of_list", 4, membervec,
788 if (status == MR_SUCCESS)
790 else if ((status != MR_USER && status != MR_NO_MATCH) ||
791 memberstruct->type != M_ANY)
793 com_err(whoami, status, "while changing tag on member %s of %s",
794 memberstruct->name, listname);
799 membervec[1] = "LIST";
800 status = mr_query("tag_member_of_list", 4, membervec,
802 if (status == MR_SUCCESS)
804 else if ((status != MR_LIST && status != MR_NO_MATCH) ||
805 memberstruct->type != M_ANY)
807 com_err(whoami, status, "while changing tag on member %s of %s",
808 memberstruct->name, listname);
813 membervec[1] = "STRING";
814 status = mr_query("tag_member_of_list", 4, membervec,
816 if (status == MR_STRING && memberstruct->type == M_ANY)
818 com_err(whoami, 0, " Unable to find member %s on list %s",
819 memberstruct->name, listname);
822 else if (status != MR_SUCCESS)
824 com_err(whoami, status, "while retagging member %s on %s",
825 memberstruct->name, listname);
830 membervec[1] = "KERBEROS";
831 status = mr_query("tag_member_of_list", 4, membervec,
833 if (status == MR_STRING || status == MR_NO_MATCH)
835 /* Try canonicalizing the Kerberos principal and trying
836 * again. If we succeed, print the message from mrcl.
837 * Otherwise, just pretend we never did this and print
838 * the original error message.
840 mrcl_validate_kerberos_member(membervec[2], &membervec[2]);
841 if (mrcl_get_message())
843 if (mr_query("tag_member_of_list", 4, membervec,
844 NULL, NULL) == MR_SUCCESS)
845 mrcl_com_err(whoami);
849 if (status != MR_SUCCESS)
851 com_err(whoami, status, "while changing tag on member %s of %s",
852 memberstruct->name, listname);
858 /* Display the members of the list now, if requested */
862 recursive_display_list_members();
865 status = mr_query(showtags ? "get_tagged_members_of_list" :
866 "get_members_of_list", 1, &listname,
867 get_list_members, memberlist);
869 com_err(whoami, status, "while getting members of list %s",
871 while (sq_get_data(memberlist, &memberstruct))
872 show_list_member(memberstruct);
878 exit(success ? 0 : 1);
881 void usage(char **argv)
883 #define USAGE_OPTIONS_FORMAT " %-39s%s\n"
884 fprintf(stderr, "Usage: %s listname [options]\n", argv[0]);
885 fprintf(stderr, "Options are\n");
886 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-v | -verbose",
888 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-m | -members",
889 "-R | -rename newname");
890 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-u | -users",
892 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-l | -lists",
894 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-s | -strings",
896 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-k | -kerberos",
898 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-i | -info",
900 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-r | -recursive",
902 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-a | -add member",
904 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-d | -delete member",
906 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-al | -addlist filename",
908 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-dl | -deletelist filename",
910 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-f | -file filename",
912 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-at | -addtagged member tag",
914 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-ct | -changetag member tag",
915 "-D | -desc description");
916 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-t | -tags",
917 "-O | -owner owner");
918 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-n | -noauth",
919 "-db | -database host[:port]");
924 /* Display the members stored in the queue */
926 void show_list_member(struct member *memberstruct)
930 switch (memberstruct->type)
953 printf("%s\n", memberstruct->name);
958 printf("%s:%s", s, memberstruct->name);
961 if (memberstruct->type == M_LIST)
962 printf("LIST:%s", memberstruct->name);
963 else if (memberstruct->type == M_KERBEROS)
964 printf("KERBEROS:%s", memberstruct->name);
965 else if (memberstruct->type == M_STRING &&
966 !strchr(memberstruct->name, '@'))
967 printf("STRING:%s", memberstruct->name);
969 printf("%s", memberstruct->name);
971 if (showtags && *(memberstruct->tag))
972 printf(" (%s)\n", memberstruct->tag);
978 /* Show the retrieved information about a list */
980 int show_list_info(int argc, char **argv, void *hint)
982 printf("List: %s\n", argv[L_NAME]);
983 printf("Description: %s\n", argv[L_DESC]);
984 printf("Flags: %s, %s, and %s\n",
985 atoi(argv[L_ACTIVE]) ? "active" : "inactive",
986 atoi(argv[L_PUBLIC]) ? "public" : "private",
987 atoi(argv[L_HIDDEN]) ? "hidden" : "visible");
988 printf("%s is %sa maillist and is %sa group", argv[L_NAME],
989 atoi(argv[L_MAILLIST]) ? "" : "not ",
990 atoi(argv[L_GROUP]) ? "" : "not ");
991 if (atoi(argv[L_GROUP]))
993 if (atoi(argv[L_NFSGROUP]))
994 printf(" (and an NFS group)");
995 printf(" with GID %d\n", atoi(argv[L_GID]));
999 printf("Owner: %s %s\n", argv[L_ACE_TYPE], argv[L_ACE_NAME]);
1000 printf("Last modified by %s with %s on %s\n",
1001 argv[L_MODBY], argv[L_MODWITH], argv[L_MODTIME]);
1006 /* Copy retrieved information about a list into a new argv */
1008 int save_list_info(int argc, char **argv, void *hint)
1010 char **nargv = hint;
1012 for (argc = 0; argc < 11; argc++)
1013 nargv[argc + 1] = strdup(argv[argc]);
1017 /* Show the retrieve list member count */
1019 int show_list_count(int argc, char **argv, void *hint)
1021 printf("Members: %s\n", argv[0]);
1026 /* Recursively find all of the members of listname, and then display them */
1028 void recursive_display_list_members(void)
1030 int status, count, savecount;
1031 struct save_queue *lists, *members;
1032 struct member *m, *m1, *data;
1034 lists = sq_create();
1035 members = sq_create();
1036 m = malloc(sizeof(struct member));
1039 sq_save_data(lists, m);
1041 while (sq_get_data(lists, &m))
1043 sq_destroy(memberlist);
1044 memberlist = sq_create();
1045 status = mr_query("get_members_of_list", 1, &(m->name),
1046 get_list_members, memberlist);
1048 com_err(whoami, status, "while getting members of list %s", m->name);
1049 while (sq_get_data(memberlist, &m1))
1051 if (m1->type == M_LIST)
1052 unique_add_member(lists, m1);
1054 unique_add_member(members, m1);
1057 savecount = count = sq_count_elts(members);
1058 data = malloc(count * sizeof(struct member));
1060 while (sq_get_data(members, &m))
1061 memcpy(&data[count++], m, sizeof(struct member));
1062 qsort(data, count, sizeof(struct member), membercmp);
1063 for (count = 0; count < savecount; count++)
1064 show_list_member(&data[count]);
1068 /* add a struct member to a queue if that member isn't already there. */
1070 void unique_add_member(struct save_queue *q, struct member *m)
1072 struct save_queue *qp;
1074 for (qp = q->q_next; qp != q; qp = qp->q_next)
1076 if (!membercmp(qp->q_data, m))
1083 /* Collect the retrieved members of the list */
1085 int get_list_members(int argc, char **argv, void *sq)
1087 struct save_queue *q = sq;
1090 m = malloc(sizeof(struct member));
1103 m->type = M_KERBEROS;
1106 m->name = strdup(argv[1]);
1108 m->tag = strdup(argv[2]);
1110 m->tag = strdup("");
1116 /* Open file, parse members from file, and put them on the specified queue */
1117 void get_members_from_file(char *filename, struct save_queue *queue)
1121 struct member *memberstruct;
1123 if (!strcmp(filename, "-"))
1127 in = fopen(filename, "r");
1130 com_err(whoami, errno, "while opening %s for input", filename);
1135 while (fgets(buf, BUFSIZ, in))
1137 if ((memberstruct = parse_member(buf)))
1138 sq_save_data(queue, memberstruct);
1142 com_err(whoami, errno, "while reading from %s", filename);
1148 /* Collect the possible expansions of the alias MAILHUB */
1150 int collect(int argc, char **argv, void *l)
1155 for (i = 0; (*list)[i]; i++)
1157 *list = realloc(*list, (i + 2) * sizeof(char *));
1158 (*list)[i] = strdup(argv[2]);
1159 (*list)[i + 1] = NULL;
1164 /* Parse a line of input, fetching a member. NULL is returned if a member
1165 * is not found. ';' is a comment character.
1168 struct member *parse_member(char *s)
1173 while (*s && isspace(*s))
1176 while (*p && *p != '\n' && *p != ';')
1178 if (isprint(*p) && !isspace(*p))
1185 if (p == s || strlen(s) == 0)
1188 if (!(m = malloc(sizeof(struct member))))
1190 m->tag = strdup("");
1192 if ((p = strchr(s, ':')))
1196 if (!strcasecmp("user", s))
1198 else if (!strcasecmp("list", s))
1200 else if (!strcasecmp("string", s))
1202 else if (!strcasecmp("kerberos", s))
1203 m->type = M_KERBEROS;
1210 m->name = strdup(m->name);
1214 m->name = strdup(s);
1222 * This routine two compares members by the following rules:
1223 * 1. A USER is less than a LIST
1224 * 2. A LIST is less than a STRING
1225 * 3. If two members are of the same type, the one alphabetically first
1226 * is less than the other
1227 * It returs < 0 if the first member is less, 0 if they are identical, and
1228 * > 0 if the second member is less (the first member is greater).
1231 int membercmp(const void *mem1, const void *mem2)
1233 const struct member *m1 = mem1, *m2 = mem2;
1235 if (m1->type == M_ANY || m2->type == M_ANY || (m1->type == m2->type))
1236 return strcmp(m1->name, m2->name);
1238 return m1->type - m2->type;
1242 int sq_count_elts(struct save_queue *q)
1248 while (sq_get_data(q, &foo))
1253 char *get_username(void)
1257 username = getenv("USER");
1260 username = mrcl_krb_user();
1263 com_err(whoami, 0, "Could not determine username");