]> andersk Git - moira.git/blame - clients/blanche/blanche.c
Code style cleanup. (No functional changes)
[moira.git] / clients / blanche / blanche.c
CommitLineData
2d7360ca 1/* $Header$
2 *
d44cee72 3 * Command line oriented Moira List tool.
2d7360ca 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>
9eb9cfb9 18#include <errno.h>
2d7360ca 19#include <stdio.h>
7b58c1b9 20#include <stdlib.h>
2d7360ca 21#include <ctype.h>
f071d8a7 22#include <string.h>
8defc06b 23#include <moira.h>
24#include <moira_site.h>
2d7360ca 25
26#ifndef LINT
d44cee72 27static char blanche_rcsid[] = "$Header$";
2d7360ca 28#endif
29
30
31struct member {
5eaef520 32 int type;
33 char *name;
2d7360ca 34};
35
b5b167d6 36/* It is important to membercmp that M_USER < M_LIST < M_STRING */
2d7360ca 37#define M_ANY 0
38#define M_USER 1
39#define M_LIST 2
40#define M_STRING 3
8c3b414d 41#define M_KERBEROS 4
2d7360ca 42
1b6b0a57 43/* argument parsing macro */
5eaef520 44#define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
1b6b0a57 45
2d7360ca 46/* flags from command line */
763465b8 47int infoflg, verbose, syncflg, memberflg, recursflg, noauth;
8c3b414d 48int showusers, showstrings, showkerberos, showlists;
763465b8 49int createflag, setinfo, active, public, hidden, maillist, grouplist;
50struct member *owner;
51char *desc, *newname;
2d7360ca 52
53/* various member lists */
54struct save_queue *addlist, *dellist, *memberlist, *synclist;
55
56char *listname, *whoami;
57
2d7360ca 58int show_list_info(), show_list_count(), get_list_members(), scream();
763465b8 59int show_list_members(), membercmp(), save_list_info();
2d7360ca 60struct member *parse_member();
61
5eaef520 62int main(int argc, char **argv)
2d7360ca 63{
5eaef520 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 == '-')
1b6b0a57 89 {
5eaef520 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
2d7360ca 254 usage(argv);
5eaef520 255 }
256 else
257 usage(argv);
1b6b0a57 258 }
5eaef520 259 else if (listname == NULL)
260 listname = *arg;
261 else
262 usage(argv);
2d7360ca 263 }
5eaef520 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);
2d7360ca 281 }
5eaef520 282 if ((status = mr_motd(&motd)))
283 {
284 com_err(whoami, status, "unable to check server status");
285 exit(2);
37e3ac2d 286 }
5eaef520 287 if (motd)
288 {
289 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n",
290 motd);
291 mr_disconnect();
292 exit(2);
37e3ac2d 293 }
294
5eaef520 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);
ece49f32 305 }
2d7360ca 306 }
307
5eaef520 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 }
763465b8 344 }
5eaef520 345 else
346 {
347 argv[7] = "USER";
348 argv[8] = getenv("USER");
349
350 status = mr_query("add_list", 10, argv, scream, NULL);
763465b8 351 }
352
5eaef520 353 if (status)
354 {
355 com_err(whoami, status, "while creating list.");
356 exit(1);
357 }
763465b8 358 }
5eaef520 359 else if (setinfo)
360 {
361 char *argv[11];
763465b8 362
5eaef520 363 status = mr_query("get_list_info", 1, &listname,
364 save_list_info, (char *)argv);
365 if (status)
366 {
d44cee72 367 com_err(whoami, status, "while getting list information");
5eaef520 368 exit(1);
2d7360ca 369 }
5eaef520 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;
2d7360ca 417 }
418
5eaef520 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");
26624cbe 431 }
5eaef520 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;
2d7360ca 464 }
465 }
5eaef520 466 if (!removed)
467 sq_save_data(addlist, memberstruct);
2d7360ca 468 }
5eaef520 469 while (sq_get_data(memberlist, &memberstruct))
470 sq_save_data(dellist, memberstruct);
471 sq_destroy(memberlist);
472 memberlist = sq_create();
2d7360ca 473 }
474
5eaef520 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;
99bdafb8 501 }
502 }
5eaef520 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;
99bdafb8 514 }
515 }
5eaef520 516 free(host);
99bdafb8 517 }
5eaef520 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);
b5b167d6 525 }
5eaef520 526 switch (memberstruct->type)
527 {
2d7360ca 528 case M_ANY:
529 case M_USER:
5eaef520 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;
2d7360ca 539 break;
2d7360ca 540 }
541 case M_LIST:
5eaef520 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]);
7b58c1b9 557 }
5eaef520 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;
2d7360ca 566 }
567 case M_STRING:
5eaef520 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;
25978f25 580 }
5eaef520 581
582 membervec[1] = "STRING";
583 status = mr_query("add_member_to_list", 3, membervec,
584 scream, NULL);
585 if (status != MR_SUCCESS)
586 {
d44cee72 587 com_err(whoami, status, "while adding member %s to %s",
2d7360ca 588 memberstruct->name, listname);
e681e918 589 success = 0;
590 }
5eaef520 591 break;
8c3b414d 592 case M_KERBEROS:
5eaef520 593 membervec[1] = "KERBEROS";
594 status = mr_query("add_member_to_list", 3, membervec,
595 scream, NULL);
596 if (status != MR_SUCCESS)
597 {
d44cee72 598 com_err(whoami, status, "while adding member %s to %s",
8c3b414d 599 memberstruct->name, listname);
e681e918 600 success = 0;
601 }
2d7360ca 602 }
603 }
604
5eaef520 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);
b5b167d6 614 }
5eaef520 615 switch (memberstruct->type)
616 {
2d7360ca 617 case M_ANY:
618 case M_USER:
5eaef520 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;
2d7360ca 630 break;
2d7360ca 631 }
632 case M_LIST:
5eaef520 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 */
40637dba 655 status = MR_NO_MATCH;
656 }
5eaef520 657 com_err(whoami, status, "while deleting member %s from %s",
658 memberstruct->name, listname);
659 success = 0;
660 break;
2d7360ca 661 }
662 case M_STRING:
5eaef520 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 {
d44cee72 668 com_err(whoami, 0, " Unable to find member %s to delete from %s",
2d7360ca 669 memberstruct->name, listname);
e681e918 670 success = 0;
5eaef520 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 {
d44cee72 681 com_err(whoami, status, "while deleting member %s from %s",
2d7360ca 682 memberstruct->name, listname);
e681e918 683 success = 0;
684 }
5eaef520 685 break;
8c3b414d 686 case M_KERBEROS:
5eaef520 687 membervec[1] = "KERBEROS";
688 status = mr_query("delete_member_from_list", 3, membervec,
689 scream, NULL);
690 if (status != MR_SUCCESS)
691 {
d44cee72 692 com_err(whoami, status, "while deleting member %s from %s",
8c3b414d 693 memberstruct->name, listname);
e681e918 694 success = 0;
695 }
2d7360ca 696 }
697 }
698
5eaef520 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);
b5b167d6 713 }
714 }
2d7360ca 715
5eaef520 716 /* We're done! */
717 mr_disconnect();
718 exit(success ? 0 : 1);
2d7360ca 719}
720
5eaef520 721usage(char **argv)
2d7360ca 722{
5eaef520 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);
2d7360ca 756}
757
758
b5b167d6 759/* Display the members stored in the queue */
1b6b0a57 760
5eaef520 761show_list_member(struct member *memberstruct)
b5b167d6 762{
5eaef520 763 char *s = "";
8b494222 764
5eaef520 765 switch (memberstruct->type)
766 {
8b494222 767 case M_USER:
5eaef520 768 if (!showusers)
769 return;
770 s = "USER";
771 break;
8b494222 772 case M_LIST:
5eaef520 773 if (!showlists)
774 return;
775 s = "LIST";
776 break;
8b494222 777 case M_STRING:
5eaef520 778 if (!showstrings)
779 return;
780 s = "STRING";
781 break;
8c3b414d 782 case M_KERBEROS:
5eaef520 783 if (!showkerberos)
8b494222 784 return;
5eaef520 785 s = "KERBEROS";
786 break;
787 case M_ANY:
788 printf("%s\n", memberstruct->name);
789 return;
8b494222 790 }
791
5eaef520 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);
1b6b0a57 805 }
806}
807
b5b167d6 808
809/* Show the retrieved information about a list */
810
5eaef520 811int show_list_info(int argc, char **argv, int hint)
2d7360ca 812{
5eaef520 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;
2d7360ca 829}
830
831
763465b8 832/* Copy retrieved information about a list into a new argv */
833
5eaef520 834int save_list_info(int argc, char **argv, int hint)
763465b8 835{
5eaef520 836 char **nargv = (char **)hint;
837
838 for (argc = 0; argc < 10; argc++)
839 nargv[argc + 1] = strdup(argv[argc]);
840 return MR_CONT;
763465b8 841}
842
b5b167d6 843/* Show the retrieve list member count */
844
5eaef520 845show_list_count(int argc, char **argv, int hint)
2d7360ca 846{
5eaef520 847 printf("Members: %s\n", argv[0]);
2d7360ca 848}
849
850
b5b167d6 851/* Recursively find all of the members of listname, and then display them */
852
5eaef520 853recursive_display_list_members(void)
1b6b0a57 854{
5eaef520 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);
b5b167d6 880 }
881 }
5eaef520 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]);
b5b167d6 890}
891
892
893/* add a struct member to a queue if that member isn't already there. */
894
5eaef520 895unique_add_member(struct save_queue *q, struct member *m)
b5b167d6 896{
5eaef520 897 struct save_queue *qp;
1b6b0a57 898
5eaef520 899 for (qp = q->q_next; qp != q; qp = qp->q_next)
900 {
901 if (!membercmp(qp->q_data, m))
902 return;
b5b167d6 903 }
5eaef520 904 sq_save_data(q, m);
1b6b0a57 905}
906
b5b167d6 907
908/* Collect the retrieved members of the list */
909
5eaef520 910int get_list_members(int argc, char **argv, struct save_queue *q)
2d7360ca 911{
5eaef520 912 struct member *m;
2d7360ca 913
5eaef520 914 m = malloc(sizeof(struct member));
915 switch (argv[0][0])
916 {
2d7360ca 917 case 'U':
5eaef520 918 m->type = M_USER;
919 break;
2d7360ca 920 case 'L':
5eaef520 921 m->type = M_LIST;
922 break;
2d7360ca 923 case 'S':
5eaef520 924 m->type = M_STRING;
925 break;
8c3b414d 926 case 'K':
5eaef520 927 m->type = M_KERBEROS;
928 break;
2d7360ca 929 }
5eaef520 930 m->name = strsave(argv[1]);
931 sq_save_data(q, m);
932 return MR_CONT;
2d7360ca 933}
934
935
b5b167d6 936/* Called only if a query returns a value that we weren't expecting */
937
5eaef520 938scream(void)
2d7360ca 939{
5eaef520 940 fprintf(stderr, "Programmer botch\n");
941 exit(3);
2d7360ca 942}
943
944
7c02cbdb 945/* Open file, parse members from file, and put them on the specified queue */
5eaef520 946get_members_from_file(char *filename, struct save_queue *queue)
7c02cbdb 947{
5eaef520 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);
7c02cbdb 961 }
962 }
963
5eaef520 964 while (fgets(buf, BUFSIZ, in))
965 {
966 if ((memberstruct = parse_member(buf)))
7c02cbdb 967 sq_save_data(queue, memberstruct);
5eaef520 968 }
969 if (!feof(in))
970 {
7c02cbdb 971 com_err(whoami, errno, "while reading from %s", filename);
e681e918 972 exit(2);
973 }
7c02cbdb 974}
975
976
99bdafb8 977/* Collect the possible expansions of the alias MAILHUB */
978
5eaef520 979int collect(int argc, char **argv, char ***list)
99bdafb8 980{
5eaef520 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;
99bdafb8 989}
990
991
b5b167d6 992/* Parse a line of input, fetching a member. NULL is returned if a member
7c02cbdb 993 * is not found. ';' is a comment character.
b5b167d6 994 */
995
5eaef520 996struct member *parse_member(register char *s)
2d7360ca 997{
5eaef520 998 register 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 {
7c02cbdb 1006 if (isprint(*p) && !isspace(*p))
1007 lastchar = p++;
1008 else
1009 p++;
5eaef520 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;
2d7360ca 1036 }
5eaef520 1037 m->name = strsave(m->name);
1038 }
1039 else
1040 {
1041 m->name = strsave(s);
1042 m->type = M_ANY;
2d7360ca 1043 }
5eaef520 1044 return m;
2d7360ca 1045}
1046
1047
5eaef520 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 */
b5b167d6 1057
5eaef520 1058int membercmp(struct member *m1, struct member *m2)
2d7360ca 1059{
5eaef520 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;
2d7360ca 1064}
b5b167d6 1065
1066
5eaef520 1067int sq_count_elts(struct save_queue *q)
b5b167d6 1068{
5eaef520 1069 char *foo;
1070 int count;
b5b167d6 1071
5eaef520 1072 count = 0;
1073 while (sq_get_data(q, &foo))
1074 count++;
1075 return count;
b5b167d6 1076}
This page took 0.355193 seconds and 5 git commands to generate.