]> andersk Git - moira.git/blame - clients/blanche/blanche.c
Initial revision
[moira.git] / clients / blanche / blanche.c
CommitLineData
2d7360ca 1/* $Header$
2 *
d44cee72 3 * Command line oriented Moira List tool.
2d7360ca 4 *
5 * by Mark Rosenstein, September 1988.
6 *
7 * Copyright 1989 by the Massachusetts Institute of Technology.
1b6b0a57 8 *
9 * (c) Copyright 1988 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, please see the file
11 * <mit-copyright.h>.
2d7360ca 12 */
13
1b6b0a57 14/* ### Aren't there a lot of sq abstraction barrier violations here?
15 Do we need to improve the support for queue operations? */
16
2d7360ca 17#include <mit-copyright.h>
18#include <stdio.h>
19#include <ctype.h>
8defc06b 20#include <moira.h>
21#include <moira_site.h>
2d7360ca 22
23#ifndef LINT
d44cee72 24static char blanche_rcsid[] = "$Header$";
2d7360ca 25#endif
26
27
28struct member {
29 int type;
30 char *name;
31};
32
b5b167d6 33/* It is important to membercmp that M_USER < M_LIST < M_STRING */
2d7360ca 34#define M_ANY 0
35#define M_USER 1
36#define M_LIST 2
37#define M_STRING 3
8c3b414d 38#define M_KERBEROS 4
2d7360ca 39
1b6b0a57 40/* argument parsing macro */
41#define argis(a,b) ((strcmp(*arg+1, a) == 0) || (strcmp(*arg+1, b) == 0))
42
2d7360ca 43/* flags from command line */
8b494222 44int infoflg, verbose, syncflg, memberflg, recursflg, debugflg, noauth;
8c3b414d 45int showusers, showstrings, showkerberos, showlists;
2d7360ca 46
47/* various member lists */
48struct save_queue *addlist, *dellist, *memberlist, *synclist;
49
50char *listname, *whoami;
51
52extern char *index();
53extern int errno;
54
55int show_list_info(), show_list_count(), get_list_members(), scream();
1b6b0a57 56int show_list_members();
2d7360ca 57struct member *parse_member();
58
59
60
61main(argc, argv)
62int argc;
63char **argv;
64{
65 int status;
66 char **arg = argv;
37e3ac2d 67 char *membervec[3], *motd;
2d7360ca 68 struct member *memberstruct;
d44cee72 69 char *server = NULL;
2d7360ca 70
71 /* clear all flags & lists */
1b6b0a57 72 infoflg = verbose = syncflg = memberflg = debugflg = recursflg = 0;
8c3b414d 73 noauth = showusers = showstrings = showkerberos = showlists = 0;
2d7360ca 74 listname = NULL;
75 addlist = sq_create();
76 dellist = sq_create();
77 memberlist = sq_create();
78 synclist = sq_create();
79 whoami = argv[0];
80
81 /* parse args, building addlist, dellist, & synclist */
82 while (++arg - argv < argc) {
83 if (**arg == '-')
1b6b0a57 84 {
85 if (argis("m", "members"))
86 memberflg++;
8b494222 87 else if (argis("u", "users"))
88 showusers++;
89 else if (argis("s", "strings"))
90 showstrings++;
91 else if (argis("l", "lists"))
92 showlists++;
8c3b414d 93 else if (argis("k", "kerberos"))
94 showkerberos++;
1b6b0a57 95 else if (argis("D", "debug"))
96 debugflg++;
62a6860a 97 else if (argis("i","info"))
2d7360ca 98 infoflg++;
8b494222 99 else if (argis("n","noauth"))
100 noauth++;
1b6b0a57 101 else if (argis("v","verbose"))
2d7360ca 102 verbose++;
1b6b0a57 103 else if (argis("r","recursive"))
104 recursflg++;
8c3b414d 105 else if (argis("S","server"))
106 if (arg - argv < argc - 1) {
107 ++arg;
108 server = *arg;
109 } else
110 usage(argv);
1b6b0a57 111 else if (argis("a","add"))
112 if (arg - argv < argc - 1) {
113 ++arg;
114 if (memberstruct = parse_member(*arg))
115 sq_save_data(addlist, memberstruct);
116 } else
117 usage(argv);
118 else if (argis("d","delete"))
119 if (arg - argv < argc - 1) {
120 ++arg;
121 if (memberstruct = parse_member(*arg))
122 sq_save_data(dellist, memberstruct);
123 } else
124 usage(argv);
125 else if (argis("f","file"))
126 if (arg - argv < argc - 1) {
127 FILE *in;
128 char buf[BUFSIZ];
b5b167d6 129
1b6b0a57 130 syncflg++;
131 ++arg;
132 if (!strcmp(*arg, "-"))
b5b167d6 133 in = stdin;
1b6b0a57 134 else {
135 in = fopen(*arg, "r");
b5b167d6 136 if (!in) {
1b6b0a57 137 com_err(whoami, errno,
d44cee72 138 "while opening %s for input", *arg);
1b6b0a57 139 exit(2);
140 }
141 }
142 while (fgets(buf, BUFSIZ, in))
b5b167d6 143 if (memberstruct = parse_member(buf))
144 sq_save_data(synclist, memberstruct);
1b6b0a57 145 if (!feof(in))
d44cee72 146 com_err(whoami, errno, "while reading from %s", *arg);
1b6b0a57 147 } else
b5b167d6 148 usage(argv);
1b6b0a57 149 else
2d7360ca 150 usage(argv);
1b6b0a57 151 }
2d7360ca 152 else if (listname == NULL)
153 listname = *arg;
154 else
155 usage(argv);
156 }
157 if (listname == NULL)
158 usage(argv);
159
160 /* if no other options specified, turn on list members flag */
161 if (!(infoflg || syncflg ||
162 addlist->q_next != addlist || dellist->q_next != dellist))
163 memberflg++;
164
8c3b414d 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;
8b494222 168
d44cee72 169 /* fire up Moira */
8defc06b 170 if (status = mr_connect(server)) {
d44cee72 171 com_err(whoami, status, "unable to connect to the Moira server");
2d7360ca 172 exit(2);
173 }
8defc06b 174 if ( status = mr_motd(&motd) ) {
d44cee72 175 com_err(whoami, status, "unable to check server status");
37e3ac2d 176 exit(2);
177 }
178 if (motd) {
95cd286e 179 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n", motd);
8defc06b 180 mr_disconnect();
37e3ac2d 181 exit(2);
182 }
183
8defc06b 184 if (!noauth && (status = mr_auth("blanche"))) {
ece49f32 185 if (status == MR_USER_AUTH)
186 com_err(whoami, status, "");
187 else {
188 com_err(whoami, status, "unable to authenticate to Moira");
189 com_err(whoami, 0,
190 " Try the -noauth flag if you don't need authentication");
191 exit(2);
192 }
2d7360ca 193 }
194
195 /* display list info if requested to */
196 if (infoflg) {
8defc06b 197 status = mr_query("get_list_info", 1, &listname, show_list_info,NULL);
2d7360ca 198 if (status)
d44cee72 199 com_err(whoami, status, "while getting list information");
2d7360ca 200 if (verbose && !memberflg) {
8defc06b 201 status = mr_query("count_members_of_list", 1, &listname,
2d7360ca 202 show_list_count, NULL);
203 if (status)
d44cee72 204 com_err(whoami, status, "while getting list count");
2d7360ca 205 }
206 }
207
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
215 */
216 if (syncflg) {
8defc06b 217 status = mr_query("get_members_of_list", 1, &listname,
1b6b0a57 218 get_list_members, (char *)memberlist);
2d7360ca 219 if (status)
d44cee72 220 com_err(whoami, status, "getting members of list %s", listname);
2d7360ca 221 while (sq_get_data(synclist, &memberstruct)) {
222 struct save_queue *q;
223 int removed = 0;
224
225 for (q = memberlist->q_next; q != memberlist; q = q->q_next) {
1b6b0a57 226 if (membercmp(q->q_data, memberstruct) == 0) {
2d7360ca 227 q->q_prev->q_next = q->q_next;
228 q->q_next->q_prev = q->q_prev;
229 removed++;
230 break;
231 }
232 }
233 if (!removed)
234 sq_save_data(addlist, memberstruct);
235 }
236 while (sq_get_data(memberlist, &memberstruct))
237 sq_save_data(dellist, memberstruct);
238 sq_destroy(memberlist);
239 memberlist = sq_create();
240 }
241
242 /* Process the add list */
243 while (sq_get_data(addlist, &memberstruct)) {
244 membervec[0] = listname;
245 membervec[2] = memberstruct->name;
97f4e1fa 246 if (verbose) {
b5b167d6 247 printf("Adding member ");
248 show_list_member(memberstruct);
249 }
2d7360ca 250 switch (memberstruct->type) {
251 case M_ANY:
252 case M_USER:
253 membervec[1] = "USER";
8defc06b 254 status = mr_query("add_member_to_list", 3, membervec, scream, NULL);
255 if (status == MR_SUCCESS)
2d7360ca 256 break;
8defc06b 257 else if (status != MR_USER || memberstruct->type != M_ANY) {
d44cee72 258 com_err(whoami, status, "while adding member %s to %s",
2d7360ca 259 memberstruct->name, listname);
260 break;
261 }
262 case M_LIST:
263 membervec[1] = "LIST";
8defc06b 264 status = mr_query("add_member_to_list", 3, membervec,
2d7360ca 265 scream, NULL);
8defc06b 266 if (status == MR_SUCCESS)
2d7360ca 267 break;
8defc06b 268 else if (status != MR_LIST || memberstruct->type != M_ANY) {
d44cee72 269 com_err(whoami, status, "while adding member %s to %s",
2d7360ca 270 memberstruct->name, listname);
271 break;
272 }
273 case M_STRING:
274 membervec[1] = "STRING";
8defc06b 275 status = mr_query("add_member_to_list", 3, membervec,
2d7360ca 276 scream, NULL);
8defc06b 277 if (status != MR_SUCCESS)
d44cee72 278 com_err(whoami, status, "while adding member %s to %s",
2d7360ca 279 memberstruct->name, listname);
8c3b414d 280 break;
281 case M_KERBEROS:
282 membervec[1] = "KERBEROS";
8defc06b 283 status = mr_query("add_member_to_list", 3, membervec,
8c3b414d 284 scream, NULL);
8defc06b 285 if (status != MR_SUCCESS)
d44cee72 286 com_err(whoami, status, "while adding member %s to %s",
8c3b414d 287 memberstruct->name, listname);
2d7360ca 288 }
289 }
290
291 /* Process the delete list */
292 while (sq_get_data(dellist, &memberstruct)) {
293 membervec[0] = listname;
294 membervec[2] = memberstruct->name;
97f4e1fa 295 if (verbose) {
b5b167d6 296 printf("Deleting member ");
297 show_list_member(memberstruct);
298 }
2d7360ca 299 switch (memberstruct->type) {
300 case M_ANY:
301 case M_USER:
302 membervec[1] = "USER";
8defc06b 303 status = mr_query("delete_member_from_list", 3, membervec,
2d7360ca 304 scream, NULL);
8defc06b 305 if (status == MR_SUCCESS)
2d7360ca 306 break;
8defc06b 307 else if ((status != MR_USER && status != MR_NO_MATCH) ||
2d7360ca 308 memberstruct->type != M_ANY) {
d44cee72 309 com_err(whoami, status, "while deleting member %s from %s",
2d7360ca 310 memberstruct->name, listname);
311 break;
312 }
313 case M_LIST:
314 membervec[1] = "LIST";
8defc06b 315 status = mr_query("delete_member_from_list", 3, membervec,
2d7360ca 316 scream, NULL);
8defc06b 317 if (status == MR_SUCCESS)
2d7360ca 318 break;
8defc06b 319 else if ((status != MR_LIST && status != MR_NO_MATCH) ||
2d7360ca 320 memberstruct->type != M_ANY) {
d44cee72 321 com_err(whoami, status, "while deleting member %s from %s",
2d7360ca 322 memberstruct->name, listname);
323 break;
324 }
325 case M_STRING:
326 membervec[1] = "STRING";
8defc06b 327 status = mr_query("delete_member_from_list", 3, membervec,
2d7360ca 328 scream, NULL);
8defc06b 329 if (status == MR_STRING && memberstruct->type == M_ANY)
d44cee72 330 com_err(whoami, 0, " Unable to find member %s to delete from %s",
2d7360ca 331 memberstruct->name, listname);
8defc06b 332 else if (status != MR_SUCCESS)
d44cee72 333 com_err(whoami, status, "while deleting member %s from %s",
2d7360ca 334 memberstruct->name, listname);
8c3b414d 335 break;
336 case M_KERBEROS:
337 membervec[1] = "KERBEROS";
8defc06b 338 status = mr_query("delete_member_from_list", 3, membervec,
8c3b414d 339 scream, NULL);
8defc06b 340 if (status != MR_SUCCESS)
d44cee72 341 com_err(whoami, status, "while deleting member %s from %s",
8c3b414d 342 memberstruct->name, listname);
2d7360ca 343 }
344 }
345
346 /* Display the members of the list now, if requested */
b5b167d6 347 if (memberflg) {
348 if (recursflg)
349 recursive_display_list_members();
350 else {
8defc06b 351 status = mr_query("get_members_of_list", 1, &listname,
b5b167d6 352 get_list_members, (char *)memberlist);
353 if (status)
d44cee72 354 com_err(whoami, status, "while getting members of list %s",
b5b167d6 355 listname);
356 while (sq_get_data(memberlist, &memberstruct))
357 show_list_member(memberstruct);
358 }
359 }
2d7360ca 360
361 /* We're done! */
8defc06b 362 mr_disconnect();
2d7360ca 363 exit(0);
364}
365
366usage(argv)
367char **argv;
368{
1b6b0a57 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");
8b494222 373 fprintf(stderr, " -u | -users\n");
374 fprintf(stderr, " -l | -lists\n");
375 fprintf(stderr, " -s | -strings\n");
8c3b414d 376 fprintf(stderr, " -k | -kerberos\n");
1b6b0a57 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");
8b494222 382 fprintf(stderr, " -n | -noauth\n");
8c3b414d 383 fprintf(stderr, " -S | -server host:port\n");
1b6b0a57 384 fprintf(stderr, " -D | -debug\n");
2d7360ca 385 exit(1);
386}
387
388
b5b167d6 389/* Display the members stored in the queue */
1b6b0a57 390
b5b167d6 391show_list_member(memberstruct)
392struct member *memberstruct;
393{
8b494222 394 char *s;
395
396 switch (memberstruct->type) {
397 case M_USER:
398 if (!showusers)
399 return;
400 s = "USER";
401 break;
402 case M_LIST:
403 if (!showlists)
404 return;
405 s = "LIST";
406 break;
407 case M_STRING:
408 if (!showstrings)
409 return;
410 s = "STRING";
411 break;
8c3b414d 412 case M_KERBEROS:
413 if (!showkerberos)
414 return;
415 s = "KERBEROS";
416 break;
8b494222 417 case M_ANY:
418 printf("%s\n", memberstruct->name);
419 return;
420 }
421
422 if (verbose)
423 printf("%s:%s\n", s, memberstruct->name);
424 else {
b5b167d6 425 if (memberstruct->type == M_LIST)
426 printf("LIST:%s\n", memberstruct->name);
8c3b414d 427 else if (memberstruct->type == M_KERBEROS)
428 printf("KERBEROS:%s\n", memberstruct->name);
b5b167d6 429 else if (memberstruct->type == M_STRING &&
430 !index(memberstruct->name, '@'))
431 printf("STRING:%s\n", memberstruct->name);
432 else
433 printf("%s\n", memberstruct->name);
1b6b0a57 434 }
435}
436
b5b167d6 437
438/* Show the retrieved information about a list */
439
2d7360ca 440show_list_info(argc, argv, hint)
441int argc;
442char **argv;
443int hint;
444{
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");
1b6b0a57 451 printf("%s is %sa maillist and is %sa group", argv[0],
2d7360ca 452 atoi(argv[4]) ? "" : "not ",
453 atoi(argv[5]) ? "" : "not ");
454 if (atoi(argv[5]))
455 printf(" with GID %d\n", atoi(argv[6]));
456 else
457 printf("\n");
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]);
8defc06b 460 return(MR_CONT);
2d7360ca 461}
462
463
b5b167d6 464/* Show the retrieve list member count */
465
2d7360ca 466show_list_count(argc, argv, hint)
467int argc;
468char **argv;
469int hint;
470{
471 printf("Members: %s\n", argv[0]);
472}
473
474
b5b167d6 475/* Recursively find all of the members of listname, and then display them */
476
477recursive_display_list_members()
1b6b0a57 478{
b5b167d6 479 int status, count, savecount;
480 struct save_queue *lists, *members;
481 struct member *m, *m1, *data;
482
483 lists = sq_create();
484 members = sq_create();
485 m = (struct member *) malloc(sizeof(struct member));
486 m->type = M_LIST;
487 m->name = listname;
488 sq_save_data(lists, m);
489
490 while (sq_get_data(lists, &m)) {
491 sq_destroy(memberlist);
492 memberlist = sq_create();
493 if (debugflg)
494 fprintf(stderr, "Fetching members of %s\n", m->name);
8defc06b 495 status = mr_query("get_members_of_list", 1, &(m->name),
b5b167d6 496 get_list_members, (char *)memberlist);
497 if (status)
d44cee72 498 com_err(whoami, status, "while getting members of list %s", m->name);
b5b167d6 499 while (sq_get_data(memberlist, &m1)) {
500 if (m1->type == M_LIST)
501 unique_add_member(lists, m1);
502 else
503 unique_add_member(members, m1);
504 }
505 }
506 savecount = count = sq_count_elts(members);
507 data = (struct member *) malloc(count * sizeof(struct member));
508 count = 0;
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]);
514 }
515}
516
517
518/* add a struct member to a queue if that member isn't already there. */
519
520unique_add_member(q, m)
521struct save_queue *q;
522struct member *m;
523{
524 struct save_queue *qp;
1b6b0a57 525
b5b167d6 526 for (qp = q->q_next; qp != q; qp = qp->q_next) {
527 if (!membercmp(qp->q_data, m))
528 return;
529 }
530 sq_save_data(q, m);
1b6b0a57 531}
532
b5b167d6 533
534/* Collect the retrieved members of the list */
535
2d7360ca 536get_list_members(argc, argv, q)
537int argc;
538char **argv;
539struct save_queue *q;
540{
541 struct member *m;
542
543 m = (struct member *) malloc(sizeof(struct member));
544 switch (argv[0][0]) {
545 case 'U':
546 m->type = M_USER;
547 break;
548 case 'L':
549 m->type = M_LIST;
550 break;
551 case 'S':
552 m->type = M_STRING;
553 break;
8c3b414d 554 case 'K':
555 m->type = M_KERBEROS;
556 break;
2d7360ca 557 }
558 m->name = strsave(argv[1]);
559 sq_save_data(q, m);
8defc06b 560 return(MR_CONT);
2d7360ca 561}
562
563
b5b167d6 564/* Called only if a query returns a value that we weren't expecting */
565
2d7360ca 566scream()
567{
568 fprintf(stderr, "Programmer botch\n");
569 exit(3);
570}
571
572
b5b167d6 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
575 * comment character.
576 */
577
2d7360ca 578struct member *parse_member(s)
579register char *s;
580{
581 register struct member *m;
582 char *p;
583
584 while (*s && isspace(*s))
585 s++;
586 p = s;
587 while (*p && isprint(*p) && !isspace(*p) && *p != ';')
588 p++;
589 *p = 0;
590 if (p == s || strlen(s) == 0)
591 return(NULL);
592
593 if ((m = (struct member *) malloc(sizeof(struct member))) == NULL)
594 return(NULL);
595
596 if (p = index(s, ':')) {
597 *p = 0;
598 m->name = ++p;
599 if (!strcasecmp("user", s))
600 m->type = M_USER;
601 else if (!strcasecmp("list", s))
602 m->type = M_LIST;
603 else if (!strcasecmp("string", s))
604 m->type = M_STRING;
8c3b414d 605 else if (!strcasecmp("kerberos", s))
606 m->type = M_KERBEROS;
2d7360ca 607 else {
608 m->type = M_STRING;
609 *(--p) = ':';
610 m->name = s;
611 }
612 m->name = strsave(m->name);
613 return(m);
614 }
615 m->name = strsave(s);
616 if (index(s, '@') || index(s, '!') || index(s, '%'))
617 m->type = M_STRING;
618 else
619 m->type = M_ANY;
620 return(m);
621}
622
623
1b6b0a57 624 /*
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).
632 */
b5b167d6 633
634int membercmp(m1, m2)
635 struct member *m1, *m2;
2d7360ca 636{
1b6b0a57 637 if (m1->type == M_ANY || m2->type == M_ANY || (m1->type == m2->type))
638 return(strcmp(m1->name, m2->name));
2d7360ca 639 else
1b6b0a57 640 return(m1->type - m2->type);
2d7360ca 641}
b5b167d6 642
643
644sq_count_elts(q)
645struct save_queue *q;
646{
647 char *foo;
648 int count;
649
650 count = 0;
651 while (sq_get_data(q, &foo))
652 count++;
653 return(count);
654}
This page took 0.1596 seconds and 5 git commands to generate.