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