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