]> andersk Git - moira.git/blob - clients/blanche/blanche.c
Initial revision
[moira.git] / clients / blanche / blanche.c
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.
8  */
9
10 #include <mit-copyright.h>
11 #include <stdio.h>
12 #include <ctype.h>
13 #include <sms.h>
14 #include <sms_app.h>
15
16 #ifndef LINT
17 static char smslist_rcsid[] = "$Header$";
18 #endif
19
20
21 struct member {
22     int type;
23     char *name;
24 };
25
26 /* member types */
27 #define M_ANY           0
28 #define M_USER          1
29 #define M_LIST          2
30 #define M_STRING        3
31
32 /* flags from command line */
33 int infoflg, verbose, syncflg, memberflg, debugflg;
34
35 /* various member lists */
36 struct save_queue *addlist, *dellist, *memberlist, *synclist;
37
38 char *listname, *whoami;
39
40 extern char *index();
41 extern int errno;
42
43 int show_list_info(), show_list_count(), get_list_members(), scream();
44 struct member *parse_member();
45
46
47
48 main(argc, argv)
49 int argc;
50 char **argv;
51 {
52     int status;
53     char **arg = argv;
54     char *membervec[3];
55     struct member *memberstruct;
56
57     /* clear all flags & lists */
58     infoflg = verbose = syncflg = memberflg = debugflg = 0;
59     listname = NULL;
60     addlist = sq_create();
61     dellist = sq_create();
62     memberlist = sq_create();
63     synclist = sq_create();
64     whoami = argv[0];
65
66     /* parse args, building addlist, dellist, & synclist */
67     while (++arg - argv < argc) {
68         if  (**arg == '-')
69           switch((*arg)[1]) {
70           case 'm':
71               memberflg++;
72               break;
73           case 'D':
74               debugflg++;
75               break;
76           case 'i':
77               infoflg++;
78               break;
79           case 'v':
80               verbose++;
81               break;
82           case 'a':
83               if (arg - argv < argc - 1) {
84                   ++arg;
85                   if (memberstruct = parse_member(*arg))
86                     sq_save_data(addlist, memberstruct);
87               } else
88                 usage(argv);
89               break;
90           case 'd':
91               if (arg - argv < argc - 1) {
92                   ++arg;
93                   if (memberstruct = parse_member(*arg))
94                     sq_save_data(dellist, memberstruct);
95               } else
96                 usage(argv);
97               break;
98           case 'f':
99               if (arg - argv < argc - 1) {
100                   FILE *in;
101                   char buf[BUFSIZ];
102
103                   syncflg++;
104                   ++arg;
105                   if (!strcmp(*arg, "-"))
106                     in = stdin;
107                   else {
108                       in = fopen(*arg, "r");
109                       if (!in) {
110                           com_err(whoami, errno, " while opening %s for input",
111                                   *arg);
112                           exit(2);
113                       }
114                   }
115                   while (fgets(buf, BUFSIZ, in))
116                     if (memberstruct = parse_member(buf))
117                       sq_save_data(synclist, memberstruct);
118                   if (!feof(in))
119                     com_err(whoami, errno, " while reading from %s", *arg);
120               } else
121                 usage(argv);
122               break;
123           default:
124               usage(argv);
125           }
126         else if (listname == NULL)
127           listname = *arg;
128         else
129           usage(argv);
130     }
131     if (listname == NULL)
132       usage(argv);
133
134     /* if no other options specified, turn on list members flag */
135     if (!(infoflg || syncflg ||
136           addlist->q_next != addlist || dellist->q_next != dellist))
137       memberflg++;
138
139     /* fire up SMS */
140     if (status = sms_connect()) {
141         com_err(whoami, status, " unable to connect to SMS");
142         exit(2);
143     }
144     if (status = sms_auth("blanche")) {
145         com_err(whoami, status, " unable to authenticate to SMS");
146         exit(2);
147     }
148
149     /* display list info if requested to */
150     if (infoflg) {
151         status = sms_query("get_list_info", 1, &listname, show_list_info,NULL);
152         if (status)
153           com_err(whoami, status, " while getting list information");
154         if (verbose && !memberflg) {
155             status = sms_query("count_members_of_list", 1, &listname,
156                                show_list_count, NULL);
157             if (status)
158               com_err(whoami, status, " while getting list count");
159         }
160     }
161
162     /* if we're synchronizing to a file, we need to:
163      *  get the current members of the list
164      *  for each member of the sync file
165      *     if they are on the list, remove them from the in-memory copy
166      *     if they're not on the list, add them to add-list
167      *  if anyone is left on the in-memory copy, put them on the delete-list
168      * lastly, reset memberlist so we can use it again later
169      */
170     if (syncflg) {
171         status = sms_query("get_members_of_list", 1, &listname,
172                            get_list_members, memberlist);
173         if (status)
174           com_err(whoami, status, " while getting members of list");
175         while (sq_get_data(synclist, &memberstruct)) {
176             struct save_queue *q;
177             int removed = 0;
178
179             for (q = memberlist->q_next; q != memberlist; q = q->q_next) {
180                 if (membermatch(q->q_data, memberstruct)) {
181                     q->q_prev->q_next = q->q_next;
182                     q->q_next->q_prev = q->q_prev;
183                     removed++;
184                     break;
185                 }
186             }
187             if (!removed)
188               sq_save_data(addlist, memberstruct);
189         }
190         while (sq_get_data(memberlist, &memberstruct))
191           sq_save_data(dellist, memberstruct);
192         sq_destroy(memberlist);
193         memberlist = sq_create();
194     }
195
196     /* Process the add list */
197     while (sq_get_data(addlist, &memberstruct)) {
198         membervec[0] = listname;
199         membervec[2] = memberstruct->name;
200         switch (memberstruct->type) {
201         case M_ANY:
202         case M_USER:
203             membervec[1] = "USER";
204             status = sms_query("add_member_to_list", 3, membervec, scream, NULL);
205             if (status == SMS_SUCCESS)
206               break;
207             else if (status != SMS_USER || memberstruct->type != M_ANY) {
208                 com_err(whoami, status, " while adding member %s to %s",
209                         memberstruct->name, listname);
210                 break;
211             }
212         case M_LIST:
213             membervec[1] = "LIST";
214             status = sms_query("add_member_to_list", 3, membervec,
215                                scream, NULL);
216             if (status == SMS_SUCCESS)
217               break;
218             else if (status != SMS_LIST || memberstruct->type != M_ANY) {
219                 com_err(whoami, status, " while adding member %s to %s",
220                         memberstruct->name, listname);
221                 break;
222             }
223         case M_STRING:
224             membervec[1] = "STRING";
225             status = sms_query("add_member_to_list", 3, membervec,
226                                scream, NULL);
227             if (status != SMS_SUCCESS)
228               com_err(whoami, status, " while adding member %s to %s",
229                       memberstruct->name, listname);
230         }
231     }
232
233     /* Process the delete list */
234     while (sq_get_data(dellist, &memberstruct)) {
235         membervec[0] = listname;
236         membervec[2] = memberstruct->name;
237         switch (memberstruct->type) {
238         case M_ANY:
239         case M_USER:
240             membervec[1] = "USER";
241             status = sms_query("delete_member_from_list", 3, membervec,
242                                scream, NULL);
243             if (status == SMS_SUCCESS)
244               break;
245             else if ((status != SMS_USER && status != SMS_NO_MATCH) ||
246                      memberstruct->type != M_ANY) {
247                 com_err(whoami, status, " while deleteing member %s from %s",
248                         memberstruct->name, listname);
249                 break;
250             }
251         case M_LIST:
252             membervec[1] = "LIST";
253             status = sms_query("delete_member_from_list", 3, membervec,
254                                scream, NULL);
255             if (status == SMS_SUCCESS)
256               break;
257             else if ((status != SMS_LIST && status != SMS_NO_MATCH) ||
258                      memberstruct->type != M_ANY) {
259                 com_err(whoami, status, " while deleteing member %s from %s",
260                         memberstruct->name, listname);
261                 break;
262             }
263         case M_STRING:
264             membervec[1] = "STRING";
265             status = sms_query("delete_member_from_list", 3, membervec,
266                                scream, NULL);
267             if (status == SMS_STRING && memberstruct->type == M_ANY)
268               com_err(whoami, 0, "Unable to find member %s to delete from %s",
269                       memberstruct->name, listname);
270             else if (status != SMS_SUCCESS)
271               com_err(whoami, status, " while deleteing member %s from %s",
272                       memberstruct->name, listname);
273         }
274     }
275
276     /* Display the members of the list now, if requested */
277     if (memberflg) {
278         status = sms_query("get_members_of_list", 1, &listname,
279                            get_list_members, memberlist);
280         if (status)
281           com_err(whoami, status, " while getting members of list");
282         while (sq_get_data(memberlist, &memberstruct)) {
283             if (verbose) {
284                 char *s;
285                 switch (memberstruct->type) {
286                 case M_USER:
287                     s = "USER";
288                     break;
289                 case M_LIST:
290                     s = "LIST";
291                     break;
292                 case M_STRING:
293                     s = "STRING";
294                     break;
295                 }
296                 printf("%s: %s\n", s, memberstruct->name);
297             } else {
298                 if (memberstruct->type == M_LIST)
299                   printf("LIST:%s\n", memberstruct->name);
300                 else if (memberstruct->type == M_STRING &&
301                          !index(memberstruct->name, '@'))
302                   printf("STRING:%s\n", memberstruct->name);
303                 else
304                   printf("%s\n", memberstruct->name);
305             }
306         }
307     }
308
309     /* We're done! */
310     sms_disconnect();
311     exit(0);
312 }
313
314 usage(argv)
315 char **argv;
316 {
317     printf("Usage: %s [-i] [-v] [-m] listname [-a member] [-d member] [-f file]\n",
318            argv[0]);
319     exit(1);
320 }
321
322
323 show_list_info(argc, argv, hint)
324 int argc;
325 char **argv;
326 int hint;
327 {
328     printf("List: %s\n", argv[0]);
329     printf("Description: %s\n", argv[9]);
330     printf("Flags: %s, %s, and %s\n",
331            atoi(argv[1]) ? "active" : "inactive",
332            atoi(argv[2]) ? "public" : "private",
333            atoi(argv[3]) ? "hidden" : "visible");
334     printf("%s is %sa maillist, and is %sa group", argv[0],
335            atoi(argv[4]) ? "" : "not ",
336            atoi(argv[5]) ? "" : "not ");
337     if (atoi(argv[5]))
338       printf(" with GID %d\n", atoi(argv[6]));
339     else
340       printf("\n");
341     printf("Owner: %s %s\n", argv[7], argv[8]);
342     printf("Last modified by %s with %s on %s\n", argv[11], argv[12], argv[10]);
343     return(SMS_CONT);
344 }
345
346
347 show_list_count(argc, argv, hint)
348 int argc;
349 char **argv;
350 int hint;
351 {
352     printf("Members: %s\n", argv[0]);
353 }
354
355
356 get_list_members(argc, argv, q)
357 int argc;
358 char **argv;
359 struct save_queue *q;
360 {
361     struct member *m;
362
363     m = (struct member *) malloc(sizeof(struct member));
364     switch (argv[0][0]) {
365     case 'U':
366         m->type = M_USER;
367         break;
368     case 'L':
369         m->type = M_LIST;
370         break;
371     case 'S':
372         m->type = M_STRING;
373         break;
374     }
375     m->name = strsave(argv[1]);
376     sq_save_data(q, m);
377     return(SMS_CONT);
378 }
379
380
381 scream()
382 {
383     fprintf(stderr, "Programmer botch\n");
384     exit(3);
385 }
386
387
388 struct member *parse_member(s)
389 register char *s;
390 {
391     register struct member *m;
392     char *p;
393
394     while (*s && isspace(*s))
395       s++;
396     p = s;
397     while (*p && isprint(*p) && !isspace(*p) && *p != ';')
398       p++;
399     *p = 0;
400     if (p == s || strlen(s) == 0)
401       return(NULL);
402
403     if ((m = (struct member *) malloc(sizeof(struct member))) == NULL)
404       return(NULL);
405
406     if (p = index(s, ':')) {
407         *p = 0;
408         m->name = ++p;
409         if (!strcasecmp("user", s))
410           m->type = M_USER;
411         else if (!strcasecmp("list", s))
412           m->type = M_LIST;
413         else if (!strcasecmp("string", s))
414           m->type = M_STRING;
415         else {
416             m->type = M_STRING;
417             *(--p) = ':';
418             m->name = s;
419         }
420         m->name = strsave(m->name);
421         return(m);
422     }
423     m->name = strsave(s);
424     if (index(s, '@') || index(s, '!') || index(s, '%'))
425       m->type = M_STRING;
426     else
427       m->type = M_ANY;
428     return(m);
429 }
430
431
432 int membermatch(m1, m2)
433 struct member *m1, *m2;
434 {
435     if (strcmp(m1->name, m2->name))
436       return(0);
437     if (m1->type == M_ANY || m2->type  == M_ANY)
438       return(1);
439     if (m1->type == m2->type)
440       return(1);
441     else
442       return(0);
443 }
This page took 0.070328 seconds and 5 git commands to generate.