]> andersk Git - moira.git/blame - clients/blanche/blanche.c
added copyright message
[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
1b6b0a57 33/* member types: ### This should be an enumerated type ?
34 It is important to membercmp that M_USER < M_LIST < M_STRING */
2d7360ca 35#define M_ANY 0
36#define M_USER 1
37#define M_LIST 2
38#define M_STRING 3
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 */
1b6b0a57 44int infoflg, verbose, syncflg, memberflg, recursflg, debugflg;
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;
2d7360ca 71 listname = NULL;
72 addlist = sq_create();
73 dellist = sq_create();
74 memberlist = sq_create();
75 synclist = sq_create();
76 whoami = argv[0];
77
78 /* parse args, building addlist, dellist, & synclist */
79 while (++arg - argv < argc) {
80 if (**arg == '-')
1b6b0a57 81 {
82 if (argis("m", "members"))
83 memberflg++;
84 else if (argis("D", "debug"))
85 debugflg++;
86 else if (argis("i","information"))
2d7360ca 87 infoflg++;
1b6b0a57 88 else if (argis("v","verbose"))
2d7360ca 89 verbose++;
1b6b0a57 90 else if (argis("r","recursive"))
91 recursflg++;
92 else if (argis("a","add"))
93 if (arg - argv < argc - 1) {
94 ++arg;
95 if (memberstruct = parse_member(*arg))
96 sq_save_data(addlist, memberstruct);
97 } else
98 usage(argv);
99 else if (argis("d","delete"))
100 if (arg - argv < argc - 1) {
101 ++arg;
102 if (memberstruct = parse_member(*arg))
103 sq_save_data(dellist, memberstruct);
104 } else
105 usage(argv);
106 else if (argis("f","file"))
107 if (arg - argv < argc - 1) {
108 FILE *in;
109 char buf[BUFSIZ];
110
111 syncflg++;
112 ++arg;
113 if (!strcmp(*arg, "-"))
114 in = stdin;
115 else {
116 in = fopen(*arg, "r");
117 if (!in) {
118 com_err(whoami, errno,
119 " while opening %s for input", *arg);
120 exit(2);
121 }
122 }
123 while (fgets(buf, BUFSIZ, in))
124 if (memberstruct = parse_member(buf))
125 sq_save_data(synclist, memberstruct);
126 if (!feof(in))
127 com_err(whoami, errno, " while reading from %s", *arg);
128 } else
129 usage(argv);
130 else
2d7360ca 131 usage(argv);
1b6b0a57 132 }
2d7360ca 133 else if (listname == NULL)
134 listname = *arg;
135 else
136 usage(argv);
137 }
138 if (listname == NULL)
139 usage(argv);
140
141 /* if no other options specified, turn on list members flag */
142 if (!(infoflg || syncflg ||
143 addlist->q_next != addlist || dellist->q_next != dellist))
144 memberflg++;
145
146 /* fire up SMS */
147 if (status = sms_connect()) {
148 com_err(whoami, status, " unable to connect to SMS");
149 exit(2);
150 }
151 if (status = sms_auth("blanche")) {
152 com_err(whoami, status, " unable to authenticate to SMS");
153 exit(2);
154 }
155
156 /* display list info if requested to */
157 if (infoflg) {
158 status = sms_query("get_list_info", 1, &listname, show_list_info,NULL);
159 if (status)
160 com_err(whoami, status, " while getting list information");
161 if (verbose && !memberflg) {
162 status = sms_query("count_members_of_list", 1, &listname,
163 show_list_count, NULL);
164 if (status)
165 com_err(whoami, status, " while getting list count");
166 }
167 }
168
169 /* if we're synchronizing to a file, we need to:
170 * get the current members of the list
171 * for each member of the sync file
172 * if they are on the list, remove them from the in-memory copy
173 * if they're not on the list, add them to add-list
174 * if anyone is left on the in-memory copy, put them on the delete-list
175 * lastly, reset memberlist so we can use it again later
176 */
177 if (syncflg) {
178 status = sms_query("get_members_of_list", 1, &listname,
1b6b0a57 179 get_list_members, (char *)memberlist);
2d7360ca 180 if (status)
181 com_err(whoami, status, " while getting members of list");
182 while (sq_get_data(synclist, &memberstruct)) {
183 struct save_queue *q;
184 int removed = 0;
185
186 for (q = memberlist->q_next; q != memberlist; q = q->q_next) {
1b6b0a57 187 if (membercmp(q->q_data, memberstruct) == 0) {
2d7360ca 188 q->q_prev->q_next = q->q_next;
189 q->q_next->q_prev = q->q_prev;
190 removed++;
191 break;
192 }
193 }
194 if (!removed)
195 sq_save_data(addlist, memberstruct);
196 }
197 while (sq_get_data(memberlist, &memberstruct))
198 sq_save_data(dellist, memberstruct);
199 sq_destroy(memberlist);
200 memberlist = sq_create();
201 }
202
203 /* Process the add list */
204 while (sq_get_data(addlist, &memberstruct)) {
205 membervec[0] = listname;
206 membervec[2] = memberstruct->name;
207 switch (memberstruct->type) {
208 case M_ANY:
209 case M_USER:
210 membervec[1] = "USER";
211 status = sms_query("add_member_to_list", 3, membervec, scream, NULL);
212 if (status == SMS_SUCCESS)
213 break;
214 else if (status != SMS_USER || memberstruct->type != M_ANY) {
215 com_err(whoami, status, " while adding member %s to %s",
216 memberstruct->name, listname);
217 break;
218 }
219 case M_LIST:
220 membervec[1] = "LIST";
221 status = sms_query("add_member_to_list", 3, membervec,
222 scream, NULL);
223 if (status == SMS_SUCCESS)
224 break;
225 else if (status != SMS_LIST || memberstruct->type != M_ANY) {
226 com_err(whoami, status, " while adding member %s to %s",
227 memberstruct->name, listname);
228 break;
229 }
230 case M_STRING:
231 membervec[1] = "STRING";
232 status = sms_query("add_member_to_list", 3, membervec,
233 scream, NULL);
234 if (status != SMS_SUCCESS)
235 com_err(whoami, status, " while adding member %s to %s",
236 memberstruct->name, listname);
237 }
238 }
239
240 /* Process the delete list */
241 while (sq_get_data(dellist, &memberstruct)) {
242 membervec[0] = listname;
243 membervec[2] = memberstruct->name;
244 switch (memberstruct->type) {
245 case M_ANY:
246 case M_USER:
247 membervec[1] = "USER";
248 status = sms_query("delete_member_from_list", 3, membervec,
249 scream, NULL);
250 if (status == SMS_SUCCESS)
251 break;
252 else if ((status != SMS_USER && status != SMS_NO_MATCH) ||
253 memberstruct->type != M_ANY) {
254 com_err(whoami, status, " while deleteing member %s from %s",
255 memberstruct->name, listname);
256 break;
257 }
258 case M_LIST:
259 membervec[1] = "LIST";
260 status = sms_query("delete_member_from_list", 3, membervec,
261 scream, NULL);
262 if (status == SMS_SUCCESS)
263 break;
264 else if ((status != SMS_LIST && status != SMS_NO_MATCH) ||
265 memberstruct->type != M_ANY) {
266 com_err(whoami, status, " while deleteing member %s from %s",
267 memberstruct->name, listname);
268 break;
269 }
270 case M_STRING:
271 membervec[1] = "STRING";
272 status = sms_query("delete_member_from_list", 3, membervec,
273 scream, NULL);
274 if (status == SMS_STRING && memberstruct->type == M_ANY)
275 com_err(whoami, 0, "Unable to find member %s to delete from %s",
276 memberstruct->name, listname);
277 else if (status != SMS_SUCCESS)
278 com_err(whoami, status, " while deleteing member %s from %s",
279 memberstruct->name, listname);
280 }
281 }
282
283 /* Display the members of the list now, if requested */
1b6b0a57 284 if (memberflg)
285 display_list_members();
2d7360ca 286
287 /* We're done! */
288 sms_disconnect();
289 exit(0);
290}
291
292usage(argv)
293char **argv;
294{
1b6b0a57 295 fprintf(stderr, "Usage: %s [options] listname [options]\n",argv[0]);
296 fprintf(stderr, "Options are\n");
297 fprintf(stderr, " -v | -verbose\n");
298 fprintf(stderr, " -m | -members\n");
299 fprintf(stderr, " -i | -info\n");
300 fprintf(stderr, " -r | -recursive\n");
301 fprintf(stderr, " -a | -add member\n");
302 fprintf(stderr, " -d | -delete member\n");
303 fprintf(stderr, " -f | -file filename\n");
304#ifdef notdef
305 fprintf(stderr, " -D | -debug\n");
306#endif
2d7360ca 307 exit(1);
308}
309
310
1b6b0a57 311show_list_members(memberlist)
312 struct sq *memberlist;
313{
314 struct member *memberstruct;
315
316 while (sq_get_data(memberlist, &memberstruct)) {
317 if (verbose) {
318 char *s;
319 switch (memberstruct->type) {
320 case M_USER:
321 s = "USER";
322 break;
323 case M_LIST:
324 s = "LIST";
325 break;
326 case M_STRING:
327 s = "STRING";
328 break;
329 }
330 printf("%s:%s\n", s, memberstruct->name);
331 } else {
332 if (memberstruct->type == M_LIST)
333 printf("LIST:%s\n", memberstruct->name);
334 else if (memberstruct->type == M_STRING &&
335 !index(memberstruct->name, '@'))
336 printf("STRING:%s\n", memberstruct->name);
337 else
338 printf("%s\n", memberstruct->name);
339 }
340 }
341}
342
2d7360ca 343show_list_info(argc, argv, hint)
344int argc;
345char **argv;
346int hint;
347{
348 printf("List: %s\n", argv[0]);
349 printf("Description: %s\n", argv[9]);
350 printf("Flags: %s, %s, and %s\n",
351 atoi(argv[1]) ? "active" : "inactive",
352 atoi(argv[2]) ? "public" : "private",
353 atoi(argv[3]) ? "hidden" : "visible");
1b6b0a57 354 printf("%s is %sa maillist and is %sa group", argv[0],
2d7360ca 355 atoi(argv[4]) ? "" : "not ",
356 atoi(argv[5]) ? "" : "not ");
357 if (atoi(argv[5]))
358 printf(" with GID %d\n", atoi(argv[6]));
359 else
360 printf("\n");
361 printf("Owner: %s %s\n", argv[7], argv[8]);
362 printf("Last modified by %s with %s on %s\n", argv[11], argv[12], argv[10]);
363 return(SMS_CONT);
364}
365
366
367show_list_count(argc, argv, hint)
368int argc;
369char **argv;
370int hint;
371{
372 printf("Members: %s\n", argv[0]);
373}
374
375
1b6b0a57 376display_list_members()
377{
378 int status;
379
380 status = sms_query("get_members_of_list", 1, &listname,
381 get_list_members, (char *)memberlist);
382 if (status)
383 com_err(whoami, status, " while getting members of list");
384 if (recursflg)
385 fprintf(stderr,"%s: The recursive flag is not yet implemented.\n",
386 whoami);
387 show_list_members(memberlist);
388}
389
2d7360ca 390get_list_members(argc, argv, q)
391int argc;
392char **argv;
393struct save_queue *q;
394{
395 struct member *m;
396
397 m = (struct member *) malloc(sizeof(struct member));
398 switch (argv[0][0]) {
399 case 'U':
400 m->type = M_USER;
401 break;
402 case 'L':
403 m->type = M_LIST;
404 break;
405 case 'S':
406 m->type = M_STRING;
407 break;
408 }
409 m->name = strsave(argv[1]);
410 sq_save_data(q, m);
411 return(SMS_CONT);
412}
413
414
415scream()
416{
417 fprintf(stderr, "Programmer botch\n");
418 exit(3);
419}
420
421
422struct member *parse_member(s)
423register char *s;
424{
425 register struct member *m;
426 char *p;
427
428 while (*s && isspace(*s))
429 s++;
430 p = s;
431 while (*p && isprint(*p) && !isspace(*p) && *p != ';')
432 p++;
433 *p = 0;
434 if (p == s || strlen(s) == 0)
435 return(NULL);
436
437 if ((m = (struct member *) malloc(sizeof(struct member))) == NULL)
438 return(NULL);
439
440 if (p = index(s, ':')) {
441 *p = 0;
442 m->name = ++p;
443 if (!strcasecmp("user", s))
444 m->type = M_USER;
445 else if (!strcasecmp("list", s))
446 m->type = M_LIST;
447 else if (!strcasecmp("string", s))
448 m->type = M_STRING;
449 else {
450 m->type = M_STRING;
451 *(--p) = ':';
452 m->name = s;
453 }
454 m->name = strsave(m->name);
455 return(m);
456 }
457 m->name = strsave(s);
458 if (index(s, '@') || index(s, '!') || index(s, '%'))
459 m->type = M_STRING;
460 else
461 m->type = M_ANY;
462 return(m);
463}
464
465
1b6b0a57 466int membercmp(m1, m2)
467 struct member *m1, *m2;
468 /*
469 * This routine two compares members by the following rules:
470 * 1. A USER is less than a LIST
471 * 2. A LIST is less than a STRING
472 * 3. If two members are of the same type, the one alphabetically first
473 * is less than the other
474 * It returs < 0 if the first member is less, 0 if they are identical, and
475 * > 0 if the second member is less (the first member is greater).
476 */
2d7360ca 477{
1b6b0a57 478 if (m1->type == M_ANY || m2->type == M_ANY || (m1->type == m2->type))
479 return(strcmp(m1->name, m2->name));
2d7360ca 480 else
1b6b0a57 481 return(m1->type - m2->type);
2d7360ca 482}
This page took 1.202686 seconds and 5 git commands to generate.