]> andersk Git - moira.git/blame - clients/stella/stella.c
from dongq: initial all elements of args[] to NULL
[moira.git] / clients / stella / stella.c
CommitLineData
80e8aa14 1/*
2 * Command line oriented Moira host tool.
3 *
4 * kolya@MIT.EDU, January 2000
5 *
6 * Somewhat based on blanche
7 *
8 * Copyright (C) 2000 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("$Header$");
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/* It is important to membercmp that M_USER < M_LIST < M_STRING */
43#define M_ANY 0
44#define M_USER 1
45#define M_LIST 2
46#define M_STRING 3
47#define M_KERBEROS 4
48#define M_NONE 5
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_map_flag;
55int update_map_flag, verbose, noauth;
56
57struct string_list *alias_add_queue, *alias_remove_queue;
58struct string_list *map_add_queue, *map_remove_queue;
59
60char *hostname, *whoami;
61
62char *newname, *address, *network, *h_status, *vendor, *model;
63char *os, *location, *contact, *adm_cmt, *op_cmt;
64
65struct owner_type *owner;
66
67void usage(char **argv);
68int store_host_info(int argc, char **argv, void *hint);
69void show_host_info(char **argv);
70int show_machine_in_cluster(int argc, char **argv, void *hint);
71struct owner_type *parse_member(char *s);
72struct string_list *add_to_string_list(struct string_list *old_list, char *s);
73int wrap_mr_query(char *handle, int argc, char **argv,
74 int (*callback)(int, char **, void *), void *callarg);
75void print_query(char *query_name, int argc, char **argv);
76
77int main(int argc, char **argv)
78{
79 int status, success;
80 char **arg = argv;
533bacb3 81 char *server = NULL;
80e8aa14 82
83 /* clear all flags & lists */
84 info_flag = update_flag = create_flag = list_map_flag = update_map_flag = 0;
85 verbose = noauth = 0;
86 newname = address = network = h_status = vendor = model = NULL;
87 os = location = contact = adm_cmt = op_cmt = NULL;
88 owner = NULL;
89 alias_add_queue = alias_remove_queue = NULL;
90 map_add_queue = map_remove_queue = NULL;
91 whoami = argv[0];
92
93 success = 1;
94
95 /* parse args, building addlist, dellist, & synclist */
96 while (++arg - argv < argc)
97 {
98 if (**arg == '-')
99 {
100 if (argis("i", "info"))
101 info_flag++;
102 else if (argis("C", "create"))
103 create_flag++;
104 else if (argis("D", "delete"))
105 delete_flag++;
106 else if (argis("R", "rename")) {
107 if (arg - argv < argc - 1) {
108 arg++;
109 update_flag++;
110 newname = *arg;
111 } else
112 usage(argv);
113 }
114 else if (argis("A", "address")) {
115 if (arg - argv < argc - 1) {
116 arg++;
117 update_flag++;
118 address = *arg;
119 } else
120 usage(argv);
121 }
122 else if (argis("O", "owner")) {
123 if (arg - argv < argc - 1) {
124 arg++;
125 update_flag++;
126 owner = parse_member(*arg);
127 } else
128 usage(argv);
129 }
130 else if (argis("N", "network")) {
131 if (arg - argv < argc - 1) {
132 arg++;
133 update_flag++;
134 network = *arg;
135 } else
136 usage(argv);
137 }
138 else if (argis("S", "status")) {
139 if (arg - argv < argc - 1) {
140 int i;
533bacb3 141 int len;
80e8aa14 142
143 arg++;
144 update_flag++;
145 h_status = *arg;
146
533bacb3 147 len = strlen(h_status);
148 for(i = 0; i < len; i++) {
80e8aa14 149 if(!isdigit(h_status[i])) {
150 printf("Error: status code %s is not numeric.\n", h_status);
151 exit(1);
152 }
153 }
154 } else
155 usage(argv);
156 }
157 else if (argis("V", "vendor")) {
158 if (arg - argv < argc - 1) {
159 arg++;
160 update_flag++;
161 vendor = *arg;
162 } else
163 usage(argv);
164 }
165 else if (argis("M", "model")) {
166 if (arg - argv < argc - 1) {
167 arg++;
168 update_flag++;
169 model = *arg;
170 } else
171 usage(argv);
172 }
173 else if (argis("o", "os")) {
174 if (arg - argv < argc - 1) {
175 arg++;
176 update_flag++;
177 os = *arg;
178 } else
179 usage(argv);
180 }
181 else if (argis("L", "location")) {
182 if (arg - argv < argc - 1) {
183 arg++;
184 update_flag++;
185 location = *arg;
186 } else
187 usage(argv);
188 }
189 else if (argis("c", "contact")) {
190 if (arg - argv < argc - 1) {
191 arg++;
192 update_flag++;
193 contact = *arg;
194 } else
195 usage(argv);
196 }
197 else if (argis("ac", "admcmt")) {
198 if (arg - argv < argc - 1) {
199 arg++;
200 update_flag++;
201 adm_cmt = *arg;
202 } else
203 usage(argv);
204 }
205 else if (argis("oc", "opcmt")) {
206 if (arg - argv < argc - 1) {
207 arg++;
208 update_flag++;
209 op_cmt = *arg;
210 } else
211 usage(argv);
212 }
213 else if (argis("a", "aliasadd")) {
214 if (arg - argv < argc - 1) {
215 arg++;
216 alias_add_queue=add_to_string_list(alias_add_queue, *arg);
217 } else
218 usage(argv);
219 }
220 else if (argis("d", "aliasdelete")) {
221 if (arg - argv < argc - 1) {
222 arg++;
223 alias_remove_queue=add_to_string_list(alias_remove_queue, *arg);
224 } else
225 usage(argv);
226 }
227 else if (argis("am", "addmap")) {
228 if (arg - argv < argc - 1) {
229 arg++;
230 map_add_queue=add_to_string_list(map_add_queue, *arg);
231 } else
232 usage(argv);
233 update_map_flag++;
234 }
235 else if (argis("dm", "deletemap")) {
236 if (arg - argv < argc - 1) {
237 arg++;
238 map_remove_queue=add_to_string_list(map_remove_queue, *arg);
239 } else
240 usage(argv);
241 update_map_flag++;
242 }
243 else if (argis("lm", "listmap"))
244 list_map_flag++;
245 else if (argis("n", "noauth"))
246 noauth++;
247 else if (argis("v", "verbose"))
248 verbose++;
249 else if (argis("db", "database"))
250 {
251 if (arg - argv < argc - 1)
252 {
253 ++arg;
254 server = *arg;
255 }
256 else
257 usage(argv);
258 }
259 else
260 usage(argv);
261 }
262 else if (hostname == NULL)
263 hostname = *arg;
264 else
265 usage(argv);
266 }
267 if (hostname == NULL)
268 usage(argv);
269
270 /* default to info_flag if nothing else was specified */
271 if(!(info_flag || update_flag || create_flag || \
272 delete_flag || list_map_flag || update_map_flag )) {
273 info_flag++;
274 }
275
276 /* fire up Moira */
277 status = mrcl_connect(server, "stella", 2, !noauth);
278 if (status == MRCL_AUTH_ERROR)
279 {
280 com_err(whoami, 0, "Try the -noauth flag if you don't "
281 "need authentication.");
282 }
283 if (status)
284 exit(2);
285
286 /* create if needed */
287 if (create_flag)
288 {
289 char *argv[30];
290 int cnt;
291
292 for (cnt = 0; cnt < 15; cnt++) {
293 argv[cnt] = "";
294 }
295
296 argv[0] = canonicalize_hostname(strdup(hostname));
297
298 if (vendor)
299 argv[1] = vendor;
300 if (model)
301 argv[2] = model;
302 if (os)
303 argv[3] = os;
304 if (location)
305 argv[4] = location;
306 if (contact)
307 argv[5] = contact;
308 /* The use field always gets set to "0" */
309 argv[6] = "0";
310 if (h_status)
311 argv[7] = h_status;
312 else
313 argv[7] = "1";
314 if (network)
315 argv[8] = network;
316 if (address)
317 argv[9] = address;
318 if (adm_cmt)
319 argv[12] = adm_cmt;
320 if (op_cmt)
321 argv[13] = op_cmt;
322
323 if (owner)
324 {
325 argv[11] = owner->name;
326 switch (owner->type)
327 {
328 case M_ANY:
329 case M_USER:
330 argv[10] = "USER";
331 status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
332 if (owner->type != M_ANY || status != MR_USER)
333 break;
334
335 case M_LIST:
336 argv[10] = "LIST";
337 status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
338 break;
339
340 case M_KERBEROS:
341 argv[10] = "KERBEROS";
342 status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
343 break;
344
345 case M_NONE:
346 argv[10] = "NONE";
347 status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
348 break;
349 }
350 }
351 else
352 {
353 argv[10] = "NONE";
354 argv[11] = "NONE";
355
356 status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
357 }
358
359 if (status)
360 {
361 com_err(whoami, status, "while creating host.");
362 exit(1);
363 }
364
365 }
366 else if (update_flag)
367 {
368 char *old_argv[30];
369 char *argv[16];
370 char *args[5];
80e8aa14 371
372 args[0] = canonicalize_hostname(strdup(hostname));
373 args[1] = args[2] = args[3] = "*";
374
375 status = wrap_mr_query("get_host", 4, args, store_host_info, old_argv);
376 if (status)
377 {
378 com_err(whoami, status, "while getting list information");
379 exit(1);
380 }
381
382 argv[1] = old_argv[0];
383 argv[2] = old_argv[1];
384 argv[3] = old_argv[2];
385 argv[4] = old_argv[3];
386 argv[5] = old_argv[4];
387 argv[6] = old_argv[5];
388 argv[7] = old_argv[6];
389 argv[8] = old_argv[7];
390 argv[9] = old_argv[9];
391 argv[10] = old_argv[10];
392 argv[11] = old_argv[11];
393 argv[12] = old_argv[12];
394 argv[13] = old_argv[13];
395 argv[14] = old_argv[14];
396
397 argv[0] = canonicalize_hostname(strdup(hostname));
398 if (newname)
399 argv[1] = newname;
400 if (vendor)
401 argv[2] = vendor;
402 if (model)
403 argv[3] = model;
404 if (os)
405 argv[4] = os;
406 if (location)
407 argv[5] = location;
408 if (contact)
409 argv[6] = contact;
410 if (h_status)
411 argv[8] = h_status;
412 if (network)
413 argv[9] = network;
414 if (address)
415 argv[10] = address;
416 if (adm_cmt)
417 argv[13] = adm_cmt;
418 if (op_cmt)
419 argv[14] = op_cmt;
420
421 if (owner)
422 {
423 argv[12] = owner->name;
424 switch (owner->type)
425 {
426 case M_ANY:
427 case M_USER:
428 argv[11] = "USER";
429 status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
430 if (owner->type != M_ANY || status != MR_USER)
431 break;
432
433 case M_LIST:
434 argv[11] = "LIST";
435 status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
436 break;
437
438 case M_KERBEROS:
439 argv[11] = "KERBEROS";
440 status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
441 break;
442
443 case M_NONE:
444 argv[11] = "NONE";
445 status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
446 break;
447 }
448 }
449 else
450 status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
451
452 if (status)
453 com_err(whoami, status, "while updating host.");
454 else if (newname)
455 hostname = newname;
456 }
457
458 /* create aliases if necessary */
459 if (alias_add_queue) {
460 struct string_list *q = alias_add_queue;
461
462 while(q) {
463 char *alias = q->string;
464 char *args[2];
465
466 args[0] = canonicalize_hostname(strdup(alias));
467 args[1] = canonicalize_hostname(strdup(hostname));
468 status = wrap_mr_query("add_hostalias", 2, args, NULL, NULL);
469 if (status) {
470 com_err(whoami, status, "while adding host alias");
471 exit(1);
472 }
473
474 q = q->next;
475 }
476 }
477
478 /* delete aliases if necessary */
479 if (alias_remove_queue) {
480 struct string_list *q = alias_remove_queue;
481
482 while(q) {
483 char *alias = q->string;
484 char *args[2];
485
486 args[0] = canonicalize_hostname(strdup(alias));
487 args[1] = canonicalize_hostname(strdup(hostname));
488 status = wrap_mr_query("delete_hostalias", 2, args, NULL, NULL);
489 if (status) {
490 com_err(whoami, status, "while deleting host alias");
491 exit(1);
492 }
493
494 q = q->next;
495 }
496 }
497
498 /* create cluster mappings */
499 if (map_add_queue) {
500 struct string_list *q = map_add_queue;
501
502 while(q) {
503 char *clustername = q->string;
504 char *args[2];
505
506 args[0] = canonicalize_hostname(strdup(hostname));
507 args[1] = clustername;
508 status = wrap_mr_query("add_machine_to_cluster", 2, args, NULL, NULL);
509 if (status) {
510 com_err(whoami, status, "while adding cluster mapping");
511 exit(1);
512 }
513
514 q = q->next;
515 }
516 }
517
518 /* delete cluster mappings */
519 if (map_remove_queue) {
520 struct string_list *q = map_remove_queue;
521
522 while(q) {
523 char *clustername = q->string;
524 char *args[2];
525
526 args[0] = canonicalize_hostname(strdup(hostname));
527 args[1] = clustername;
528 status = wrap_mr_query("delete_machine_from_cluster", 2, args,
529 NULL, NULL);
530 if (status) {
531 com_err(whoami, status, "while deleting cluster mapping");
532 exit(1);
533 }
534
535 q = q->next;
536 }
537 }
538
539 /* display list info if requested to */
540 if (info_flag) {
541 struct mqelem *elem = NULL;
542 char *args[5];
543 char *argv[30];
544
545 args[0] = canonicalize_hostname(strdup(hostname));
546 args[1] = args[2] = args[3] = "*";
547 status = wrap_mr_query("get_host", 4, args, store_host_info, argv);
548 if (status) {
549 com_err(whoami, status, "while getting host information");
550 exit(1);
551 }
552 show_host_info(argv);
553 }
554
555 /* list cluster mappings if needed */
556 if (list_map_flag) {
557 char *args[3];
558
559 args[0] = canonicalize_hostname(strdup(hostname));
560 args[1] = "*";
561 status = wrap_mr_query("get_machine_to_cluster_map", 2, args,
562 show_machine_in_cluster, NULL);
563 if (status)
564 if (status != MR_NO_MATCH) {
565 com_err(whoami, status, "while getting cluster mappings");
566 exit(1);
567 }
568 }
569
570 if (delete_flag) {
571 char *argv[1];
572
573 argv[0] = canonicalize_hostname(strdup(hostname));
574 status = wrap_mr_query("delete_host", 1, argv, NULL, NULL);
575 if (status) {
576 com_err(whoami, status, "while deleting host");
577 exit(1);
578 }
579 }
580
581 /* We're done! */
582 mr_disconnect();
583 exit(success ? 0 : 1);
584}
585
586void usage(char **argv)
587{
533bacb3 588#define USAGE_OPTIONS_FORMAT " %-39s%s\n"
80e8aa14 589 fprintf(stderr, "Usage: %s hostname [options]\n", argv[0]);
590 fprintf(stderr, "Options are\n");
533bacb3 591 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-C | -create",
80e8aa14 592 "-O | -owner owner");
533bacb3 593 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-D | -delete",
80e8aa14 594 "-S | -status status");
533bacb3 595 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-R | -rename newname",
80e8aa14 596 "-V | -vendor vendor");
533bacb3 597 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-a | -addalias alias",
80e8aa14 598 "-M | -model model");
533bacb3 599 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-d | -deletealias alias",
80e8aa14 600 "-L | -location location");
533bacb3 601 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-i | -info",
80e8aa14 602 "-o | -os os");
533bacb3 603 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-oc | -opcmt op_cmt",
80e8aa14 604 "-c | -contact contact");
533bacb3 605 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-ac | -admcmt adm_cmt",
80e8aa14 606 "-A | -address address");
533bacb3 607 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-am | -addmap cluster",
80e8aa14 608 "-N | -network network");
533bacb3 609 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-dm | -deletemap cluster",
80e8aa14 610 "-lm | -listmap");
533bacb3 611 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-db | -database host[:port]",
80e8aa14 612 "-n | -noauth");
533bacb3 613 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-v | -verbose",
80e8aa14 614 "");
615 exit(1);
616}
617
618/* Show alias information */
619
620static int show_has_aliases;
621
622int show_alias_info(int argc, char **argv, void *hint)
623{
624 if(!show_has_aliases++)
625 printf("Aliases: %s", argv[0]);
626 else
627 printf(", %s", argv[0]);
628
629 return MR_CONT;
630}
631
632static char *states[] = {
633 "Reserved (0)",
634 "Active (1)",
635 "None (2)",
636 "Deleted (3)"
637};
638
639static char *MacState(int state)
640{
641 static char buf[BUFSIZ];
642
643 if (state < 0 || state > 3)
644 {
645 sprintf(buf, "Unknown (%d)", state);
646 return buf;
647 }
648 return states[state];
649}
650
651/* Retrieve information about a host */
652
653int store_host_info(int argc, char **argv, void *hint)
654{
655 int i;
656 char **nargv = hint;
657
658 for(i=0; i<argc; i++)
659 nargv[i] = strdup(argv[i]);
660
661 return MR_CONT;
662}
663
664void show_host_info(char **argv)
665{
666 char tbuf[256];
667 char *args[3];
668 struct mqelem *elem = NULL;
669 int stat;
670
671 printf("Machine: %s\n", argv[M_NAME]);
672 args[0] = "*";
673 args[1] = argv[M_NAME];
674 show_has_aliases = 0;
675 stat = wrap_mr_query("get_hostalias", 2, args, show_alias_info, &elem);
676 printf("\n");
677 if (stat) {
678 if (stat != MR_NO_MATCH)
679 com_err(whoami, stat, "while getting aliases");
680 } else {
681 printf("\n");
682 }
683 sprintf(tbuf, "%s %s", argv[M_OWNER_TYPE],
684 strcmp(argv[M_OWNER_TYPE], "NONE") ? argv[M_OWNER_NAME] : "");
685 printf("Address: %-16s Network: %-16s\n",
686 argv[M_ADDR], argv[M_SUBNET]);
687 printf("Owner: %-16s Use data: %s\n", tbuf, argv[M_INUSE]);
688 printf("Status: %-16s Changed: %s\n",
689 MacState(atoi(argv[M_STAT])), argv[M_STAT_CHNG]);
690 printf("\n");
691
692 printf("Vendor: %-16s Model: %-20s OS: %s\n",
693 argv[M_VENDOR], argv[M_MODEL], argv[M_OS]);
694 printf("Location: %-16s Contact: %-20s Opt: %s\n",
695 argv[M_LOC], argv[M_CONTACT], argv[M_USE]);
696 printf("\nAdm cmt: %s\n", argv[M_ACOMMENT]);
697 printf("Op cmt: %s\n", argv[M_OCOMMENT]);
698 printf("\n");
699 printf("Created by %s on %s\n", argv[M_CREATOR], argv[M_CREATED]);
700 printf("Last mod by %s at %s with %s.\n", argv[M_MODBY], argv[M_MODTIME], argv[M_MODWITH]);
701}
702
703int show_machine_in_cluster(int argc, char **argv, void *hint)
704{
705 printf("Machine: %-30s Cluster: %-30s\n", argv[0], argv[1]);
706
707 return MR_CONT;
708}
709
710/* Parse a line of input, fetching a member. NULL is returned if a member
711 * is not found. ';' is a comment character.
712 */
713
714struct owner_type *parse_member(char *s)
715{
716 struct owner_type *m;
717 char *p, *lastchar;
718
719 while (*s && isspace(*s))
720 s++;
721 lastchar = p = s;
722 while (*p && *p != '\n' && *p != ';')
723 {
724 if (isprint(*p) && !isspace(*p))
725 lastchar = p++;
726 else
727 p++;
728 }
729 lastchar++;
730 *lastchar = '\0';
731 if (p == s || strlen(s) == 0)
732 return NULL;
733
734 if (!(m = malloc(sizeof(struct owner_type))))
735 return NULL;
736
737 if ((p = strchr(s, ':')))
738 {
739 *p = '\0';
740 m->name = ++p;
741 if (!strcasecmp("user", s))
742 m->type = M_USER;
743 else if (!strcasecmp("list", s))
744 m->type = M_LIST;
745 else if (!strcasecmp("string", s))
746 m->type = M_STRING;
747 else if (!strcasecmp("kerberos", s))
748 m->type = M_KERBEROS;
749 else if (!strcasecmp("none", s))
750 m->type = M_NONE;
751 else
752 {
753 m->type = M_ANY;
754 *(--p) = ':';
755 m->name = s;
756 }
757 m->name = strdup(m->name);
758 }
759 else
760 {
761 m->name = strdup(s);
762 m->type = strcasecmp(s, "none") ? M_ANY : M_NONE;
763 }
764 return m;
765}
766
767struct string_list *add_to_string_list(struct string_list *old_list, char *s) {
768 struct string_list *new_list;
769
770 new_list = (struct string_list *)malloc(sizeof(struct string_list *));
771 new_list->next = old_list;
772 new_list->string = s;
773
774 return new_list;
775}
776
777int wrap_mr_query(char *handle, int argc, char **argv,
778 int (*callback)(int, char **, void *), void *callarg) {
779 if (verbose)
780 print_query(handle, argc, argv);
781
782 return mr_query(handle, argc, argv, callback, callarg);
783}
784
785void print_query(char *query_name, int argc, char **argv) {
786 int cnt;
787
788 printf("qy %s", query_name);
789 for(cnt=0; cnt<argc; cnt++)
790 printf(" <%s>", argv[cnt]);
791 printf("\n");
792}
This page took 0.799923 seconds and 5 git commands to generate.