]> andersk Git - moira.git/blame - clients/moira/cluster.c
Fix typo.
[moira.git] / clients / moira / cluster.c
CommitLineData
c441a31a 1/* $Id$
7ac48069 2 *
3 * This is the file cluster.c for the Moira Client, which allows users
59ec8dae 4 * to quickly and easily maintain most parts of the Moira database.
5eaef520 5 * It Contains:
6 *
08345b74 7 * Created: 4/22/88
8 * By: Chris D. Peterson
08345b74 9 *
7ac48069 10 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
11 * For copying and distribution information, please see the file
12 * <mit-copyright.h>.
08345b74 13 */
14
15/* BTW: for anyone who cares MCD is short for Machine, Cluster, Data. */
16
7ac48069 17#include <mit-copyright.h>
8defc06b 18#include <moira.h>
19#include <moira_site.h>
a721bbae 20#include <mrclient.h>
7ac48069 21
22#include "defs.h"
23#include "f_defs.h"
24#include "globals.h"
25
600b459e 26#include <sys/types.h>
533bacb3 27
28#ifdef HAVE_UNAME
7ac48069 29#include <sys/utsname.h>
533bacb3 30#endif
7ac48069 31
533bacb3 32#ifndef _WIN32
ad7e0e04 33#include <netinet/in.h>
34#include <arpa/inet.h>
5cfca28f 35#include <netdb.h>
533bacb3 36#endif /* _WIN32 */
7ac48069 37
5098c1de 38#include <ctype.h>
7ac48069 39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
08345b74 42
7ac48069 43void PrintAliases(char **info);
bc8eefd1 44static void PrintMachine(char **info);
600b459e 45struct mqelem *GetMCInfo(int type, char *name1, char *name2);
7399b4b2 46struct mqelem *GetMachineByOwner(char *type, char *name);
7ac48069 47char **AskMCDInfo(char **info, int type, Bool name);
48int CheckAndRemoveFromCluster(char *name, Bool ask_user);
6d35002c 49int CheckAndRemoveCnames(char *name, Bool ask_user);
7ac48069 50int CheckAndRemoveMachines(char *name, Bool ask_first);
08345b74 51
9cd2d193 52static char *PrintContainerInfo(char **info);
53static void RealUpdateContainer(char **info, Bool junk);
54static void RealDeleteContainer(char **info, Bool one_container);
55static void RealRemoveMachineFromContainer(char **info, Bool one_contmap);
56
57#define MACHINE 0
58#define CLUSTER 1
59#define DATA 2
60#define MAP 3
61#define SUBNET 4
62#define CNAME 5
63#define CONTAINER 6
64#define CONTMAP 7
08345b74 65
85ca828a 66#define M_DEFAULT_TYPE DEFAULT_NONE
67
68#define C_DEFAULT_DESCRIPT DEFAULT_NONE
69#define C_DEFAULT_LOCATION DEFAULT_NONE
70
9cd2d193 71#define CON_DEFAULT_TYPE DEFAULT_NONE
72
85ca828a 73#define CD_DEFAULT_LABEL DEFAULT_NONE
74#define CD_DEFAULT_DATA DEFAULT_NONE
75
54864ee6 76#define S_DEFAULT_LOW "18.0.0.20"
77#define S_DEFAULT_HIGH "18.0.2.249"
ad7e0e04 78
5eaef520 79static char *states[] = {
80 "Reserved (0)",
81 "Active (1)",
82 "None (2)",
83 "Deleted (3)"
84};
85
4f6b1a05 86static char *subnet_states[] = {
87 "Reserved (0)",
88 "Billable (1)",
3faf730e 89 "Private, 10 Mbps (2)",
90 "Private, 100 Mbps (3)",
91 "Private, Other (4)",
92 "Resnet (5)",
93 "Infrastructure (6)"
4f6b1a05 94};
95
5eaef520 96static char *MacState(int state)
ad7e0e04 97{
5eaef520 98 static char buf[BUFSIZ];
ad7e0e04 99
5eaef520 100 if (state < 0 || state > 3)
101 {
102 sprintf(buf, "Unknown (%d)", state);
103 return buf;
ad7e0e04 104 }
5eaef520 105 return states[state];
ad7e0e04 106}
107
4f6b1a05 108static char *SubnetState(int state)
109{
110 static char buf[BUFSIZ];
ad7e0e04 111
3faf730e 112 if (state < 0 || state > 6)
4f6b1a05 113 {
114 sprintf(buf, "Unknown (%d)", state);
115 return buf;
116 }
117 return subnet_states[state];
118}
ad7e0e04 119
85ca828a 120/* -------------------- Set Defaults -------------------- */
121
122/* Function Name: SetMachineDefaults
123 * Description: sets machine defaults.
124 * Arguments: info - an array to put the defaults into.
125 * name - Canonacalized name of the machine.
126 * Returns: info - the array.
127 */
128
5eaef520 129static char **SetMachineDefaults(char **info, char *name)
85ca828a 130{
7ac48069 131 info[M_NAME] = strdup(name);
132 info[M_VENDOR] = strdup(M_DEFAULT_TYPE);
133 info[M_MODEL] = strdup(M_DEFAULT_TYPE);
134 info[M_OS] = strdup(M_DEFAULT_TYPE);
135 info[M_LOC] = strdup(M_DEFAULT_TYPE);
136 info[M_CONTACT] = strdup(M_DEFAULT_TYPE);
2f2d9dfc 137 info[M_BILL_CONTACT] = strdup(M_DEFAULT_TYPE);
4f6b1a05 138 info[M_ACCT_NUMBER] = strdup("");
7ac48069 139 info[M_USE] = strdup("0");
140 info[M_STAT] = strdup("1");
141 info[M_SUBNET] = strdup("NONE");
142 info[M_ADDR] = strdup("unique");
143 info[M_OWNER_TYPE] = strdup("NONE");
144 info[M_OWNER_NAME] = strdup("NONE");
145 info[M_ACOMMENT] = strdup("");
146 info[M_OCOMMENT] = strdup("");
4f6b1a05 147 info[17] = info[18] = NULL;
5eaef520 148 return info;
85ca828a 149}
150
151/* Function Name: SetClusterDefaults
152 * Description: sets Cluster defaults.
153 * Arguments: info - an array to put the defaults into.
154 * name - name of the Cluster.
155 * Returns: info - the array.
156 */
157
5eaef520 158static char **SetClusterDefaults(char **info, char *name)
85ca828a 159{
7ac48069 160 info[C_NAME] = strdup(name);
161 info[C_DESCRIPT] = strdup(C_DEFAULT_DESCRIPT);
162 info[C_LOCATION] = strdup(C_DEFAULT_LOCATION);
5eaef520 163 info[C_MODBY] = info[C_MODTIME] = info[C_MODWITH] = info[C_END] = NULL;
164 return info;
85ca828a 165}
166
9cd2d193 167static char **SetContainerDefaults(char **info, char *name)
168{
169 info[CON_NAME] = strdup(name);
170 info[CON_DESCRIPT] = strdup(CON_DEFAULT_TYPE);
171 info[CON_LOCATION] = strdup(CON_DEFAULT_TYPE);
172 info[CON_CONTACT] = strdup(CON_DEFAULT_TYPE);
173 info[CON_OWNER_TYPE] = strdup("NONE");
174 info[CON_OWNER_NAME] = strdup("NONE");
175 info[CON_MEMACE_TYPE] = strdup("NONE");
176 info[CON_MEMACE_NAME] = strdup("NONE");
177 info[CON_MODBY] = info[CON_MODTIME] = info[CON_MODWITH] = NULL;
178 info[CON_END] = NULL;
179 return info;
180}
181
ad7e0e04 182/* Function Name: SetSubnetDefaults
183 * Description: sets Subnet defaults.
184 * Arguments: info - an array to put the defaults into.
185 * name - name of the Subnet.
186 * Returns: info - the array.
187 */
188
5eaef520 189static char **SetSubnetDefaults(char **info, char *name)
ad7e0e04 190{
5eaef520 191 char buf[256];
192
4f6b1a05 193 info[SN_NAME] = strdup(name);
7ac48069 194 info[SN_DESC] = strdup("");
4f6b1a05 195 info[SN_STATUS] = strdup("1");
196 info[SN_CONTACT] = strdup(DEFAULT_NONE);
197 info[SN_ACCT_NUMBER] = strdup("");
5eaef520 198 sprintf(buf, "%ld", ntohl(inet_addr("18.255.0.0")));
7ac48069 199 info[SN_ADDRESS] = strdup(buf);
5eaef520 200 sprintf(buf, "%ld", ntohl(inet_addr("255.255.0.0")));
7ac48069 201 info[SN_MASK] = strdup(buf);
5eaef520 202 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_LOW)));
7ac48069 203 info[SN_LOW] = strdup(buf);
5eaef520 204 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_HIGH)));
7ac48069 205 info[SN_HIGH] = strdup(buf);
206 info[SN_PREFIX] = strdup("");
207 info[SN_ACE_TYPE] = strdup("LIST");
208 info[SN_ACE_NAME] = strdup("network");
5eaef520 209 info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL;
210 return info;
ad7e0e04 211}
212
85ca828a 213/* -------------------- General Functions -------------------- */
214
5cfca28f 215static char aliasbuf[256];
216
7ac48069 217void PrintAliases(char **info)
5cfca28f 218{
5eaef520 219 if (strlen(aliasbuf) == 0)
220 sprintf(aliasbuf, "Aliases: %s", info[0]);
221 else
222 {
223 strcat(aliasbuf, ", ");
224 strcat(aliasbuf, info[0]);
5cfca28f 225 }
226}
227
228
08345b74 229/* Function Name: PrintMachInfo
5eaef520 230 * Description: This function Prints out the Machine info in
08345b74 231 * a coherent form.
232 * Arguments: info - array of information about a machine.
402461ad 233 * Returns: The name of the Machine
08345b74 234 */
235
5eaef520 236static char *PrintMachInfo(char **info)
08345b74 237{
5eaef520 238 char buf[BUFSIZ], tbuf[256];
239 char *args[3];
cb3515b1 240 struct mqelem *elem = NULL, *elem2 = NULL;
5eaef520 241 int stat;
242
243 Put_message("");
244 sprintf(buf, "Machine: %s", info[M_NAME]);
245 Put_message(buf);
246 args[0] = "*";
247 args[1] = info[M_NAME];
7ac48069 248 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
5eaef520 249 {
250 if (stat != MR_NO_MATCH)
251 com_err(program_name, stat, " looking up aliases");
252 }
253 else
254 {
255 aliasbuf[0] = 0;
a6da9354 256 Loop(QueueTop(elem), (void (*)(char **)) PrintAliases);
5eaef520 257 FreeQueue(elem);
258 Put_message(aliasbuf);
5cfca28f 259 }
5eaef520 260 sprintf(tbuf, "%s %s", info[M_OWNER_TYPE],
261 strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : "");
262 sprintf(buf, "Address: %-16s Network: %-16s",
263 info[M_ADDR], info[M_SUBNET]);
264 Put_message(buf);
265 sprintf(buf, "Owner: %-16s Use data: %s", tbuf, info[M_INUSE]);
266 Put_message(buf);
267 sprintf(buf, "Status: %-16s Changed: %s",
268 MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]);
269 Put_message(buf);
270 Put_message("");
2f2d9dfc 271 sprintf(buf, "Vendor: %-16s Location: %s", info[M_VENDOR],
272 info[M_LOC]);
5eaef520 273 Put_message(buf);
2f2d9dfc 274 sprintf(buf, "Model: %-16s Contact: %s", info[M_MODEL],
275 info[M_CONTACT]);
276 Put_message(buf);
277 sprintf(buf, "OS: %-16s Billing Contact: %s", info[M_OS],
278 info[M_BILL_CONTACT]);
279 Put_message(buf);
4f6b1a05 280 sprintf(buf, "Opt: %-16s Account Number: %s", info[M_USE],
281 info[M_ACCT_NUMBER]);
5eaef520 282 Put_message(buf);
8595ce23 283 Put_message("");
284 sprintf(buf, "Adm cmt: %s", info[M_ACOMMENT]);
5eaef520 285 Put_message(buf);
286 sprintf(buf, "Op cmt: %s", info[M_OCOMMENT]);
287 Put_message(buf);
288 Put_message("");
289 sprintf(buf, "Created by %s on %s", info[M_CREATOR], info[M_CREATED]);
290 Put_message(buf);
291 sprintf(buf, MOD_FORMAT, info[M_MODBY], info[M_MODTIME], info[M_MODWITH]);
292 Put_message(buf);
4f6b1a05 293 /* Do a get_subnet for the machine's subnet. We need to know if it's
294 * Private.
295 */
296 args[0] = info[M_SUBNET];
cb3515b1 297 stat = do_mr_query("get_subnet", 1, args, StoreInfo, &elem2);
4f6b1a05 298 if (stat)
299 com_err(program_name, stat, " looking up subnet info");
79f30489 300 else if (atoi(((char **)elem2->q_data)[2]) == SNET_STATUS_PRIVATE_10MBPS ||
301 atoi(((char **)elem2->q_data)[2]) == SNET_STATUS_PRIVATE_100MBPS)
4f6b1a05 302 {
303 Put_message("");
304 sprintf(buf, "Warning: This host is on a private subnet.");
305 Put_message(buf);
9632ee31 306 sprintf(buf, "Billing information shown is superseded by billing information for the subnet.");
4f6b1a05 307 Put_message(buf);
cb3515b1 308 FreeQueue(elem2);
4f6b1a05 309 }
310
5eaef520 311 return info[M_NAME];
08345b74 312}
313
7399b4b2 314/* Function Name: PrintMachine
315 * Description: Prints the name of a machine record
316 * Arguments: info - array of information about the machine.
317 * Returns: nothing.
318 */
319
320static void PrintMachine(char **info)
321{
322 char buf[BUFSIZ];
323
324 sprintf(buf, "Machine: %s", info[M_NAME]);
325 Put_message(buf);
326}
327
ad7e0e04 328/* Function Name: PrintCname
329 * Description: Prints the Data on a host alias
330 * Arguments: info a pointer to the data array.
331 * Returns: The name of the alias.
332 */
333
5eaef520 334static char *PrintCname(char **info)
ad7e0e04 335{
5eaef520 336 char buf[BUFSIZ];
ad7e0e04 337
5eaef520 338 sprintf(buf, "Alias: %-32s Canonical Name: %s", info[0], info[1]);
339 Put_message(buf);
340 return info[0];
ad7e0e04 341}
342
08345b74 343/* Function Name: PrintClusterInfo
5eaef520 344 * Description: This function Prints out the cluster info
08345b74 345 * in a coherent form.
346 * Arguments: info - array of information about a cluster.
402461ad 347 * Returns: The name of the cluster.
08345b74 348 */
349
5eaef520 350static char *PrintClusterInfo(char **info)
08345b74 351{
5eaef520 352 char buf[BUFSIZ];
353
354 Put_message("");
355 sprintf(buf, "Cluster: %s", info[C_NAME]);
356 Put_message(buf);
357 sprintf(buf, "Description: %s", info[C_DESCRIPT]);
358 Put_message(buf);
359 sprintf(buf, "Location: %s", info[C_LOCATION]);
360 Put_message(buf);
361 sprintf(buf, MOD_FORMAT, info[C_MODBY], info[C_MODTIME], info[C_MODWITH]);
362 Put_message(buf);
363 return info[C_NAME];
08345b74 364}
365
366/* Function Name: PrintClusterData
367 * Description: Prints the Data on a cluster
368 * Arguments: info a pointer to the data array.
402461ad 369 * Returns: The name of the cluster.
08345b74 370 */
371
5eaef520 372static char *PrintClusterData(char **info)
08345b74 373{
5eaef520 374 char buf[BUFSIZ];
85ca828a 375
5eaef520 376 Put_message("");
377 sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s",
378 info[CD_NAME], info[CD_LABEL], info[CD_DATA]);
379 Put_message(buf);
380 return info[CD_NAME];
08345b74 381}
382
461c03b6 383/* Function Name: PrintMCMap
384 * Description: Prints the data about a machine to cluster mapping.
385 * Arguments: info a pointer to the data array.
386 * Returns: none
387 */
388
5eaef520 389static char *PrintMCMap(char **info)
461c03b6 390{
5eaef520 391 char buf[BUFSIZ];
392 sprintf(buf, "Cluster: %-30s Machine: %-20s",
393 info[MAP_CLUSTER], info[MAP_MACHINE]);
394 Put_message(buf);
395 return ""; /* Used by QueryLoop(). */
461c03b6 396}
397
ad7e0e04 398/* Function Name: PrintSubnetInfo
5eaef520 399 * Description: This function Prints out the subnet info
ad7e0e04 400 * in a coherent form.
401 * Arguments: info - array of information about a subnet.
402 * Returns: The name of the subnet.
403 */
404
5eaef520 405static char *PrintSubnetInfo(char **info)
ad7e0e04 406{
5eaef520 407 char buf[BUFSIZ];
408 struct in_addr addr, mask, low, high;
409
410 Put_message("");
411 sprintf(buf, " Network: %s", info[SN_NAME]);
412 Put_message(buf);
413 sprintf(buf, " Description: %s", info[SN_DESC]);
414 Put_message(buf);
4f6b1a05 415 sprintf(buf, " Status: %s", SubnetState(atoi(info[SN_STATUS])));
416 Put_message(buf);
417 sprintf(buf, " Contact: %s", info[SN_CONTACT]);
418 Put_message(buf);
419 sprintf(buf, " Account Number: %s", info[SN_ACCT_NUMBER]);
420 Put_message(buf);
5eaef520 421 addr.s_addr = htonl(atoi(info[SN_ADDRESS]));
422 mask.s_addr = htonl(atoi(info[SN_MASK]));
423 low.s_addr = htonl(atoi(info[SN_LOW]));
424 high.s_addr = htonl(atoi(info[SN_HIGH]));
425 /* screwy sequence is here because inet_ntoa returns a pointer to
426 a static buf. If it were all one sprintf, the last value would
427 appear 4 times. */
428 sprintf(buf, " Address: %s Mask: ", inet_ntoa(addr));
429 strcat(buf, inet_ntoa(mask));
430 strcat(buf, "\n High: ");
431 strcat(buf, inet_ntoa(high));
432 strcat(buf, " Low: ");
433 strcat(buf, inet_ntoa(low));
434 Put_message(buf);
435 sprintf(buf, "Hostname prefix: %s", info[SN_PREFIX]);
436 Put_message(buf);
437 sprintf(buf, " Owner: %s %s\n", info[SN_ACE_TYPE],
438 strcmp(info[SN_ACE_TYPE], "NONE") ? info[SN_ACE_NAME] : "");
439 Put_message(buf);
440 sprintf(buf, MOD_FORMAT, info[SN_MODBY], info[SN_MODTIME], info[SN_MODWITH]);
441 Put_message(buf);
442 return info[SN_NAME];
ad7e0e04 443}
444
08345b74 445/* Function Name: GetMCInfo.
446 * Description: This function stores info about a machine.
447 * type - type of data we are trying to retrieve.
448 * name1 - the name of argv[0] for the call.
449 * name2 - the name of argv[1] for the call.
450 * Returns: the top element of a queue containing the data or NULL.
451 */
452
600b459e 453struct mqelem *GetMCInfo(int type, char *name1, char *name2)
08345b74 454{
5eaef520 455 int stat;
600b459e 456 struct mqelem *elem = NULL;
5eaef520 457 char *args[5];
08345b74 458
5eaef520 459 switch (type)
460 {
461c03b6 461 case MACHINE:
5eaef520 462 args[0] = name1;
463 args[1] = args[2] = args[3] = "*";
7ac48069 464 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
5eaef520 465 {
466 if (stat == MR_NO_MATCH)
467 {
468 char buf[128];
469 sprintf(buf, "Machine '%s' is not in the database.", name1);
470 Put_message(buf);
471 }
472 else
473 com_err(program_name, stat, " in get_machine.");
474 return NULL;
08345b74 475 }
5eaef520 476 break;
ad7e0e04 477 case CNAME:
5eaef520 478 args[0] = name1;
479 args[1] = name2;
7ac48069 480 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
5eaef520 481 {
482 com_err(program_name, stat, " in get_hostalias.");
483 return NULL;
ad7e0e04 484 }
5eaef520 485 break;
ad7e0e04 486 case SUBNET:
7ac48069 487 if ((stat = do_mr_query("get_subnet", 1, &name1, StoreInfo, &elem)))
5eaef520 488 {
489 if (stat == MR_NO_MATCH)
490 {
491 char buf[128];
492 sprintf(buf, "Network '%s' is not in the database.", name1);
493 Put_message(buf);
494 }
495 else
496 com_err(program_name, stat, " in get_subnet.");
497 return NULL;
ad7e0e04 498 }
5eaef520 499 break;
461c03b6 500 case CLUSTER:
7ac48069 501 if ((stat = do_mr_query("get_cluster", 1, &name1, StoreInfo, &elem)))
5eaef520 502 {
503 com_err(program_name, stat, " in get_cluster.");
504 return NULL;
08345b74 505 }
5eaef520 506 break;
461c03b6 507 case MAP:
5eaef520 508 args[MAP_MACHINE] = name1;
509 args[MAP_CLUSTER] = name2;
510 if ((stat = do_mr_query("get_machine_to_cluster_map", 2, args,
7ac48069 511 StoreInfo, &elem)))
5eaef520 512 {
513 com_err(program_name, stat, " in get_machine_to_cluster_map.");
514 return NULL;
08345b74 515 }
5eaef520 516 break;
461c03b6 517 case DATA:
5eaef520 518 args[CD_NAME] = name1;
519 args[CD_LABEL] = name2;
7ac48069 520 if ((stat = do_mr_query("get_cluster_data", 2, args, StoreInfo, &elem)))
5eaef520 521 {
522 com_err(program_name, stat, " in get_cluster_data.");
523 return NULL;
08345b74 524 }
9cd2d193 525 break;
526 case CONTAINER:
527 args[CON_NAME] = name1;
528 if ((stat = do_mr_query("get_container", 1, &name1, StoreInfo, &elem)))
529 {
530 com_err(program_name, stat, " in get_container.");
531 return NULL;
532 }
533 break;
534 case CONTMAP:
535 args[0] = name1;
536 if ((stat = do_mr_query("get_machine_to_container_map", 1, &name1,
537 StoreInfo, &elem)))
538 {
539 com_err(program_name, stat, " in get_machine_to_container_map.");
540 return NULL;
541 }
08345b74 542 }
5eaef520 543 return QueueTop(elem);
08345b74 544}
545
461c03b6 546/* Function Name: AskMCDInfo.
5eaef520 547 * Description: This function askes the user for information about a
08345b74 548 * machine and saves it into a structure.
549 * Arguments: info - a pointer the information to ask about
461c03b6 550 * type - type of information - MACHINE
551 * CLUSTER
552 * DATA
9cd2d193 553 * CONTAINER
08345b74 554 * name - T/F : change the name of this type.
555 * Returns: none.
556 */
557
5eaef520 558char **AskMCDInfo(char **info, int type, Bool name)
08345b74 559{
5eaef520 560 char temp_buf[BUFSIZ], *newname, *oldnewname;
08345b74 561
5eaef520 562 switch (type)
563 {
461c03b6 564 case MACHINE:
5eaef520 565 sprintf(temp_buf, "\nSetting the information for the Machine %s...",
566 info[M_NAME]);
567 break;
ad7e0e04 568 case SUBNET:
5eaef520 569 sprintf(temp_buf, "Setting the information for the Network %s...",
570 info[SN_NAME]);
571 break;
461c03b6 572 case CLUSTER:
5eaef520 573 sprintf(temp_buf, "Setting the information for the Cluster %s...",
574 info[C_NAME]);
575 break;
461c03b6 576 case DATA:
5eaef520 577 sprintf(temp_buf, "Setting the Data for the Cluster %s...",
578 info[CD_NAME]);
579 break;
9cd2d193 580 case CONTAINER:
581 sprintf(temp_buf, "Setting the Data for the Container %s...",
582 info[CON_NAME]);
583 break;
08345b74 584 }
5eaef520 585 Put_message(temp_buf);
08345b74 586
5eaef520 587 if (name)
588 {
589 switch (type)
590 {
461c03b6 591 case MACHINE:
7ac48069 592 newname = strdup(info[M_NAME]);
5eaef520 593 if (GetValueFromUser("The new name for this machine? ", &newname) ==
594 SUB_ERROR)
595 return NULL;
7ac48069 596 oldnewname = strdup(newname);
5eaef520 597 newname = canonicalize_hostname(newname);
598 if (strcasecmp(newname, oldnewname) && *oldnewname != '"')
599 {
600 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n",
601 oldnewname, newname);
602 Put_message(temp_buf);
576ba5e7 603 }
5eaef520 604 free(oldnewname);
605 break;
ad7e0e04 606 case SUBNET:
7ac48069 607 newname = strdup(info[SN_NAME]);
5eaef520 608 if (GetValueFromUser("The new name for this network? ", &newname) ==
609 SUB_ERROR)
610 return NULL;
611 break;
461c03b6 612 case CLUSTER:
7ac48069 613 newname = strdup(info[C_NAME]);
5eaef520 614 if (GetValueFromUser("The new name for this cluster? ", &newname) ==
615 SUB_ERROR)
616 return NULL;
617 break;
9cd2d193 618 case CONTAINER:
619 newname = strdup(info[CON_NAME]);
620 if (GetValueFromUser("The new name for this container? ", &newname)
621 == SUB_ERROR)
622 return NULL;
623 break;
08345b74 624 default:
5eaef520 625 Put_message("Unknown type in AskMCDInfo, programmer botch");
626 return NULL;
08345b74 627 }
628 }
629
5eaef520 630 switch (type)
631 {
461c03b6 632 case MACHINE:
5eaef520 633 if (GetValueFromUser("Machine's vendor", &info[M_VENDOR]) == SUB_ERROR)
634 return NULL;
635 if (GetValueFromUser("Machine's model", &info[M_MODEL]) == SUB_ERROR)
636 return NULL;
637 if (GetValueFromUser("Machine's operating system", &info[M_OS]) ==
638 SUB_ERROR)
639 return NULL;
640 if (GetValueFromUser("Machine's location", &info[M_LOC]) == SUB_ERROR)
641 return NULL;
642 if (GetValueFromUser("Machine's contact", &info[M_CONTACT]) ==
643 SUB_ERROR)
644 return NULL;
2f2d9dfc 645 if (GetValueFromUser("Machine's billing contact",
646 &info[M_BILL_CONTACT]) == SUB_ERROR)
647 return NULL;
4f6b1a05 648 if (GetValueFromUser("Machine's billing account number",
649 &info[M_ACCT_NUMBER]) == SUB_ERROR)
650 return NULL;
5eaef520 651 while (1)
652 {
653 int i;
654 if (GetValueFromUser("Machine's status (? for help)",
ad7e0e04 655 &info[M_STAT]) == SUB_ERROR)
5eaef520 656 return NULL;
657 if (isdigit(info[M_STAT][0]))
658 break;
659 Put_message("Valid status numbers:");
660 for (i = 0; i < 4; i++)
661 Put_message(states[i]);
662 }
663
664 /* there appears to be some argument mismatch between the client
665 * and the server.. so here is this argument shuffler.
666 * I have since modified this to always shuffle the arguments..
667 * not just do so when performing a modify all fields request.
668 * The SetMachinedefaults() has been changed to reflect this.
669 * pray for us and may we attain enlightenment through structures.
670 */
671
672 if (name)
673 {
674 /* info did not come from SetMachineDefaults(), which does not
4f6b1a05 675 * initialize entry 10 (M_STAT_CHNG), therefore we can
5eaef520 676 * free it.
677 */
678 /* This is an update of an existing machine and the structure
679 * was filled in thru a query to the db which does fill in this
680 * field.
681 */
4f6b1a05 682 free(info[10]);
ad7e0e04 683 }
5eaef520 684
4f6b1a05 685 info[10] = info[M_SUBNET];
686 info[11] = info[M_ADDR];
687 info[12] = info[M_OWNER_TYPE];
688 info[13] = info[M_OWNER_NAME];
689 info[14] = info[M_ACOMMENT];
690 info[15] = info[M_OCOMMENT];
5eaef520 691
692 if (name)
693 {
4f6b1a05 694 if (GetValueFromUser("Machine's network (or 'none')", &info[10])
5eaef520 695 == SUB_ERROR)
696 return NULL;
4bae4be1 697 }
5eaef520 698 if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
4f6b1a05 699 &info[11]) == SUB_ERROR)
5eaef520 700 return NULL;
4f6b1a05 701 if (GetTypeFromUser("Machine's owner type", "ace_type", &info[12]) ==
5eaef520 702 SUB_ERROR)
703 return NULL;
4f6b1a05 704 if (strcmp(info[12], "NONE") &&
705 GetValueFromUser("Owner's Name", &info[13]) == SUB_ERROR)
5eaef520 706 return NULL;
4f6b1a05 707 if (!strcmp(info[12], "KERBEROS"))
5cef9ecf 708 {
709 char *canon;
710
4f6b1a05 711 mrcl_validate_kerberos_member(info[13], &canon);
5cef9ecf 712 if (mrcl_get_message())
713 Put_message(mrcl_get_message());
4f6b1a05 714 free(info[13]);
715 info[13] = canon;
5cef9ecf 716 }
4f6b1a05 717 if (GetValueFromUser("Administrative comment", &info[14]) == SUB_ERROR)
5eaef520 718 return NULL;
4f6b1a05 719 if (GetValueFromUser("Operational comment", &info[15]) == SUB_ERROR)
5eaef520 720 return NULL;
4f6b1a05 721 info[16] = NULL;
2f2d9dfc 722 FreeAndClear(&info[17], TRUE);
4f6b1a05 723 FreeAndClear(&info[18], TRUE);
5eaef520 724 break;
ad7e0e04 725 case SUBNET:
5eaef520 726 if (GetValueFromUser("Network description", &info[SN_DESC]) == SUB_ERROR)
727 return NULL;
4f6b1a05 728 while (1)
729 {
730 int i;
731 if (GetValueFromUser("Network's status (? for help)",
732 &info[SN_STATUS]) == SUB_ERROR)
733 return NULL;
734 if (isdigit(info[SN_STATUS][0]))
735 break;
736 Put_message("Valid status numbers:");
3faf730e 737 for (i = 0; i < 7; i++)
4f6b1a05 738 Put_message(subnet_states[i]);
739 }
740 if (GetValueFromUser("Network's contact", &info[SN_CONTACT]) == SUB_ERROR)
741 return NULL;
742 if (GetValueFromUser("Network's billing account number",
743 &info[SN_ACCT_NUMBER]) == SUB_ERROR)
744 return NULL;
5eaef520 745 if (GetAddressFromUser("Network address", &info[SN_ADDRESS]) == SUB_ERROR)
746 return NULL;
747 if (GetAddressFromUser("Network mask", &info[SN_MASK]) == SUB_ERROR)
748 return NULL;
533bacb3 749 if (atoi(info[SN_LOW]) == (int)ntohl(inet_addr(S_DEFAULT_LOW)))
5eaef520 750 {
751 struct in_addr low;
752 unsigned long mask, addr;
753
754 addr = atoi(info[SN_ADDRESS]);
755 mask = atoi(info[SN_MASK]);
756 low.s_addr = atoi(info[SN_LOW]);
757 low.s_addr = (low.s_addr & ~mask) | (addr & mask);
758 free(info[SN_LOW]);
7ac48069 759 sprintf(temp_buf, "%ld", low.s_addr);
760 info[SN_LOW] = strdup(temp_buf);
5cfca28f 761 }
5eaef520 762 if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) ==
763 SUB_ERROR)
764 return NULL;
533bacb3 765 if (atoi(info[SN_HIGH]) == (int)ntohl(inet_addr(S_DEFAULT_HIGH)))
5eaef520 766 {
767 struct in_addr high;
768 unsigned long mask, addr;
769
770 addr = atoi(info[SN_ADDRESS]);
771 mask = atoi(info[SN_MASK]);
772 high.s_addr = atoi(info[SN_HIGH]);
773 high.s_addr = (high.s_addr & ~mask) | (addr & mask);
774 free(info[SN_HIGH]);
7ac48069 775 sprintf(temp_buf, "%ld", high.s_addr);
776 info[SN_HIGH] = strdup(temp_buf);
5cfca28f 777 }
5eaef520 778 if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) ==
779 SUB_ERROR)
780 return NULL;
781 if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR)
782 return NULL;
783 if (GetTypeFromUser("Owner type", "ace_type", &info[SN_ACE_TYPE]) ==
784 SUB_ERROR)
785 return NULL;
786 if (strcmp(info[SN_ACE_TYPE], "NONE") &&
787 GetValueFromUser("Owner name", &info[SN_ACE_NAME]) == SUB_ERROR)
788 return NULL;
5cef9ecf 789 if (!strcmp(info[SN_ACE_TYPE], "KERBEROS"))
790 {
791 char *canon;
792
793 mrcl_validate_kerberos_member(info[SN_ACE_NAME], &canon);
794 if (mrcl_get_message())
795 Put_message(mrcl_get_message());
796 free(info[SN_ACE_NAME]);
797 info[SN_ACE_NAME] = canon;
798 }
5eaef520 799 FreeAndClear(&info[SN_MODTIME], TRUE);
800 FreeAndClear(&info[SN_MODBY], TRUE);
801 FreeAndClear(&info[SN_MODWITH], TRUE);
802 break;
461c03b6 803 case CLUSTER:
5eaef520 804 if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
805 SUB_ERROR)
806 return NULL;
807 if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
808 SUB_ERROR)
809 return NULL;
810 FreeAndClear(&info[C_MODTIME], TRUE);
811 FreeAndClear(&info[C_MODBY], TRUE);
812 FreeAndClear(&info[C_MODWITH], TRUE);
813 break;
461c03b6 814 case DATA:
5eaef520 815 if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
816 SUB_ERROR)
817 return NULL;
818 if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
819 return NULL;
820 break;
9cd2d193 821 case CONTAINER:
822 if (GetValueFromUser("Container's Description:", &info[CON_DESCRIPT]) ==
823 SUB_ERROR)
824 return NULL;
825 if (GetValueFromUser("Container's Location:", &info[CON_LOCATION]) ==
826 SUB_ERROR)
827 return NULL;
828 if (GetValueFromUser("Container's Contact:", &info[CON_CONTACT]) ==
829 SUB_ERROR)
830 return NULL;
831 if (GetTypeFromUser("Container's owner type", "ace_type",
832 &info[CON_OWNER_TYPE]) == SUB_ERROR)
833 return NULL;
834 if (strcmp(info[CON_OWNER_TYPE], "NONE") &&
835 GetValueFromUser("Owner's Name", &info[CON_OWNER_NAME]) == SUB_ERROR)
836 return NULL;
837 if (!strcmp(info[CON_OWNER_TYPE], "KERBEROS"))
838 {
839 char *canon;
840
841 mrcl_validate_kerberos_member(info[CON_OWNER_NAME], &canon);
842 if (mrcl_get_message())
843 Put_message(mrcl_get_message());
844 free(info[CON_OWNER_NAME]);
845 info[CON_OWNER_NAME] = canon;
846 }
847 if (GetTypeFromUser("Container's Membership ACL", "ace_type",
848 &info[CON_MEMACE_TYPE]) == SUB_ERROR)
849 return NULL;
850 if (strcmp(info[CON_MEMACE_TYPE], "NONE") &&
851 GetValueFromUser("Membership ACL", &info[CON_MEMACE_NAME])
852 == SUB_ERROR)
853 return NULL;
854 if (!strcmp(info[CON_MEMACE_TYPE], "KERBEROS"))
855 {
856 char *canon;
857
858 mrcl_validate_kerberos_member(info[CON_MEMACE_NAME], &canon);
859 if (mrcl_get_message())
860 Put_message(mrcl_get_message());
861 free(info[CON_MEMACE_NAME]);
862 info[CON_MEMACE_NAME] = canon;
863 }
864 FreeAndClear(&info[CON_MODTIME], TRUE);
865 FreeAndClear(&info[CON_MODBY], TRUE);
866 FreeAndClear(&info[CON_MODWITH], TRUE);
867 break;
08345b74 868 }
869
5eaef520 870 /*
871 * Slide the newname into the #2 slot, this screws up all future references
872 * to this list.
873 */
874 if (name)
875 SlipInNewName(info, newname);
08345b74 876
5eaef520 877 return info;
08345b74 878}
879
880/* ----------- Machine Menu ----------- */
881
882/* Function Name: ShowMachineInfo
883 * Description: This function shows the information about a machine.
884 * Arguments: argc, argv - the name of the machine in argv[1].
885 * Returns: DM_NORMAL.
886 */
887
5eaef520 888int ShowMachineInfo(int argc, char **argv)
08345b74 889{
600b459e 890 struct mqelem *top;
5eaef520 891 char *tmpname;
892
7ac48069 893 tmpname = canonicalize_hostname(strdup(argv[1]));
5eaef520 894 top = GetMCInfo(MACHINE, tmpname, NULL);
a6da9354 895 Loop(top, ((void (*)(char **)) PrintMachInfo));
5eaef520 896 FreeQueue(top);
897 return DM_NORMAL;
08345b74 898}
899
ad7e0e04 900/* Function Name: ShowMachineQuery
901 * Description: This function shows the information about a machine.
902 * or group of machines, which may be selected through a
5eaef520 903 * number of criteria.
ad7e0e04 904 * Arguments: argc, argv - the name of the machine in argv[1],
905 * the address of the machine in argv[2],
906 * the location of the machine in argv[3],
907 * and the contact name in argv[4].
908 * any of these may be wildcards.
909 * Returns: DM_NORMAL.
910 */
911
5eaef520 912int ShowMachineQuery(int argc, char **argv)
ad7e0e04 913{
5eaef520 914 int stat;
600b459e 915 struct mqelem *top, *elem = NULL;
5eaef520 916 char *args[5];
917
918 if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
919 !strcmp(argv[3], "") && !strcmp(argv[4], ""))
920 {
921 Put_message("You must specify at least one parameter of the query.");
922 return DM_NORMAL;
ad7e0e04 923 }
924
5eaef520 925 if (*argv[1])
7ac48069 926 args[0] = canonicalize_hostname(strdup(argv[1]));
5eaef520 927 else
928 args[0] = "*";
929 if (*argv[2])
930 args[1] = argv[2];
931 else
932 args[1] = "*";
933 if (*argv[3])
934 args[2] = argv[3];
935 else
936 args[2] = "*";
937 if (*argv[4])
938 args[3] = argv[4];
939 else
940 args[3] = "*";
941
7ac48069 942 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
5eaef520 943 {
944 if (stat == MR_NO_MATCH)
945 Put_message("No machine(s) found matching query in the database.");
946 else
947 com_err(program_name, stat, " in get_machine.");
948 return DM_NORMAL;
ad7e0e04 949 }
5eaef520 950 top = QueueTop(elem);
a6da9354 951 Loop(top, ((void (*)(char **)) PrintMachInfo));
5eaef520 952 FreeQueue(top);
953 return DM_NORMAL;
ad7e0e04 954}
955
08345b74 956/* Function Name: AddMachine
957 * Description: This function adds a new machine to the database.
54864ee6 958 * Arguments: argc, argv - the name of the network in argv[1].
08345b74 959 * Returns: DM_NORMAL.
960 */
961
5eaef520 962int AddMachine(int argc, char **argv)
08345b74 963{
5eaef520 964 char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
965 char **rinfo;
600b459e 966 struct mqelem *elem = NULL;
5eaef520 967 int stat;
968
969 if (!ValidName(argv[1])) /* Checks for wildcards. */
970 return DM_NORMAL;
971
972 /*
973 * get the network record
974 */
975
976 if (strcasecmp(argv[1], "none") &&
7ac48069 977 (stat = do_mr_query("get_subnet", 1, &argv[1], StoreInfo, &elem)))
5eaef520 978 {
979 if (stat == MR_NO_MATCH)
980 {
981 char buf[128];
982 sprintf(buf, "Network '%s' is not in the database.", argv[1]);
983 Put_message(buf);
54864ee6 984 } else
5eaef520 985 com_err(program_name, stat, " in get_subnet.");
986 return DM_NORMAL;
987 }
54864ee6 988
5eaef520 989 /*
990 * Check to see if this machine already exists.
991 */
54864ee6 992
7ac48069 993 name = strdup(""); /* want to put prefix here */
5eaef520 994 if (GetValueFromUser("Machine name", &name) == SUB_ERROR)
995 return 0;
08345b74 996
7ac48069 997 name = canonicalize_hostname(strdup(name));
5eaef520 998
999 xargs[0] = name;
1000 xargs[1] = xargs[2] = xargs[3] = "*";
7ac48069 1001 if (!(stat = do_mr_query("get_host", 4, xargs, NULL, NULL)))
5eaef520 1002 {
1003 sprintf(buf, "The machine '%s' already exists.", name);
1004 Put_message(buf);
1005 free(name);
1006 return DM_NORMAL;
08345b74 1007 }
5eaef520 1008 else if (stat != MR_NO_MATCH)
1009 {
1010 com_err(program_name, stat,
1011 " while checking machine '%s' in AddMachine.", name);
1012 free(name);
1013 return DM_NORMAL;
08345b74 1014 }
5eaef520 1015 rinfo = SetMachineDefaults(info, name);
7ac48069 1016 rinfo[M_SUBNET] = strdup(argv[1]);
5eaef520 1017 if (!(args = AskMCDInfo(rinfo, MACHINE, FALSE)))
1018 {
1019 Put_message("Aborted.");
1020 return DM_NORMAL;
576ba5e7 1021 }
08345b74 1022
5eaef520 1023 /*
1024 * Actually create the new Machine.
1025 */
1026
7ac48069 1027 if ((stat = do_mr_query("add_host", CountArgs(args), args, NULL, NULL)))
5eaef520 1028 com_err(program_name, stat, " in AddMachine.");
1029
1030 FreeInfo(info);
1031 free(name);
1032 return DM_NORMAL;
08345b74 1033}
1034
402461ad 1035/* Function Name: RealUpdateMachine
1036 * Description: Performs the actual update of the machine data.
1037 * Arguments: info - the information on the machine to update.
1038 * junk - an UNUSED Boolean.
1039 * Returns: none.
1040 */
1041
5eaef520 1042static void RealUpdateMachine(char **info, Bool junk)
402461ad 1043{
44d12d58 1044 int stat;
5eaef520 1045 char **args = AskMCDInfo(info, MACHINE, TRUE);
1046 if (!args)
1047 {
1048 Put_message("Aborted.");
1049 return;
576ba5e7 1050 }
7ac48069 1051 if ((stat = do_mr_query("update_host", CountArgs(args), args, NULL, NULL)))
5eaef520 1052 com_err(program_name, stat, " in UpdateMachine.");
1053 else
1054 Put_message("Machine successfully updated.");
402461ad 1055}
1056
08345b74 1057/* Function Name: UpdateMachine
1058 * Description: This function adds a new machine to the database.
1059 * Arguments: argc, argv - the name of the machine in argv[1].
1060 * Returns: DM_NORMAL.
1061 */
1062
5eaef520 1063int UpdateMachine(int argc, char **argv)
08345b74 1064{
600b459e 1065 struct mqelem *top;
5eaef520 1066 char *tmpname;
1c3831ea 1067
7ac48069 1068 tmpname = canonicalize_hostname(strdup(argv[1]));
5eaef520 1069 top = GetMCInfo(MACHINE, tmpname, NULL);
1070 QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
08345b74 1071
5eaef520 1072 FreeQueue(top);
1073 free(tmpname);
1074 return DM_NORMAL;
08345b74 1075}
1076
85ca828a 1077/* Function Name: CheckAndRemoveFromCluster
1078 * Description: This func tests to see if a machine is in a cluster.
1079 * and if so then removes it
6d35002c 1080 * Arguments: name - name of the machine (already Canonicalized).
85ca828a 1081 * ask_user- query the user before removing if from clusters?
8defc06b 1082 * Returns: MR_ERROR if machine left in a cluster, or mr_error.
85ca828a 1083 */
1084
5eaef520 1085int CheckAndRemoveFromCluster(char *name, Bool ask_user)
85ca828a 1086{
44d12d58 1087 int stat, ret_value;
5eaef520 1088 Bool delete_it;
1089 char *args[10], temp_buf[BUFSIZ], *ptr;
600b459e 1090 struct mqelem *top, *elem = NULL;
5eaef520 1091
1092 ret_value = SUB_NORMAL; /* initialize ret_value. */
1093 args[0] = name;
1094 args[1] = "*";
7ac48069 1095 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
5eaef520 1096 if (stat && stat != MR_NO_MATCH)
1097 {
1098 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1099 return DM_NORMAL;
85ca828a 1100 }
5eaef520 1101 if (stat == MR_SUCCESS)
1102 {
1103 elem = top = QueueTop(elem);
1104 if (ask_user)
1105 {
1106 sprintf(temp_buf, "%s is assigned to the following clusters.", name);
1107 Put_message(temp_buf);
a6da9354 1108 Loop(top, (void (*)(char **)) PrintMCMap);
5eaef520 1109 ptr = "Remove this machine from ** ALL ** these clusters?";
1110 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1111 delete_it = TRUE;
1112 else
1113 {
1114 Put_message("Aborting...");
1115 FreeQueue(top);
1116 return SUB_ERROR;
85ca828a 1117 }
1118 }
5eaef520 1119 else
1120 delete_it = TRUE;
1121
1122 if (delete_it)
1123 {
1124 while (elem)
1125 {
7ac48069 1126 char **info = elem->q_data;
5eaef520 1127 if ((stat = do_mr_query("delete_machine_from_cluster",
7ac48069 1128 2, info, NULL, NULL)))
5eaef520 1129 {
1130 ret_value = SUB_ERROR;
1131 com_err(program_name, stat,
1132 " in delete_machine_from_cluster.");
1133 sprintf(temp_buf,
1134 "Machine %s ** NOT ** removed from cluster %s.",
1135 info[MAP_MACHINE], info[MAP_CLUSTER]);
1136 Put_message(temp_buf);
85ca828a 1137 }
5eaef520 1138 elem = elem->q_forw;
85ca828a 1139 }
1140 }
1141 }
5eaef520 1142 return ret_value;
85ca828a 1143}
1144
6d35002c 1145/* Function Name: CheckAndRemoveCnames
1146 * Description: This func tests to see if a machine has cnames,
1147 * and if so then removes them.
1148 * Arguments: name - name of the machine (already Canonicalized).
1149 * ask_user- query the user before removing cnames?
7811165a 1150 * Returns: MR_ERROR if machine left with a cname, or mr_error.
6d35002c 1151 */
1152
1153int CheckAndRemoveCnames(char *name, Bool ask_user)
1154{
1155 int stat, ret_value;
1156 Bool delete_it;
1157 char *args[10], temp_buf[BUFSIZ], *ptr;
1158 struct mqelem *top, *elem = NULL;
1159
1160 ret_value = SUB_NORMAL;
1161 args[0] = "*";
1162 args[1] = name;
1163 stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem);
1164 if (stat && stat != MR_NO_MATCH)
1165 {
1166 com_err(program_name, stat, " in get_hostalias.");
1167 return DM_NORMAL;
1168 }
1169 if (stat == MR_SUCCESS)
1170 {
1171 elem = top = QueueTop(elem);
1172 if (ask_user)
1173 {
1174 sprintf(temp_buf, "%s has the following cnames.", name);
1175 Put_message(temp_buf);
1176 Loop(top, (void (*)(char **)) PrintCname);
1177 ptr = "Remove ** ALL ** these cnames?";
1178 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1179 delete_it = TRUE;
1180 else
1181 {
1182 Put_message("Aborting...");
1183 FreeQueue(top);
1184 return SUB_ERROR;
1185 }
1186 }
1187 else
1188 delete_it = TRUE;
1189
1190 if (delete_it)
1191 {
1192 while (elem)
1193 {
1194 char **info = elem->q_data;
1195 if ((stat = do_mr_query("delete_hostalias", 2, info,
1196 NULL, NULL)))
1197 {
1198 ret_value = SUB_ERROR;
1199 com_err(program_name, stat, " in delete_hostalias.");
1200 sprintf(temp_buf,
1201 "Cname %s ** NOT ** removed from host %s.",
1202 info[0], info[1]);
1203 Put_message(temp_buf);
1204 }
1205 elem = elem->q_forw;
1206 }
1207 }
1208 }
1209 return ret_value;
1210}
1211
402461ad 1212/* Function Name: RealDeleteMachine
1213 * Description: Actually Deletes the Machine.
1214 * Arguments: info - nescessary information stored as an array of char *'s
1215 * one_machine - a boolean, true if there is only one item in
1216 * the query.
1217 * Returns: none.
1218 */
1219
5eaef520 1220static void RealDeleteMachine(char **info, Bool one_machine)
402461ad 1221{
44d12d58 1222 int stat;
5eaef520 1223 char temp_buf[BUFSIZ];
1224
1225 sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
1226 info[M_NAME]);
1227 if (!one_machine || Confirm(temp_buf))
1228 {
1229 if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR)
1230 {
6d35002c 1231 if (CheckAndRemoveCnames(info[M_NAME], TRUE) != SUB_ERROR)
5eaef520 1232 {
6d35002c 1233 if ((stat = do_mr_query("delete_host", 1,
1234 &info[M_NAME], NULL, NULL)))
1235 {
1236 com_err(program_name, stat, " in DeleteMachine.");
1237 sprintf(temp_buf, "%s ** NOT ** deleted.",
1238 info[M_NAME]);
1239 Put_message(temp_buf);
1240 }
1241 else
1242 {
1243 sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
1244 Put_message(temp_buf);
1245 }
402461ad 1246 }
1247 }
1248 }
1249}
7811165a 1250
08345b74 1251/* Function Name: DeleteMachine
1252 * Description: This function removes a machine from the data base.
1253 * Arguments: argc, argv - the machines name int argv[1].
1254 * Returns: DM_NORMAL.
1255 */
1256
85ca828a 1257/* Perhaps we should remove the cluster if it has no machine now. */
1258
5eaef520 1259int DeleteMachine(int argc, char **argv)
08345b74 1260{
600b459e 1261 struct mqelem *top;
5eaef520 1262 char *tmpname;
1263
7ac48069 1264 tmpname = canonicalize_hostname(strdup(argv[1]));
5eaef520 1265 top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
1266 QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
1267 FreeQueue(top);
1268 free(tmpname);
1269 return DM_NORMAL;
08345b74 1270}
1271
5cfca28f 1272
ad7e0e04 1273/* Function Name: ShowCname
1274 * Description: This function shows machine aliases
1275 * Arguments: argc, argv - the alias argv[1], the real name in argv[2]
1276 * Returns: DM_NORMAL.
1277 */
1278
5eaef520 1279int ShowCname(int argc, char **argv)
ad7e0e04 1280{
600b459e 1281 struct mqelem *top;
5eaef520 1282 char *tmpalias, *tmpname;
1283
7ac48069 1284 tmpalias = partial_canonicalize_hostname(strdup(argv[1]));
1285 tmpname = canonicalize_hostname(strdup(argv[2]));
5eaef520 1286 top = GetMCInfo(CNAME, tmpalias, tmpname);
1287 Put_message(""); /* blank line on screen */
a6da9354 1288 Loop(top, ((void (*)(char **)) PrintCname));
5eaef520 1289 FreeQueue(top);
1290 return DM_NORMAL;
ad7e0e04 1291}
1292
1293
5eaef520 1294int AddCname(int argc, char **argv)
ad7e0e04 1295{
5eaef520 1296 int stat;
1297 char *args[10];
1298
7ac48069 1299 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1300 args[1] = canonicalize_hostname(strdup(argv[2]));
1301 stat = do_mr_query("add_hostalias", 2, args, NULL, NULL);
5eaef520 1302 switch (stat)
1303 {
ad7e0e04 1304 case MR_SUCCESS:
5eaef520 1305 break;
ad7e0e04 1306 case MR_EXISTS:
5eaef520 1307 Put_message("That alias name is already in use.");
1308 break;
ad7e0e04 1309 case MR_PERM:
5eaef520 1310 Put_message("Permission denied. "
1311 "(Regular users can only add two aliases to a host.");
1312 break;
ad7e0e04 1313 default:
5eaef520 1314 com_err(program_name, stat, " in add_hostalias");
ad7e0e04 1315 }
5eaef520 1316 return DM_NORMAL;
ad7e0e04 1317}
1318
1319
5eaef520 1320int DeleteCname(int argc, char **argv)
ad7e0e04 1321{
5eaef520 1322 int stat;
7ac48069 1323 char *args[10];
5eaef520 1324
7ac48069 1325 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1326 args[1] = canonicalize_hostname(strdup(argv[2]));
1327 stat = do_mr_query("delete_hostalias", 2, args, NULL, NULL);
5eaef520 1328 if (stat)
1329 com_err(program_name, stat, " in delete_hostalias");
1330 return DM_NORMAL;
ad7e0e04 1331}
1332
1333
08345b74 1334/* Function Name: AddMachineToCluster
1335 * Description: This function adds a machine to a cluster
1336 * Arguments: argc, argv - The machine name is argv[1].
1337 * The cluster name in argv[2].
1338 * Returns: DM_NORMAL.
1339 */
1340
5eaef520 1341int AddMachineToCluster(int argc, char **argv)
08345b74 1342{
5eaef520 1343 int stat;
1344 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1345 Bool add_it, one_machine, one_cluster;
600b459e 1346 struct mqelem *melem, *mtop, *celem, *ctop;
5eaef520 1347
7ac48069 1348 machine = canonicalize_hostname(strdup(argv[1]));
5eaef520 1349 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
1350 {
1351 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1352 argv[1], machine);
1353 Put_message(temp_buf);
576ba5e7 1354 }
5eaef520 1355 cluster = argv[2];
1356
1357 celem = ctop = GetMCInfo(CLUSTER, cluster, NULL);
1358 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
1359 free(machine);
1360
1361 one_machine = (QueueCount(mtop) == 1);
1362 one_cluster = (QueueCount(ctop) == 1);
1363
1364 /* No good way to use QueryLoop() here, sigh */
1365
1366 while (melem)
1367 {
7ac48069 1368 char **minfo = melem->q_data;
5eaef520 1369 while (celem)
1370 {
7ac48069 1371 char **cinfo = celem->q_data;
5eaef520 1372 if (one_machine && one_cluster)
1373 add_it = TRUE;
1374 else
1375 {
1376 sprintf(temp_buf, "Add machine %s to cluster %s (y/n/q) ?",
1377 minfo[M_NAME], cinfo[C_NAME]);
1378 switch (YesNoQuitQuestion(temp_buf, FALSE))
1379 {
85ca828a 1380 case TRUE:
5eaef520 1381 add_it = TRUE;
1382 break;
85ca828a 1383 case FALSE:
5eaef520 1384 add_it = FALSE;
1385 break;
85ca828a 1386 default:
5eaef520 1387 Put_message("Aborting...");
1388 FreeQueue(ctop);
1389 FreeQueue(mtop);
1390 return DM_NORMAL;
85ca828a 1391 }
1392 }
5eaef520 1393 if (add_it)
1394 {
1395 args[0] = minfo[M_NAME];
1396 args[1] = cinfo[C_NAME];
1397 stat = do_mr_query("add_machine_to_cluster", 2, args,
7ac48069 1398 NULL, NULL);
5eaef520 1399 switch (stat)
1400 {
8defc06b 1401 case MR_SUCCESS:
5eaef520 1402 break;
8defc06b 1403 case MR_EXISTS:
5eaef520 1404 sprintf(temp_buf, "%s is already in cluster %s",
1405 minfo[M_NAME], cinfo[C_NAME]);
1406 Put_message(temp_buf);
1407 break;
85ca828a 1408 default:
5eaef520 1409 com_err(program_name, stat, " in AddMachineToCluster.");
1410 break;
85ca828a 1411 }
1412 }
5eaef520 1413 celem = celem->q_forw;
85ca828a 1414 }
5eaef520 1415 celem = ctop; /* reset cluster element. */
1416 melem = melem->q_forw;
85ca828a 1417 }
5eaef520 1418 FreeQueue(ctop);
1419 FreeQueue(mtop);
1420 return DM_NORMAL;
08345b74 1421}
1422
402461ad 1423/* Function Name: RealRemoveMachineFromCluster
5eaef520 1424 * Description: This function actually removes the machine from its
402461ad 1425 * cluster.
1426 * Arguments: info - all information nescessary to perform the removal.
1427 * one_map - True if there is only one case, and we should
1428 * confirm.
1429 * Returns: none.
1430 */
1431
5eaef520 1432static void RealRemoveMachineFromCluster(char **info, Bool one_map)
402461ad 1433{
5eaef520 1434 char temp_buf[BUFSIZ];
44d12d58 1435 int stat;
5eaef520 1436
1437 sprintf(temp_buf, "Remove %s from the cluster %s",
1438 info[MAP_MACHINE], info[MAP_CLUSTER]);
1439 if (!one_map || Confirm(temp_buf))
1440 {
1441 if ((stat = do_mr_query("delete_machine_from_cluster", 2,
7ac48069 1442 info, NULL, NULL)))
5eaef520 1443 com_err(program_name, stat, " in delete_machine_from_cluster");
1444 else
1445 {
1446 sprintf(temp_buf, "%s has been removed from the cluster %s.",
1447 info[MAP_MACHINE], info[MAP_CLUSTER]);
1448 Put_message(temp_buf);
402461ad 1449 }
1450 }
5eaef520 1451 else
1452 Put_message("Machine not removed.");
402461ad 1453}
1454
08345b74 1455/* Function Name: RemoveMachineFromCluster
1456 * Description: Removes this machine form a specific cluster.
1457 * Arguments: argc, argv - Name of machine in argv[1].
85ca828a 1458 * Name of cluster in argv[2].
08345b74 1459 * Returns: none.
1460 */
1461
5eaef520 1462int RemoveMachineFromCluster(int argc, char **argv)
08345b74 1463{
600b459e 1464 struct mqelem *elem = NULL;
9cd2d193 1465 char buf[BUFSIZ], *args[10];
44d12d58 1466 int stat;
5eaef520 1467
7ac48069 1468 args[MAP_MACHINE] = canonicalize_hostname(strdup(argv[1]));
5eaef520 1469 if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"')
1470 {
1471 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1472 argv[1], args[MAP_MACHINE]);
1473 Put_message(buf);
576ba5e7 1474 }
5eaef520 1475 args[MAP_CLUSTER] = argv[2];
1476 args[MAP_END] = NULL;
1477
1478 stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
7ac48069 1479 StoreInfo, &elem);
5eaef520 1480 if (stat == MR_NO_MATCH)
1481 {
9cd2d193 1482 sprintf(buf, "The machine %s is not in the cluster %s.",
5eaef520 1483 args[MAP_MACHINE], args[MAP_CLUSTER]);
1484 Put_message(buf);
1485 free(args[MAP_MACHINE]);
1486 return DM_NORMAL;
08345b74 1487 }
5eaef520 1488 if (stat != MR_SUCCESS)
1489 com_err(program_name, stat, " in delete_machine_from_cluster");
85ca828a 1490
5eaef520 1491 elem = QueueTop(elem);
1492 QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1493 "Remove this machine from this cluster");
402461ad 1494
5eaef520 1495 FreeQueue(elem);
1496 free(args[MAP_MACHINE]);
1497 return DM_NORMAL;
08345b74 1498}
1499
ad7e0e04 1500/* ---------- Subnet Menu -------- */
1501
1502/* Function Name: ShowSubnetInfo
1503 * Description: Gets information about a subnet given its name.
1504 * Arguments: argc, argc - the name of the subnet in in argv[1].
1505 * Returns: DM_NORMAL.
1506 */
1507
5eaef520 1508int ShowSubnetInfo(int argc, char **argv)
ad7e0e04 1509{
600b459e 1510 struct mqelem *top;
ad7e0e04 1511
5eaef520 1512 top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
a6da9354 1513 Loop(top, (void (*)(char **)) PrintSubnetInfo);
5eaef520 1514 FreeQueue(top);
1515 return DM_NORMAL;
ad7e0e04 1516}
1517
1518/* Function Name: AddSubnet
1519 * Description: Creates a new subnet.
1520 * Arguments: argc, argv - the name of the new subnet is argv[1].
1521 * Returns: DM_NORMAL.
1522 */
1523
5eaef520 1524int AddSubnet(int argc, char **argv)
ad7e0e04 1525{
5eaef520 1526 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1527 int stat;
1528
1529 /*
1530 * Check to see if this subnet already exists.
1531 */
1532 if (!ValidName(name))
1533 return DM_NORMAL;
1534
7ac48069 1535 if ((stat = do_mr_query("get_subnet", 1, &name, NULL, NULL)) == MR_SUCCESS)
5eaef520 1536 {
1537 Put_message("This subnet already exists.");
1538 return DM_NORMAL;
ad7e0e04 1539 }
5eaef520 1540 else if (stat != MR_NO_MATCH)
1541 {
1542 com_err(program_name, stat, " in AddSubnet.");
1543 return DM_NORMAL;
ad7e0e04 1544 }
5eaef520 1545 if (!(args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)))
1546 {
1547 Put_message("Aborted.");
1548 FreeInfo(info);
1549 return DM_NORMAL;
ad7e0e04 1550 }
1551
5eaef520 1552 /*
1553 * Actually create the new Subnet.
1554 */
7ac48069 1555 if ((stat = do_mr_query("add_subnet", CountArgs(args), args, NULL, NULL)))
5eaef520 1556 com_err(program_name, stat, " in AddSubnet.");
ad7e0e04 1557
5eaef520 1558 FreeInfo(info);
1559 return DM_NORMAL;
ad7e0e04 1560}
1561
1562/* Function Name: RealUpdateSubnet
1563 * Description: This function actually performs the subnet update.
1564 * Arguments: info - all information nesc. for updating the subnet.
1565 * junk - an UNUSED boolean.
1566 * Returns: none.
1567 */
1568
5eaef520 1569static void RealUpdateSubnet(char **info, Bool junk)
ad7e0e04 1570{
44d12d58 1571 int stat;
5eaef520 1572 char **args = AskMCDInfo(info, SUBNET, TRUE);
1573 if (!args)
1574 {
1575 Put_message("Aborted.");
1576 return;
ad7e0e04 1577 }
7ac48069 1578 if ((stat = do_mr_query("update_subnet", CountArgs(args), args, NULL, NULL)))
5eaef520 1579 com_err(program_name, stat, " in UpdateSubnet.");
1580 else
1581 Put_message("Subnet successfully updated.");
ad7e0e04 1582}
1583
1584/* Function Name: UpdateSubnet
1585 * Description: This Function Updates a subnet
1586 * Arguments: name of the subnet in argv[1].
1587 * Returns: DM_NORMAL.
1588 */
1589
5eaef520 1590int UpdateSubnet(int argc, char **argv)
ad7e0e04 1591{
600b459e 1592 struct mqelem *top;
5eaef520 1593 top = GetMCInfo(SUBNET, argv[1], NULL);
1594 QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
ad7e0e04 1595
5eaef520 1596 FreeQueue(top);
1597 return DM_NORMAL;
ad7e0e04 1598}
1599
1600/* Function Name: RealDeleteSubnet
1601 * Description: Actually performs the subnet deletion.
1602 * Arguments: info - all information about this subnet.
1603 * one_subnet - If true then there was only one subnet in
1604 * the queue, and we should confirm.
1605 * Returns: none.
1606 */
1607
5eaef520 1608static void RealDeleteSubnet(char **info, Bool one_subnet)
ad7e0e04 1609{
44d12d58 1610 int stat;
5eaef520 1611 char temp_buf[BUFSIZ];
1612
1613 sprintf(temp_buf,
1614 "Are you sure the you want to delete the subnet %s (y/n) ?",
1615 info[C_NAME]);
1616 if (!one_subnet || Confirm(temp_buf))
1617 {
7ac48069 1618 if ((stat = do_mr_query("delete_subnet", 1, &info[C_NAME], NULL, NULL)))
5eaef520 1619 {
1620 com_err(program_name, stat, " in delete_subnet.");
1621 sprintf(temp_buf, "Subnet %s ** NOT ** deleted.", info[C_NAME]);
1622 Put_message(temp_buf);
ad7e0e04 1623 }
5eaef520 1624 else
1625 {
1626 sprintf(temp_buf, "subnet %s successfully deleted.",
1627 info[C_NAME]);
1628 Put_message(temp_buf);
ad7e0e04 1629 }
1630 }
1631}
1632
1633/* Function Name: DeleteSubnet
1634 * Description: This function removes a subnet from the database.
1635 * Arguments: argc, argv - the name of the subnet is stored in argv[1].
1636 * Returns: DM_NORMAL.
1637 */
1638
5eaef520 1639int DeleteSubnet(int argc, char **argv)
ad7e0e04 1640{
600b459e 1641 struct mqelem *top;
ad7e0e04 1642
5eaef520 1643 top = GetMCInfo(SUBNET, argv[1], NULL);
1644 QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
ad7e0e04 1645
5eaef520 1646 FreeQueue(top);
1647 return DM_NORMAL;
ad7e0e04 1648}
5eaef520 1649
08345b74 1650/* ---------- Cluster Menu -------- */
1651
1652/* Function Name: ShowClusterInfo
1653 * Description: Gets information about a cluser given its name.
1654 * Arguments: argc, argc - the name of the cluster in in argv[1].
1655 * Returns: DM_NORMAL.
1656 */
1657
5eaef520 1658int ShowClusterInfo(int argc, char **argv)
08345b74 1659{
600b459e 1660 struct mqelem *top;
08345b74 1661
5eaef520 1662 top = GetMCInfo(CLUSTER, argv[1], NULL);
a6da9354 1663 Loop(top, (void (*)(char **)) PrintClusterInfo);
5eaef520 1664 FreeQueue(top);
1665 return DM_NORMAL;
08345b74 1666}
1667
1668/* Function Name: AddCluster
1669 * Description: Creates a new cluster.
1670 * Arguments: argc, argv - the name of the new cluster is argv[1].
1671 * Returns: DM_NORMAL.
1672 */
1673
5eaef520 1674int AddCluster(int argc, char **argv)
08345b74 1675{
5eaef520 1676 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1677 int stat;
1678
1679 /*
1680 * Check to see if this cluster already exists.
1681 */
1682 if (!ValidName(name))
1683 return DM_NORMAL;
1684
7ac48069 1685 if ((stat = do_mr_query("get_cluster", 1, &name, NULL, NULL)) == MR_SUCCESS)
5eaef520 1686 {
1687 Put_message("This cluster already exists.");
1688 return DM_NORMAL;
08345b74 1689 }
5eaef520 1690 else if (stat != MR_NO_MATCH)
1691 {
1692 com_err(program_name, stat, " in AddCluster.");
1693 return DM_NORMAL;
08345b74 1694 }
5eaef520 1695 if (!(args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)))
1696 {
1697 Put_message("Aborted.");
1698 FreeInfo(info);
1699 return DM_NORMAL;
576ba5e7 1700 }
1701
5eaef520 1702 /*
1703 * Actually create the new Cluster.
1704 */
7ac48069 1705 if ((stat = do_mr_query("add_cluster", CountArgs(args), args, NULL, NULL)))
5eaef520 1706 com_err(program_name, stat, " in AddCluster.");
08345b74 1707
5eaef520 1708 FreeInfo(info);
1709 return DM_NORMAL;
08345b74 1710}
1711
402461ad 1712/* Function Name: RealUpdateCluster
1713 * Description: This function actually performs the cluster update.
1714 * Arguments: info - all information nesc. for updating the cluster.
1715 * junk - an UNUSED boolean.
1716 * Returns: none.
1717 */
1718
5eaef520 1719static void RealUpdateCluster(char **info, Bool junk)
402461ad 1720{
44d12d58 1721 int stat;
5eaef520 1722 char **args = AskMCDInfo(info, CLUSTER, TRUE);
1723
1724 if (!args)
1725 {
1726 Put_message("Aborted.");
1727 return;
576ba5e7 1728 }
5eaef520 1729 if ((stat = do_mr_query("update_cluster", CountArgs(args),
7ac48069 1730 args, NULL, NULL)))
5eaef520 1731 com_err(program_name, stat, " in UpdateCluster.");
1732 else
1733 Put_message("Cluster successfully updated.");
402461ad 1734}
1735
08345b74 1736/* Function Name: UpdateCluster
1737 * Description: This Function Updates a cluster
1738 * Arguments: name of the cluster in argv[1].
1739 * Returns: DM_NORMAL.
1740 */
1741
5eaef520 1742int UpdateCluster(int argc, char **argv)
08345b74 1743{
600b459e 1744 struct mqelem *top;
5eaef520 1745 top = GetMCInfo(CLUSTER, argv[1], NULL);
1746 QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
08345b74 1747
5eaef520 1748 FreeQueue(top);
1749 return DM_NORMAL;
08345b74 1750}
1751
85ca828a 1752/* Function Name: CheckAndRemoveMachine
1753 * Description: This function checks and removes all machines from a
1754 * cluster.
1755 * Arguments: name - name of the cluster.
1756 * ask_first - if TRUE, then we will query the user, before
1757 * deletion.
1758 * Returns: SUB_ERROR if all machines not removed.
1759 */
1760
5eaef520 1761int CheckAndRemoveMachines(char *name, Bool ask_first)
85ca828a 1762{
44d12d58 1763 int stat, ret_value;
5eaef520 1764 Bool delete_it;
1765 char *args[10], temp_buf[BUFSIZ], *ptr;
600b459e 1766 struct mqelem *top, *elem = NULL;
5eaef520 1767
1768 ret_value = SUB_NORMAL;
1769 args[MAP_MACHINE] = "*";
1770 args[MAP_CLUSTER] = name;
7ac48069 1771 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
5eaef520 1772 if (stat && stat != MR_NO_MATCH)
1773 {
1774 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1775 return DM_NORMAL;
85ca828a 1776 }
5eaef520 1777 if (stat == MR_SUCCESS)
1778 {
1779 elem = top = QueueTop(elem);
1780 if (ask_first)
1781 {
1782 sprintf(temp_buf, "The cluster %s has the following machines in it:",
1783 name);
1784 Put_message(temp_buf);
1785 while (elem)
1786 {
7ac48069 1787 char **info = elem->q_data;
5eaef520 1788 Print(1, &info[MAP_MACHINE], (char *) NULL);
1789 elem = elem->q_forw;
85ca828a 1790 }
5eaef520 1791 ptr = "Remove ** ALL ** these machines from this cluster?";
1792
1793 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1794 delete_it = TRUE;
1795 else
1796 {
1797 Put_message("Aborting...");
1798 FreeQueue(top);
1799 return SUB_ERROR;
85ca828a 1800 }
1801 }
5eaef520 1802 else
1803 delete_it = TRUE;
1804
1805 if (delete_it)
1806 {
1807 elem = top;
1808 while (elem)
1809 {
7ac48069 1810 char **info = elem->q_data;
5eaef520 1811 if ((stat = do_mr_query("delete_machine_from_cluster",
7ac48069 1812 2, info, NULL, NULL)))
5eaef520 1813 {
1814 ret_value = SUB_ERROR;
1815 com_err(program_name, stat,
1816 " in delete_machine_from_cluster.");
1817 sprintf(temp_buf,
1818 "Machine %s ** NOT ** removed from cluster %s.",
1819 info[MAP_MACHINE], info[MAP_CLUSTER]);
1820 Put_message(temp_buf);
85ca828a 1821 }
5eaef520 1822 elem = elem->q_forw;
85ca828a 1823 }
1824 }
1825 }
5eaef520 1826 return ret_value;
85ca828a 1827}
1828
402461ad 1829/* Function Name: RealDeleteCluster
1830 * Description: Actually performs the cluster deletion.
1831 * Arguments: info - all information about this cluster.
1832 * one_cluster - If true then there was only one cluster in
1833 * the queue, and we should confirm.
1834 * Returns: none.
1835 */
1836
5eaef520 1837static void RealDeleteCluster(char **info, Bool one_cluster)
402461ad 1838{
44d12d58 1839 int stat;
5eaef520 1840 char temp_buf[BUFSIZ];
1841
1842 sprintf(temp_buf,
1843 "Are you sure the you want to delete the cluster %s (y/n) ?",
1844 info[C_NAME]);
1845 if (!one_cluster || Confirm(temp_buf))
1846 {
1847 if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR)
1848 {
1849 if ((stat = do_mr_query("delete_cluster", 1,
7ac48069 1850 &info[C_NAME], NULL, NULL)))
5eaef520 1851 {
1852 com_err(program_name, stat, " in delete_cluster.");
1853 sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", info[C_NAME]);
1854 Put_message(temp_buf);
402461ad 1855 }
5eaef520 1856 else
1857 {
1858 sprintf(temp_buf, "cluster %s successfully deleted.",
1859 info[C_NAME]);
1860 Put_message(temp_buf);
402461ad 1861 }
1862 }
1863 }
1864}
85ca828a 1865
08345b74 1866/* Function Name: DeleteCluster
1867 * Description: This function removes a cluster from the database.
1868 * Arguments: argc, argv - the name of the cluster is stored in argv[1].
1869 * Returns: DM_NORMAL.
1870 */
1871
5eaef520 1872int DeleteCluster(int argc, char **argv)
08345b74 1873{
600b459e 1874 struct mqelem *top;
08345b74 1875
5eaef520 1876 top = GetMCInfo(CLUSTER, argv[1], NULL);
1877 QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
08345b74 1878
5eaef520 1879 FreeQueue(top);
1880 return DM_NORMAL;
08345b74 1881}
5eaef520 1882
08345b74 1883/* ----------- Cluster Data Menu -------------- */
1884
1885/* Function Name: ShowClusterData
1886 * Description: This function shows the services for one cluster.
1887 * Arguments: argc, argv - The name of the cluster is argv[1].
461c03b6 1888 * The label of the data in argv[2].
08345b74 1889 * Returns: DM_NORMAL.
1890 */
1891
5eaef520 1892int ShowClusterData(int argc, char **argv)
1893{
600b459e 1894 struct mqelem *elem, *top;
5eaef520 1895 char **info;
1896
1897 top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1898 while (elem)
1899 {
7ac48069 1900 info = elem->q_data;
5eaef520 1901 PrintClusterData(info);
1902 elem = elem->q_forw;
08345b74 1903 }
5eaef520 1904 FreeQueue(top);
1905 return DM_NORMAL;
08345b74 1906}
1907
1908/* Function Name: AddClusterData
1909 * Description: This function adds some data to the cluster.
1910 * Arguments: argv, argc: argv[1] - the name of the cluster.
1911 * argv[2] - the label of the data.
1912 * argv[3] - the data.
1913 * Returns: DM_NORMAL.
1914 */
1915
5eaef520 1916int AddClusterData(int argc, char **argv)
1917{
7b07cdab 1918 int stat, i;
5eaef520 1919
7b07cdab 1920 for (i = 1; i < 4; i++)
1921 {
1922 if (IS_EMPTY(argv[i]))
1923 {
1924 Put_message("Cluster data cannot be an empty string.");
1925 return DM_NORMAL;
1926 }
1927 }
7ac48069 1928 if ((stat = do_mr_query("add_cluster_data", 3, argv + 1, NULL, NULL)))
5eaef520 1929 com_err(program_name, stat, " in AddClusterData.");
1930 return DM_NORMAL;
08345b74 1931}
1932
402461ad 1933/* Function Name: RealRemoveClusterData
1934 * Description: actually removes the cluster data.
1935 * Arguments: info - all info necessary to remove the cluster, in an array
1936 * of strings.
1937 * one_item - if true then the queue has only one elem and we
1938 * should confirm.
1939 * Returns: none.
1940 */
1941
5eaef520 1942static void RealRemoveClusterData(char **info, Bool one_item)
402461ad 1943{
44d12d58 1944 int stat;
5eaef520 1945 char *temp_ptr;
1946
1947 Put_message(" ");
1948 temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1949 PrintClusterData(info);
1950 if (!one_item || Confirm(temp_ptr))
1951 {
7ac48069 1952 if ((stat = do_mr_query("delete_cluster_data", 3, info, NULL, NULL)))
5eaef520 1953 {
1954 com_err(program_name, stat, " in DeleteClusterData.");
1955 Put_message("Data not removed.");
402461ad 1956 }
5eaef520 1957 else
1958 Put_message("Removal successful.");
402461ad 1959 }
1960}
1961
461c03b6 1962/* Function Name: RemoveClusterData
1963 * Description: This function removes data on a given cluster.
08345b74 1964 * Arguments: argv, argc: argv[1] - the name of the cluster.
1965 * argv[2] - the label of the data.
1966 * argv[3] - the data.
1967 * Returns: DM_NORMAL.
1968 */
1969
5eaef520 1970int RemoveClusterData(int argc, char **argv)
08345b74 1971{
600b459e 1972 struct mqelem *top;
08345b74 1973
5eaef520 1974 top = GetMCInfo(DATA, argv[1], argv[2]);
1975 QueryLoop(top, PrintClusterData, RealRemoveClusterData,
1976 "Remove data from cluster");
08345b74 1977
5eaef520 1978 FreeQueue(top);
1979 return DM_NORMAL;
08345b74 1980}
1981
08345b74 1982/* Function Name: MachineToClusterMap
1983 * Description: This Retrieves the mapping between machine and cluster
1984 * Arguments: argc, argv - argv[1] -> machine name or wildcard.
1985 * argv[2] -> cluster name or wildcard.
1986 * Returns: none.
1987 */
1988
5eaef520 1989int MachineToClusterMap(int argc, char **argv)
08345b74 1990{
600b459e 1991 struct mqelem *elem, *top;
5eaef520 1992 char *tmpname, temp_buf[256];
1993
7ac48069 1994 tmpname = canonicalize_hostname(strdup(argv[1]));
5eaef520 1995 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
1996 {
1997 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1998 argv[1], tmpname);
1999 Put_message(temp_buf);
576ba5e7 2000 }
5eaef520 2001 top = elem = GetMCInfo(MAP, tmpname, argv[2]);
2002
2003 Put_message(""); /* blank line on screen */
2004 while (elem)
2005 {
7ac48069 2006 char **info = elem->q_data;
5eaef520 2007 PrintMCMap(info);
2008 elem = elem->q_forw;
461c03b6 2009 }
2010
5eaef520 2011 FreeQueue(top);
2012 free(tmpname);
2013 return DM_NORMAL;
461c03b6 2014}
7399b4b2 2015
2016/* Function Name: MachineByOwner
2017 * Description: This function prints all machines which are owned by
2018 * a given user or group.
2019 * Arguments: none.
2020 * Returns: DM_NORMAL.
2021 */
2022
2023int MachineByOwner(int argc, char **argv)
2024{
2025 char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
2026 struct mqelem *top;
2027
2028 type = strdup("USER");
2029 if (GetTypeFromUser("Type of owner", "ace_type", &type) == SUB_ERROR)
2030 return DM_NORMAL;
2031
2032 sprintf(buf, "Name of %s", type);
2033 name = strdup(user);
2034 if (GetValueFromUser(buf, &name) == SUB_ERROR)
2035 return DM_NORMAL;
2036
2037 switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE))
2038 {
2039 case TRUE:
2040 sprintf(temp_buf, "R%s", type); /* "USER to "RUSER", etc. */
2041 free(type);
2042 type = strdup(temp_buf);
2043 break;
2044 case FALSE:
2045 break;
2046 default:
2047 return DM_NORMAL;
2048 }
2049
2050 top = GetMachineByOwner(type, name);
2051 Loop(top, PrintMachine);
2052
2053 FreeQueue(top);
2054 return DM_NORMAL;
2055}
2056
2057/* Function Name: GetMachineByOwner
2058 * Description: This function stores information retrieved by
2059 * the get_host_by_owner query
2060 * Arguments: type - an ace_type, argv[0] for the query
2061 * name - name of machine, argv[1] for the query
2062 * Returns: the top element of a queue returning the data, or NULL.
2063 */
2064
2065struct mqelem *GetMachineByOwner(char *type, char *name)
2066{
2067 char *args[2];
2068 struct mqelem *elem = NULL;
2069 int status;
2070
2071 args[0] = type;
2072 args[1] = name;
2073 if ((status = do_mr_query("get_host_by_owner", 2, args, StoreInfo, &elem)))
2074 {
2075 com_err(program_name, status, " in get_host_by_owner");
2076 return NULL;
2077 }
2078 return QueueTop(elem);
2079}
9cd2d193 2080
4f6b1a05 2081int MachineByAcctNumber(int argc, char **argv)
2082{
8c3e924b 2083 char *args[1], *account_number;
4f6b1a05 2084 int status;
2085 struct mqelem *elem = NULL;
2086
e34d27e3 2087 account_number = strdup("");
4f6b1a05 2088 if (GetValueFromUser("Account Number", &account_number) == SUB_ERROR)
2089 return DM_NORMAL;
2090
2091 args[0] = account_number;
2092 if (status = do_mr_query("get_host_by_account_number", 1, args, StoreInfo,
2093 &elem))
2094 {
2095 com_err(program_name, status, " in get_host_by_account_number");
2096 return DM_NORMAL;
2097 }
2098 Loop(QueueTop(elem), (void (*)(char **)) PrintMachInfo);
2099 FreeQueue(elem);
2100
2101 return DM_NORMAL;
2102}
2103
9cd2d193 2104int ShowContainerInfo(int argc, char **argv)
2105{
2106 struct mqelem *top;
2107
2108 top = GetMCInfo(CONTAINER, argv[1], NULL);
2109 Loop(top, (void (*)(char **)) PrintContainerInfo);
2110 FreeQueue(top);
2111 return DM_NORMAL;
2112}
2113
2114static char *PrintContainerInfo(char **info)
2115{
2116 char buf[BUFSIZ], tbuf[256];
2117
2118 Put_message("");
2119 sprintf(buf, "Container: %-16s", info[CON_NAME]);
2120 Put_message(buf);
2121 sprintf(buf, "Description: %-16s", info[CON_DESCRIPT]);
2122 Put_message(buf);
2123 sprintf(buf, "Location: %-16s Contact: %s", info[CON_LOCATION],
2124 info[CON_CONTACT]);
2125 Put_message(buf);
2126 sprintf(tbuf, "%s %s", info[CON_OWNER_TYPE],
2127 strcmp(info[CON_OWNER_TYPE], "NONE") ? info[CON_OWNER_NAME] : "");
2128 sprintf(buf, "Owner: %-16s", tbuf);
2129 Put_message(buf);
2130 sprintf(tbuf, "%s %s", info[CON_MEMACE_TYPE],
2131 strcmp(info[CON_MEMACE_TYPE], "NONE") ? info[CON_MEMACE_NAME] : "");
2132 sprintf(buf, "Membership ACL: %-16s", tbuf);
2133 Put_message(buf);
2134 Put_message("");
2135 sprintf(buf, MOD_FORMAT, info[CON_MODBY], info[CON_MODTIME],
2136 info[CON_MODWITH]);
2137 Put_message(buf);
2138 return info[CON_NAME];
2139}
2140
2141static char *PrintContainer(char **info)
2142{
2143 char buf[BUFSIZ];
2144
2145 sprintf(buf, "Container: %s", info[CON_NAME]);
2146 Put_message(buf);
84dc1928 2147 return "";
9cd2d193 2148}
2149
2150static char *PrintMContMap(char **info)
2151{
2152 char buf[BUFSIZ];
2153 sprintf(buf, "Container: %-30s Machine: %-20s",
2154 info[1], info[0]);
2155 Put_message(buf);
2156 return "";
2157}
2158
2159int AddContainer(int argc, char **argv)
2160{
2161 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
2162 int stat;
2163
bb52f279 2164 /* Can't use ValidName() because spaces are allowed in container names */
2165 if (IS_EMPTY(name))
2166 {
2167 Put_message("Please use a non-empty name.");
2168 return DM_NORMAL;
2169 }
2170
2171 if (strchr(name, '*') || strchr(name, '?'))
2172 {
2173 Put_message("Wildcards not accepted here.");
2174 return DM_NORMAL;
2175 }
9cd2d193 2176
2177 /* Check if this cluster already exists. */
2178 if ((stat = do_mr_query("get_container", 1, &name, NULL, NULL))
2179 == MR_SUCCESS)
2180 {
2181 Put_message("This container already exists.");
2182 return DM_NORMAL;
2183 }
2184 else if (stat != MR_NO_MATCH)
2185 {
2186 com_err(program_name, stat, " in AddContainer.");
2187 return DM_NORMAL;
2188 }
2189 if (!(args = AskMCDInfo(SetContainerDefaults(info, name), CONTAINER, FALSE)))
2190 {
2191 Put_message("Aborted.");
2192 FreeInfo(info);
2193 return DM_NORMAL;
2194 }
2195
2196 /* Create the new container. */
2197 if ((stat = do_mr_query("add_container", CountArgs(args), args, NULL, NULL)))
2198 com_err(program_name, stat, " in AddContainer.");
2199
2200 FreeInfo(info);
2201 return DM_NORMAL;
2202}
2203
2204int UpdateContainer(int argc, char **argv)
2205{
2206 struct mqelem *top;
2207 top = GetMCInfo(CONTAINER, argv[1], NULL);
2208 QueryLoop(top, NullPrint, RealUpdateContainer, "Update the container");
2209
2210 FreeQueue(top);
2211 return DM_NORMAL;
2212}
2213
2214static void RealUpdateContainer(char **info, Bool junk)
2215{
2216 int stat;
2217 char **args = AskMCDInfo(info, CONTAINER, TRUE);
2218
2219 if (!args)
2220 {
2221 Put_message("Aborted.");
2222 return;
2223 }
2224 if ((stat = do_mr_query("update_container", CountArgs(args), args,
2225 NULL, NULL)))
2226 com_err(program_name, stat, " in UpdateContainer.");
2227 else
2228 Put_message("Container successfully updated.");
2229}
2230
2231int DeleteContainer(int argc, char **argv)
2232{
2233 struct mqelem *top;
2234
2235 top = GetMCInfo(CONTAINER, argv[1], NULL);
2236 QueryLoop(top, PrintClusterInfo, RealDeleteContainer,
2237 "Delete the container");
2238
2239 FreeQueue(top);
2240 return DM_NORMAL;
2241}
2242
2243static void RealDeleteContainer(char **info, Bool one_container)
2244{
2245 int stat;
2246 char temp_buf[BUFSIZ];
2247
2248 sprintf(temp_buf,
2249 "Are you sure you want to delete the container %s (y/n) ?",
2250 info[CON_NAME]);
2251 if (!one_container || Confirm(temp_buf))
2252 {
2253 if (CheckAndRemoveMachinesFromContainer(info[CON_NAME], TRUE)
2254 != SUB_ERROR)
2255 {
2256 if ((stat = do_mr_query("delete_container", 1, &info[CON_NAME],
2257 NULL, NULL)))
2258 {
2259 com_err(program_name, stat, " in delete_container.");
2260 sprintf(temp_buf, "Container %s ** NOT ** deleted.",
2261 info[CON_NAME]);
2262 Put_message(temp_buf);
2263 }
2264 else
2265 {
2266 sprintf(temp_buf, "Container %s successfully deleted.",
2267 info[CON_NAME]);
2268 Put_message(temp_buf);
2269 }
2270 }
2271 }
2272}
2273
2274int CheckAndRemoveMachinesFromContainer(char *name, Bool ask_first)
2275{
2276 int stat, ret_value;
2277 Bool delete_it;
2278 char *args[10], temp_buf[BUFSIZ], *ptr;
2279 struct mqelem *top, *elem = NULL;
2280
2281 ret_value = SUB_NORMAL;
2282 args[0] = name;
2283 args[1] = "0";
2284 stat = do_mr_query("get_machines_of_container", 2, args, StoreInfo,
2285 &elem);
2286 if (stat && stat != MR_NO_MATCH)
2287 {
2288 com_err(program_name, stat, " in get_machines_of_container");
2289 return DM_NORMAL;
2290 }
2291 if (stat == MR_SUCCESS)
2292 {
2293 elem = top = QueueTop(elem);
2294 if (ask_first)
2295 {
2296 sprintf(temp_buf,
2297 "The container %s has the following machines in it:", name);
2298 Put_message(temp_buf);
2299 while (elem)
2300 {
2301 char **info = elem->q_data;
2302 Print(1, &info[0], (char *) NULL);
2303 elem = elem->q_forw;
2304 }
2305 ptr = "Remove ** ALL ** these machines from this container?";
2306
2307 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
2308 delete_it = TRUE;
2309 else
2310 {
2311 Put_message("Aborting...");
2312 FreeQueue(top);
2313 return SUB_ERROR;
2314 }
2315 }
2316 else
2317 delete_it = TRUE;
2318
2319 if (delete_it)
2320 {
2321 elem = top;
2322 while (elem)
2323 {
2324 char **info = elem->q_data;
2325 if ((stat = do_mr_query("delete_machine_from_container",
2326 2, info, NULL, NULL)))
2327 {
2328 ret_value = SUB_ERROR;
2329 com_err(program_name, stat,
2330 " in delete_machine_from_container.");
2331 sprintf(temp_buf,
2332 "Machine %s ** NOT ** removed from container %s.",
2333 info[0], info[1]);
2334 Put_message(temp_buf);
2335 }
2336 elem = elem->q_forw;
2337 }
2338 }
2339 }
2340 return ret_value;
2341}
2342
2343int GetSubContainers(int argc, char **argv)
2344{
2345 char *args[2];
2346 struct mqelem *elem = NULL, *top = NULL;
2347 int stat;
2348
2349 args[0] = argv[1];
2350
2351 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2352 args[1] = "1";
2353 else
2354 args[1] = "0";
2355
2356 if (stat = do_mr_query("get_subcontainers_of_container", 2, args,
2357 StoreInfo, &elem))
2358 com_err(program_name, stat, " in get_subcontainers_of_container");
2359
2360 top = QueueTop(elem);
2361 Loop(top, ((void (*)(char **)) PrintContainer));
2362 FreeQueue(top);
2363 return DM_NORMAL;
2364}
2365
2366int MachineToContainerMap(int argc, char **argv)
2367{
2368 struct mqelem *elem, *top;
2369 char *tmpname, temp_buf[256];
2370
2371 tmpname = canonicalize_hostname(strdup(argv[1]));
2372 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
2373 {
2374 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2375 argv[1], tmpname);
2376 Put_message(temp_buf);
2377 }
2378 top = elem = GetMCInfo(CONTMAP, tmpname, NULL);
2379
2380 Put_message("");
2381 while (elem)
2382 {
2383 char **info = elem->q_data;
2384 PrintMContMap(info);
2385 elem = elem->q_forw;
2386 }
2387
2388 FreeQueue(top);
2389 free(tmpname);
2390 return DM_NORMAL;
2391}
2392
2393int AddMachineToContainer(int argc, char **argv)
2394{
2395 int stat;
2396 char *machine, *container, temp_buf[BUFSIZ], *args[10];
2397 Bool add_it, one_machine, one_container;
2398 struct mqelem *melem, *mtop, *celem, *ctop;
2399
2400 machine = canonicalize_hostname(strdup(argv[1]));
2401 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
2402 {
2403 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2404 argv[1], machine);
2405 Put_message(temp_buf);
2406 }
2407 container = argv[2];
2408
2409 celem = ctop = GetMCInfo(CONTAINER, container, NULL);
2410 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
2411 free(machine);
2412
2413 one_machine = (QueueCount(mtop) == 1);
2414 one_container = (QueueCount(ctop) == 1);
2415
2416 while (melem)
2417 {
2418 char **minfo = melem->q_data;
2419 while (celem)
2420 {
2421 char **cinfo = celem->q_data;
2422 if (one_machine && one_container)
2423 add_it = TRUE;
2424 else
2425 {
2426 sprintf(temp_buf, "Add machine %s to container %s (y/n/q) ?",
2427 minfo[M_NAME], cinfo[CON_NAME]);
2428 switch (YesNoQuestion(temp_buf, FALSE))
2429 {
2430 case TRUE:
2431 add_it = TRUE;
2432 break;
2433 case FALSE:
2434 add_it = FALSE;
2435 break;
2436 default:
2437 Put_message("Aborting...");
2438 FreeQueue(ctop);
2439 FreeQueue(mtop);
2440 return DM_NORMAL;
2441 }
2442 }
2443 if (add_it)
2444 {
2445 args[0] = minfo[M_NAME];
2446 args[1] = cinfo[CON_NAME];
2447 stat = do_mr_query("add_machine_to_container", 2, args, NULL,
2448 NULL);
2449 switch (stat)
2450 {
2451 case MR_SUCCESS:
2452 break;
2453 case MR_EXISTS:
2454 sprintf(temp_buf, "%s is already in container %s",
2455 minfo[M_NAME], cinfo[CON_NAME]);
2456 Put_message(temp_buf);
2457 break;
2458 default:
2459 com_err(program_name, stat, " in AddMachineToContainer.");
2460 break;
2461 }
2462 }
2463 celem = celem->q_forw;
2464 }
2465 celem = ctop;
2466 melem = melem->q_forw;
2467 }
2468 FreeQueue(ctop);
2469 FreeQueue(mtop);
2470 return DM_NORMAL;
2471}
2472
2473int RemoveMachineFromContainer(int argc, char **argv)
2474{
2475 struct mqelem *elem = NULL;
2476 char buf[BUFSIZ], *args[10];
2477 int stat;
2478
2479 args[0] = canonicalize_hostname(strdup(argv[1]));
2480 if (strcasecmp(args[0], argv[1]) && *argv[1] != '"')
2481 {
2482 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
2483 argv[1], args[0]);
2484 Put_message(buf);
2485 }
2486 args[1] = argv[2];
2487 args[2] = NULL;
2488
2489 stat = do_mr_query("get_machine_to_container_map", 1, args, StoreInfo,
2490 &elem);
2491 if (stat == MR_NO_MATCH)
2492 {
2493 sprintf(buf, "The machine %s is not in the container %s.",
2494 args[0], args[1]);
2495 Put_message(buf);
2496 free(args[0]);
2497 return DM_NORMAL;
2498 }
2499 if (stat != MR_SUCCESS)
2500 com_err(program_name, stat, " in deleter_machine_from_container");
2501
2502 elem = QueueTop(elem);
2503 QueryLoop(elem, PrintMContMap, RealRemoveMachineFromContainer,
2504 "Remove this machine from this container");
2505
2506 FreeQueue(elem);
2507 free(args[0]);
2508 return DM_NORMAL;
2509}
2510
2511static void RealRemoveMachineFromContainer(char **info, Bool one_contmap)
2512{
2513 char temp_buf[BUFSIZ];
2514 int stat;
2515
2516 sprintf(temp_buf, "Remove %s from the container %s",
2517 info[0], info[1]);
2518 if (!one_contmap || Confirm(temp_buf))
2519 {
2520 if ((stat = do_mr_query("delete_machine_from_container", 2,
2521 info, NULL, NULL)))
2522 com_err(program_name, stat, " in delete_machine_from_container");
2523 else
2524 {
2525 sprintf(temp_buf, "%s has been removed from the container %s.",
2526 info[0], info[1]);
2527 Put_message(temp_buf);
2528 }
2529 }
2530 else
2531 Put_message("Machine not removed.");
2532}
2533
2534int GetMachinesOfContainer(int argc, char **argv)
2535{
2536 char *args[2];
2537 struct mqelem *elem = NULL, *top = NULL;
2538 int stat;
2539
2540 args[0] = argv[1];
2541
2542 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2543 args[1] = "1";
2544 else
2545 args[1] = "0";
2546
2547 if (stat = do_mr_query("get_machines_of_container", 2, args,
2548 StoreInfo, &elem))
2549 com_err(program_name, stat, " in get_machines_of_container");
2550
2551 top = QueueTop(elem);
2552 Loop(top, ((void (*)(char **)) PrintMContMap));
2553 FreeQueue(top);
2554 return DM_NORMAL;
2555}
86ad14f9 2556
2557int GetTopLevelCont(int argc, char **argv)
2558{
2559 int status;
2560 struct mqelem *elem = NULL;
2561 if (status = do_mr_query("get_toplevel_containers", 0, NULL, StoreInfo,
2562 &elem))
2563 {
2564 com_err(program_name, status, " in get_toplevel_containers");
2565 return DM_NORMAL;
2566 }
2567 Loop(QueueTop(elem), (void(*)(char **)) PrintContainer);
2568 FreeQueue(elem);
2569 return DM_NORMAL;
2570}
This page took 0.537978 seconds and 5 git commands to generate.