2 * Command line oriented Moira containers tool.
4 * Garry Zacheiss <zacheiss@mit.edu>, January 2003
8 * Copyright (C) 2002 by the Massachusetts Institute of Technology.
9 * For copying and distribution information, please see the file
13 #include <mit-copyright.h>
15 #include <moira_site.h>
32 struct mqelem *q_forw;
33 struct mqelem *q_back;
39 struct string_list *next;
48 char *typename[] = { "ANY", "USER", "LIST", "KERBEROS", "NONE" };
50 /* argument parsing macro */
51 #define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
53 /* flags from command line */
54 int info_flag, update_flag, create_flag, delete_flag, list_subcon_flag;
55 int list_mach_flag, update_mach_flag, verbose, noauth, unformatted_flag;
58 struct string_list *container_add_queue, *container_remove_queue;
60 char *containername, *whoami;
62 char *newname, *desc, *location, *contact;
64 struct owner_type *owner, *memacl;
66 void usage(char **argv);
67 int store_container_info(int argc, char **argv, void *hint);
68 void show_container_info(char **argv);
69 int show_container_list(int argc, char **argv, void *hint);
70 void show_container_info_unformatted(char **argv);
71 int show_container_list_unformatted(int argc, char **argv, void *hint);
72 int show_machine_in_container(int argc, char **argv, void *hint);
73 int show_subcontainers_of_container(int argc, char **argv, void *hint);
74 struct owner_type *parse_member(char *s);
75 struct string_list *add_to_string_list(struct string_list *old_list, char *s);
76 int wrap_mr_query(char *handle, int argc, char **argv,
77 int (*callback)(int, char **, void *), void *callarg);
78 void print_query(char *query_name, int argc, char **argv);
80 int main(int argc, char **argv)
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;
91 container_add_queue = container_remove_queue = NULL;
92 newname = desc = location = contact = NULL;
93 owner = memacl = NULL;
99 while (++arg - argv < argc)
103 if (argis("i", "info"))
105 else if (argis("C", "create"))
107 else if (argis("D", "delete"))
109 else if (argis("R", "rename")) {
110 if (arg - argv < argc - 1) {
117 else if (argis("d", "desc")) {
118 if (arg - argv < argc - 1) {
125 else if (argis("L", "location")) {
126 if (arg - argv < argc - 1) {
133 else if (argis("c", "contact")) {
134 if (arg - argv < argc - 1) {
141 else if (argis("P", "public"))
146 else if (argis("NP", "private"))
151 else if (argis("O", "owner")) {
152 if (arg - argv < argc - 1) {
155 owner = parse_member(*arg);
159 else if (argis("MA", "memacl")) {
160 if (arg - argv < argc - 1) {
163 memacl = parse_member(*arg);
167 else if (argis("ls", "listsub"))
169 else if (argis("lm", "listmach"))
171 else if (argis("am", "addmach")) {
172 if (arg - argv < argc - 1) {
174 container_add_queue =
175 add_to_string_list(container_add_queue, *arg);
180 else if (argis("dm", "deletemach")) {
181 if (arg - argv < argc - 1) {
183 container_remove_queue =
184 add_to_string_list(container_remove_queue, *arg);
189 else if (argis("r", "recursive"))
191 else if (argis("u", "unformatted"))
193 else if (argis("n", "noauth"))
195 else if (argis("v", "verbose"))
197 else if (argis("db", "database"))
199 if (arg - argv < argc - 1)
210 else if (containername == NULL)
211 containername = *arg;
215 if (containername == NULL)
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)) {
225 status = mrcl_connect(server, "mitch", 9, !noauth);
226 if (status == MRCL_AUTH_ERROR)
228 com_err(whoami, 0, "Try the -noauth flag if you don't "
229 "need authentication.");
234 /* create if needed */
240 for (cnt = 0; cnt < 11; cnt ++) {
244 argv[CON_NAME] = containername;
245 argv[CON_PUBLIC] = (public == 1) ? "1" : "0";
246 argv[CON_DESCRIPT] = desc ? desc : "none";
248 argv[CON_LOCATION] = location;
250 argv[CON_CONTACT] = contact;
254 if (memacl->type == M_ANY)
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;
261 memacl->type = M_USER;
263 argv[CON_MEMACE_TYPE] = typename[memacl->type];
264 argv[CON_MEMACE_NAME] = memacl->name;
265 if (memacl->type == M_KERBEROS)
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)
276 argv[CON_MEMACE_TYPE] = argv[CON_MEMACE_NAME] = "NONE";
280 argv[CON_OWNER_NAME] = owner->name;
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)
291 argv[CON_OWNER_TYPE] = "LIST";
292 status = wrap_mr_query("add_container", 9, argv, NULL, NULL);
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)
303 status = wrap_mr_query("add_container", 9, argv, NULL, NULL);
306 argv[CON_OWNER_TYPE] = argv[CON_OWNER_NAME] = "NONE";
307 status = wrap_mr_query("add_containr", 9, argv, NULL, NULL);
313 argv[CON_OWNER_TYPE] = argv[CON_OWNER_NAME] = "NONE";
314 status = wrap_mr_query("add_container", 9, argv, NULL, NULL);
319 com_err(whoami, status, "while creating container.");
323 else if (update_flag)
329 args[0] = containername;
331 status = wrap_mr_query("get_container", 1, args, store_container_info,
335 com_err(whoami, status, "while getting container information.");
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];
349 argv[CON_NAME] = containername;
351 argv[CON_NAME + 1] = newname;
352 argv[CON_PUBLIC + 1] = (public == 1) ? "1" : "0";
354 argv[CON_DESCRIPT + 1] = desc;
356 argv[CON_LOCATION + 1] = location;
358 argv[CON_CONTACT + 1] = contact;
362 if (memacl->type == M_ANY)
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;
369 memacl->type = M_USER;
371 argv[CON_MEMACE_TYPE + 1] = typename[memacl->type];
372 argv[CON_MEMACE_NAME + 1] = memacl->name;
373 if (memacl->type == M_KERBEROS)
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)
386 argv[CON_OWNER_NAME + 1] = owner->name;
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)
397 argv[CON_OWNER_TYPE + 1] = "LIST";
398 status = wrap_mr_query("update_container", 10, argv, NULL, NULL);
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)
409 status = wrap_mr_query("update_container", 10, argv, NULL, NULL);
413 argv[CON_OWNER_TYPE + 1] = argv[CON_OWNER_NAME + 1] = "NONE";
414 status = wrap_mr_query("update_container", 10, argv, NULL, NULL);
419 status = wrap_mr_query("update_container", 10, argv, NULL, NULL);
423 com_err(whoami, status, "while updating container.");
427 containername = newname;
430 /* add machines to container */
431 if (container_add_queue) {
432 struct string_list *q = container_add_queue;
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);
442 com_err(whoami, status, "while adding machine to container.");
450 /* delete machines from container */
451 if (container_remove_queue) {
452 struct string_list *q = container_remove_queue;
457 args[0] = canonicalize_hostname(strdup(q->string));
458 args[1] = containername;
459 status = wrap_mr_query("delete_machine_from_container", 2, args, NULL,
463 com_err(whoami, status, "while removing machine from container.");
476 args[0] = containername;
477 status = wrap_mr_query("get_container", 1, args, store_container_info,
481 com_err(whoami, status, "while getting container information.");
485 if (unformatted_flag)
486 show_container_info_unformatted(argv);
488 show_container_info(argv);
495 args[0] = containername;
496 status = wrap_mr_query("delete_container", 1, args, NULL, NULL);
499 com_err(whoami, status, "while deleting container.");
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);
514 com_err(whoami, status, "while getting machines of container.");
519 if (list_subcon_flag)
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);
529 com_err(whoami, status, "while getting subcontainers of container.");
535 exit(success ? 0 : 1);
538 void usage(char **argv)
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",
553 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-O | -owner owner",
554 "-MA | -memacl membership_acl");
555 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-ls | -listsub",
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",
563 fprintf(stderr, " %-39s\n" , "-db | -database host[:port]");
567 /* Retrieve information about a container */
568 int store_container_info(int argc, char **argv, void *hint)
573 for(i = 0; i < argc; i++)
574 nargv[i] = strdup(argv[i]);
579 void show_container_info(char **argv)
583 struct mqelem *elem = NULL;
586 printf("Container: %-16s Public: %s\n", argv[CON_NAME],
588 args[0] = argv[CON_NAME];
589 status = wrap_mr_query("get_container_list", 1, args, show_container_list,
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],
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);
603 printf("Last mod by %s at %s with %s.\n", argv[CON_MODBY], argv[CON_MODTIME],
607 int show_container_list(int argc, char **argv, void *hint)
609 printf("Container's associated list is: LIST %s\n", argv[1]);
614 void show_container_info_unformatted(char **argv)
617 struct mqelem *elem = NULL;
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.");
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]);
641 int show_container_list_unformatted(int argc, char **argv, void *hint)
643 printf("Associated list: %s", argv[1]);
648 int show_machine_in_container(int argc, char **argv, void *hint)
650 printf("Machine: %-30s Container: %-25s\n", argv[0], argv[1]);
655 int show_subcontainers_of_container(int argc, char **argv, void *hint)
657 printf("Container: %-25s\n", argv[0]);
662 /* Parse a line of input, fetching a member. NULL is returned if a member
663 * is not found. ';' is a comment character.
666 struct owner_type *parse_member(char *s)
668 struct owner_type *m;
671 while (*s && isspace(*s))
674 while (*p && *p != '\n' && *p != ';')
676 if (isprint(*p) && !isspace(*p))
683 if (p == s || strlen(s) == 0)
686 if (!(m = malloc(sizeof(struct owner_type))))
689 if ((p = strchr(s, ':')))
693 if (!strcasecmp("user", s))
695 else if (!strcasecmp("list", s))
697 else if (!strcasecmp("kerberos", s))
698 m->type = M_KERBEROS;
699 else if (!strcasecmp("none", s))
707 m->name = strdup(m->name);
712 m->type = strcasecmp(s, "none") ? M_ANY : M_NONE;
717 struct string_list *add_to_string_list(struct string_list *old_list, char *s) {
718 struct string_list *new_list;
720 new_list = (struct string_list *)malloc(sizeof(struct string_list *));
721 new_list->next = old_list;
722 new_list->string = s;
727 int wrap_mr_query(char *handle, int argc, char **argv,
728 int (*callback)(int, char **, void *), void *callarg) {
730 print_query(handle, argc, argv);
732 return mr_query(handle, argc, argv, callback, callarg);
735 void print_query(char *query_name, int argc, char **argv) {
738 printf("qy %s", query_name);
739 for(cnt=0; cnt<argc; cnt++)
740 printf(" <%s>", argv[cnt]);