]> andersk Git - moira.git/blame - clients/mitch/mitch.c
bella becomes mitch to stay consistant with our naming scheme
[moira.git] / clients / mitch / mitch.c
CommitLineData
7cc696ad 1/*
2 * Command line oriented Moira containers tool.
3 *
4 * Garry Zacheiss <zacheiss@mit.edu>, January 2003
5 *
6 * Inspired by blanche
7 *
8 * Copyright (C) 2002 by the Massachusetts Institute of Technology.
9 * For copying and distribution information, please see the file
10 * <mit-copyright.h>.
11 */
12
13#include <mit-copyright.h>
14#include <moira.h>
15#include <moira_site.h>
16#include <mrclient.h>
17
18#include <ctype.h>
19#include <errno.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24RCSID("$Id$");
25
26struct owner_type {
27 int type;
28 char *name;
29};
30
31struct mqelem {
32 struct mqelem *q_forw;
33 struct mqelem *q_back;
34 void *q_data;
35};
36
37struct string_list {
38 char *string;
39 struct string_list *next;
40};
41
42#define M_ANY 0
43#define M_USER 1
44#define M_LIST 2
45#define M_KERBEROS 3
46#define M_NONE 4
47
48char *typename[] = { "ANY", "USER", "LIST", "KERBEROS", "NONE" };
49
50/* argument parsing macro */
51#define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
52
53/* flags from command line */
54int info_flag, update_flag, create_flag, delete_flag, list_subcon_flag;
55int list_mach_flag, update_mach_flag, verbose, noauth, unformatted_flag;
56int recurse_flag;
57
58struct string_list *container_add_queue, *container_remove_queue;
59
60char *containername, *whoami;
61
62char *newname, *desc, *location, *contact;
63int public;
64struct owner_type *owner, *memacl;
65
66void usage(char **argv);
67int store_container_info(int argc, char **argv, void *hint);
68void show_container_info(char **argv);
69int show_container_list(int argc, char **argv, void *hint);
70void show_container_info_unformatted(char **argv);
71int show_container_list_unformatted(int argc, char **argv, void *hint);
72int show_machine_in_container(int argc, char **argv, void *hint);
73int show_subcontainers_of_container(int argc, char **argv, void *hint);
74struct owner_type *parse_member(char *s);
75struct string_list *add_to_string_list(struct string_list *old_list, char *s);
76int wrap_mr_query(char *handle, int argc, char **argv,
77 int (*callback)(int, char **, void *), void *callarg);
78void print_query(char *query_name, int argc, char **argv);
79
80int main(int argc, char **argv)
81{
82 int status, success;
83 char **arg = argv;
84 char *server = NULL;
85
86 /* clear all flags & lists */
87 info_flag = update_flag = create_flag = delete_flag = list_subcon_flag = 0;
88 list_mach_flag = update_mach_flag = verbose = noauth = unformatted_flag = 0;
89 recurse_flag = 0;
90 public = -1;
91 container_add_queue = container_remove_queue = NULL;
92 newname = desc = location = contact = NULL;
93 owner = memacl = NULL;
94 whoami = argv[0];
95
96 success = 1;
97
98 /* parse args */
99 while (++arg - argv < argc)
100 {
101 if (**arg == '-')
102 {
103 if (argis("i", "info"))
104 info_flag++;
105 else if (argis("C", "create"))
106 create_flag++;
107 else if (argis("D", "delete"))
108 delete_flag++;
109 else if (argis("R", "rename")) {
110 if (arg - argv < argc - 1) {
111 arg++;
112 update_flag++;
113 newname = *arg;
114 } else
115 usage(argv);
116 }
117 else if (argis("d", "desc")) {
118 if (arg - argv < argc - 1) {
119 arg++;
120 update_flag++;
121 desc = *arg;
122 } else
123 usage(argv);
124 }
125 else if (argis("L", "location")) {
126 if (arg - argv < argc - 1) {
127 arg++;
128 update_flag++;
129 location = *arg;
130 } else
131 usage(argv);
132 }
133 else if (argis("c", "contact")) {
134 if (arg - argv < argc - 1) {
135 arg++;
136 update_flag++;
137 contact = *arg;
138 } else
139 usage(argv);
140 }
141 else if (argis("P", "public"))
142 {
143 update_flag++;
144 public = 1;
145 }
146 else if (argis("NP", "private"))
147 {
148 update_flag++;
149 public = 0;
150 }
151 else if (argis("O", "owner")) {
152 if (arg - argv < argc - 1) {
153 arg++;
154 update_flag++;
155 owner = parse_member(*arg);
156 } else
157 usage(argv);
158 }
159 else if (argis("MA", "memacl")) {
160 if (arg - argv < argc - 1) {
161 arg++;
162 update_flag++;
163 memacl = parse_member(*arg);
164 } else
165 usage(argv);
166 }
167 else if (argis("ls", "listsub"))
168 list_subcon_flag++;
169 else if (argis("lm", "listmach"))
170 list_mach_flag++;
171 else if (argis("am", "addmach")) {
172 if (arg - argv < argc - 1) {
173 arg++;
174 container_add_queue =
175 add_to_string_list(container_add_queue, *arg);
176 } else
177 usage(argv);
178 update_mach_flag++;
179 }
180 else if (argis("dm", "deletemach")) {
181 if (arg - argv < argc - 1) {
182 arg++;
183 container_remove_queue =
184 add_to_string_list(container_remove_queue, *arg);
185 } else
186 usage(argv);
187 update_mach_flag++;
188 }
189 else if (argis("r", "recursive"))
190 recurse_flag++;
191 else if (argis("u", "unformatted"))
192 unformatted_flag++;
193 else if (argis("n", "noauth"))
194 noauth++;
195 else if (argis("v", "verbose"))
196 verbose++;
197 else if (argis("db", "database"))
198 {
199 if (arg - argv < argc - 1)
200 {
201 ++arg;
202 server = *arg;
203 }
204 else
205 usage(argv);
206 }
207 else
208 usage(argv);
209 }
210 else if (containername == NULL)
211 containername = *arg;
212 else
213 usage(argv);
214 }
215 if (containername == NULL)
216 usage(argv);
217
218 /* default to info_flag if nothing else was specified */
219 if(!(info_flag || update_flag || create_flag || delete_flag || \
220 list_subcon_flag || list_mach_flag || update_mach_flag)) {
221 info_flag++;
222 }
223
224 /* fire up Moira */
f62cd5c0 225 status = mrcl_connect(server, "mitch", 9, !noauth);
7cc696ad 226 if (status == MRCL_AUTH_ERROR)
227 {
228 com_err(whoami, 0, "Try the -noauth flag if you don't "
229 "need authentication.");
230 }
231 if (status)
232 exit(2);
233
234 /* create if needed */
235 if (create_flag)
236 {
237 char *argv[15];
238 int cnt;
239
240 for (cnt = 0; cnt < 11; cnt ++) {
241 argv[cnt] = "";
242 }
243
244 argv[CON_NAME] = containername;
245 argv[CON_PUBLIC] = (public == 1) ? "1" : "0";
246 argv[CON_DESCRIPT] = desc ? desc : "none";
247 if (location)
248 argv[CON_LOCATION] = location;
249 if (contact)
250 argv[CON_CONTACT] = contact;
251
252 if (memacl)
253 {
254 if (memacl->type == M_ANY)
255 {
256 status = wrap_mr_query("get_user_account_by_login", 1,
257 &memacl->name, NULL, NULL);
258 if (status == MR_NO_MATCH)
259 memacl->type = M_LIST;
260 else
261 memacl->type = M_USER;
262 }
263 argv[CON_MEMACE_TYPE] = typename[memacl->type];
264 argv[CON_MEMACE_NAME] = memacl->name;
265 if (memacl->type == M_KERBEROS)
266 {
267 status = mrcl_validate_kerberos_member(argv[CON_MEMACE_NAME],
268 &argv[CON_MEMACE_NAME]);
269 if (mrcl_get_message())
270 mrcl_com_err(whoami);
271 if (status == MRCL_REJECT)
272 exit(1);
273 }
274 }
275 else
276 argv[CON_MEMACE_TYPE] = argv[CON_MEMACE_NAME] = "NONE";
277
278 if (owner)
279 {
280 argv[CON_OWNER_NAME] = owner->name;
281 switch (owner->type)
282 {
283 case M_ANY:
284 case M_USER:
285 argv[CON_OWNER_TYPE] = "USER";
286 status = wrap_mr_query("add_container", 9, argv, NULL, NULL);
287 if (owner->type != M_ANY || status != MR_USER)
288 break;
289
290 case M_LIST:
291 argv[CON_OWNER_TYPE] = "LIST";
292 status = wrap_mr_query("add_container", 9, argv, NULL, NULL);
293 break;
294
295 case M_KERBEROS:
296 argv[CON_OWNER_TYPE] = "KERBEROS";
297 status = mrcl_validate_kerberos_member(argv[CON_OWNER_TYPE],
298 &argv[CON_OWNER_TYPE]);
299 if (mrcl_get_message())
300 mrcl_com_err(whoami);
301 if (status == MRCL_REJECT)
302 exit(1);
303 status = wrap_mr_query("add_container", 9, argv, NULL, NULL);
304 break;
305 case M_NONE:
306 argv[CON_OWNER_TYPE] = argv[CON_OWNER_NAME] = "NONE";
307 status = wrap_mr_query("add_containr", 9, argv, NULL, NULL);
308 break;
309 }
310 }
311 else
312 {
313 argv[CON_OWNER_TYPE] = argv[CON_OWNER_NAME] = "NONE";
314 status = wrap_mr_query("add_container", 9, argv, NULL, NULL);
315 }
316
317 if (status)
318 {
319 com_err(whoami, status, "while creating container.");
320 exit(1);
321 }
322 }
323 else if (update_flag)
324 {
325 char *old_argv[15];
326 char *argv[15];
327 char *args[2];
328
329 args[0] = containername;
330
331 status = wrap_mr_query("get_container", 1, args, store_container_info,
332 old_argv);
333 if (status)
334 {
335 com_err(whoami, status, "while getting container information.");
336 exit(1);
337 }
338
339 argv[1] = old_argv[0];
340 argv[2] = old_argv[1];
341 argv[3] = old_argv[2];
342 argv[4] = old_argv[3];
343 argv[5] = old_argv[4];
344 argv[6] = old_argv[5];
345 argv[7] = old_argv[6];
346 argv[8] = old_argv[7];
347 argv[9] = old_argv[8];
348
349 argv[CON_NAME] = containername;
350 if (newname)
351 argv[CON_NAME + 1] = newname;
352 argv[CON_PUBLIC + 1] = (public == 1) ? "1" : "0";
353 if (desc)
354 argv[CON_DESCRIPT + 1] = desc;
355 if (location)
356 argv[CON_LOCATION + 1] = location;
357 if (contact)
358 argv[CON_CONTACT + 1] = contact;
359
360 if (memacl)
361 {
362 if (memacl->type == M_ANY)
363 {
364 status = wrap_mr_query("get_user_account_by_login", 1,
365 &memacl->name, NULL, NULL);
366 if (status == MR_NO_MATCH)
367 memacl->type = M_LIST;
368 else
369 memacl->type = M_USER;
370 }
371 argv[CON_MEMACE_TYPE + 1] = typename[memacl->type];
372 argv[CON_MEMACE_NAME + 1] = memacl->name;
373 if (memacl->type == M_KERBEROS)
374 {
375 status = mrcl_validate_kerberos_member(argv[CON_MEMACE_NAME + 1],
376 &argv[CON_MEMACE_NAME + 1]);
377 if (mrcl_get_message())
378 mrcl_com_err(whoami);
379 if (status == MRCL_REJECT)
380 exit(1);
381 }
382 }
383
384 if (owner)
385 {
386 argv[CON_OWNER_NAME + 1] = owner->name;
387 switch (owner->type)
388 {
389 case M_ANY:
390 case M_USER:
391 argv[CON_OWNER_TYPE + 1] = "USER";
392 status = wrap_mr_query("update_container", 10, argv, NULL, NULL);
393 if (owner->type != M_ANY || status != MR_USER)
394 break;
395
396 case M_LIST:
397 argv[CON_OWNER_TYPE + 1] = "LIST";
398 status = wrap_mr_query("update_container", 10, argv, NULL, NULL);
399 break;
400
401 case M_KERBEROS:
402 argv[CON_OWNER_TYPE + 1] = "KERBEROS";
403 status = mrcl_validate_kerberos_member(argv[CON_OWNER_NAME + 1],
404 &argv[CON_OWNER_NAME + 1]);
405 if (mrcl_get_message())
406 mrcl_com_err(whoami);
407 if (status == MRCL_REJECT)
408 exit(1);
409 status = wrap_mr_query("update_container", 10, argv, NULL, NULL);
410 break;
411
412 case M_NONE:
413 argv[CON_OWNER_TYPE + 1] = argv[CON_OWNER_NAME + 1] = "NONE";
414 status = wrap_mr_query("update_container", 10, argv, NULL, NULL);
415 break;
416 }
417 }
418 else
419 status = wrap_mr_query("update_container", 10, argv, NULL, NULL);
420
421 if (status)
422 {
423 com_err(whoami, status, "while updating container.");
424 success = 0;
425 }
426 else if (newname)
427 containername = newname;
428 }
429
430 /* add machines to container */
431 if (container_add_queue) {
432 struct string_list *q = container_add_queue;
433
434 while (q) {
435 char *args[2];
436
437 args[0] = canonicalize_hostname(strdup(q->string));
438 args[1] = containername;
439 status = wrap_mr_query("add_machine_to_container", 2, args, NULL, NULL);
440 if (status)
441 {
442 com_err(whoami, status, "while adding machine to container.");
443 exit(1);
444 }
445
446 q = q->next;
447 }
448 }
449
450 /* delete machines from container */
451 if (container_remove_queue) {
452 struct string_list *q = container_remove_queue;
453
454 while (q) {
455 char *args[2];
456
457 args[0] = canonicalize_hostname(strdup(q->string));
458 args[1] = containername;
459 status = wrap_mr_query("delete_machine_from_container", 2, args, NULL,
460 NULL);
461 if (status)
462 {
463 com_err(whoami, status, "while removing machine from container.");
464 exit(1);
465 }
466
467 q = q->next;
468 }
469 }
470
471 if (info_flag)
472 {
473 char *args[2];
474 char *argv[20];
475
476 args[0] = containername;
477 status = wrap_mr_query("get_container", 1, args, store_container_info,
478 argv);
479 if (status)
480 {
481 com_err(whoami, status, "while getting container information.");
482 exit(1);
483 }
484
485 if (unformatted_flag)
486 show_container_info_unformatted(argv);
487 else
488 show_container_info(argv);
489 }
490
491 if (delete_flag)
492 {
493 char *args[2];
494
495 args[0] = containername;
496 status = wrap_mr_query("delete_container", 1, args, NULL, NULL);
497 if (status)
498 {
499 com_err(whoami, status, "while deleting container.");
500 exit(1);
501 }
502 }
503
504 if (list_mach_flag)
505 {
506 char *args[3];
507
508 args[0] = containername;
509 args[1] = (recurse_flag == 1) ? "1" : "0";
510 status = wrap_mr_query("get_machines_of_container", 2, args,
511 show_machine_in_container, NULL);
512 if (status)
513 {
514 com_err(whoami, status, "while getting machines of container.");
515 exit(1);
516 }
517 }
518
519 if (list_subcon_flag)
520 {
521 char *args[3];
522
523 args[0] = containername;
524 args[1] = (recurse_flag == 1) ? "1" : "0";
525 status = wrap_mr_query("get_subcontainers_of_container", 2, args,
526 show_subcontainers_of_container, NULL);
527 if (status)
528 {
529 com_err(whoami, status, "while getting subcontainers of container.");
530 exit(1);
531 }
532 }
533
534 mr_disconnect();
535 exit(success ? 0 : 1);
536}
537
538void usage(char **argv)
539{
540#define USAGE_OPTIONS_FORMAT " %-39s%s\n"
541 fprintf(stderr, "Usage: %s containername [options]\n", argv[0]);
542 fprintf(stderr, "Options are\n");
543 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-C | -create",
544 "-O | -owner owner");
545 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-D | -delete",
546 "-d | -desc description");
547 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-R | -rename newname",
548 "-L | -location location");
549 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-i | -info",
550 "-c | -contact contact");
551 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-P | -public",
552 "-NP | -private");
553 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-O | -owner owner",
554 "-MA | -memacl membership_acl");
555 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-ls | -listsub",
556 "-lm | -listmach");
557 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-am | -addmach hostname",
558 "-dm | -deletemach hostname");
559 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-r | -recursive",
560 "-u | -unformatted");
561 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-v | -verbose",
562 "-n | -noauth");
563 fprintf(stderr, " %-39s\n" , "-db | -database host[:port]");
564 exit(1);
565}
566
567/* Retrieve information about a container */
568int store_container_info(int argc, char **argv, void *hint)
569{
570 int i;
571 char **nargv = hint;
572
573 for(i = 0; i < argc; i++)
574 nargv[i] = strdup(argv[i]);
575
576 return MR_CONT;
577}
578
579void show_container_info(char **argv)
580{
581 char tbuf[256];
582 char *args[2];
583 struct mqelem *elem = NULL;
584 int status;
585
586 printf("Container: %-16s Public: %s\n", argv[CON_NAME],
587 argv[CON_PUBLIC]);
588 args[0] = argv[CON_NAME];
589 status = wrap_mr_query("get_container_list", 1, args, show_container_list,
590 &elem);
591 if (status && status != MR_NO_MATCH)
592 com_err(whoami, status, "while getting container list.");
593 printf("Description: %-16s\n", argv[CON_DESCRIPT]);
594 printf("Location: %-16s Contact: %s\n", argv[CON_LOCATION],
595 argv[CON_CONTACT]);
596 sprintf(tbuf, "%s %s", argv[CON_OWNER_TYPE],
597 strcmp(argv[CON_OWNER_TYPE], "NONE") ? argv[CON_OWNER_NAME] : "");
598 printf("Owner: %-16s\n", tbuf);
599 sprintf(tbuf, "%s %s", argv[CON_MEMACE_TYPE],
600 strcmp(argv[CON_MEMACE_TYPE], "NONE") ? argv[CON_MEMACE_NAME] : "");
601 printf("Membership ACL: %-16s\n", tbuf);
602 printf("\n");
603 printf("Last mod by %s at %s with %s.\n", argv[CON_MODBY], argv[CON_MODTIME],
604 argv[CON_MODWITH]);
605}
606
607int show_container_list(int argc, char **argv, void *hint)
608{
609 printf("Container's associated list is: LIST %s\n", argv[1]);
610
611 return MR_CONT;
612}
613
614void show_container_info_unformatted(char **argv)
615{
616 char *args[2];
617 struct mqelem *elem = NULL;
618 int status;
619
620 printf("Container: %s\n", argv[CON_NAME]);
621 args[0] = argv[CON_NAME];
622 status = wrap_mr_query("get_container_list", 1, args,
623 show_container_list_unformatted, &elem);
624 if (status && status != MR_NO_MATCH)
625 com_err(whoami, status, "while getting container list.");
626 else
627 printf("\n");
628 printf("Public: %s\n", argv[CON_PUBLIC]);
629 printf("Description: %s\n", argv[CON_DESCRIPT]);
630 printf("Location: %s\n", argv[CON_LOCATION]);
631 printf("Contact: %s\n", argv[CON_CONTACT]);
632 printf("Owner Type: %s\n", argv[CON_OWNER_TYPE]);
633 printf("Owner: %s\n", argv[CON_OWNER_NAME]);
634 printf("Memacl Type: %s\n", argv[CON_MEMACE_TYPE]);
635 printf("Memacl: %s\n", argv[CON_MEMACE_NAME]);
636 printf("Last mod by: %s\n", argv[CON_MODBY]);
637 printf("Last mod on: %s\n", argv[CON_MODTIME]);
638 printf("Last mod with: %s\n", argv[CON_MODWITH]);
639}
640
641int show_container_list_unformatted(int argc, char **argv, void *hint)
642{
643 printf("Associated list: %s", argv[1]);
644
645 return MR_CONT;
646}
647
648int show_machine_in_container(int argc, char **argv, void *hint)
649{
650 printf("Machine: %-30s Container: %-25s\n", argv[0], argv[1]);
651
652 return MR_CONT;
653}
654
655int show_subcontainers_of_container(int argc, char **argv, void *hint)
656{
657 printf("Container: %-25s\n", argv[0]);
658
659 return MR_CONT;
660}
661
662/* Parse a line of input, fetching a member. NULL is returned if a member
663 * is not found. ';' is a comment character.
664 */
665
666struct owner_type *parse_member(char *s)
667{
668 struct owner_type *m;
669 char *p, *lastchar;
670
671 while (*s && isspace(*s))
672 s++;
673 lastchar = p = s;
674 while (*p && *p != '\n' && *p != ';')
675 {
676 if (isprint(*p) && !isspace(*p))
677 lastchar = p++;
678 else
679 p++;
680 }
681 lastchar++;
682 *lastchar = '\0';
683 if (p == s || strlen(s) == 0)
684 return NULL;
685
686 if (!(m = malloc(sizeof(struct owner_type))))
687 return NULL;
688
689 if ((p = strchr(s, ':')))
690 {
691 *p = '\0';
692 m->name = ++p;
693 if (!strcasecmp("user", s))
694 m->type = M_USER;
695 else if (!strcasecmp("list", s))
696 m->type = M_LIST;
697 else if (!strcasecmp("kerberos", s))
698 m->type = M_KERBEROS;
699 else if (!strcasecmp("none", s))
700 m->type = M_NONE;
701 else
702 {
703 m->type = M_ANY;
704 *(--p) = ':';
705 m->name = s;
706 }
707 m->name = strdup(m->name);
708 }
709 else
710 {
711 m->name = strdup(s);
712 m->type = strcasecmp(s, "none") ? M_ANY : M_NONE;
713 }
714 return m;
715}
716
717struct string_list *add_to_string_list(struct string_list *old_list, char *s) {
718 struct string_list *new_list;
719
720 new_list = (struct string_list *)malloc(sizeof(struct string_list *));
721 new_list->next = old_list;
722 new_list->string = s;
723
724 return new_list;
725}
726
727int wrap_mr_query(char *handle, int argc, char **argv,
728 int (*callback)(int, char **, void *), void *callarg) {
729 if (verbose)
730 print_query(handle, argc, argv);
731
732 return mr_query(handle, argc, argv, callback, callarg);
733}
734
735void print_query(char *query_name, int argc, char **argv) {
736 int cnt;
737
738 printf("qy %s", query_name);
739 for(cnt=0; cnt<argc; cnt++)
740 printf(" <%s>", argv[cnt]);
741 printf("\n");
742}
This page took 0.369297 seconds and 5 git commands to generate.