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