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("al","addlist"))
119 if (arg - argv < argc - 1) {
121 get_members_from_file(*arg, addlist);
124 else if (argis("d","delete"))
125 if (arg - argv < argc - 1) {
127 if (memberstruct = parse_member(*arg))
128 sq_save_data(dellist, memberstruct);
131 else if (argis("dl","deletelist"))
132 if (arg - argv < argc - 1) {
134 get_members_from_file(*arg, dellist);
137 else if (argis("f","file"))
138 if (arg - argv < argc - 1) {
141 get_members_from_file(*arg, synclist);
147 else if (listname == NULL)
152 if (listname == NULL)
155 /* if no other options specified, turn on list members flag */
156 if (!(infoflg || syncflg ||
157 addlist->q_next != addlist || dellist->q_next != dellist))
160 /* If none of {users,strings,lists,kerberos} specified, turn them all on */
161 if (!(showusers || showstrings || showlists || showkerberos))
162 showusers = showstrings = showlists = showkerberos = 1;
165 if (status = mr_connect(server)) {
166 com_err(whoami, status, "unable to connect to the Moira server");
169 if ( status = mr_motd(&motd) ) {
170 com_err(whoami, status, "unable to check server status");
174 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n", motd);
179 if (!noauth && (status = mr_auth("blanche"))) {
180 if (status == MR_USER_AUTH)
181 com_err(whoami, status, "");
183 com_err(whoami, status, "unable to authenticate to Moira");
185 " Try the -noauth flag if you don't need authentication");
190 /* display list info if requested to */
192 status = mr_query("get_list_info", 1, &listname, show_list_info,NULL);
194 com_err(whoami, status, "while getting list information");
195 if (verbose && !memberflg) {
196 status = mr_query("count_members_of_list", 1, &listname,
197 show_list_count, NULL);
199 com_err(whoami, status, "while getting list count");
203 /* if we're synchronizing to a file, we need to:
204 * get the current members of the list
205 * for each member of the sync file
206 * if they are on the list, remove them from the in-memory copy
207 * if they're not on the list, add them to add-list
208 * if anyone is left on the in-memory copy, put them on the delete-list
209 * lastly, reset memberlist so we can use it again later
212 status = mr_query("get_members_of_list", 1, &listname,
213 get_list_members, (char *)memberlist);
215 com_err(whoami, status, "getting members of list %s", listname);
216 while (sq_get_data(synclist, &memberstruct)) {
217 struct save_queue *q;
220 for (q = memberlist->q_next; q != memberlist; q = q->q_next) {
221 if (membercmp(q->q_data, memberstruct) == 0) {
222 q->q_prev->q_next = q->q_next;
223 q->q_next->q_prev = q->q_prev;
229 sq_save_data(addlist, memberstruct);
231 while (sq_get_data(memberlist, &memberstruct))
232 sq_save_data(dellist, memberstruct);
233 sq_destroy(memberlist);
234 memberlist = sq_create();
237 /* Process the add list */
238 while (sq_get_data(addlist, &memberstruct)) {
239 membervec[0] = listname;
240 membervec[2] = memberstruct->name;
242 printf("Adding member ");
243 show_list_member(memberstruct);
245 switch (memberstruct->type) {
248 membervec[1] = "USER";
249 status = mr_query("add_member_to_list", 3, membervec, scream, NULL);
250 if (status == MR_SUCCESS)
252 else if (status != MR_USER || memberstruct->type != M_ANY) {
253 com_err(whoami, status, "while adding member %s to %s",
254 memberstruct->name, listname);
258 membervec[1] = "LIST";
259 status = mr_query("add_member_to_list", 3, membervec,
261 if (status == MR_SUCCESS)
263 else if (status != MR_LIST || memberstruct->type != M_ANY) {
264 com_err(whoami, status, "while adding member %s to %s",
265 memberstruct->name, listname);
269 membervec[1] = "STRING";
270 status = mr_query("add_member_to_list", 3, membervec,
272 if (status != MR_SUCCESS)
273 com_err(whoami, status, "while adding member %s to %s",
274 memberstruct->name, listname);
277 membervec[1] = "KERBEROS";
278 status = mr_query("add_member_to_list", 3, membervec,
280 if (status != MR_SUCCESS)
281 com_err(whoami, status, "while adding member %s to %s",
282 memberstruct->name, listname);
286 /* Process the delete list */
287 while (sq_get_data(dellist, &memberstruct)) {
288 membervec[0] = listname;
289 membervec[2] = memberstruct->name;
291 printf("Deleting member ");
292 show_list_member(memberstruct);
294 switch (memberstruct->type) {
297 membervec[1] = "USER";
298 status = mr_query("delete_member_from_list", 3, membervec,
300 if (status == MR_SUCCESS)
302 else if ((status != MR_USER && status != MR_NO_MATCH) ||
303 memberstruct->type != M_ANY) {
304 com_err(whoami, status, "while deleting member %s from %s",
305 memberstruct->name, listname);
309 membervec[1] = "LIST";
310 status = mr_query("delete_member_from_list", 3, membervec,
312 if (status == MR_SUCCESS)
314 else if ((status != MR_LIST && status != MR_NO_MATCH) ||
315 memberstruct->type != M_ANY) {
316 com_err(whoami, status, "while deleting member %s from %s",
317 memberstruct->name, listname);
321 membervec[1] = "STRING";
322 status = mr_query("delete_member_from_list", 3, membervec,
324 if (status == MR_STRING && memberstruct->type == M_ANY)
325 com_err(whoami, 0, " Unable to find member %s to delete from %s",
326 memberstruct->name, listname);
327 else if (status != MR_SUCCESS)
328 com_err(whoami, status, "while deleting member %s from %s",
329 memberstruct->name, listname);
332 membervec[1] = "KERBEROS";
333 status = mr_query("delete_member_from_list", 3, membervec,
335 if (status != MR_SUCCESS)
336 com_err(whoami, status, "while deleting member %s from %s",
337 memberstruct->name, listname);
341 /* Display the members of the list now, if requested */
344 recursive_display_list_members();
346 status = mr_query("get_members_of_list", 1, &listname,
347 get_list_members, (char *)memberlist);
349 com_err(whoami, status, "while getting members of list %s",
351 while (sq_get_data(memberlist, &memberstruct))
352 show_list_member(memberstruct);
364 fprintf(stderr, "Usage: %s [options] listname [options]\n",argv[0]);
365 fprintf(stderr, "Options are\n");
366 fprintf(stderr, " -v | -verbose\n");
367 fprintf(stderr, " -m | -members\n");
368 fprintf(stderr, " -u | -users\n");
369 fprintf(stderr, " -l | -lists\n");
370 fprintf(stderr, " -s | -strings\n");
371 fprintf(stderr, " -k | -kerberos\n");
372 fprintf(stderr, " -i | -info\n");
373 fprintf(stderr, " -r | -recursive\n");
374 fprintf(stderr, " -a | -add member\n");
375 fprintf(stderr, " -d | -delete member\n");
376 fprintf(stderr, " -al | -addlist filename\n");
377 fprintf(stderr, " -dl | -deletelist filename\n");
378 fprintf(stderr, " -f | -file filename\n");
379 fprintf(stderr, " -n | -noauth\n");
380 fprintf(stderr, " -S | -server host[:port]\n");
381 fprintf(stderr, " -D | -debug\n");
386 /* Display the members stored in the queue */
388 show_list_member(memberstruct)
389 struct member *memberstruct;
393 switch (memberstruct->type) {
415 printf("%s\n", memberstruct->name);
420 printf("%s:%s\n", s, memberstruct->name);
422 if (memberstruct->type == M_LIST)
423 printf("LIST:%s\n", memberstruct->name);
424 else if (memberstruct->type == M_KERBEROS)
425 printf("KERBEROS:%s\n", memberstruct->name);
426 else if (memberstruct->type == M_STRING &&
427 !index(memberstruct->name, '@'))
428 printf("STRING:%s\n", memberstruct->name);
430 printf("%s\n", memberstruct->name);
435 /* Show the retrieved information about a list */
437 show_list_info(argc, argv, hint)
442 printf("List: %s\n", argv[0]);
443 printf("Description: %s\n", argv[9]);
444 printf("Flags: %s, %s, and %s\n",
445 atoi(argv[1]) ? "active" : "inactive",
446 atoi(argv[2]) ? "public" : "private",
447 atoi(argv[3]) ? "hidden" : "visible");
448 printf("%s is %sa maillist and is %sa group", argv[0],
449 atoi(argv[4]) ? "" : "not ",
450 atoi(argv[5]) ? "" : "not ");
452 printf(" with GID %d\n", atoi(argv[6]));
455 printf("Owner: %s %s\n", argv[7], argv[8]);
456 printf("Last modified by %s with %s on %s\n", argv[11], argv[12], argv[10]);
461 /* Show the retrieve list member count */
463 show_list_count(argc, argv, hint)
468 printf("Members: %s\n", argv[0]);
472 /* Recursively find all of the members of listname, and then display them */
474 recursive_display_list_members()
476 int status, count, savecount;
477 struct save_queue *lists, *members;
478 struct member *m, *m1, *data;
481 members = sq_create();
482 m = (struct member *) malloc(sizeof(struct member));
485 sq_save_data(lists, m);
487 while (sq_get_data(lists, &m)) {
488 sq_destroy(memberlist);
489 memberlist = sq_create();
491 fprintf(stderr, "Fetching members of %s\n", m->name);
492 status = mr_query("get_members_of_list", 1, &(m->name),
493 get_list_members, (char *)memberlist);
495 com_err(whoami, status, "while getting members of list %s", m->name);
496 while (sq_get_data(memberlist, &m1)) {
497 if (m1->type == M_LIST)
498 unique_add_member(lists, m1);
500 unique_add_member(members, m1);
503 savecount = count = sq_count_elts(members);
504 data = (struct member *) malloc(count * sizeof(struct member));
506 while (sq_get_data(members, &m))
507 bcopy(m, &data[count++], sizeof(struct member));
508 qsort(data, count, sizeof(struct member), membercmp);
509 for (count = 0; count < savecount; count++) {
510 show_list_member(&data[count]);
515 /* add a struct member to a queue if that member isn't already there. */
517 unique_add_member(q, m)
518 struct save_queue *q;
521 struct save_queue *qp;
523 for (qp = q->q_next; qp != q; qp = qp->q_next) {
524 if (!membercmp(qp->q_data, m))
531 /* Collect the retrieved members of the list */
533 get_list_members(argc, argv, q)
536 struct save_queue *q;
540 m = (struct member *) malloc(sizeof(struct member));
541 switch (argv[0][0]) {
552 m->type = M_KERBEROS;
555 m->name = strsave(argv[1]);
561 /* Called only if a query returns a value that we weren't expecting */
565 fprintf(stderr, "Programmer botch\n");
570 /* Open file, parse members from file, and put them on the specified queue */
571 get_members_from_file(filename, queue)
573 struct save_queue *queue;
577 struct member *memberstruct;
579 if (!strcmp(filename, "-"))
582 in = fopen(filename, "r");
584 com_err(whoami, errno, "while opening %s for input", filename);
589 while (fgets(buf, BUFSIZ, in))
590 if (memberstruct = parse_member(buf))
591 sq_save_data(queue, memberstruct);
593 com_err(whoami, errno, "while reading from %s", filename);
597 /* Parse a line of input, fetching a member. NULL is returned if a member
598 * is not found. ';' is a comment character.
601 struct member *parse_member(s)
604 register struct member *m;
607 while (*s && isspace(*s))
610 while (*p && *p != '\n' && *p != ';')
611 if (isprint(*p) && !isspace(*p))
617 if (p == s || strlen(s) == 0)
620 if ((m = (struct member *) malloc(sizeof(struct member))) == NULL)
623 if (p = index(s, ':')) {
626 if (!strcasecmp("user", s))
628 else if (!strcasecmp("list", s))
630 else if (!strcasecmp("string", s))
632 else if (!strcasecmp("kerberos", s))
633 m->type = M_KERBEROS;
639 m->name = strsave(m->name);
642 m->name = strsave(s);
643 if (index(s, '@') || index(s, '!') || index(s, '%') || index(s, ' '))
652 * This routine two compares members by the following rules:
653 * 1. A USER is less than a LIST
654 * 2. A LIST is less than a STRING
655 * 3. If two members are of the same type, the one alphabetically first
656 * is less than the other
657 * It returs < 0 if the first member is less, 0 if they are identical, and
658 * > 0 if the second member is less (the first member is greater).
661 int membercmp(m1, m2)
662 struct member *m1, *m2;
664 if (m1->type == M_ANY || m2->type == M_ANY || (m1->type == m2->type))
665 return(strcmp(m1->name, m2->name));
667 return(m1->type - m2->type);
672 struct save_queue *q;
678 while (sq_get_data(q, &foo))