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