]> andersk Git - moira.git/blame - clients/blanche/blanche.c
support type KERBEROS list members
[moira.git] / clients / blanche / blanche.c
CommitLineData
2d7360ca 1/* $Header$
2 *
3 * Command line oriented SMS List tool.
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>
20#include <sms.h>
21#include <sms_app.h>
22
23#ifndef LINT
24static char smslist_rcsid[] = "$Header$";
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
38
1b6b0a57 39/* argument parsing macro */
40#define argis(a,b) ((strcmp(*arg+1, a) == 0) || (strcmp(*arg+1, b) == 0))
41
2d7360ca 42/* flags from command line */
8b494222 43int infoflg, verbose, syncflg, memberflg, recursflg, debugflg, noauth;
44int showusers, showstrings, showlists;
2d7360ca 45
46/* various member lists */
47struct save_queue *addlist, *dellist, *memberlist, *synclist;
48
49char *listname, *whoami;
50
51extern char *index();
52extern int errno;
53
54int show_list_info(), show_list_count(), get_list_members(), scream();
1b6b0a57 55int show_list_members();
2d7360ca 56struct member *parse_member();
57
58
59
60main(argc, argv)
61int argc;
62char **argv;
63{
64 int status;
65 char **arg = argv;
66 char *membervec[3];
67 struct member *memberstruct;
68
69 /* clear all flags & lists */
1b6b0a57 70 infoflg = verbose = syncflg = memberflg = debugflg = recursflg = 0;
8b494222 71 noauth = showusers = showstrings = showlists = 0;
2d7360ca 72 listname = NULL;
73 addlist = sq_create();
74 dellist = sq_create();
75 memberlist = sq_create();
76 synclist = sq_create();
77 whoami = argv[0];
78
79 /* parse args, building addlist, dellist, & synclist */
80 while (++arg - argv < argc) {
81 if (**arg == '-')
1b6b0a57 82 {
83 if (argis("m", "members"))
84 memberflg++;
8b494222 85 else if (argis("u", "users"))
86 showusers++;
87 else if (argis("s", "strings"))
88 showstrings++;
89 else if (argis("l", "lists"))
90 showlists++;
1b6b0a57 91 else if (argis("D", "debug"))
92 debugflg++;
93 else if (argis("i","information"))
2d7360ca 94 infoflg++;
8b494222 95 else if (argis("n","noauth"))
96 noauth++;
1b6b0a57 97 else if (argis("v","verbose"))
2d7360ca 98 verbose++;
1b6b0a57 99 else if (argis("r","recursive"))
100 recursflg++;
101 else if (argis("a","add"))
102 if (arg - argv < argc - 1) {
103 ++arg;
104 if (memberstruct = parse_member(*arg))
105 sq_save_data(addlist, memberstruct);
106 } else
107 usage(argv);
108 else if (argis("d","delete"))
109 if (arg - argv < argc - 1) {
110 ++arg;
111 if (memberstruct = parse_member(*arg))
112 sq_save_data(dellist, memberstruct);
113 } else
114 usage(argv);
115 else if (argis("f","file"))
116 if (arg - argv < argc - 1) {
117 FILE *in;
118 char buf[BUFSIZ];
b5b167d6 119
1b6b0a57 120 syncflg++;
121 ++arg;
122 if (!strcmp(*arg, "-"))
b5b167d6 123 in = stdin;
1b6b0a57 124 else {
125 in = fopen(*arg, "r");
b5b167d6 126 if (!in) {
1b6b0a57 127 com_err(whoami, errno,
128 " while opening %s for input", *arg);
129 exit(2);
130 }
131 }
132 while (fgets(buf, BUFSIZ, in))
b5b167d6 133 if (memberstruct = parse_member(buf))
134 sq_save_data(synclist, memberstruct);
1b6b0a57 135 if (!feof(in))
b5b167d6 136 com_err(whoami, errno, " while reading from %s", *arg);
1b6b0a57 137 } else
b5b167d6 138 usage(argv);
1b6b0a57 139 else
2d7360ca 140 usage(argv);
1b6b0a57 141 }
2d7360ca 142 else if (listname == NULL)
143 listname = *arg;
144 else
145 usage(argv);
146 }
147 if (listname == NULL)
148 usage(argv);
149
150 /* if no other options specified, turn on list members flag */
151 if (!(infoflg || syncflg ||
152 addlist->q_next != addlist || dellist->q_next != dellist))
153 memberflg++;
154
8b494222 155 /* If none of {users,strings,lists} specified, turn them all on */
156 if (!(showusers || showstrings || showlists))
157 showusers = showstrings = showlists = 1;
158
2d7360ca 159 /* fire up SMS */
a4ed33c1 160 if (status = sms_connect(SMS_SERVER)) {
2d7360ca 161 com_err(whoami, status, " unable to connect to SMS");
162 exit(2);
163 }
8b494222 164 if (!noauth && (status = sms_auth("blanche"))) {
2d7360ca 165 com_err(whoami, status, " unable to authenticate to SMS");
8b494222 166 com_err(whoami, 0,
167 "Try the -noauth flag if you don't need authentication");
2d7360ca 168 exit(2);
169 }
170
171 /* display list info if requested to */
172 if (infoflg) {
173 status = sms_query("get_list_info", 1, &listname, show_list_info,NULL);
174 if (status)
175 com_err(whoami, status, " while getting list information");
176 if (verbose && !memberflg) {
177 status = sms_query("count_members_of_list", 1, &listname,
178 show_list_count, NULL);
179 if (status)
180 com_err(whoami, status, " while getting list count");
181 }
182 }
183
184 /* if we're synchronizing to a file, we need to:
185 * get the current members of the list
186 * for each member of the sync file
187 * if they are on the list, remove them from the in-memory copy
188 * if they're not on the list, add them to add-list
189 * if anyone is left on the in-memory copy, put them on the delete-list
190 * lastly, reset memberlist so we can use it again later
191 */
192 if (syncflg) {
193 status = sms_query("get_members_of_list", 1, &listname,
1b6b0a57 194 get_list_members, (char *)memberlist);
2d7360ca 195 if (status)
b5b167d6 196 com_err(whoami, status, " getting members of list %s", listname);
2d7360ca 197 while (sq_get_data(synclist, &memberstruct)) {
198 struct save_queue *q;
199 int removed = 0;
200
201 for (q = memberlist->q_next; q != memberlist; q = q->q_next) {
1b6b0a57 202 if (membercmp(q->q_data, memberstruct) == 0) {
2d7360ca 203 q->q_prev->q_next = q->q_next;
204 q->q_next->q_prev = q->q_prev;
205 removed++;
206 break;
207 }
208 }
209 if (!removed)
210 sq_save_data(addlist, memberstruct);
211 }
212 while (sq_get_data(memberlist, &memberstruct))
213 sq_save_data(dellist, memberstruct);
214 sq_destroy(memberlist);
215 memberlist = sq_create();
216 }
217
218 /* Process the add list */
219 while (sq_get_data(addlist, &memberstruct)) {
220 membervec[0] = listname;
221 membervec[2] = memberstruct->name;
b5b167d6 222 if (verbose && syncflg) {
223 printf("Adding member ");
224 show_list_member(memberstruct);
225 }
2d7360ca 226 switch (memberstruct->type) {
227 case M_ANY:
228 case M_USER:
229 membervec[1] = "USER";
230 status = sms_query("add_member_to_list", 3, membervec, scream, NULL);
231 if (status == SMS_SUCCESS)
232 break;
233 else if (status != SMS_USER || memberstruct->type != M_ANY) {
234 com_err(whoami, status, " while adding member %s to %s",
235 memberstruct->name, listname);
236 break;
237 }
238 case M_LIST:
239 membervec[1] = "LIST";
240 status = sms_query("add_member_to_list", 3, membervec,
241 scream, NULL);
242 if (status == SMS_SUCCESS)
243 break;
244 else if (status != SMS_LIST || memberstruct->type != M_ANY) {
245 com_err(whoami, status, " while adding member %s to %s",
246 memberstruct->name, listname);
247 break;
248 }
249 case M_STRING:
250 membervec[1] = "STRING";
251 status = sms_query("add_member_to_list", 3, membervec,
252 scream, NULL);
253 if (status != SMS_SUCCESS)
254 com_err(whoami, status, " while adding member %s to %s",
255 memberstruct->name, listname);
256 }
257 }
258
259 /* Process the delete list */
260 while (sq_get_data(dellist, &memberstruct)) {
261 membervec[0] = listname;
262 membervec[2] = memberstruct->name;
b5b167d6 263 if (verbose && syncflg) {
264 printf("Deleting member ");
265 show_list_member(memberstruct);
266 }
2d7360ca 267 switch (memberstruct->type) {
268 case M_ANY:
269 case M_USER:
270 membervec[1] = "USER";
271 status = sms_query("delete_member_from_list", 3, membervec,
272 scream, NULL);
273 if (status == SMS_SUCCESS)
274 break;
275 else if ((status != SMS_USER && status != SMS_NO_MATCH) ||
276 memberstruct->type != M_ANY) {
277 com_err(whoami, status, " while deleteing member %s from %s",
278 memberstruct->name, listname);
279 break;
280 }
281 case M_LIST:
282 membervec[1] = "LIST";
283 status = sms_query("delete_member_from_list", 3, membervec,
284 scream, NULL);
285 if (status == SMS_SUCCESS)
286 break;
287 else if ((status != SMS_LIST && status != SMS_NO_MATCH) ||
288 memberstruct->type != M_ANY) {
289 com_err(whoami, status, " while deleteing member %s from %s",
290 memberstruct->name, listname);
291 break;
292 }
293 case M_STRING:
294 membervec[1] = "STRING";
295 status = sms_query("delete_member_from_list", 3, membervec,
296 scream, NULL);
297 if (status == SMS_STRING && memberstruct->type == M_ANY)
298 com_err(whoami, 0, "Unable to find member %s to delete from %s",
299 memberstruct->name, listname);
300 else if (status != SMS_SUCCESS)
301 com_err(whoami, status, " while deleteing member %s from %s",
302 memberstruct->name, listname);
303 }
304 }
305
306 /* Display the members of the list now, if requested */
b5b167d6 307 if (memberflg) {
308 if (recursflg)
309 recursive_display_list_members();
310 else {
311 status = sms_query("get_members_of_list", 1, &listname,
312 get_list_members, (char *)memberlist);
313 if (status)
314 com_err(whoami, status, " while getting members of list %s",
315 listname);
316 while (sq_get_data(memberlist, &memberstruct))
317 show_list_member(memberstruct);
318 }
319 }
2d7360ca 320
321 /* We're done! */
322 sms_disconnect();
323 exit(0);
324}
325
326usage(argv)
327char **argv;
328{
1b6b0a57 329 fprintf(stderr, "Usage: %s [options] listname [options]\n",argv[0]);
330 fprintf(stderr, "Options are\n");
331 fprintf(stderr, " -v | -verbose\n");
332 fprintf(stderr, " -m | -members\n");
8b494222 333 fprintf(stderr, " -u | -users\n");
334 fprintf(stderr, " -l | -lists\n");
335 fprintf(stderr, " -s | -strings\n");
1b6b0a57 336 fprintf(stderr, " -i | -info\n");
337 fprintf(stderr, " -r | -recursive\n");
338 fprintf(stderr, " -a | -add member\n");
339 fprintf(stderr, " -d | -delete member\n");
340 fprintf(stderr, " -f | -file filename\n");
8b494222 341 fprintf(stderr, " -n | -noauth\n");
1b6b0a57 342 fprintf(stderr, " -D | -debug\n");
2d7360ca 343 exit(1);
344}
345
346
b5b167d6 347/* Display the members stored in the queue */
1b6b0a57 348
b5b167d6 349show_list_member(memberstruct)
350struct member *memberstruct;
351{
8b494222 352 char *s;
353
354 switch (memberstruct->type) {
355 case M_USER:
356 if (!showusers)
357 return;
358 s = "USER";
359 break;
360 case M_LIST:
361 if (!showlists)
362 return;
363 s = "LIST";
364 break;
365 case M_STRING:
366 if (!showstrings)
367 return;
368 s = "STRING";
369 break;
370 case M_ANY:
371 printf("%s\n", memberstruct->name);
372 return;
373 }
374
375 if (verbose)
376 printf("%s:%s\n", s, memberstruct->name);
377 else {
b5b167d6 378 if (memberstruct->type == M_LIST)
379 printf("LIST:%s\n", memberstruct->name);
380 else if (memberstruct->type == M_STRING &&
381 !index(memberstruct->name, '@'))
382 printf("STRING:%s\n", memberstruct->name);
383 else
384 printf("%s\n", memberstruct->name);
1b6b0a57 385 }
386}
387
b5b167d6 388
389/* Show the retrieved information about a list */
390
2d7360ca 391show_list_info(argc, argv, hint)
392int argc;
393char **argv;
394int hint;
395{
396 printf("List: %s\n", argv[0]);
397 printf("Description: %s\n", argv[9]);
398 printf("Flags: %s, %s, and %s\n",
399 atoi(argv[1]) ? "active" : "inactive",
400 atoi(argv[2]) ? "public" : "private",
401 atoi(argv[3]) ? "hidden" : "visible");
1b6b0a57 402 printf("%s is %sa maillist and is %sa group", argv[0],
2d7360ca 403 atoi(argv[4]) ? "" : "not ",
404 atoi(argv[5]) ? "" : "not ");
405 if (atoi(argv[5]))
406 printf(" with GID %d\n", atoi(argv[6]));
407 else
408 printf("\n");
409 printf("Owner: %s %s\n", argv[7], argv[8]);
410 printf("Last modified by %s with %s on %s\n", argv[11], argv[12], argv[10]);
411 return(SMS_CONT);
412}
413
414
b5b167d6 415/* Show the retrieve list member count */
416
2d7360ca 417show_list_count(argc, argv, hint)
418int argc;
419char **argv;
420int hint;
421{
422 printf("Members: %s\n", argv[0]);
423}
424
425
b5b167d6 426/* Recursively find all of the members of listname, and then display them */
427
428recursive_display_list_members()
1b6b0a57 429{
b5b167d6 430 int status, count, savecount;
431 struct save_queue *lists, *members;
432 struct member *m, *m1, *data;
433
434 lists = sq_create();
435 members = sq_create();
436 m = (struct member *) malloc(sizeof(struct member));
437 m->type = M_LIST;
438 m->name = listname;
439 sq_save_data(lists, m);
440
441 while (sq_get_data(lists, &m)) {
442 sq_destroy(memberlist);
443 memberlist = sq_create();
444 if (debugflg)
445 fprintf(stderr, "Fetching members of %s\n", m->name);
446 status = sms_query("get_members_of_list", 1, &(m->name),
447 get_list_members, (char *)memberlist);
448 if (status)
449 com_err(whoami, status, " while getting members of list %s", m->name);
450 while (sq_get_data(memberlist, &m1)) {
451 if (m1->type == M_LIST)
452 unique_add_member(lists, m1);
453 else
454 unique_add_member(members, m1);
455 }
456 }
457 savecount = count = sq_count_elts(members);
458 data = (struct member *) malloc(count * sizeof(struct member));
459 count = 0;
460 while (sq_get_data(members, &m))
461 bcopy(m, &data[count++], sizeof(struct member));
462 qsort(data, count, sizeof(struct member), membercmp);
463 for (count = 0; count < savecount; count++) {
464 show_list_member(&data[count]);
465 }
466}
467
468
469/* add a struct member to a queue if that member isn't already there. */
470
471unique_add_member(q, m)
472struct save_queue *q;
473struct member *m;
474{
475 struct save_queue *qp;
1b6b0a57 476
b5b167d6 477 for (qp = q->q_next; qp != q; qp = qp->q_next) {
478 if (!membercmp(qp->q_data, m))
479 return;
480 }
481 sq_save_data(q, m);
1b6b0a57 482}
483
b5b167d6 484
485/* Collect the retrieved members of the list */
486
2d7360ca 487get_list_members(argc, argv, q)
488int argc;
489char **argv;
490struct save_queue *q;
491{
492 struct member *m;
493
494 m = (struct member *) malloc(sizeof(struct member));
495 switch (argv[0][0]) {
496 case 'U':
497 m->type = M_USER;
498 break;
499 case 'L':
500 m->type = M_LIST;
501 break;
502 case 'S':
503 m->type = M_STRING;
504 break;
505 }
506 m->name = strsave(argv[1]);
507 sq_save_data(q, m);
508 return(SMS_CONT);
509}
510
511
b5b167d6 512/* Called only if a query returns a value that we weren't expecting */
513
2d7360ca 514scream()
515{
516 fprintf(stderr, "Programmer botch\n");
517 exit(3);
518}
519
520
b5b167d6 521/* Parse a line of input, fetching a member. NULL is returned if a member
522 * is not found. Only the first token on the line is parsed. ';' is a
523 * comment character.
524 */
525
2d7360ca 526struct member *parse_member(s)
527register char *s;
528{
529 register struct member *m;
530 char *p;
531
532 while (*s && isspace(*s))
533 s++;
534 p = s;
535 while (*p && isprint(*p) && !isspace(*p) && *p != ';')
536 p++;
537 *p = 0;
538 if (p == s || strlen(s) == 0)
539 return(NULL);
540
541 if ((m = (struct member *) malloc(sizeof(struct member))) == NULL)
542 return(NULL);
543
544 if (p = index(s, ':')) {
545 *p = 0;
546 m->name = ++p;
547 if (!strcasecmp("user", s))
548 m->type = M_USER;
549 else if (!strcasecmp("list", s))
550 m->type = M_LIST;
551 else if (!strcasecmp("string", s))
552 m->type = M_STRING;
553 else {
554 m->type = M_STRING;
555 *(--p) = ':';
556 m->name = s;
557 }
558 m->name = strsave(m->name);
559 return(m);
560 }
561 m->name = strsave(s);
562 if (index(s, '@') || index(s, '!') || index(s, '%'))
563 m->type = M_STRING;
564 else
565 m->type = M_ANY;
566 return(m);
567}
568
569
1b6b0a57 570 /*
571 * This routine two compares members by the following rules:
572 * 1. A USER is less than a LIST
573 * 2. A LIST is less than a STRING
574 * 3. If two members are of the same type, the one alphabetically first
575 * is less than the other
576 * It returs < 0 if the first member is less, 0 if they are identical, and
577 * > 0 if the second member is less (the first member is greater).
578 */
b5b167d6 579
580int membercmp(m1, m2)
581 struct member *m1, *m2;
2d7360ca 582{
1b6b0a57 583 if (m1->type == M_ANY || m2->type == M_ANY || (m1->type == m2->type))
584 return(strcmp(m1->name, m2->name));
2d7360ca 585 else
1b6b0a57 586 return(m1->type - m2->type);
2d7360ca 587}
b5b167d6 588
589
590sq_count_elts(q)
591struct save_queue *q;
592{
593 char *foo;
594 int count;
595
596 count = 0;
597 while (sq_get_data(q, &foo))
598 count++;
599 return(count);
600}
This page took 0.134181 seconds and 5 git commands to generate.