]> andersk Git - moira.git/blame - clients/blanche/blanche.c
fix quota records when moving an NFS filesystem to AFS
[moira.git] / clients / blanche / blanche.c
CommitLineData
2d7360ca 1/* $Header$
2 *
3 * Command line oriented SMS List tool.
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>
20#include <sms.h>
21#include <sms_app.h>
22
23#ifndef LINT
24static char smslist_rcsid[] = "$Header$";
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();
1b6b0a57 56int show_list_members();
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;
8c3b414d 69 char *server = SMS_SERVER;
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++;
97 else if (argis("i","information"))
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);
118 else if (argis("d","delete"))
119 if (arg - argv < argc - 1) {
120 ++arg;
121 if (memberstruct = parse_member(*arg))
122 sq_save_data(dellist, memberstruct);
123 } else
124 usage(argv);
125 else if (argis("f","file"))
126 if (arg - argv < argc - 1) {
127 FILE *in;
128 char buf[BUFSIZ];
b5b167d6 129
1b6b0a57 130 syncflg++;
131 ++arg;
132 if (!strcmp(*arg, "-"))
b5b167d6 133 in = stdin;
1b6b0a57 134 else {
135 in = fopen(*arg, "r");
b5b167d6 136 if (!in) {
1b6b0a57 137 com_err(whoami, errno,
138 " while opening %s for input", *arg);
139 exit(2);
140 }
141 }
142 while (fgets(buf, BUFSIZ, in))
b5b167d6 143 if (memberstruct = parse_member(buf))
144 sq_save_data(synclist, memberstruct);
1b6b0a57 145 if (!feof(in))
b5b167d6 146 com_err(whoami, errno, " while reading from %s", *arg);
1b6b0a57 147 } else
b5b167d6 148 usage(argv);
1b6b0a57 149 else
2d7360ca 150 usage(argv);
1b6b0a57 151 }
2d7360ca 152 else if (listname == NULL)
153 listname = *arg;
154 else
155 usage(argv);
156 }
157 if (listname == NULL)
158 usage(argv);
159
160 /* if no other options specified, turn on list members flag */
161 if (!(infoflg || syncflg ||
162 addlist->q_next != addlist || dellist->q_next != dellist))
163 memberflg++;
164
8c3b414d 165 /* If none of {users,strings,lists,kerberos} specified, turn them all on */
166 if (!(showusers || showstrings || showlists || showkerberos))
167 showusers = showstrings = showlists = showkerberos = 1;
8b494222 168
2d7360ca 169 /* fire up SMS */
8c3b414d 170 if (status = sms_connect(server)) {
95cd286e 171 com_err(whoami, status, " unable to connect to the Moira server");
2d7360ca 172 exit(2);
173 }
37e3ac2d 174 if ( status = sms_motd(&motd) ) {
175 com_err(whoami, status, " unable to check server status");
176 exit(2);
177 }
178 if (motd) {
95cd286e 179 fprintf(stderr, "The Moira server is currently unavailable:\n%s\n", motd);
37e3ac2d 180 sms_disconnect();
181 exit(2);
182 }
183
8b494222 184 if (!noauth && (status = sms_auth("blanche"))) {
95cd286e 185 com_err(whoami, status, " unable to authenticate to Moira");
8b494222 186 com_err(whoami, 0,
187 "Try the -noauth flag if you don't need authentication");
2d7360ca 188 exit(2);
189 }
190
191 /* display list info if requested to */
192 if (infoflg) {
193 status = sms_query("get_list_info", 1, &listname, show_list_info,NULL);
194 if (status)
195 com_err(whoami, status, " while getting list information");
196 if (verbose && !memberflg) {
197 status = sms_query("count_members_of_list", 1, &listname,
198 show_list_count, NULL);
199 if (status)
200 com_err(whoami, status, " while getting list count");
201 }
202 }
203
204 /* if we're synchronizing to a file, we need to:
205 * get the current members of the list
206 * for each member of the sync file
207 * if they are on the list, remove them from the in-memory copy
208 * if they're not on the list, add them to add-list
209 * if anyone is left on the in-memory copy, put them on the delete-list
210 * lastly, reset memberlist so we can use it again later
211 */
212 if (syncflg) {
213 status = sms_query("get_members_of_list", 1, &listname,
1b6b0a57 214 get_list_members, (char *)memberlist);
2d7360ca 215 if (status)
b5b167d6 216 com_err(whoami, status, " getting members of list %s", listname);
2d7360ca 217 while (sq_get_data(synclist, &memberstruct)) {
218 struct save_queue *q;
219 int removed = 0;
220
221 for (q = memberlist->q_next; q != memberlist; q = q->q_next) {
1b6b0a57 222 if (membercmp(q->q_data, memberstruct) == 0) {
2d7360ca 223 q->q_prev->q_next = q->q_next;
224 q->q_next->q_prev = q->q_prev;
225 removed++;
226 break;
227 }
228 }
229 if (!removed)
230 sq_save_data(addlist, memberstruct);
231 }
232 while (sq_get_data(memberlist, &memberstruct))
233 sq_save_data(dellist, memberstruct);
234 sq_destroy(memberlist);
235 memberlist = sq_create();
236 }
237
238 /* Process the add list */
239 while (sq_get_data(addlist, &memberstruct)) {
240 membervec[0] = listname;
241 membervec[2] = memberstruct->name;
b5b167d6 242 if (verbose && syncflg) {
243 printf("Adding member ");
244 show_list_member(memberstruct);
245 }
2d7360ca 246 switch (memberstruct->type) {
247 case M_ANY:
248 case M_USER:
249 membervec[1] = "USER";
250 status = sms_query("add_member_to_list", 3, membervec, scream, NULL);
251 if (status == SMS_SUCCESS)
252 break;
253 else if (status != SMS_USER || memberstruct->type != M_ANY) {
254 com_err(whoami, status, " while adding member %s to %s",
255 memberstruct->name, listname);
256 break;
257 }
258 case M_LIST:
259 membervec[1] = "LIST";
260 status = sms_query("add_member_to_list", 3, membervec,
261 scream, NULL);
262 if (status == SMS_SUCCESS)
263 break;
264 else if (status != SMS_LIST || memberstruct->type != M_ANY) {
265 com_err(whoami, status, " while adding member %s to %s",
266 memberstruct->name, listname);
267 break;
268 }
269 case M_STRING:
270 membervec[1] = "STRING";
271 status = sms_query("add_member_to_list", 3, membervec,
272 scream, NULL);
273 if (status != SMS_SUCCESS)
274 com_err(whoami, status, " while adding member %s to %s",
275 memberstruct->name, listname);
8c3b414d 276 break;
277 case M_KERBEROS:
278 membervec[1] = "KERBEROS";
279 status = sms_query("add_member_to_list", 3, membervec,
280 scream, NULL);
281 if (status != SMS_SUCCESS)
282 com_err(whoami, status, " while adding member %s to %s",
283 memberstruct->name, listname);
2d7360ca 284 }
285 }
286
287 /* Process the delete list */
288 while (sq_get_data(dellist, &memberstruct)) {
289 membervec[0] = listname;
290 membervec[2] = memberstruct->name;
b5b167d6 291 if (verbose && syncflg) {
292 printf("Deleting member ");
293 show_list_member(memberstruct);
294 }
2d7360ca 295 switch (memberstruct->type) {
296 case M_ANY:
297 case M_USER:
298 membervec[1] = "USER";
299 status = sms_query("delete_member_from_list", 3, membervec,
300 scream, NULL);
301 if (status == SMS_SUCCESS)
302 break;
303 else if ((status != SMS_USER && status != SMS_NO_MATCH) ||
304 memberstruct->type != M_ANY) {
305 com_err(whoami, status, " while deleteing member %s from %s",
306 memberstruct->name, listname);
307 break;
308 }
309 case M_LIST:
310 membervec[1] = "LIST";
311 status = sms_query("delete_member_from_list", 3, membervec,
312 scream, NULL);
313 if (status == SMS_SUCCESS)
314 break;
315 else if ((status != SMS_LIST && status != SMS_NO_MATCH) ||
316 memberstruct->type != M_ANY) {
317 com_err(whoami, status, " while deleteing member %s from %s",
318 memberstruct->name, listname);
319 break;
320 }
321 case M_STRING:
322 membervec[1] = "STRING";
323 status = sms_query("delete_member_from_list", 3, membervec,
324 scream, NULL);
325 if (status == SMS_STRING && memberstruct->type == M_ANY)
326 com_err(whoami, 0, "Unable to find member %s to delete from %s",
327 memberstruct->name, listname);
328 else if (status != SMS_SUCCESS)
329 com_err(whoami, status, " while deleteing member %s from %s",
330 memberstruct->name, listname);
8c3b414d 331 break;
332 case M_KERBEROS:
333 membervec[1] = "KERBEROS";
334 status = sms_query("delete_member_from_list", 3, membervec,
335 scream, NULL);
336 if (status != SMS_SUCCESS)
337 com_err(whoami, status, " while deleteing member %s from %s",
338 memberstruct->name, listname);
2d7360ca 339 }
340 }
341
342 /* Display the members of the list now, if requested */
b5b167d6 343 if (memberflg) {
344 if (recursflg)
345 recursive_display_list_members();
346 else {
347 status = sms_query("get_members_of_list", 1, &listname,
348 get_list_members, (char *)memberlist);
349 if (status)
350 com_err(whoami, status, " while getting members of list %s",
351 listname);
352 while (sq_get_data(memberlist, &memberstruct))
353 show_list_member(memberstruct);
354 }
355 }
2d7360ca 356
357 /* We're done! */
358 sms_disconnect();
359 exit(0);
360}
361
362usage(argv)
363char **argv;
364{
1b6b0a57 365 fprintf(stderr, "Usage: %s [options] listname [options]\n",argv[0]);
366 fprintf(stderr, "Options are\n");
367 fprintf(stderr, " -v | -verbose\n");
368 fprintf(stderr, " -m | -members\n");
8b494222 369 fprintf(stderr, " -u | -users\n");
370 fprintf(stderr, " -l | -lists\n");
371 fprintf(stderr, " -s | -strings\n");
8c3b414d 372 fprintf(stderr, " -k | -kerberos\n");
1b6b0a57 373 fprintf(stderr, " -i | -info\n");
374 fprintf(stderr, " -r | -recursive\n");
375 fprintf(stderr, " -a | -add member\n");
376 fprintf(stderr, " -d | -delete member\n");
377 fprintf(stderr, " -f | -file filename\n");
8b494222 378 fprintf(stderr, " -n | -noauth\n");
8c3b414d 379 fprintf(stderr, " -S | -server host:port\n");
1b6b0a57 380 fprintf(stderr, " -D | -debug\n");
2d7360ca 381 exit(1);
382}
383
384
b5b167d6 385/* Display the members stored in the queue */
1b6b0a57 386
b5b167d6 387show_list_member(memberstruct)
388struct member *memberstruct;
389{
8b494222 390 char *s;
391
392 switch (memberstruct->type) {
393 case M_USER:
394 if (!showusers)
395 return;
396 s = "USER";
397 break;
398 case M_LIST:
399 if (!showlists)
400 return;
401 s = "LIST";
402 break;
403 case M_STRING:
404 if (!showstrings)
405 return;
406 s = "STRING";
407 break;
8c3b414d 408 case M_KERBEROS:
409 if (!showkerberos)
410 return;
411 s = "KERBEROS";
412 break;
8b494222 413 case M_ANY:
414 printf("%s\n", memberstruct->name);
415 return;
416 }
417
418 if (verbose)
419 printf("%s:%s\n", s, memberstruct->name);
420 else {
b5b167d6 421 if (memberstruct->type == M_LIST)
422 printf("LIST:%s\n", memberstruct->name);
8c3b414d 423 else if (memberstruct->type == M_KERBEROS)
424 printf("KERBEROS:%s\n", memberstruct->name);
b5b167d6 425 else if (memberstruct->type == M_STRING &&
426 !index(memberstruct->name, '@'))
427 printf("STRING:%s\n", memberstruct->name);
428 else
429 printf("%s\n", memberstruct->name);
1b6b0a57 430 }
431}
432
b5b167d6 433
434/* Show the retrieved information about a list */
435
2d7360ca 436show_list_info(argc, argv, hint)
437int argc;
438char **argv;
439int hint;
440{
441 printf("List: %s\n", argv[0]);
442 printf("Description: %s\n", argv[9]);
443 printf("Flags: %s, %s, and %s\n",
444 atoi(argv[1]) ? "active" : "inactive",
445 atoi(argv[2]) ? "public" : "private",
446 atoi(argv[3]) ? "hidden" : "visible");
1b6b0a57 447 printf("%s is %sa maillist and is %sa group", argv[0],
2d7360ca 448 atoi(argv[4]) ? "" : "not ",
449 atoi(argv[5]) ? "" : "not ");
450 if (atoi(argv[5]))
451 printf(" with GID %d\n", atoi(argv[6]));
452 else
453 printf("\n");
454 printf("Owner: %s %s\n", argv[7], argv[8]);
455 printf("Last modified by %s with %s on %s\n", argv[11], argv[12], argv[10]);
456 return(SMS_CONT);
457}
458
459
b5b167d6 460/* Show the retrieve list member count */
461
2d7360ca 462show_list_count(argc, argv, hint)
463int argc;
464char **argv;
465int hint;
466{
467 printf("Members: %s\n", argv[0]);
468}
469
470
b5b167d6 471/* Recursively find all of the members of listname, and then display them */
472
473recursive_display_list_members()
1b6b0a57 474{
b5b167d6 475 int status, count, savecount;
476 struct save_queue *lists, *members;
477 struct member *m, *m1, *data;
478
479 lists = sq_create();
480 members = sq_create();
481 m = (struct member *) malloc(sizeof(struct member));
482 m->type = M_LIST;
483 m->name = listname;
484 sq_save_data(lists, m);
485
486 while (sq_get_data(lists, &m)) {
487 sq_destroy(memberlist);
488 memberlist = sq_create();
489 if (debugflg)
490 fprintf(stderr, "Fetching members of %s\n", m->name);
491 status = sms_query("get_members_of_list", 1, &(m->name),
492 get_list_members, (char *)memberlist);
493 if (status)
494 com_err(whoami, status, " while getting members of list %s", m->name);
495 while (sq_get_data(memberlist, &m1)) {
496 if (m1->type == M_LIST)
497 unique_add_member(lists, m1);
498 else
499 unique_add_member(members, m1);
500 }
501 }
502 savecount = count = sq_count_elts(members);
503 data = (struct member *) malloc(count * sizeof(struct member));
504 count = 0;
505 while (sq_get_data(members, &m))
506 bcopy(m, &data[count++], sizeof(struct member));
507 qsort(data, count, sizeof(struct member), membercmp);
508 for (count = 0; count < savecount; count++) {
509 show_list_member(&data[count]);
510 }
511}
512
513
514/* add a struct member to a queue if that member isn't already there. */
515
516unique_add_member(q, m)
517struct save_queue *q;
518struct member *m;
519{
520 struct save_queue *qp;
1b6b0a57 521
b5b167d6 522 for (qp = q->q_next; qp != q; qp = qp->q_next) {
523 if (!membercmp(qp->q_data, m))
524 return;
525 }
526 sq_save_data(q, m);
1b6b0a57 527}
528
b5b167d6 529
530/* Collect the retrieved members of the list */
531
2d7360ca 532get_list_members(argc, argv, q)
533int argc;
534char **argv;
535struct save_queue *q;
536{
537 struct member *m;
538
539 m = (struct member *) malloc(sizeof(struct member));
540 switch (argv[0][0]) {
541 case 'U':
542 m->type = M_USER;
543 break;
544 case 'L':
545 m->type = M_LIST;
546 break;
547 case 'S':
548 m->type = M_STRING;
549 break;
8c3b414d 550 case 'K':
551 m->type = M_KERBEROS;
552 break;
2d7360ca 553 }
554 m->name = strsave(argv[1]);
555 sq_save_data(q, m);
556 return(SMS_CONT);
557}
558
559
b5b167d6 560/* Called only if a query returns a value that we weren't expecting */
561
2d7360ca 562scream()
563{
564 fprintf(stderr, "Programmer botch\n");
565 exit(3);
566}
567
568
b5b167d6 569/* Parse a line of input, fetching a member. NULL is returned if a member
570 * is not found. Only the first token on the line is parsed. ';' is a
571 * comment character.
572 */
573
2d7360ca 574struct member *parse_member(s)
575register char *s;
576{
577 register struct member *m;
578 char *p;
579
580 while (*s && isspace(*s))
581 s++;
582 p = s;
583 while (*p && isprint(*p) && !isspace(*p) && *p != ';')
584 p++;
585 *p = 0;
586 if (p == s || strlen(s) == 0)
587 return(NULL);
588
589 if ((m = (struct member *) malloc(sizeof(struct member))) == NULL)
590 return(NULL);
591
592 if (p = index(s, ':')) {
593 *p = 0;
594 m->name = ++p;
595 if (!strcasecmp("user", s))
596 m->type = M_USER;
597 else if (!strcasecmp("list", s))
598 m->type = M_LIST;
599 else if (!strcasecmp("string", s))
600 m->type = M_STRING;
8c3b414d 601 else if (!strcasecmp("kerberos", s))
602 m->type = M_KERBEROS;
2d7360ca 603 else {
604 m->type = M_STRING;
605 *(--p) = ':';
606 m->name = s;
607 }
608 m->name = strsave(m->name);
609 return(m);
610 }
611 m->name = strsave(s);
612 if (index(s, '@') || index(s, '!') || index(s, '%'))
613 m->type = M_STRING;
614 else
615 m->type = M_ANY;
616 return(m);
617}
618
619
1b6b0a57 620 /*
621 * This routine two compares members by the following rules:
622 * 1. A USER is less than a LIST
623 * 2. A LIST is less than a STRING
624 * 3. If two members are of the same type, the one alphabetically first
625 * is less than the other
626 * It returs < 0 if the first member is less, 0 if they are identical, and
627 * > 0 if the second member is less (the first member is greater).
628 */
b5b167d6 629
630int membercmp(m1, m2)
631 struct member *m1, *m2;
2d7360ca 632{
1b6b0a57 633 if (m1->type == M_ANY || m2->type == M_ANY || (m1->type == m2->type))
634 return(strcmp(m1->name, m2->name));
2d7360ca 635 else
1b6b0a57 636 return(m1->type - m2->type);
2d7360ca 637}
b5b167d6 638
639
640sq_count_elts(q)
641struct save_queue *q;
642{
643 char *foo;
644 int count;
645
646 count = 0;
647 while (sq_get_data(q, &foo))
648 count++;
649 return(count);
650}
This page took 0.150815 seconds and 5 git commands to generate.