3 * Command line oriented Moira List tool.
5 * by Mark Rosenstein, September 1988.
7 * Copyright 1989 by the Massachusetts Institute of Technology.
9 * (c) Copyright 1988 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, please see the file
14 /* ### Aren't there a lot of sq abstraction barrier violations here?
15 Do we need to improve the support for queue operations? */
17 #include <mit-copyright.h>
21 #include <moira_site.h>
24 static char blanche_rcsid[] = "$Header$";
33 /* It is important to membercmp that M_USER < M_LIST < M_STRING */
40 /* argument parsing macro */
41 #define argis(a,b) ((strcmp(*arg+1, a) == 0) || (strcmp(*arg+1, b) == 0))
43 /* flags from command line */
44 int infoflg, verbose, syncflg, memberflg, recursflg, debugflg, noauth;
45 int showusers, showstrings, showkerberos, showlists;
47 /* various member lists */
48 struct save_queue *addlist, *dellist, *memberlist, *synclist;
50 char *listname, *whoami;
55 int show_list_info(), show_list_count(), get_list_members(), scream();
56 int show_list_members();
57 struct member *parse_member();
67 char *membervec[3], *motd;
68 struct member *memberstruct;
71 /* clear all flags & lists */
72 infoflg = verbose = syncflg = memberflg = debugflg = recursflg = 0;
73 noauth = showusers = showstrings = showkerberos = showlists = 0;
75 addlist = sq_create();
76 dellist = sq_create();
77 memberlist = sq_create();
78 synclist = sq_create();
81 /* parse args, building addlist, dellist, & synclist */
82 while (++arg - argv < argc) {
85 if (argis("m", "members"))
87 else if (argis("u", "users"))
89 else if (argis("s", "strings"))
91 else if (argis("l", "lists"))
93 else if (argis("k", "kerberos"))
95 else if (argis("D", "debug"))
97 else if (argis("i","info"))
99 else if (argis("n","noauth"))
101 else if (argis("v","verbose"))
103 else if (argis("r","recursive"))
105 else if (argis("S","server"))
106 if (arg - argv < argc - 1) {
111 else if (argis("a","add"))
112 if (arg - argv < argc - 1) {
114 if (memberstruct = parse_member(*arg))
115 sq_save_data(addlist, memberstruct);
118 else if (argis("d","delete"))
119 if (arg - argv < argc - 1) {
121 if (memberstruct = parse_member(*arg))
122 sq_save_data(dellist, memberstruct);
125 else if (argis("f","file"))
126 if (arg - argv < argc - 1) {
132 if (!strcmp(*arg, "-"))
135 in = fopen(*arg, "r");
137 com_err(whoami, errno,
138 "while opening %s for input", *arg);
142 while (fgets(buf, BUFSIZ, in))
143 if (memberstruct = parse_member(buf))
144 sq_save_data(synclist, memberstruct);
146 com_err(whoami, errno, "while reading from %s", *arg);
152 else if (listname == NULL)
157 if (listname == NULL)
160 /* if no other options specified, turn on list members flag */
161 if (!(infoflg || syncflg ||
162 addlist->q_next != addlist || dellist->q_next != dellist))
165 /* If none of {users,strings,lists,kerberos} specified, turn them all on */
166 if (!(showusers || showstrings || showlists || showkerberos))
167 showusers = showstrings = showlists = showkerberos = 1;
170 if (status = mr_connect(server)) {
171 com_err(whoami, status, "unable to connect to the Moira server");
174 if ( status = mr_motd(&motd) ) {
175 com_err(whoami, status, "unable to check server status");
179 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n", motd);
184 if (!noauth && (status = mr_auth("blanche"))) {
185 if (status == MR_USER_AUTH)
186 com_err(whoami, status, "");
188 com_err(whoami, status, "unable to authenticate to Moira");
190 " Try the -noauth flag if you don't need authentication");
195 /* display list info if requested to */
197 status = mr_query("get_list_info", 1, &listname, show_list_info,NULL);
199 com_err(whoami, status, "while getting list information");
200 if (verbose && !memberflg) {
201 status = mr_query("count_members_of_list", 1, &listname,
202 show_list_count, NULL);
204 com_err(whoami, status, "while getting list count");
208 /* if we're synchronizing to a file, we need to:
209 * get the current members of the list
210 * for each member of the sync file
211 * if they are on the list, remove them from the in-memory copy
212 * if they're not on the list, add them to add-list
213 * if anyone is left on the in-memory copy, put them on the delete-list
214 * lastly, reset memberlist so we can use it again later
217 status = mr_query("get_members_of_list", 1, &listname,
218 get_list_members, (char *)memberlist);
220 com_err(whoami, status, "getting members of list %s", listname);
221 while (sq_get_data(synclist, &memberstruct)) {
222 struct save_queue *q;
225 for (q = memberlist->q_next; q != memberlist; q = q->q_next) {
226 if (membercmp(q->q_data, memberstruct) == 0) {
227 q->q_prev->q_next = q->q_next;
228 q->q_next->q_prev = q->q_prev;
234 sq_save_data(addlist, memberstruct);
236 while (sq_get_data(memberlist, &memberstruct))
237 sq_save_data(dellist, memberstruct);
238 sq_destroy(memberlist);
239 memberlist = sq_create();
242 /* Process the add list */
243 while (sq_get_data(addlist, &memberstruct)) {
244 membervec[0] = listname;
245 membervec[2] = memberstruct->name;
247 printf("Adding member ");
248 show_list_member(memberstruct);
250 switch (memberstruct->type) {
253 membervec[1] = "USER";
254 status = mr_query("add_member_to_list", 3, membervec, scream, NULL);
255 if (status == MR_SUCCESS)
257 else if (status != MR_USER || memberstruct->type != M_ANY) {
258 com_err(whoami, status, "while adding member %s to %s",
259 memberstruct->name, listname);
263 membervec[1] = "LIST";
264 status = mr_query("add_member_to_list", 3, membervec,
266 if (status == MR_SUCCESS)
268 else if (status != MR_LIST || memberstruct->type != M_ANY) {
269 com_err(whoami, status, "while adding member %s to %s",
270 memberstruct->name, listname);
274 membervec[1] = "STRING";
275 status = mr_query("add_member_to_list", 3, membervec,
277 if (status != MR_SUCCESS)
278 com_err(whoami, status, "while adding member %s to %s",
279 memberstruct->name, listname);
282 membervec[1] = "KERBEROS";
283 status = mr_query("add_member_to_list", 3, membervec,
285 if (status != MR_SUCCESS)
286 com_err(whoami, status, "while adding member %s to %s",
287 memberstruct->name, listname);
291 /* Process the delete list */
292 while (sq_get_data(dellist, &memberstruct)) {
293 membervec[0] = listname;
294 membervec[2] = memberstruct->name;
296 printf("Deleting member ");
297 show_list_member(memberstruct);
299 switch (memberstruct->type) {
302 membervec[1] = "USER";
303 status = mr_query("delete_member_from_list", 3, membervec,
305 if (status == MR_SUCCESS)
307 else if ((status != MR_USER && status != MR_NO_MATCH) ||
308 memberstruct->type != M_ANY) {
309 com_err(whoami, status, "while deleting member %s from %s",
310 memberstruct->name, listname);
314 membervec[1] = "LIST";
315 status = mr_query("delete_member_from_list", 3, membervec,
317 if (status == MR_SUCCESS)
319 else if ((status != MR_LIST && status != MR_NO_MATCH) ||
320 memberstruct->type != M_ANY) {
321 com_err(whoami, status, "while deleting member %s from %s",
322 memberstruct->name, listname);
326 membervec[1] = "STRING";
327 status = mr_query("delete_member_from_list", 3, membervec,
329 if (status == MR_STRING && memberstruct->type == M_ANY)
330 com_err(whoami, 0, " Unable to find member %s to delete from %s",
331 memberstruct->name, listname);
332 else if (status != MR_SUCCESS)
333 com_err(whoami, status, "while deleting member %s from %s",
334 memberstruct->name, listname);
337 membervec[1] = "KERBEROS";
338 status = mr_query("delete_member_from_list", 3, membervec,
340 if (status != MR_SUCCESS)
341 com_err(whoami, status, "while deleting member %s from %s",
342 memberstruct->name, listname);
346 /* Display the members of the list now, if requested */
349 recursive_display_list_members();
351 status = mr_query("get_members_of_list", 1, &listname,
352 get_list_members, (char *)memberlist);
354 com_err(whoami, status, "while getting members of list %s",
356 while (sq_get_data(memberlist, &memberstruct))
357 show_list_member(memberstruct);
369 fprintf(stderr, "Usage: %s [options] listname [options]\n",argv[0]);
370 fprintf(stderr, "Options are\n");
371 fprintf(stderr, " -v | -verbose\n");
372 fprintf(stderr, " -m | -members\n");
373 fprintf(stderr, " -u | -users\n");
374 fprintf(stderr, " -l | -lists\n");
375 fprintf(stderr, " -s | -strings\n");
376 fprintf(stderr, " -k | -kerberos\n");
377 fprintf(stderr, " -i | -info\n");
378 fprintf(stderr, " -r | -recursive\n");
379 fprintf(stderr, " -a | -add member\n");
380 fprintf(stderr, " -d | -delete member\n");
381 fprintf(stderr, " -f | -file filename\n");
382 fprintf(stderr, " -n | -noauth\n");
383 fprintf(stderr, " -S | -server host:port\n");
384 fprintf(stderr, " -D | -debug\n");
389 /* Display the members stored in the queue */
391 show_list_member(memberstruct)
392 struct member *memberstruct;
396 switch (memberstruct->type) {
418 printf("%s\n", memberstruct->name);
423 printf("%s:%s\n", s, memberstruct->name);
425 if (memberstruct->type == M_LIST)
426 printf("LIST:%s\n", memberstruct->name);
427 else if (memberstruct->type == M_KERBEROS)
428 printf("KERBEROS:%s\n", memberstruct->name);
429 else if (memberstruct->type == M_STRING &&
430 !index(memberstruct->name, '@'))
431 printf("STRING:%s\n", memberstruct->name);
433 printf("%s\n", memberstruct->name);
438 /* Show the retrieved information about a list */
440 show_list_info(argc, argv, hint)
445 printf("List: %s\n", argv[0]);
446 printf("Description: %s\n", argv[9]);
447 printf("Flags: %s, %s, and %s\n",
448 atoi(argv[1]) ? "active" : "inactive",
449 atoi(argv[2]) ? "public" : "private",
450 atoi(argv[3]) ? "hidden" : "visible");
451 printf("%s is %sa maillist and is %sa group", argv[0],
452 atoi(argv[4]) ? "" : "not ",
453 atoi(argv[5]) ? "" : "not ");
455 printf(" with GID %d\n", atoi(argv[6]));
458 printf("Owner: %s %s\n", argv[7], argv[8]);
459 printf("Last modified by %s with %s on %s\n", argv[11], argv[12], argv[10]);
464 /* Show the retrieve list member count */
466 show_list_count(argc, argv, hint)
471 printf("Members: %s\n", argv[0]);
475 /* Recursively find all of the members of listname, and then display them */
477 recursive_display_list_members()
479 int status, count, savecount;
480 struct save_queue *lists, *members;
481 struct member *m, *m1, *data;
484 members = sq_create();
485 m = (struct member *) malloc(sizeof(struct member));
488 sq_save_data(lists, m);
490 while (sq_get_data(lists, &m)) {
491 sq_destroy(memberlist);
492 memberlist = sq_create();
494 fprintf(stderr, "Fetching members of %s\n", m->name);
495 status = mr_query("get_members_of_list", 1, &(m->name),
496 get_list_members, (char *)memberlist);
498 com_err(whoami, status, "while getting members of list %s", m->name);
499 while (sq_get_data(memberlist, &m1)) {
500 if (m1->type == M_LIST)
501 unique_add_member(lists, m1);
503 unique_add_member(members, m1);
506 savecount = count = sq_count_elts(members);
507 data = (struct member *) malloc(count * sizeof(struct member));
509 while (sq_get_data(members, &m))
510 bcopy(m, &data[count++], sizeof(struct member));
511 qsort(data, count, sizeof(struct member), membercmp);
512 for (count = 0; count < savecount; count++) {
513 show_list_member(&data[count]);
518 /* add a struct member to a queue if that member isn't already there. */
520 unique_add_member(q, m)
521 struct save_queue *q;
524 struct save_queue *qp;
526 for (qp = q->q_next; qp != q; qp = qp->q_next) {
527 if (!membercmp(qp->q_data, m))
534 /* Collect the retrieved members of the list */
536 get_list_members(argc, argv, q)
539 struct save_queue *q;
543 m = (struct member *) malloc(sizeof(struct member));
544 switch (argv[0][0]) {
555 m->type = M_KERBEROS;
558 m->name = strsave(argv[1]);
564 /* Called only if a query returns a value that we weren't expecting */
568 fprintf(stderr, "Programmer botch\n");
573 /* Parse a line of input, fetching a member. NULL is returned if a member
574 * is not found. Only the first token on the line is parsed. ';' is a
578 struct member *parse_member(s)
581 register struct member *m;
584 while (*s && isspace(*s))
587 while (*p && isprint(*p) && !isspace(*p) && *p != ';')
590 if (p == s || strlen(s) == 0)
593 if ((m = (struct member *) malloc(sizeof(struct member))) == NULL)
596 if (p = index(s, ':')) {
599 if (!strcasecmp("user", s))
601 else if (!strcasecmp("list", s))
603 else if (!strcasecmp("string", s))
605 else if (!strcasecmp("kerberos", s))
606 m->type = M_KERBEROS;
612 m->name = strsave(m->name);
615 m->name = strsave(s);
616 if (index(s, '@') || index(s, '!') || index(s, '%'))
625 * This routine two compares members by the following rules:
626 * 1. A USER is less than a LIST
627 * 2. A LIST is less than a STRING
628 * 3. If two members are of the same type, the one alphabetically first
629 * is less than the other
630 * It returs < 0 if the first member is less, 0 if they are identical, and
631 * > 0 if the second member is less (the first member is greater).
634 int membercmp(m1, m2)
635 struct member *m1, *m2;
637 if (m1->type == M_ANY || m2->type == M_ANY || (m1->type == m2->type))
638 return(strcmp(m1->name, m2->name));
640 return(m1->type - m2->type);
645 struct save_queue *q;
651 while (sq_get_data(q, &foo))