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 if (memberstruct->type == M_ANY &&
616 !strchr(memberstruct->name, '@') &&
617 !strchr(memberstruct->name, '!') &&
618 !strchr(memberstruct->name, '%'))
620 /* if user is trying to add something which isn't a
621 remote string, or a list, or a user, and didn't
622 explicitly specify `STRING:', it's probably a typo */
623 com_err(whoami, MR_NO_MATCH, "while adding member %s to %s",
624 memberstruct->name, listname);
629 membervec[1] = "STRING";
630 status = mr_query("add_tagged_member_to_list", 4, membervec,
632 if (status != MR_SUCCESS)
634 com_err(whoami, status, "while adding member %s to %s",
635 memberstruct->name, listname);
640 membervec[1] = "KERBEROS";
641 status = mr_query("add_tagged_member_to_list", 4, membervec,
643 if (status != MR_SUCCESS)
645 com_err(whoami, status, "while adding member %s to %s",
646 memberstruct->name, listname);
652 /* Process the delete list */
653 while (sq_get_data(dellist, &memberstruct))
655 membervec[0] = listname;
656 membervec[2] = memberstruct->name;
659 printf("Deleting member ");
660 show_list_member(memberstruct);
662 switch (memberstruct->type)
666 membervec[1] = "USER";
667 status = mr_query("delete_member_from_list", 3, membervec,
669 if (status == MR_SUCCESS)
671 else if ((status != MR_USER && status != MR_NO_MATCH) ||
672 memberstruct->type != M_ANY)
674 com_err(whoami, status, "while deleting member %s from %s",
675 memberstruct->name, listname);
680 membervec[1] = "LIST";
681 status = mr_query("delete_member_from_list", 3, membervec,
683 if (status == MR_SUCCESS)
685 else if ((status != MR_LIST && status != MR_NO_MATCH) ||
686 memberstruct->type != M_ANY)
688 if (status == MR_PERM && memberstruct->type == M_ANY &&
689 !strcmp(membervec[2], get_username()))
691 /* M_ANY means we've fallen through from the user
692 * case. The user is trying to remove himself from
693 * a list, but we got MR_USER or MR_NO_MATCH above,
694 * meaning he's not really on it, and we got MR_PERM
695 * when trying to remove LIST:$USER because he's not
696 * on the acl. That error is useless, so return
697 * MR_NO_MATCH instead. However, this will generate the
698 * wrong error if the user was trying to remove the list
699 * with his username from a list he doesn't administrate
700 * without explicitly specifying "list:".
702 status = MR_NO_MATCH;
704 com_err(whoami, status, "while deleting member %s from %s",
705 memberstruct->name, listname);
710 membervec[1] = "STRING";
711 status = mr_query("delete_member_from_list", 3, membervec,
713 if (status == MR_STRING && memberstruct->type == M_ANY)
715 com_err(whoami, 0, " Unable to find member %s to delete from %s",
716 memberstruct->name, listname);
718 if (!strcmp(membervec[0], get_username()))
720 fprintf(stderr, "(If you were trying to remove yourself "
721 "from the list \"%s\",\n", membervec[2]);
722 fprintf(stderr, "the correct command is \"blanche %s -d "
723 "%s\".)\n", membervec[2], membervec[0]);
726 else if (status != MR_SUCCESS)
728 com_err(whoami, status, "while deleting member %s from %s",
729 memberstruct->name, listname);
734 membervec[1] = "KERBEROS";
735 status = mr_query("delete_member_from_list", 3, membervec,
737 if (status != MR_SUCCESS)
739 com_err(whoami, status, "while deleting member %s from %s",
740 memberstruct->name, listname);
746 /* Process the tag list */
747 while (sq_get_data(taglist, &memberstruct))
749 membervec[0] = listname;
750 membervec[2] = memberstruct->name;
751 membervec[3] = memberstruct->tag;
754 printf("Tagging member ");
755 show_list_member(memberstruct);
757 switch (memberstruct->type)
761 membervec[1] = "USER";
762 status = mr_query("tag_member_of_list", 4, membervec,
764 if (status == MR_SUCCESS)
766 else if ((status != MR_USER && status != MR_NO_MATCH) ||
767 memberstruct->type != M_ANY)
769 com_err(whoami, status, "while changing tag on member %s of %s",
770 memberstruct->name, listname);
775 membervec[1] = "LIST";
776 status = mr_query("tag_member_of_list", 4, membervec,
778 if (status == MR_SUCCESS)
780 else if ((status != MR_LIST && status != MR_NO_MATCH) ||
781 memberstruct->type != M_ANY)
783 com_err(whoami, status, "while changing tag on member %s of %s",
784 memberstruct->name, listname);
789 membervec[1] = "STRING";
790 status = mr_query("tag_member_of_list", 4, membervec,
792 if (status == MR_STRING && memberstruct->type == M_ANY)
794 com_err(whoami, 0, " Unable to find member %s on list %s",
795 memberstruct->name, listname);
798 else if (status != MR_SUCCESS)
800 com_err(whoami, status, "while retagging member %s on %s",
801 memberstruct->name, listname);
806 membervec[1] = "KERBEROS";
807 status = mr_query("tag_member_of_list", 4, membervec,
809 if (status != MR_SUCCESS)
811 com_err(whoami, status, "while changing tag on member %s of %s",
812 memberstruct->name, listname);
819 /* Display the members of the list now, if requested */
823 recursive_display_list_members();
826 status = mr_query(showtags ? "get_tagged_members_of_list" :
827 "get_members_of_list", 1, &listname,
828 get_list_members, memberlist);
830 com_err(whoami, status, "while getting members of list %s",
832 while (sq_get_data(memberlist, &memberstruct))
833 show_list_member(memberstruct);
839 exit(success ? 0 : 1);
842 void usage(char **argv)
844 #define USAGE_OPTIONS_FORMAT " %-39s%s\n"
845 fprintf(stderr, "Usage: %s listname [options]\n", argv[0]);
846 fprintf(stderr, "Options are\n");
847 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-v | -verbose",
849 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-m | -members",
850 "-R | -rename newname");
851 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-u | -users",
853 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-l | -lists",
855 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-s | -strings",
857 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-k | -kerberos",
859 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-i | -info",
861 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-r | -recursive",
863 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-a | -add member",
865 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-d | -delete member",
867 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-al | -addlist filename",
869 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-dl | -deletelist filename",
871 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-f | -file filename",
873 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-at | -addtagged member tag",
875 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-ct | -changetag member tag",
876 "-D | -desc description");
877 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-t | -tags",
878 "-O | -owner owner");
879 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-n | -noauth",
880 "-db | -database host[:port]");
885 /* Display the members stored in the queue */
887 void show_list_member(struct member *memberstruct)
891 switch (memberstruct->type)
914 printf("%s\n", memberstruct->name);
919 printf("%s:%s", s, memberstruct->name);
922 if (memberstruct->type == M_LIST)
923 printf("LIST:%s", memberstruct->name);
924 else if (memberstruct->type == M_KERBEROS)
925 printf("KERBEROS:%s", memberstruct->name);
926 else if (memberstruct->type == M_STRING &&
927 !strchr(memberstruct->name, '@'))
928 printf("STRING:%s", memberstruct->name);
930 printf("%s", memberstruct->name);
932 if (showtags && *(memberstruct->tag))
933 printf(" (%s)\n", memberstruct->tag);
939 /* Show the retrieved information about a list */
941 int show_list_info(int argc, char **argv, void *hint)
943 printf("List: %s\n", argv[L_NAME]);
944 printf("Description: %s\n", argv[L_DESC]);
945 printf("Flags: %s, %s, and %s\n",
946 atoi(argv[L_ACTIVE]) ? "active" : "inactive",
947 atoi(argv[L_PUBLIC]) ? "public" : "private",
948 atoi(argv[L_HIDDEN]) ? "hidden" : "visible");
949 printf("%s is %sa maillist and is %sa group", argv[L_NAME],
950 atoi(argv[L_MAILLIST]) ? "" : "not ",
951 atoi(argv[L_GROUP]) ? "" : "not ");
952 if (atoi(argv[L_GROUP]))
954 if (atoi(argv[L_NFSGROUP]))
955 printf(" (and an NFS group)");
956 printf(" with GID %d\n", atoi(argv[L_GID]));
960 printf("Owner: %s %s\n", argv[L_ACE_TYPE], argv[L_ACE_NAME]);
961 printf("Last modified by %s with %s on %s\n",
962 argv[L_MODBY], argv[L_MODWITH], argv[L_MODTIME]);
967 /* Copy retrieved information about a list into a new argv */
969 int save_list_info(int argc, char **argv, void *hint)
973 for (argc = 0; argc < 11; argc++)
974 nargv[argc + 1] = strdup(argv[argc]);
978 /* Show the retrieve list member count */
980 int show_list_count(int argc, char **argv, void *hint)
982 printf("Members: %s\n", argv[0]);
987 /* Recursively find all of the members of listname, and then display them */
989 void recursive_display_list_members(void)
991 int status, count, savecount;
992 struct save_queue *lists, *members;
993 struct member *m, *m1, *data;
996 members = sq_create();
997 m = malloc(sizeof(struct member));
1000 sq_save_data(lists, m);
1002 while (sq_get_data(lists, &m))
1004 sq_destroy(memberlist);
1005 memberlist = sq_create();
1006 status = mr_query("get_members_of_list", 1, &(m->name),
1007 get_list_members, memberlist);
1009 com_err(whoami, status, "while getting members of list %s", m->name);
1010 while (sq_get_data(memberlist, &m1))
1012 if (m1->type == M_LIST)
1013 unique_add_member(lists, m1);
1015 unique_add_member(members, m1);
1018 savecount = count = sq_count_elts(members);
1019 data = malloc(count * sizeof(struct member));
1021 while (sq_get_data(members, &m))
1022 memcpy(&data[count++], m, sizeof(struct member));
1023 qsort(data, count, sizeof(struct member), membercmp);
1024 for (count = 0; count < savecount; count++)
1025 show_list_member(&data[count]);
1029 /* add a struct member to a queue if that member isn't already there. */
1031 void unique_add_member(struct save_queue *q, struct member *m)
1033 struct save_queue *qp;
1035 for (qp = q->q_next; qp != q; qp = qp->q_next)
1037 if (!membercmp(qp->q_data, m))
1044 /* Collect the retrieved members of the list */
1046 int get_list_members(int argc, char **argv, void *sq)
1048 struct save_queue *q = sq;
1051 m = malloc(sizeof(struct member));
1064 m->type = M_KERBEROS;
1067 m->name = strdup(argv[1]);
1069 m->tag = strdup(argv[2]);
1071 m->tag = strdup("");
1077 /* Open file, parse members from file, and put them on the specified queue */
1078 void get_members_from_file(char *filename, struct save_queue *queue)
1082 struct member *memberstruct;
1084 if (!strcmp(filename, "-"))
1088 in = fopen(filename, "r");
1091 com_err(whoami, errno, "while opening %s for input", filename);
1096 while (fgets(buf, BUFSIZ, in))
1098 if ((memberstruct = parse_member(buf)))
1099 sq_save_data(queue, memberstruct);
1103 com_err(whoami, errno, "while reading from %s", filename);
1109 /* Collect the possible expansions of the alias MAILHUB */
1111 int collect(int argc, char **argv, void *l)
1116 for (i = 0; (*list)[i]; i++)
1118 *list = realloc(*list, (i + 2) * sizeof(char *));
1119 (*list)[i] = strdup(argv[2]);
1120 (*list)[i + 1] = NULL;
1125 /* Parse a line of input, fetching a member. NULL is returned if a member
1126 * is not found. ';' is a comment character.
1129 struct member *parse_member(char *s)
1134 while (*s && isspace(*s))
1137 while (*p && *p != '\n' && *p != ';')
1139 if (isprint(*p) && !isspace(*p))
1146 if (p == s || strlen(s) == 0)
1149 if (!(m = malloc(sizeof(struct member))))
1151 m->tag = strdup("");
1153 if ((p = strchr(s, ':')))
1157 if (!strcasecmp("user", s))
1159 else if (!strcasecmp("list", s))
1161 else if (!strcasecmp("string", s))
1163 else if (!strcasecmp("kerberos", s))
1164 m->type = M_KERBEROS;
1171 m->name = strdup(m->name);
1175 m->name = strdup(s);
1183 * This routine two compares members by the following rules:
1184 * 1. A USER is less than a LIST
1185 * 2. A LIST is less than a STRING
1186 * 3. If two members are of the same type, the one alphabetically first
1187 * is less than the other
1188 * It returs < 0 if the first member is less, 0 if they are identical, and
1189 * > 0 if the second member is less (the first member is greater).
1192 int membercmp(const void *mem1, const void *mem2)
1194 const struct member *m1 = mem1, *m2 = mem2;
1196 if (m1->type == M_ANY || m2->type == M_ANY || (m1->type == m2->type))
1197 return strcmp(m1->name, m2->name);
1199 return m1->type - m2->type;
1203 int sq_count_elts(struct save_queue *q)
1209 while (sq_get_data(q, &foo))
1214 char *get_username(void)
1218 username = getenv("USER");
1221 username = mrcl_krb_user();
1224 com_err(whoami, 0, "Could not determine username");