]> andersk Git - moira.git/blob - clients/blanche/blanche.c
eliminate use of the `register' keyword: let the compiler decide
[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 <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <ctype.h>
22 #include <string.h>
23 #include <moira.h>
24 #include <moira_site.h>
25
26 #ifndef LINT
27 static char blanche_rcsid[] = "$Header$";
28 #endif
29
30
31 struct member {
32   int type;
33   char *name;
34 };
35
36 /* It is important to membercmp that M_USER < M_LIST < M_STRING */
37 #define M_ANY           0
38 #define M_USER          1
39 #define M_LIST          2
40 #define M_STRING        3
41 #define M_KERBEROS      4
42
43 /* argument parsing macro */
44 #define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
45
46 /* flags from command line */
47 int infoflg, verbose, syncflg, memberflg, recursflg, noauth;
48 int showusers, showstrings, showkerberos, showlists;
49 int createflag, setinfo, active, public, hidden, maillist, grouplist;
50 struct member *owner;
51 char *desc, *newname;
52
53 /* various member lists */
54 struct save_queue *addlist, *dellist, *memberlist, *synclist;
55
56 char *listname, *whoami;
57
58 int show_list_info(), show_list_count(), get_list_members(), scream();
59 int show_list_members(), membercmp(), save_list_info();
60 struct member *parse_member();
61
62 int main(int argc, char **argv)
63 {
64   int status, success;
65   char **arg = argv;
66   char *membervec[3], *motd;
67   struct member *memberstruct;
68   char *server = NULL, *p;
69
70   /* clear all flags & lists */
71   infoflg = verbose = syncflg = memberflg = recursflg = 0;
72   noauth = showusers = showstrings = showkerberos = showlists = 0;
73   createflag = setinfo = 0;
74   active = public = hidden = maillist = grouplist = -1;
75   listname = newname = desc = NULL;
76   owner = NULL;
77   addlist = sq_create();
78   dellist = sq_create();
79   memberlist = sq_create();
80   synclist = sq_create();
81   whoami = argv[0];
82
83   success = 1;
84
85   /* parse args, building addlist, dellist, & synclist */
86   while (++arg - argv < argc)
87     {
88       if (**arg == '-')
89         {
90           if (argis("m", "members"))
91             memberflg++;
92           else if (argis("u", "users"))
93             showusers++;
94           else if (argis("s", "strings"))
95             showstrings++;
96           else if (argis("l", "lists"))
97             showlists++;
98           else if (argis("k", "kerberos"))
99             showkerberos++;
100           else if (argis("i", "info"))
101             infoflg++;
102           else if (argis("n", "noauth"))
103             noauth++;
104           else if (argis("v", "verbose"))
105             verbose++;
106           else if (argis("r", "recursive"))
107             recursflg++;
108           else if (argis("S", "server") || argis("db", "database"))
109             {
110               if (arg - argv < argc - 1)
111                 {
112                   ++arg;
113                   server = *arg;
114                 }
115               else
116                 usage(argv);
117             }
118           else if (argis("a", "add"))
119             {
120               if (arg - argv < argc - 1)
121                 {
122                   ++arg;
123                   if ((memberstruct = parse_member(*arg)))
124                     sq_save_data(addlist, memberstruct);
125                 }
126               else
127                 usage(argv);
128             }
129           else if (argis("al", "addlist"))
130             {
131               if (arg - argv < argc - 1)
132                 {
133                   ++arg;
134                   get_members_from_file(*arg, addlist);
135                 }
136               else
137                 usage(argv);
138             }
139           else if (argis("d", "delete"))
140             {
141               if (arg - argv < argc - 1)
142                 {
143                   ++arg;
144                   if ((memberstruct = parse_member(*arg)))
145                     sq_save_data(dellist, memberstruct);
146                 }
147               else
148                 usage(argv);
149             }
150           else if (argis("dl", "deletelist"))
151             {
152               if (arg - argv < argc - 1)
153                 {
154                   ++arg;
155                   get_members_from_file(*arg, dellist);
156                 }
157               else
158                 usage(argv);
159             }
160           else if (argis("f", "file"))
161             {
162               if (arg - argv < argc - 1)
163                 {
164                   syncflg++;
165                   ++arg;
166                   get_members_from_file(*arg, synclist);
167                 }
168               else
169                 usage(argv);
170             }
171           else if (argis("C", "create"))
172             createflag++;
173           else if (argis("P", "public"))
174             {
175               setinfo++;
176               public = 1;
177             }
178           else if (argis("NP", "private"))
179             {
180               setinfo++;
181               public = 0;
182             }
183           else if (argis("A", "active"))
184             {
185               setinfo++;
186               active = 1;
187             }
188           else if (argis("I", "inactive"))
189             {
190               setinfo++;
191               active = 0;
192             }
193           else if (argis("V", "visible"))
194             {
195               setinfo++;
196               hidden = 0;
197             }
198           else if (argis("H", "hidden"))
199             {
200               setinfo++;
201               hidden = 1;
202             }
203           else if (argis("M", "mail"))
204             {
205               setinfo++;
206               maillist = 1;
207             }
208           else if (argis("NM", "notmail"))
209             {
210               setinfo++;
211               maillist = 0;
212             }
213           else if (argis("G", "group"))
214             {
215               setinfo++;
216               grouplist = 1;
217             }
218           else if (argis("NG", "notgroup"))
219             {
220               setinfo++;
221               grouplist = 0;
222             }
223           else if (argis("D", "desc"))
224             {
225               if (arg - argv < argc - 1)
226                 {
227                   setinfo++;
228                   ++arg;
229                   desc = *arg;
230                 }
231               else
232                 usage(argv);
233             }
234           else if (argis("O", "owner"))
235             {
236               if (arg - argv < argc - 1)
237                 {
238                   setinfo++;
239                   ++arg;
240                   owner = parse_member(*arg);
241                 }
242               else
243                 usage(argv);
244             }
245           else if (argis("R", "rename"))
246             {
247               if (arg - argv < argc - 1)
248                 {
249                   setinfo++;
250                   ++arg;
251                   newname = *arg;
252                 }
253               else
254                 usage(argv);
255             }
256           else
257             usage(argv);
258         }
259       else if (listname == NULL)
260         listname = *arg;
261       else
262         usage(argv);
263     }
264   if (listname == NULL)
265     usage(argv);
266
267   /* if no other options specified, turn on list members flag */
268   if (!(infoflg || syncflg || createflag || setinfo ||
269         addlist->q_next != addlist || dellist->q_next != dellist))
270     memberflg++;
271
272   /* If none of {users,strings,lists,kerberos} specified, turn them all on */
273   if (!(showusers || showstrings || showlists || showkerberos))
274     showusers = showstrings = showlists = showkerberos = 1;
275
276   /* fire up Moira */
277   if ((status = mr_connect(server)))
278     {
279       com_err(whoami, status, "unable to connect to the Moira server");
280       exit(2);
281     }
282   if ((status = mr_motd(&motd)))
283     {
284       com_err(whoami, status, "unable to check server status");
285       exit(2);
286     }
287   if (motd)
288     {
289       fprintf(stderr, "The Moira server is currently unavailable:\n%s\n",
290               motd);
291       mr_disconnect();
292       exit(2);
293     }
294
295   if (!noauth && (status = mr_auth("blanche")))
296     {
297       if (status == MR_USER_AUTH)
298         com_err(whoami, status, "");
299       else
300         {
301           com_err(whoami, status, "unable to authenticate to Moira");
302           com_err(whoami, 0,
303                   " Try the -noauth flag if you don't need authentication");
304           exit(2);
305         }
306     }
307
308   /* create if needed */
309   if (createflag)
310     {
311       char *argv[10];
312
313       argv[0] = listname;
314       argv[1] = (active == 0) ? "0" : "1";
315       argv[2] = (public == 1) ? "1" : "0";
316       argv[3] = (hidden == 1) ? "1" : "0";
317       argv[4] = (maillist == 0) ? "0" : "1";
318       argv[5] = (grouplist == 1) ? "1" : "0";
319       argv[6] = UNIQUE_GID;
320       argv[9] = desc ? desc : "none";
321
322       if (owner)
323         {
324           argv[8] = owner->name;
325           switch (owner->type)
326             {
327             case M_ANY:
328             case M_USER:
329               argv[7] = "USER";
330               status = mr_query("add_list", 10, argv, scream, NULL);
331               if (owner->type != M_ANY || status != MR_USER)
332                 break;
333
334             case M_LIST:
335               argv[7] = "LIST";
336               status = mr_query("add_list", 10, argv, scream, NULL);
337               break;
338
339             case M_KERBEROS:
340               argv[7] = "KERBEROS";
341               status = mr_query("add_list", 10, argv, scream, NULL);
342               break;
343             }
344         }
345       else
346         {
347           argv[7] = "USER";
348           argv[8] = getenv("USER");
349
350           status = mr_query("add_list", 10, argv, scream, NULL);
351         }
352
353       if (status)
354         {
355           com_err(whoami, status, "while creating list.");
356           exit(1);
357         }
358     }
359   else if (setinfo)
360     {
361       char *argv[11];
362
363       status = mr_query("get_list_info", 1, &listname,
364                         save_list_info, (char *)argv);
365       if (status)
366         {
367           com_err(whoami, status, "while getting list information");
368           exit(1);
369         }
370
371       argv[0] = listname;
372       if (newname)
373         argv[1] = newname;
374       if (active != -1)
375         argv[2] = active ? "1" : "0";
376       if (public != -1)
377         argv[3] = public ? "1" : "0";
378       if (hidden != -1)
379         argv[4] = hidden ? "1" : "0";
380       if (maillist != -1)
381         argv[5] = maillist ? "1" : "0";
382       if (grouplist != -1)
383         argv[6] = grouplist ? "1" : "0";
384       if (desc)
385         argv[10] = desc;
386
387       if (owner)
388         {
389           argv[9] = owner->name;
390           switch (owner->type)
391             {
392             case M_ANY:
393             case M_USER:
394               argv[8] = "USER";
395               status = mr_query("update_list", 11, argv, scream, NULL);
396               if (owner->type != M_ANY || status != MR_USER)
397                 break;
398
399             case M_LIST:
400               argv[8] = "LIST";
401               status = mr_query("update_list", 11, argv, scream, NULL);
402               break;
403
404             case M_KERBEROS:
405               argv[8] = "KERBEROS";
406               status = mr_query("update_list", 11, argv, scream, NULL);
407               break;
408             }
409         }
410       else
411         status = mr_query("update_list", 11, argv, scream, NULL);
412
413       if (status)
414         com_err(whoami, status, "while updating list.");
415       else if (newname)
416         listname = newname;
417     }
418
419   /* display list info if requested to */
420   if (infoflg)
421     {
422       status = mr_query("get_list_info", 1, &listname, show_list_info, NULL);
423       if (status)
424         com_err(whoami, status, "while getting list information");
425       if (verbose && !memberflg)
426         {
427           status = mr_query("count_members_of_list", 1, &listname,
428                             show_list_count, NULL);
429           if (status)
430             com_err(whoami, status, "while getting list count");
431         }
432     }
433
434   /* if we're synchronizing to a file, we need to:
435    *  get the current members of the list
436    *    for each member of the sync file
437    *       if they are on the list, remove them from the in-memory copy
438    *       if they're not on the list, add them to add-list
439    *    if anyone is left on the in-memory copy, put them on the delete-list
440    * lastly, reset memberlist so we can use it again later
441    */
442   if (syncflg)
443     {
444       status = mr_query("get_members_of_list", 1, &listname,
445                         get_list_members, (char *)memberlist);
446       if (status)
447         {
448           com_err(whoami, status, "getting members of list %s", listname);
449           exit(2);
450         }
451       while (sq_get_data(synclist, &memberstruct))
452         {
453           struct save_queue *q;
454           int removed = 0;
455
456           for (q = memberlist->q_next; q != memberlist; q = q->q_next)
457             {
458               if (membercmp(q->q_data, memberstruct) == 0)
459                 {
460                   q->q_prev->q_next = q->q_next;
461                   q->q_next->q_prev = q->q_prev;
462                   removed++;
463                   break;
464                 }
465             }
466           if (!removed)
467             sq_save_data(addlist, memberstruct);
468         }
469       while (sq_get_data(memberlist, &memberstruct))
470         sq_save_data(dellist, memberstruct);
471       sq_destroy(memberlist);
472       memberlist = sq_create();
473     }
474
475   /* Process the add list */
476   while (sq_get_data(addlist, &memberstruct))
477     {
478       /* canonicalize string if necessary */
479       if (memberstruct->type == M_STRING &&
480           (p = strchr(memberstruct->name, '@')))
481         {
482           char *host = canonicalize_hostname(strsave(++p));
483           static char **mailhubs = NULL;
484           char *argv[4];
485           int i, collect();
486
487           if (!mailhubs)
488             {
489               argv[0] = "mailhub";
490               argv[1] = "TYPE";
491               argv[2] = "*";
492               mailhubs = malloc(sizeof(char *));
493               mailhubs[0] = NULL;
494               status = mr_query("get_alias", 3, argv, collect,
495                                 (char *)&mailhubs);
496               if (status != MR_SUCCESS && status != MR_NO_MATCH)
497                 {
498                   com_err(whoami, status,
499                           " while reading list of MAILHUB servers");
500                   mailhubs[0] = NULL;
501                 }
502             }
503           for (i = 0; (p = mailhubs[i]); i++)
504             {
505               if (!strcasecmp(p, host))
506                 {
507                   host = strsave(memberstruct->name);
508                   *(strchr(memberstruct->name, '@')) = 0;
509                   memberstruct->type = M_ANY;
510                   fprintf(stderr, "Warning: \"STRING:%s\" converted to "
511                           "\"%s\" because it is a local name.\n",
512                           host, memberstruct->name);
513                   break;
514                 }
515             }
516           free(host);
517         }
518       /* now continue adding member */
519       membervec[0] = listname;
520       membervec[2] = memberstruct->name;
521       if (verbose)
522         {
523           printf("Adding member ");
524           show_list_member(memberstruct);
525         }
526       switch (memberstruct->type)
527         {
528         case M_ANY:
529         case M_USER:
530           membervec[1] = "USER";
531           status = mr_query("add_member_to_list", 3, membervec, scream, NULL);
532           if (status == MR_SUCCESS)
533             break;
534           else if (status != MR_USER || memberstruct->type != M_ANY)
535             {
536               com_err(whoami, status, "while adding member %s to %s",
537                       memberstruct->name, listname);
538               success = 0;
539               break;
540             }
541         case M_LIST:
542           membervec[1] = "LIST";
543           status = mr_query("add_member_to_list", 3, membervec,
544                             scream, NULL);
545           if (status == MR_SUCCESS)
546             {
547               if (!strcmp(membervec[0], getenv("USER")))
548                 {
549                   fprintf(stderr, "\nWARNING: \"LIST:%s\" was just added "
550                           "to list \"%s\".\n", membervec[2], membervec[0]);
551                   fprintf(stderr, "If you meant to add yourself to the list "
552                           "\"%s\", type:\n", membervec[2]);
553                   fprintf(stderr, "\tblanche %s -d %s\t(to undo this)\n",
554                           membervec[0], membervec[2]);
555                   fprintf(stderr, "\tblanche %s -a %s\t(to add yourself to "
556                           "that list)\n", membervec[2], membervec[0]);
557                 }
558               break;
559             }
560           else if (status != MR_LIST || memberstruct->type != M_ANY)
561             {
562               com_err(whoami, status, "while adding member %s to %s",
563                       memberstruct->name, listname);
564               success = 0;
565               break;
566             }
567         case M_STRING:
568           if (memberstruct->type == M_ANY &&
569               !strchr(memberstruct->name, '@') &&
570               !strchr(memberstruct->name, '!') &&
571               !strchr(memberstruct->name, '%'))
572             {
573               /* if user is trying to add something which isn't a
574                  remote string, or a list, or a user, and didn't
575                  explicitly specify `STRING:', it's probably a typo */
576               com_err(whoami, MR_NO_MATCH, "while adding member %s to %s",
577                       memberstruct->name, listname);
578               success = 0;
579               break;
580             }
581
582           membervec[1] = "STRING";
583           status = mr_query("add_member_to_list", 3, membervec,
584                             scream, NULL);
585           if (status != MR_SUCCESS)
586             {
587               com_err(whoami, status, "while adding member %s to %s",
588                       memberstruct->name, listname);
589               success = 0;
590             }
591           break;
592         case M_KERBEROS:
593           membervec[1] = "KERBEROS";
594           status = mr_query("add_member_to_list", 3, membervec,
595                             scream, NULL);
596           if (status != MR_SUCCESS)
597             {
598               com_err(whoami, status, "while adding member %s to %s",
599                       memberstruct->name, listname);
600               success = 0;
601             }
602         }
603     }
604
605   /* Process the delete list */
606   while (sq_get_data(dellist, &memberstruct))
607     {
608       membervec[0] = listname;
609       membervec[2] = memberstruct->name;
610       if (verbose)
611         {
612           printf("Deleting member ");
613           show_list_member(memberstruct);
614         }
615       switch (memberstruct->type)
616         {
617         case M_ANY:
618         case M_USER:
619           membervec[1] = "USER";
620           status = mr_query("delete_member_from_list", 3, membervec,
621                             scream, NULL);
622           if (status == MR_SUCCESS)
623             break;
624           else if ((status != MR_USER && status != MR_NO_MATCH) ||
625                    memberstruct->type != M_ANY)
626             {
627               com_err(whoami, status, "while deleting member %s from %s",
628                       memberstruct->name, listname);
629               success = 0;
630               break;
631             }
632         case M_LIST:
633           membervec[1] = "LIST";
634           status = mr_query("delete_member_from_list", 3, membervec,
635                             scream, NULL);
636           if (status == MR_SUCCESS)
637             break;
638           else if ((status != MR_LIST && status != MR_NO_MATCH) ||
639                    memberstruct->type != M_ANY)
640             {
641               if (status == MR_PERM && memberstruct->type == M_ANY &&
642                   !strcmp(membervec[2], getenv("USER")))
643                 {
644                   /* M_ANY means we've fallen through from the user
645                    * case. The user is trying to remove himself from
646                    * a list, but we got MR_USER or MR_NO_MATCH above,
647                    * meaning he's not really on it, and we got MR_PERM
648                    * when trying to remove LIST:$USER because he's not
649                    * on the acl. That error is useless, so return
650                    * MR_NO_MATCH instead. However, this will generate the
651                    * wrong error if the user was trying to remove the list
652                    * with his username from a list he doesn't administrate
653                    * without explicitly specifying "list:".
654                    */
655                   status = MR_NO_MATCH;
656                 }
657               com_err(whoami, status, "while deleting member %s from %s",
658                       memberstruct->name, listname);
659               success = 0;
660               break;
661             }
662         case M_STRING:
663           membervec[1] = "STRING";
664           status = mr_query("delete_member_from_list", 3, membervec,
665                             scream, NULL);
666           if (status == MR_STRING && memberstruct->type == M_ANY)
667             {
668               com_err(whoami, 0, " Unable to find member %s to delete from %s",
669                       memberstruct->name, listname);
670               success = 0;
671               if (!strcmp(membervec[0], getenv("USER")))
672                 {
673                   fprintf(stderr, "(If you were trying to remove yourself "
674                           "from the list \"%s\",\n", membervec[2]);
675                   fprintf(stderr, "the correct command is \"blanche %s -d "
676                           "%s\".)\n", membervec[2], membervec[0]);
677                 }
678             }
679           else if (status != MR_SUCCESS)
680             {
681               com_err(whoami, status, "while deleting member %s from %s",
682                       memberstruct->name, listname);
683               success = 0;
684             }
685           break;
686         case M_KERBEROS:
687           membervec[1] = "KERBEROS";
688           status = mr_query("delete_member_from_list", 3, membervec,
689                             scream, NULL);
690           if (status != MR_SUCCESS)
691             {
692               com_err(whoami, status, "while deleting member %s from %s",
693                       memberstruct->name, listname);
694               success = 0;
695             }
696         }
697     }
698
699   /* Display the members of the list now, if requested */
700   if (memberflg)
701     {
702       if (recursflg)
703         recursive_display_list_members();
704       else
705         {
706           status = mr_query("get_members_of_list", 1, &listname,
707                             get_list_members, (char *)memberlist);
708           if (status)
709             com_err(whoami, status, "while getting members of list %s",
710                     listname);
711           while (sq_get_data(memberlist, &memberstruct))
712             show_list_member(memberstruct);
713         }
714     }
715
716   /* We're done! */
717   mr_disconnect();
718   exit(success ? 0 : 1);
719 }
720
721 usage(char **argv)
722 {
723   fprintf(stderr, "Usage: %s listname [options]\n", argv[0]);
724   fprintf(stderr, "Options are\n");
725   fprintf(stderr, "  %-39s%-39s\n", "-v  | -verbose",
726           "-C  | -create");
727   fprintf(stderr, "  %-39s%-39s\n", "-m  | -members",
728           "-R  | -rename newname");
729   fprintf(stderr, "  %-39s%-39s\n", "-u  | -users",
730           "-P  | -public");
731   fprintf(stderr, "  %-39s%-39s\n", "-l  | -lists",
732           "-NP | -private");
733   fprintf(stderr, "  %-39s%-39s\n", "-s  | -strings",
734           "-A  | -active");
735   fprintf(stderr, "  %-39s%-39s\n", "-k  | -kerberos",
736           "-I  | -inactive");
737   fprintf(stderr, "  %-39s%-39s\n", "-i  | -info",
738           "-V  | -visible");
739   fprintf(stderr, "  %-39s%-39s\n", "-r  | -recursive",
740           "-H  | -hidden");
741   fprintf(stderr, "  %-39s%-39s\n", "-a  | -add member",
742           "-M  | -mail");
743   fprintf(stderr, "  %-39s%-39s\n", "-d  | -delete member",
744           "-NM | -notmail");
745   fprintf(stderr, "  %-39s%-39s\n", "-al | -addlist filename",
746           "-G  | -group");
747   fprintf(stderr, "  %-39s%-39s\n", "-dl | -deletelist filename",
748           "-NG | -notgroup");
749   fprintf(stderr, "  %-39s%-39s\n", "-f  | -file filename",
750           "-D  | -desc description");
751   fprintf(stderr, "  %-39s%-39s\n", "-n  | -noauth",
752           "-O  | -owner owner");
753   fprintf(stderr, "  %-39s%-39s\n", "-db | -database host[:port]",
754           "");
755   exit(1);
756 }
757
758
759 /* Display the members stored in the queue */
760
761 show_list_member(struct member *memberstruct)
762 {
763   char *s = "";
764
765   switch (memberstruct->type)
766     {
767     case M_USER:
768       if (!showusers)
769         return;
770       s = "USER";
771       break;
772     case M_LIST:
773       if (!showlists)
774         return;
775       s = "LIST";
776       break;
777     case M_STRING:
778       if (!showstrings)
779         return;
780       s = "STRING";
781       break;
782     case M_KERBEROS:
783       if (!showkerberos)
784         return;
785       s = "KERBEROS";
786       break;
787     case M_ANY:
788       printf("%s\n", memberstruct->name);
789       return;
790     }
791
792   if (verbose)
793     printf("%s:%s\n", s, memberstruct->name);
794   else
795     {
796       if (memberstruct->type == M_LIST)
797         printf("LIST:%s\n", memberstruct->name);
798       else if (memberstruct->type == M_KERBEROS)
799         printf("KERBEROS:%s\n", memberstruct->name);
800       else if (memberstruct->type == M_STRING &&
801                !strchr(memberstruct->name, '@'))
802         printf("STRING:%s\n", memberstruct->name);
803       else
804         printf("%s\n", memberstruct->name);
805     }
806 }
807
808
809 /* Show the retrieved information about a list */
810
811 int show_list_info(int argc, char **argv, int hint)
812 {
813   printf("List: %s\n", argv[0]);
814   printf("Description: %s\n", argv[9]);
815   printf("Flags: %s, %s, and %s\n",
816          atoi(argv[1]) ? "active" : "inactive",
817          atoi(argv[2]) ? "public" : "private",
818          atoi(argv[3]) ? "hidden" : "visible");
819   printf("%s is %sa maillist and is %sa group", argv[0],
820          atoi(argv[4]) ? "" : "not ",
821          atoi(argv[5]) ? "" : "not ");
822   if (atoi(argv[5]))
823     printf(" with GID %d\n", atoi(argv[6]));
824   else
825     printf("\n");
826   printf("Owner: %s %s\n", argv[7], argv[8]);
827   printf("Last modified by %s with %s on %s\n", argv[11], argv[12], argv[10]);
828   return MR_CONT;
829 }
830
831
832 /* Copy retrieved information about a list into a new argv */
833
834 int save_list_info(int argc, char **argv, int hint)
835 {
836   char **nargv = (char **)hint;
837
838   for (argc = 0; argc < 10; argc++)
839     nargv[argc + 1] = strdup(argv[argc]);
840   return MR_CONT;
841 }
842
843 /* Show the retrieve list member count */
844
845 show_list_count(int argc, char **argv, int hint)
846 {
847   printf("Members: %s\n", argv[0]);
848 }
849
850
851 /* Recursively find all of the members of listname, and then display them */
852
853 recursive_display_list_members(void)
854 {
855   int status, count, savecount;
856   struct save_queue *lists, *members;
857   struct member *m, *m1, *data;
858
859   lists = sq_create();
860   members = sq_create();
861   m = malloc(sizeof(struct member));
862   m->type = M_LIST;
863   m->name = listname;
864   sq_save_data(lists, m);
865
866   while (sq_get_data(lists, &m))
867     {
868       sq_destroy(memberlist);
869       memberlist = sq_create();
870       status = mr_query("get_members_of_list", 1, &(m->name),
871                         get_list_members, (char *)memberlist);
872       if (status)
873         com_err(whoami, status, "while getting members of list %s", m->name);
874       while (sq_get_data(memberlist, &m1))
875         {
876           if (m1->type == M_LIST)
877             unique_add_member(lists, m1);
878           else
879             unique_add_member(members, m1);
880         }
881     }
882   savecount = count = sq_count_elts(members);
883   data = malloc(count * sizeof(struct member));
884   count = 0;
885   while (sq_get_data(members, &m))
886     memcpy(&data[count++], m, sizeof(struct member));
887   qsort(data, count, sizeof(struct member), membercmp);
888   for (count = 0; count < savecount; count++)
889     show_list_member(&data[count]);
890 }
891
892
893 /* add a struct member to a queue if that member isn't already there. */
894
895 unique_add_member(struct save_queue *q, struct member *m)
896 {
897   struct save_queue *qp;
898
899   for (qp = q->q_next; qp != q; qp = qp->q_next)
900     {
901       if (!membercmp(qp->q_data, m))
902         return;
903     }
904   sq_save_data(q, m);
905 }
906
907
908 /* Collect the retrieved members of the list */
909
910 int get_list_members(int argc, char **argv, struct save_queue *q)
911 {
912   struct member *m;
913
914   m = malloc(sizeof(struct member));
915   switch (argv[0][0])
916     {
917     case 'U':
918       m->type = M_USER;
919       break;
920     case 'L':
921       m->type = M_LIST;
922       break;
923     case 'S':
924       m->type = M_STRING;
925       break;
926     case 'K':
927       m->type = M_KERBEROS;
928       break;
929     }
930   m->name = strsave(argv[1]);
931   sq_save_data(q, m);
932   return MR_CONT;
933 }
934
935
936 /* Called only if a query returns a value that we weren't expecting */
937
938 scream(void)
939 {
940   fprintf(stderr, "Programmer botch\n");
941   exit(3);
942 }
943
944
945 /* Open file, parse members from file, and put them on the specified queue */
946 get_members_from_file(char *filename, struct save_queue *queue)
947 {
948   FILE *in;
949   char buf[BUFSIZ];
950   struct member *memberstruct;
951
952   if (!strcmp(filename, "-"))
953     in = stdin;
954   else
955     {
956       in = fopen(filename, "r");
957       if (!in)
958         {
959           com_err(whoami, errno, "while opening %s for input", filename);
960           exit(2);
961         }
962     }
963
964   while (fgets(buf, BUFSIZ, in))
965     {
966       if ((memberstruct = parse_member(buf)))
967         sq_save_data(queue, memberstruct);
968     }
969   if (!feof(in))
970     {
971       com_err(whoami, errno, "while reading from %s", filename);
972       exit(2);
973     }
974 }
975
976
977 /* Collect the possible expansions of the alias MAILHUB */
978
979 int collect(int argc, char **argv, char ***list)
980 {
981   int i;
982
983   for (i = 0; (*list)[i]; i++)
984     ;
985   *list = realloc(*list, (i + 2) * sizeof(char *));
986   (*list)[i] = strsave(argv[2]);
987   (*list)[i + 1] = NULL;
988   return MR_CONT;
989 }
990
991
992 /* Parse a line of input, fetching a member.  NULL is returned if a member
993  * is not found.  ';' is a comment character.
994  */
995
996 struct member *parse_member(char *s)
997 {
998   struct member *m;
999   char *p, *lastchar;
1000
1001   while (*s && isspace(*s))
1002     s++;
1003   lastchar = p = s;
1004   while (*p && *p != '\n' && *p != ';')
1005     {
1006       if (isprint(*p) && !isspace(*p))
1007         lastchar = p++;
1008       else
1009         p++;
1010     }
1011   lastchar++;
1012   *lastchar = '\0';
1013   if (p == s || strlen(s) == 0)
1014     return NULL;
1015
1016   if (!(m = malloc(sizeof(struct member))))
1017     return NULL;
1018
1019   if ((p = strchr(s, ':')))
1020     {
1021       *p = '\0';
1022       m->name = ++p;
1023       if (!strcasecmp("user", s))
1024         m->type = M_USER;
1025       else if (!strcasecmp("list", s))
1026         m->type = M_LIST;
1027       else if (!strcasecmp("string", s))
1028         m->type = M_STRING;
1029       else if (!strcasecmp("kerberos", s))
1030         m->type = M_KERBEROS;
1031       else
1032         {
1033           m->type = M_ANY;
1034           *(--p) = ':';
1035           m->name = s;
1036         }
1037       m->name = strsave(m->name);
1038     }
1039   else
1040     {
1041       m->name = strsave(s);
1042       m->type = M_ANY;
1043     }
1044   return m;
1045 }
1046
1047
1048 /*
1049  * This routine two compares members by the following rules:
1050  * 1.  A USER is less than a LIST
1051  * 2.  A LIST is less than a STRING
1052  * 3.  If two members are of the same type, the one alphabetically first
1053  *     is less than the other
1054  * It returs < 0 if the first member is less, 0 if they are identical, and
1055  * > 0 if the second member is less (the first member is greater).
1056  */
1057
1058 int membercmp(struct member *m1, struct member *m2)
1059 {
1060   if (m1->type == M_ANY || m2->type == M_ANY || (m1->type == m2->type))
1061     return strcmp(m1->name, m2->name);
1062   else
1063     return m1->type - m2->type;
1064 }
1065
1066
1067 int sq_count_elts(struct save_queue *q)
1068 {
1069   char *foo;
1070   int count;
1071
1072   count = 0;
1073   while (sq_get_data(q, &foo))
1074     count++;
1075   return count;
1076 }
This page took 0.178983 seconds and 5 git commands to generate.