]> andersk Git - moira.git/blame - clients/blanche/blanche.c
detect setting pobox to local mailhub and complain
[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();
135cd06a 56int show_list_members(), membercmp();
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);
7c02cbdb 118 else if (argis("al","addlist"))
119 if (arg - argv < argc - 1) {
120 ++arg;
121 get_members_from_file(*arg, addlist);
122 } else
123 usage(argv);
1b6b0a57 124 else if (argis("d","delete"))
125 if (arg - argv < argc - 1) {
126 ++arg;
127 if (memberstruct = parse_member(*arg))
128 sq_save_data(dellist, memberstruct);
129 } else
130 usage(argv);
7c02cbdb 131 else if (argis("dl","deletelist"))
132 if (arg - argv < argc - 1) {
133 ++arg;
134 get_members_from_file(*arg, dellist);
135 } else
136 usage(argv);
1b6b0a57 137 else if (argis("f","file"))
138 if (arg - argv < argc - 1) {
1b6b0a57 139 syncflg++;
140 ++arg;
7c02cbdb 141 get_members_from_file(*arg, synclist);
1b6b0a57 142 } else
b5b167d6 143 usage(argv);
1b6b0a57 144 else
2d7360ca 145 usage(argv);
1b6b0a57 146 }
2d7360ca 147 else if (listname == NULL)
148 listname = *arg;
149 else
150 usage(argv);
151 }
152 if (listname == NULL)
153 usage(argv);
154
155 /* if no other options specified, turn on list members flag */
156 if (!(infoflg || syncflg ||
157 addlist->q_next != addlist || dellist->q_next != dellist))
158 memberflg++;
159
8c3b414d 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;
8b494222 163
d44cee72 164 /* fire up Moira */
8defc06b 165 if (status = mr_connect(server)) {
d44cee72 166 com_err(whoami, status, "unable to connect to the Moira server");
2d7360ca 167 exit(2);
168 }
8defc06b 169 if ( status = mr_motd(&motd) ) {
d44cee72 170 com_err(whoami, status, "unable to check server status");
37e3ac2d 171 exit(2);
172 }
173 if (motd) {
95cd286e 174 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n", motd);
8defc06b 175 mr_disconnect();
37e3ac2d 176 exit(2);
177 }
178
8defc06b 179 if (!noauth && (status = mr_auth("blanche"))) {
ece49f32 180 if (status == MR_USER_AUTH)
181 com_err(whoami, status, "");
182 else {
183 com_err(whoami, status, "unable to authenticate to Moira");
184 com_err(whoami, 0,
185 " Try the -noauth flag if you don't need authentication");
186 exit(2);
187 }
2d7360ca 188 }
189
190 /* display list info if requested to */
191 if (infoflg) {
8defc06b 192 status = mr_query("get_list_info", 1, &listname, show_list_info,NULL);
2d7360ca 193 if (status)
d44cee72 194 com_err(whoami, status, "while getting list information");
2d7360ca 195 if (verbose && !memberflg) {
8defc06b 196 status = mr_query("count_members_of_list", 1, &listname,
2d7360ca 197 show_list_count, NULL);
198 if (status)
d44cee72 199 com_err(whoami, status, "while getting list count");
2d7360ca 200 }
201 }
202
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
210 */
211 if (syncflg) {
8defc06b 212 status = mr_query("get_members_of_list", 1, &listname,
1b6b0a57 213 get_list_members, (char *)memberlist);
2d7360ca 214 if (status)
d44cee72 215 com_err(whoami, status, "getting members of list %s", listname);
2d7360ca 216 while (sq_get_data(synclist, &memberstruct)) {
217 struct save_queue *q;
218 int removed = 0;
219
220 for (q = memberlist->q_next; q != memberlist; q = q->q_next) {
1b6b0a57 221 if (membercmp(q->q_data, memberstruct) == 0) {
2d7360ca 222 q->q_prev->q_next = q->q_next;
223 q->q_next->q_prev = q->q_prev;
224 removed++;
225 break;
226 }
227 }
228 if (!removed)
229 sq_save_data(addlist, memberstruct);
230 }
231 while (sq_get_data(memberlist, &memberstruct))
232 sq_save_data(dellist, memberstruct);
233 sq_destroy(memberlist);
234 memberlist = sq_create();
235 }
236
237 /* Process the add list */
238 while (sq_get_data(addlist, &memberstruct)) {
239 membervec[0] = listname;
240 membervec[2] = memberstruct->name;
97f4e1fa 241 if (verbose) {
b5b167d6 242 printf("Adding member ");
243 show_list_member(memberstruct);
244 }
2d7360ca 245 switch (memberstruct->type) {
246 case M_ANY:
247 case M_USER:
248 membervec[1] = "USER";
8defc06b 249 status = mr_query("add_member_to_list", 3, membervec, scream, NULL);
250 if (status == MR_SUCCESS)
2d7360ca 251 break;
8defc06b 252 else if (status != MR_USER || memberstruct->type != M_ANY) {
d44cee72 253 com_err(whoami, status, "while adding member %s to %s",
2d7360ca 254 memberstruct->name, listname);
255 break;
256 }
257 case M_LIST:
258 membervec[1] = "LIST";
8defc06b 259 status = mr_query("add_member_to_list", 3, membervec,
2d7360ca 260 scream, NULL);
8defc06b 261 if (status == MR_SUCCESS)
2d7360ca 262 break;
8defc06b 263 else if (status != MR_LIST || memberstruct->type != M_ANY) {
d44cee72 264 com_err(whoami, status, "while adding member %s to %s",
2d7360ca 265 memberstruct->name, listname);
266 break;
267 }
268 case M_STRING:
269 membervec[1] = "STRING";
8defc06b 270 status = mr_query("add_member_to_list", 3, membervec,
2d7360ca 271 scream, NULL);
8defc06b 272 if (status != MR_SUCCESS)
d44cee72 273 com_err(whoami, status, "while adding member %s to %s",
2d7360ca 274 memberstruct->name, listname);
8c3b414d 275 break;
276 case M_KERBEROS:
277 membervec[1] = "KERBEROS";
8defc06b 278 status = mr_query("add_member_to_list", 3, membervec,
8c3b414d 279 scream, NULL);
8defc06b 280 if (status != MR_SUCCESS)
d44cee72 281 com_err(whoami, status, "while adding member %s to %s",
8c3b414d 282 memberstruct->name, listname);
2d7360ca 283 }
284 }
285
286 /* Process the delete list */
287 while (sq_get_data(dellist, &memberstruct)) {
288 membervec[0] = listname;
289 membervec[2] = memberstruct->name;
97f4e1fa 290 if (verbose) {
b5b167d6 291 printf("Deleting member ");
292 show_list_member(memberstruct);
293 }
2d7360ca 294 switch (memberstruct->type) {
295 case M_ANY:
296 case M_USER:
297 membervec[1] = "USER";
8defc06b 298 status = mr_query("delete_member_from_list", 3, membervec,
2d7360ca 299 scream, NULL);
8defc06b 300 if (status == MR_SUCCESS)
2d7360ca 301 break;
8defc06b 302 else if ((status != MR_USER && status != MR_NO_MATCH) ||
2d7360ca 303 memberstruct->type != M_ANY) {
d44cee72 304 com_err(whoami, status, "while deleting member %s from %s",
2d7360ca 305 memberstruct->name, listname);
306 break;
307 }
308 case M_LIST:
309 membervec[1] = "LIST";
8defc06b 310 status = mr_query("delete_member_from_list", 3, membervec,
2d7360ca 311 scream, NULL);
8defc06b 312 if (status == MR_SUCCESS)
2d7360ca 313 break;
8defc06b 314 else if ((status != MR_LIST && status != MR_NO_MATCH) ||
2d7360ca 315 memberstruct->type != M_ANY) {
d44cee72 316 com_err(whoami, status, "while deleting member %s from %s",
2d7360ca 317 memberstruct->name, listname);
318 break;
319 }
320 case M_STRING:
321 membervec[1] = "STRING";
8defc06b 322 status = mr_query("delete_member_from_list", 3, membervec,
2d7360ca 323 scream, NULL);
8defc06b 324 if (status == MR_STRING && memberstruct->type == M_ANY)
d44cee72 325 com_err(whoami, 0, " Unable to find member %s to delete from %s",
2d7360ca 326 memberstruct->name, listname);
8defc06b 327 else if (status != MR_SUCCESS)
d44cee72 328 com_err(whoami, status, "while deleting member %s from %s",
2d7360ca 329 memberstruct->name, listname);
8c3b414d 330 break;
331 case M_KERBEROS:
332 membervec[1] = "KERBEROS";
8defc06b 333 status = mr_query("delete_member_from_list", 3, membervec,
8c3b414d 334 scream, NULL);
8defc06b 335 if (status != MR_SUCCESS)
d44cee72 336 com_err(whoami, status, "while deleting member %s from %s",
8c3b414d 337 memberstruct->name, listname);
2d7360ca 338 }
339 }
340
341 /* Display the members of the list now, if requested */
b5b167d6 342 if (memberflg) {
343 if (recursflg)
344 recursive_display_list_members();
345 else {
8defc06b 346 status = mr_query("get_members_of_list", 1, &listname,
b5b167d6 347 get_list_members, (char *)memberlist);
348 if (status)
d44cee72 349 com_err(whoami, status, "while getting members of list %s",
b5b167d6 350 listname);
351 while (sq_get_data(memberlist, &memberstruct))
352 show_list_member(memberstruct);
353 }
354 }
2d7360ca 355
356 /* We're done! */
8defc06b 357 mr_disconnect();
2d7360ca 358 exit(0);
359}
360
361usage(argv)
362char **argv;
363{
1b6b0a57 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");
8b494222 368 fprintf(stderr, " -u | -users\n");
369 fprintf(stderr, " -l | -lists\n");
370 fprintf(stderr, " -s | -strings\n");
8c3b414d 371 fprintf(stderr, " -k | -kerberos\n");
1b6b0a57 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");
7c02cbdb 376 fprintf(stderr, " -al | -addlist filename\n");
377 fprintf(stderr, " -dl | -deletelist filename\n");
1b6b0a57 378 fprintf(stderr, " -f | -file filename\n");
8b494222 379 fprintf(stderr, " -n | -noauth\n");
7c02cbdb 380 fprintf(stderr, " -S | -server host[:port]\n");
1b6b0a57 381 fprintf(stderr, " -D | -debug\n");
2d7360ca 382 exit(1);
383}
384
385
b5b167d6 386/* Display the members stored in the queue */
1b6b0a57 387
b5b167d6 388show_list_member(memberstruct)
389struct member *memberstruct;
390{
24582af9 391 char *s = "";
8b494222 392
393 switch (memberstruct->type) {
394 case M_USER:
395 if (!showusers)
396 return;
397 s = "USER";
398 break;
399 case M_LIST:
400 if (!showlists)
401 return;
402 s = "LIST";
403 break;
404 case M_STRING:
405 if (!showstrings)
406 return;
407 s = "STRING";
408 break;
8c3b414d 409 case M_KERBEROS:
410 if (!showkerberos)
411 return;
412 s = "KERBEROS";
413 break;
8b494222 414 case M_ANY:
415 printf("%s\n", memberstruct->name);
416 return;
417 }
418
419 if (verbose)
420 printf("%s:%s\n", s, memberstruct->name);
421 else {
b5b167d6 422 if (memberstruct->type == M_LIST)
423 printf("LIST:%s\n", memberstruct->name);
8c3b414d 424 else if (memberstruct->type == M_KERBEROS)
425 printf("KERBEROS:%s\n", memberstruct->name);
b5b167d6 426 else if (memberstruct->type == M_STRING &&
427 !index(memberstruct->name, '@'))
428 printf("STRING:%s\n", memberstruct->name);
429 else
430 printf("%s\n", memberstruct->name);
1b6b0a57 431 }
432}
433
b5b167d6 434
435/* Show the retrieved information about a list */
436
2d7360ca 437show_list_info(argc, argv, hint)
438int argc;
439char **argv;
440int hint;
441{
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");
1b6b0a57 448 printf("%s is %sa maillist and is %sa group", argv[0],
2d7360ca 449 atoi(argv[4]) ? "" : "not ",
450 atoi(argv[5]) ? "" : "not ");
451 if (atoi(argv[5]))
452 printf(" with GID %d\n", atoi(argv[6]));
453 else
454 printf("\n");
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]);
8defc06b 457 return(MR_CONT);
2d7360ca 458}
459
460
b5b167d6 461/* Show the retrieve list member count */
462
2d7360ca 463show_list_count(argc, argv, hint)
464int argc;
465char **argv;
466int hint;
467{
468 printf("Members: %s\n", argv[0]);
469}
470
471
b5b167d6 472/* Recursively find all of the members of listname, and then display them */
473
474recursive_display_list_members()
1b6b0a57 475{
b5b167d6 476 int status, count, savecount;
477 struct save_queue *lists, *members;
478 struct member *m, *m1, *data;
479
480 lists = sq_create();
481 members = sq_create();
482 m = (struct member *) malloc(sizeof(struct member));
483 m->type = M_LIST;
484 m->name = listname;
485 sq_save_data(lists, m);
486
487 while (sq_get_data(lists, &m)) {
488 sq_destroy(memberlist);
489 memberlist = sq_create();
490 if (debugflg)
491 fprintf(stderr, "Fetching members of %s\n", m->name);
8defc06b 492 status = mr_query("get_members_of_list", 1, &(m->name),
b5b167d6 493 get_list_members, (char *)memberlist);
494 if (status)
d44cee72 495 com_err(whoami, status, "while getting members of list %s", m->name);
b5b167d6 496 while (sq_get_data(memberlist, &m1)) {
497 if (m1->type == M_LIST)
498 unique_add_member(lists, m1);
499 else
500 unique_add_member(members, m1);
501 }
502 }
503 savecount = count = sq_count_elts(members);
504 data = (struct member *) malloc(count * sizeof(struct member));
505 count = 0;
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]);
511 }
512}
513
514
515/* add a struct member to a queue if that member isn't already there. */
516
517unique_add_member(q, m)
518struct save_queue *q;
519struct member *m;
520{
521 struct save_queue *qp;
1b6b0a57 522
b5b167d6 523 for (qp = q->q_next; qp != q; qp = qp->q_next) {
524 if (!membercmp(qp->q_data, m))
525 return;
526 }
527 sq_save_data(q, m);
1b6b0a57 528}
529
b5b167d6 530
531/* Collect the retrieved members of the list */
532
2d7360ca 533get_list_members(argc, argv, q)
534int argc;
535char **argv;
536struct save_queue *q;
537{
538 struct member *m;
539
540 m = (struct member *) malloc(sizeof(struct member));
541 switch (argv[0][0]) {
542 case 'U':
543 m->type = M_USER;
544 break;
545 case 'L':
546 m->type = M_LIST;
547 break;
548 case 'S':
549 m->type = M_STRING;
550 break;
8c3b414d 551 case 'K':
552 m->type = M_KERBEROS;
553 break;
2d7360ca 554 }
555 m->name = strsave(argv[1]);
556 sq_save_data(q, m);
8defc06b 557 return(MR_CONT);
2d7360ca 558}
559
560
b5b167d6 561/* Called only if a query returns a value that we weren't expecting */
562
2d7360ca 563scream()
564{
565 fprintf(stderr, "Programmer botch\n");
566 exit(3);
567}
568
569
7c02cbdb 570/* Open file, parse members from file, and put them on the specified queue */
571get_members_from_file(filename, queue)
572char *filename;
573struct save_queue *queue;
574{
575 FILE *in;
576 char buf[BUFSIZ];
577 struct member *memberstruct;
578
579 if (!strcmp(filename, "-"))
580 in = stdin;
581 else {
582 in = fopen(filename, "r");
583 if (!in) {
584 com_err(whoami, errno, "while opening %s for input", filename);
585 exit(2);
586 }
587 }
588
589 while (fgets(buf, BUFSIZ, in))
590 if (memberstruct = parse_member(buf))
591 sq_save_data(queue, memberstruct);
592 if (!feof(in))
593 com_err(whoami, errno, "while reading from %s", filename);
594}
595
596
b5b167d6 597/* Parse a line of input, fetching a member. NULL is returned if a member
7c02cbdb 598 * is not found. ';' is a comment character.
b5b167d6 599 */
600
2d7360ca 601struct member *parse_member(s)
602register char *s;
603{
604 register struct member *m;
7c02cbdb 605 char *p, *lastchar;
2d7360ca 606
607 while (*s && isspace(*s))
608 s++;
7c02cbdb 609 lastchar = p = s;
610 while (*p && *p != '\n' && *p != ';')
611 if (isprint(*p) && !isspace(*p))
612 lastchar = p++;
613 else
614 p++;
615 lastchar++;
616 *lastchar = 0;
2d7360ca 617 if (p == s || strlen(s) == 0)
618 return(NULL);
619
620 if ((m = (struct member *) malloc(sizeof(struct member))) == NULL)
621 return(NULL);
622
623 if (p = index(s, ':')) {
624 *p = 0;
625 m->name = ++p;
626 if (!strcasecmp("user", s))
627 m->type = M_USER;
628 else if (!strcasecmp("list", s))
629 m->type = M_LIST;
630 else if (!strcasecmp("string", s))
631 m->type = M_STRING;
8c3b414d 632 else if (!strcasecmp("kerberos", s))
633 m->type = M_KERBEROS;
2d7360ca 634 else {
635 m->type = M_STRING;
636 *(--p) = ':';
637 m->name = s;
638 }
639 m->name = strsave(m->name);
640 return(m);
641 }
642 m->name = strsave(s);
7c02cbdb 643 if (index(s, '@') || index(s, '!') || index(s, '%') || index(s, ' '))
2d7360ca 644 m->type = M_STRING;
645 else
646 m->type = M_ANY;
647 return(m);
648}
649
650
1b6b0a57 651 /*
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).
659 */
b5b167d6 660
661int membercmp(m1, m2)
662 struct member *m1, *m2;
2d7360ca 663{
1b6b0a57 664 if (m1->type == M_ANY || m2->type == M_ANY || (m1->type == m2->type))
665 return(strcmp(m1->name, m2->name));
2d7360ca 666 else
1b6b0a57 667 return(m1->type - m2->type);
2d7360ca 668}
b5b167d6 669
670
671sq_count_elts(q)
672struct save_queue *q;
673{
674 char *foo;
675 int count;
676
677 count = 0;
678 while (sq_get_data(q, &foo))
679 count++;
680 return(count);
681}
This page took 0.173704 seconds and 5 git commands to generate.