]> andersk Git - moira.git/blame - clients/blanche/blanche.c
blanche should exit if it is sync-ing a list to a file and
[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>
20#include <ctype.h>
f071d8a7 21#include <string.h>
8defc06b 22#include <moira.h>
23#include <moira_site.h>
2d7360ca 24
25#ifndef LINT
d44cee72 26static char blanche_rcsid[] = "$Header$";
2d7360ca 27#endif
28
29
30struct member {
31 int type;
32 char *name;
33};
34
b5b167d6 35/* It is important to membercmp that M_USER < M_LIST < M_STRING */
2d7360ca 36#define M_ANY 0
37#define M_USER 1
38#define M_LIST 2
39#define M_STRING 3
8c3b414d 40#define M_KERBEROS 4
2d7360ca 41
1b6b0a57 42/* argument parsing macro */
43#define argis(a,b) ((strcmp(*arg+1, a) == 0) || (strcmp(*arg+1, b) == 0))
44
2d7360ca 45/* flags from command line */
8b494222 46int infoflg, verbose, syncflg, memberflg, recursflg, debugflg, noauth;
8c3b414d 47int showusers, showstrings, showkerberos, showlists;
2d7360ca 48
49/* various member lists */
50struct save_queue *addlist, *dellist, *memberlist, *synclist;
51
52char *listname, *whoami;
53
f071d8a7 54#ifndef POSIX
2d7360ca 55extern int errno;
f071d8a7 56#endif
2d7360ca 57
58int show_list_info(), show_list_count(), get_list_members(), scream();
135cd06a 59int show_list_members(), membercmp();
2d7360ca 60struct member *parse_member();
61
62
63
64main(argc, argv)
65int argc;
66char **argv;
67{
68 int status;
69 char **arg = argv;
37e3ac2d 70 char *membervec[3], *motd;
2d7360ca 71 struct member *memberstruct;
99bdafb8 72 char *server = NULL, *p;
2d7360ca 73
74 /* clear all flags & lists */
1b6b0a57 75 infoflg = verbose = syncflg = memberflg = debugflg = recursflg = 0;
8c3b414d 76 noauth = showusers = showstrings = showkerberos = showlists = 0;
2d7360ca 77 listname = NULL;
78 addlist = sq_create();
79 dellist = sq_create();
80 memberlist = sq_create();
81 synclist = sq_create();
82 whoami = argv[0];
83
84 /* parse args, building addlist, dellist, & synclist */
85 while (++arg - argv < argc) {
86 if (**arg == '-')
1b6b0a57 87 {
88 if (argis("m", "members"))
89 memberflg++;
8b494222 90 else if (argis("u", "users"))
91 showusers++;
92 else if (argis("s", "strings"))
93 showstrings++;
94 else if (argis("l", "lists"))
95 showlists++;
8c3b414d 96 else if (argis("k", "kerberos"))
97 showkerberos++;
1b6b0a57 98 else if (argis("D", "debug"))
99 debugflg++;
62a6860a 100 else if (argis("i","info"))
2d7360ca 101 infoflg++;
8b494222 102 else if (argis("n","noauth"))
103 noauth++;
1b6b0a57 104 else if (argis("v","verbose"))
2d7360ca 105 verbose++;
1b6b0a57 106 else if (argis("r","recursive"))
107 recursflg++;
8c3b414d 108 else if (argis("S","server"))
109 if (arg - argv < argc - 1) {
110 ++arg;
111 server = *arg;
112 } else
113 usage(argv);
1b6b0a57 114 else if (argis("a","add"))
115 if (arg - argv < argc - 1) {
116 ++arg;
117 if (memberstruct = parse_member(*arg))
118 sq_save_data(addlist, memberstruct);
119 } else
120 usage(argv);
7c02cbdb 121 else if (argis("al","addlist"))
122 if (arg - argv < argc - 1) {
123 ++arg;
124 get_members_from_file(*arg, addlist);
125 } else
126 usage(argv);
1b6b0a57 127 else if (argis("d","delete"))
128 if (arg - argv < argc - 1) {
129 ++arg;
130 if (memberstruct = parse_member(*arg))
131 sq_save_data(dellist, memberstruct);
132 } else
133 usage(argv);
7c02cbdb 134 else if (argis("dl","deletelist"))
135 if (arg - argv < argc - 1) {
136 ++arg;
137 get_members_from_file(*arg, dellist);
138 } else
139 usage(argv);
1b6b0a57 140 else if (argis("f","file"))
141 if (arg - argv < argc - 1) {
1b6b0a57 142 syncflg++;
143 ++arg;
7c02cbdb 144 get_members_from_file(*arg, synclist);
1b6b0a57 145 } else
b5b167d6 146 usage(argv);
1b6b0a57 147 else
2d7360ca 148 usage(argv);
1b6b0a57 149 }
2d7360ca 150 else if (listname == NULL)
151 listname = *arg;
152 else
153 usage(argv);
154 }
155 if (listname == NULL)
156 usage(argv);
157
158 /* if no other options specified, turn on list members flag */
159 if (!(infoflg || syncflg ||
160 addlist->q_next != addlist || dellist->q_next != dellist))
161 memberflg++;
162
8c3b414d 163 /* If none of {users,strings,lists,kerberos} specified, turn them all on */
164 if (!(showusers || showstrings || showlists || showkerberos))
165 showusers = showstrings = showlists = showkerberos = 1;
8b494222 166
d44cee72 167 /* fire up Moira */
8defc06b 168 if (status = mr_connect(server)) {
d44cee72 169 com_err(whoami, status, "unable to connect to the Moira server");
2d7360ca 170 exit(2);
171 }
8defc06b 172 if ( status = mr_motd(&motd) ) {
d44cee72 173 com_err(whoami, status, "unable to check server status");
37e3ac2d 174 exit(2);
175 }
176 if (motd) {
95cd286e 177 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n", motd);
8defc06b 178 mr_disconnect();
37e3ac2d 179 exit(2);
180 }
181
8defc06b 182 if (!noauth && (status = mr_auth("blanche"))) {
ece49f32 183 if (status == MR_USER_AUTH)
184 com_err(whoami, status, "");
185 else {
186 com_err(whoami, status, "unable to authenticate to Moira");
187 com_err(whoami, 0,
188 " Try the -noauth flag if you don't need authentication");
189 exit(2);
190 }
2d7360ca 191 }
192
193 /* display list info if requested to */
194 if (infoflg) {
8defc06b 195 status = mr_query("get_list_info", 1, &listname, show_list_info,NULL);
2d7360ca 196 if (status)
d44cee72 197 com_err(whoami, status, "while getting list information");
2d7360ca 198 if (verbose && !memberflg) {
8defc06b 199 status = mr_query("count_members_of_list", 1, &listname,
2d7360ca 200 show_list_count, NULL);
201 if (status)
d44cee72 202 com_err(whoami, status, "while getting list count");
2d7360ca 203 }
204 }
205
206 /* if we're synchronizing to a file, we need to:
207 * get the current members of the list
208 * for each member of the sync file
209 * if they are on the list, remove them from the in-memory copy
210 * if they're not on the list, add them to add-list
211 * if anyone is left on the in-memory copy, put them on the delete-list
212 * lastly, reset memberlist so we can use it again later
213 */
214 if (syncflg) {
8defc06b 215 status = mr_query("get_members_of_list", 1, &listname,
1b6b0a57 216 get_list_members, (char *)memberlist);
26624cbe 217 if (status) {
218 com_err(whoami, status, "getting members of list %s", listname);
219 exit (2);
220 }
2d7360ca 221 while (sq_get_data(synclist, &memberstruct)) {
222 struct save_queue *q;
223 int removed = 0;
224
225 for (q = memberlist->q_next; q != memberlist; q = q->q_next) {
1b6b0a57 226 if (membercmp(q->q_data, memberstruct) == 0) {
2d7360ca 227 q->q_prev->q_next = q->q_next;
228 q->q_next->q_prev = q->q_prev;
229 removed++;
230 break;
231 }
232 }
233 if (!removed)
234 sq_save_data(addlist, memberstruct);
235 }
236 while (sq_get_data(memberlist, &memberstruct))
237 sq_save_data(dellist, memberstruct);
238 sq_destroy(memberlist);
239 memberlist = sq_create();
240 }
241
242 /* Process the add list */
243 while (sq_get_data(addlist, &memberstruct)) {
f1f92ff7 244 if ((memberstruct->type == M_STRING ||
245 memberstruct->type == M_ANY) &&
246 strchr(memberstruct->name, '\'')) {
247 fprintf(stderr, "Illegal character \"'\" in \"STRING:%s\", aborting blanche.\n",
248 memberstruct->name);
249 fprintf(stderr, "No changes were made.\n");
26624cbe 250 exit(2);
f1f92ff7 251 }
99bdafb8 252 /* canonicalize string if necessary */
253 if (memberstruct->type == M_STRING &&
f071d8a7 254 (p = strchr(memberstruct->name, '@'))) {
99bdafb8 255 char *host = canonicalize_hostname(strsave(++p));
256 static char **mailhubs = NULL;
257 char *argv[4];
258 int i, collect();
259
260 if (!mailhubs) {
261 argv[0] = "mailhub";
262 argv[1] = "TYPE";
263 argv[2] = "*";
264 mailhubs = (char **)malloc(sizeof(char *));
265 mailhubs[0] = NULL;
f416d13d 266 status = mr_query("get_alias", 3, argv, collect,
267 (char *)&mailhubs);
99bdafb8 268 if (status != MR_SUCCESS && status != MR_NO_MATCH) {
269 com_err(whoami, status,
270 " while reading list of MAILHUB servers");
271 mailhubs[0] = NULL;
272 }
273 }
274 for (i = 0; p = mailhubs[i]; i++) {
275 if (!strcasecmp(p, host)) {
276 host = strsave(memberstruct->name);
f071d8a7 277 *(strchr(memberstruct->name, '@')) = 0;
99bdafb8 278 memberstruct->type = M_ANY;
279 fprintf(stderr, "Warning: \"STRING:%s\" converted to \"%s\" because it is a local name.\n",
280 host, memberstruct->name);
281 break;
282 }
283 }
284 free(host);
285 }
286 /* now continue adding member */
2d7360ca 287 membervec[0] = listname;
288 membervec[2] = memberstruct->name;
97f4e1fa 289 if (verbose) {
b5b167d6 290 printf("Adding member ");
291 show_list_member(memberstruct);
292 }
2d7360ca 293 switch (memberstruct->type) {
294 case M_ANY:
295 case M_USER:
296 membervec[1] = "USER";
8defc06b 297 status = mr_query("add_member_to_list", 3, membervec, scream, NULL);
298 if (status == MR_SUCCESS)
2d7360ca 299 break;
8defc06b 300 else if (status != MR_USER || memberstruct->type != M_ANY) {
d44cee72 301 com_err(whoami, status, "while adding member %s to %s",
2d7360ca 302 memberstruct->name, listname);
303 break;
304 }
305 case M_LIST:
306 membervec[1] = "LIST";
8defc06b 307 status = mr_query("add_member_to_list", 3, membervec,
2d7360ca 308 scream, NULL);
8defc06b 309 if (status == MR_SUCCESS)
2d7360ca 310 break;
8defc06b 311 else if (status != MR_LIST || memberstruct->type != M_ANY) {
d44cee72 312 com_err(whoami, status, "while adding member %s to %s",
2d7360ca 313 memberstruct->name, listname);
314 break;
315 }
316 case M_STRING:
317 membervec[1] = "STRING";
8defc06b 318 status = mr_query("add_member_to_list", 3, membervec,
2d7360ca 319 scream, NULL);
8defc06b 320 if (status != MR_SUCCESS)
d44cee72 321 com_err(whoami, status, "while adding member %s to %s",
2d7360ca 322 memberstruct->name, listname);
f1f92ff7 323 else if (!strchr(memberstruct->name, '@') &&
324 !strchr(memberstruct->name, '!') &&
325 !strchr(memberstruct->name, '%')) {
326 fprintf(stderr, "\nWARNING: \"STRING:%s\" was just added to list \"%s\".\n",
327 memberstruct->name, listname);
328 fprintf(stderr, "\tIf %s is a mailing list, this may cause it to stop working.\n", listname);
329 fprintf(stderr, "\tYou should consider removing \"STRING:%s\" from the list.\n", memberstruct->name);
330 }
8c3b414d 331 break;
332 case M_KERBEROS:
333 membervec[1] = "KERBEROS";
8defc06b 334 status = mr_query("add_member_to_list", 3, membervec,
8c3b414d 335 scream, NULL);
8defc06b 336 if (status != MR_SUCCESS)
d44cee72 337 com_err(whoami, status, "while adding member %s to %s",
8c3b414d 338 memberstruct->name, listname);
2d7360ca 339 }
340 }
341
342 /* Process the delete list */
343 while (sq_get_data(dellist, &memberstruct)) {
344 membervec[0] = listname;
345 membervec[2] = memberstruct->name;
97f4e1fa 346 if (verbose) {
b5b167d6 347 printf("Deleting member ");
348 show_list_member(memberstruct);
349 }
2d7360ca 350 switch (memberstruct->type) {
351 case M_ANY:
352 case M_USER:
353 membervec[1] = "USER";
8defc06b 354 status = mr_query("delete_member_from_list", 3, membervec,
2d7360ca 355 scream, NULL);
8defc06b 356 if (status == MR_SUCCESS)
2d7360ca 357 break;
8defc06b 358 else if ((status != MR_USER && status != MR_NO_MATCH) ||
2d7360ca 359 memberstruct->type != M_ANY) {
d44cee72 360 com_err(whoami, status, "while deleting member %s from %s",
2d7360ca 361 memberstruct->name, listname);
362 break;
363 }
364 case M_LIST:
365 membervec[1] = "LIST";
8defc06b 366 status = mr_query("delete_member_from_list", 3, membervec,
2d7360ca 367 scream, NULL);
8defc06b 368 if (status == MR_SUCCESS)
2d7360ca 369 break;
8defc06b 370 else if ((status != MR_LIST && status != MR_NO_MATCH) ||
2d7360ca 371 memberstruct->type != M_ANY) {
40637dba 372 if (status == MR_PERM && memberstruct->type == M_ANY) {
373 /* M_ANY means we've fallen through from the user case
374 * The fact that we didn't get MR_PERM there indicates
375 * that we had permission to remove the specified member
376 * from the list if it is a user, but not a list. This is
377 * if we are the member in question. Since we exist as a user
378 * we must have gotten the MR_NO_MATCH error, so we will
379 * return that, since it will be less confusing. However,
380 * This will generate the wrongerror if the user was trying
381 * to remove the list with his/her username from a list they
382 * don't administrate, without explicitly specifying "list:".
383 */
384 status = MR_NO_MATCH;
385 }
d44cee72 386 com_err(whoami, status, "while deleting member %s from %s",
2d7360ca 387 memberstruct->name, listname);
388 break;
389 }
390 case M_STRING:
391 membervec[1] = "STRING";
8defc06b 392 status = mr_query("delete_member_from_list", 3, membervec,
2d7360ca 393 scream, NULL);
8defc06b 394 if (status == MR_STRING && memberstruct->type == M_ANY)
d44cee72 395 com_err(whoami, 0, " Unable to find member %s to delete from %s",
2d7360ca 396 memberstruct->name, listname);
8defc06b 397 else if (status != MR_SUCCESS)
d44cee72 398 com_err(whoami, status, "while deleting member %s from %s",
2d7360ca 399 memberstruct->name, listname);
8c3b414d 400 break;
401 case M_KERBEROS:
402 membervec[1] = "KERBEROS";
8defc06b 403 status = mr_query("delete_member_from_list", 3, membervec,
8c3b414d 404 scream, NULL);
8defc06b 405 if (status != MR_SUCCESS)
d44cee72 406 com_err(whoami, status, "while deleting member %s from %s",
8c3b414d 407 memberstruct->name, listname);
2d7360ca 408 }
409 }
410
411 /* Display the members of the list now, if requested */
b5b167d6 412 if (memberflg) {
413 if (recursflg)
414 recursive_display_list_members();
415 else {
8defc06b 416 status = mr_query("get_members_of_list", 1, &listname,
b5b167d6 417 get_list_members, (char *)memberlist);
418 if (status)
d44cee72 419 com_err(whoami, status, "while getting members of list %s",
b5b167d6 420 listname);
421 while (sq_get_data(memberlist, &memberstruct))
422 show_list_member(memberstruct);
423 }
424 }
2d7360ca 425
426 /* We're done! */
8defc06b 427 mr_disconnect();
2d7360ca 428 exit(0);
429}
430
431usage(argv)
432char **argv;
433{
d465790c 434 fprintf(stderr, "Usage: %s listname [options]\n",argv[0]);
1b6b0a57 435 fprintf(stderr, "Options are\n");
436 fprintf(stderr, " -v | -verbose\n");
437 fprintf(stderr, " -m | -members\n");
8b494222 438 fprintf(stderr, " -u | -users\n");
439 fprintf(stderr, " -l | -lists\n");
440 fprintf(stderr, " -s | -strings\n");
8c3b414d 441 fprintf(stderr, " -k | -kerberos\n");
1b6b0a57 442 fprintf(stderr, " -i | -info\n");
443 fprintf(stderr, " -r | -recursive\n");
444 fprintf(stderr, " -a | -add member\n");
445 fprintf(stderr, " -d | -delete member\n");
7c02cbdb 446 fprintf(stderr, " -al | -addlist filename\n");
447 fprintf(stderr, " -dl | -deletelist filename\n");
1b6b0a57 448 fprintf(stderr, " -f | -file filename\n");
8b494222 449 fprintf(stderr, " -n | -noauth\n");
7c02cbdb 450 fprintf(stderr, " -S | -server host[:port]\n");
1b6b0a57 451 fprintf(stderr, " -D | -debug\n");
2d7360ca 452 exit(1);
453}
454
455
b5b167d6 456/* Display the members stored in the queue */
1b6b0a57 457
b5b167d6 458show_list_member(memberstruct)
459struct member *memberstruct;
460{
24582af9 461 char *s = "";
8b494222 462
463 switch (memberstruct->type) {
464 case M_USER:
465 if (!showusers)
466 return;
467 s = "USER";
468 break;
469 case M_LIST:
470 if (!showlists)
471 return;
472 s = "LIST";
473 break;
474 case M_STRING:
475 if (!showstrings)
476 return;
477 s = "STRING";
478 break;
8c3b414d 479 case M_KERBEROS:
480 if (!showkerberos)
481 return;
482 s = "KERBEROS";
483 break;
8b494222 484 case M_ANY:
485 printf("%s\n", memberstruct->name);
486 return;
487 }
488
489 if (verbose)
490 printf("%s:%s\n", s, memberstruct->name);
491 else {
b5b167d6 492 if (memberstruct->type == M_LIST)
493 printf("LIST:%s\n", memberstruct->name);
8c3b414d 494 else if (memberstruct->type == M_KERBEROS)
495 printf("KERBEROS:%s\n", memberstruct->name);
b5b167d6 496 else if (memberstruct->type == M_STRING &&
f071d8a7 497 !strchr(memberstruct->name, '@'))
b5b167d6 498 printf("STRING:%s\n", memberstruct->name);
499 else
500 printf("%s\n", memberstruct->name);
1b6b0a57 501 }
502}
503
b5b167d6 504
505/* Show the retrieved information about a list */
506
2d7360ca 507show_list_info(argc, argv, hint)
508int argc;
509char **argv;
510int hint;
511{
512 printf("List: %s\n", argv[0]);
513 printf("Description: %s\n", argv[9]);
514 printf("Flags: %s, %s, and %s\n",
515 atoi(argv[1]) ? "active" : "inactive",
516 atoi(argv[2]) ? "public" : "private",
517 atoi(argv[3]) ? "hidden" : "visible");
1b6b0a57 518 printf("%s is %sa maillist and is %sa group", argv[0],
2d7360ca 519 atoi(argv[4]) ? "" : "not ",
520 atoi(argv[5]) ? "" : "not ");
521 if (atoi(argv[5]))
522 printf(" with GID %d\n", atoi(argv[6]));
523 else
524 printf("\n");
525 printf("Owner: %s %s\n", argv[7], argv[8]);
526 printf("Last modified by %s with %s on %s\n", argv[11], argv[12], argv[10]);
8defc06b 527 return(MR_CONT);
2d7360ca 528}
529
530
b5b167d6 531/* Show the retrieve list member count */
532
2d7360ca 533show_list_count(argc, argv, hint)
534int argc;
535char **argv;
536int hint;
537{
538 printf("Members: %s\n", argv[0]);
539}
540
541
b5b167d6 542/* Recursively find all of the members of listname, and then display them */
543
544recursive_display_list_members()
1b6b0a57 545{
b5b167d6 546 int status, count, savecount;
547 struct save_queue *lists, *members;
548 struct member *m, *m1, *data;
549
550 lists = sq_create();
551 members = sq_create();
552 m = (struct member *) malloc(sizeof(struct member));
553 m->type = M_LIST;
554 m->name = listname;
555 sq_save_data(lists, m);
556
557 while (sq_get_data(lists, &m)) {
558 sq_destroy(memberlist);
559 memberlist = sq_create();
560 if (debugflg)
561 fprintf(stderr, "Fetching members of %s\n", m->name);
8defc06b 562 status = mr_query("get_members_of_list", 1, &(m->name),
b5b167d6 563 get_list_members, (char *)memberlist);
564 if (status)
d44cee72 565 com_err(whoami, status, "while getting members of list %s", m->name);
b5b167d6 566 while (sq_get_data(memberlist, &m1)) {
567 if (m1->type == M_LIST)
568 unique_add_member(lists, m1);
569 else
570 unique_add_member(members, m1);
571 }
572 }
573 savecount = count = sq_count_elts(members);
574 data = (struct member *) malloc(count * sizeof(struct member));
575 count = 0;
576 while (sq_get_data(members, &m))
f071d8a7 577 memcpy(&data[count++], m, sizeof(struct member));
b5b167d6 578 qsort(data, count, sizeof(struct member), membercmp);
579 for (count = 0; count < savecount; count++) {
580 show_list_member(&data[count]);
581 }
582}
583
584
585/* add a struct member to a queue if that member isn't already there. */
586
587unique_add_member(q, m)
588struct save_queue *q;
589struct member *m;
590{
591 struct save_queue *qp;
1b6b0a57 592
b5b167d6 593 for (qp = q->q_next; qp != q; qp = qp->q_next) {
594 if (!membercmp(qp->q_data, m))
595 return;
596 }
597 sq_save_data(q, m);
1b6b0a57 598}
599
b5b167d6 600
601/* Collect the retrieved members of the list */
602
2d7360ca 603get_list_members(argc, argv, q)
604int argc;
605char **argv;
606struct save_queue *q;
607{
608 struct member *m;
609
610 m = (struct member *) malloc(sizeof(struct member));
611 switch (argv[0][0]) {
612 case 'U':
613 m->type = M_USER;
614 break;
615 case 'L':
616 m->type = M_LIST;
617 break;
618 case 'S':
619 m->type = M_STRING;
620 break;
8c3b414d 621 case 'K':
622 m->type = M_KERBEROS;
623 break;
2d7360ca 624 }
625 m->name = strsave(argv[1]);
626 sq_save_data(q, m);
8defc06b 627 return(MR_CONT);
2d7360ca 628}
629
630
b5b167d6 631/* Called only if a query returns a value that we weren't expecting */
632
2d7360ca 633scream()
634{
635 fprintf(stderr, "Programmer botch\n");
636 exit(3);
637}
638
639
7c02cbdb 640/* Open file, parse members from file, and put them on the specified queue */
641get_members_from_file(filename, queue)
642char *filename;
643struct save_queue *queue;
644{
645 FILE *in;
646 char buf[BUFSIZ];
647 struct member *memberstruct;
648
649 if (!strcmp(filename, "-"))
650 in = stdin;
651 else {
652 in = fopen(filename, "r");
653 if (!in) {
654 com_err(whoami, errno, "while opening %s for input", filename);
655 exit(2);
656 }
657 }
658
659 while (fgets(buf, BUFSIZ, in))
660 if (memberstruct = parse_member(buf))
661 sq_save_data(queue, memberstruct);
662 if (!feof(in))
663 com_err(whoami, errno, "while reading from %s", filename);
664}
665
666
99bdafb8 667/* Collect the possible expansions of the alias MAILHUB */
668
669int collect(argc, argv, list)
670int argc;
671char **argv;
672char ***list;
673{
674 int i;
675
676 for (i = 0; (*list)[i]; i++);
677 *list = (char **)realloc(*list, (i + 2) * sizeof(char *));
678 (*list)[i] = strsave(argv[2]);
679 (*list)[i+1] = NULL;
680 return(MR_CONT);
681}
682
683
b5b167d6 684/* Parse a line of input, fetching a member. NULL is returned if a member
7c02cbdb 685 * is not found. ';' is a comment character.
b5b167d6 686 */
687
2d7360ca 688struct member *parse_member(s)
689register char *s;
690{
691 register struct member *m;
7c02cbdb 692 char *p, *lastchar;
2d7360ca 693
694 while (*s && isspace(*s))
695 s++;
7c02cbdb 696 lastchar = p = s;
697 while (*p && *p != '\n' && *p != ';')
698 if (isprint(*p) && !isspace(*p))
699 lastchar = p++;
700 else
701 p++;
702 lastchar++;
703 *lastchar = 0;
2d7360ca 704 if (p == s || strlen(s) == 0)
705 return(NULL);
706
707 if ((m = (struct member *) malloc(sizeof(struct member))) == NULL)
708 return(NULL);
709
f071d8a7 710 if (p = strchr(s, ':')) {
2d7360ca 711 *p = 0;
712 m->name = ++p;
713 if (!strcasecmp("user", s))
714 m->type = M_USER;
715 else if (!strcasecmp("list", s))
716 m->type = M_LIST;
717 else if (!strcasecmp("string", s))
718 m->type = M_STRING;
8c3b414d 719 else if (!strcasecmp("kerberos", s))
720 m->type = M_KERBEROS;
2d7360ca 721 else {
722 m->type = M_STRING;
723 *(--p) = ':';
724 m->name = s;
725 }
726 m->name = strsave(m->name);
99bdafb8 727 } else {
728 m->name = strsave(s);
f071d8a7 729 if (strchr(s, '@') || strchr(s, '!') || strchr(s, '%') || strchr(s, ' '))
99bdafb8 730 m->type = M_STRING;
731 else
732 m->type = M_ANY;
2d7360ca 733 }
2d7360ca 734 return(m);
735}
736
737
1b6b0a57 738 /*
739 * This routine two compares members by the following rules:
740 * 1. A USER is less than a LIST
741 * 2. A LIST is less than a STRING
742 * 3. If two members are of the same type, the one alphabetically first
743 * is less than the other
744 * It returs < 0 if the first member is less, 0 if they are identical, and
745 * > 0 if the second member is less (the first member is greater).
746 */
b5b167d6 747
748int membercmp(m1, m2)
749 struct member *m1, *m2;
2d7360ca 750{
1b6b0a57 751 if (m1->type == M_ANY || m2->type == M_ANY || (m1->type == m2->type))
752 return(strcmp(m1->name, m2->name));
2d7360ca 753 else
1b6b0a57 754 return(m1->type - m2->type);
2d7360ca 755}
b5b167d6 756
757
758sq_count_elts(q)
759struct save_queue *q;
760{
761 char *foo;
762 int count;
763
764 count = 0;
765 while (sq_get_data(q, &foo))
766 count++;
767 return(count);
768}
This page took 0.212967 seconds and 5 git commands to generate.