/* $Header$ */
#include <stdio.h>
-#include <WcCreate.h>
+#include <Wc/WcCreate.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Text.h>
+#include <netdb.h>
+#include "MList.h"
#include <moira.h>
#include <moira_site.h>
+#include <strings.h>
extern void AriRegisterAthena();
+extern int errno;
typedef struct _ClusterResources {
char *server;
#undef Offset
-void getClusters(), getMachines(), localErrorHandler(), mr_x_input();
+char *substr();
+void localErrorHandler(), mr_x_input(), inputDone(), Help(), popup_error_hook();
+void getClusters(), getClusterMachine();
+void selectClusters(), selectClusterMachine(), selectClusterData();
+void deselectClusters(), clearClusters();
+void getMachines(), getMachineCluster();
+void selectMachines(), selectMachineCluster();
+void deselectMachines(), clearMachines(), getMachineTypes();
+void selectMachineType(), selectMachineSubnet(), getClusterServer();
+void addMachineCluster(), removeMachineCluster(), removeMachineAllCluster();
+void selectAllCluster(), selectAllMachine();
+void saveCluster(), saveMachine();
XtActionsRec actions[] = {
+ { "inputDone", inputDone },
+};
+
+XtActionsRec callbacks[] = {
+ { "HelpCB", Help },
{ "getClusters", getClusters },
+ { "getClusterMachine", getClusterMachine },
+ { "selectClusters", selectClusters },
+ { "selectClusterData", selectClusterData },
+ { "selectAllCluster", selectAllCluster },
+ { "selectClusterMachine", selectClusterMachine },
+ { "deselectClusters", deselectClusters },
+ { "clearClusters", clearClusters },
+ { "getClusterServer", getClusterServer },
{ "getMachines", getMachines },
+ { "getMachineCluster", getMachineCluster },
+ { "selectMachines", selectMachines },
+ { "selectAllMachine", selectAllMachine },
+ { "selectMachineCluster", selectMachineCluster },
+ { "deselectMachines", deselectMachines },
+ { "clearMachines", clearMachines },
+ { "getMachineTypes", getMachineTypes },
+ { "selectMachineType", selectMachineType },
+ { "selectMachineSubnet", selectMachineSubnet },
+ { "addMachineCluster", addMachineCluster },
+ { "removeMachineCluster", removeMachineCluster },
+ { "removeMachineAllCluster", removeMachineAllCluster },
+ { "saveCluster", saveCluster },
+ { "saveMachine", saveMachine },
};
-Widget appShell;
+char *moira_help = "Moira is the Athena configuration management system.";
+
+char *program_help =
+"This program allows you to manipulate machine/cluster mappings. To\n\
+create or delete machines or clusters, use one of the other moira\n\
+clients.\n\
+\n\
+You can fetch from the database clusters and machines, which will be\n\
+listed in the two scrolling windows. They may be fetched by name\n\
+(wildcards are allowed), machine<->cluster mappings, or fileservers\n\
+used.\n\
+\n\
+The machines and clusters you are going to change must be selected.\n\
+You can do this by mousing on them or using operations similar ton\n\
+those that fetched them from the database. Then you can use the\n\
+commands in the Mappings menu.";
+char *author_help = "Written by Mark Rosenstein <mar@MIT.EDU>, MIT Project Athena.";
+char *unknown_help = "Sorry, help is not available on that topic.";
+
+#define MACHLEN 32
+#define CLULEN 16
+
+typedef struct _mattr {
+ char type[9];
+ long addr;
+} mattr;
+
+Widget appShell, clist, mlist;
ClusterResources resources;
Display *dpy;
char *program_name;
-char *clusters[256], *machines[100];
+char *clusters[256], *machines[1000];
+mattr machattr[1000];
int nclusters = 0, nmachines = 0;
+int suppress_updates = 0;
+
void
main(argc, argv)
int argc;
char* argv[];
{
- int status;
+ int status, i;
char *motd;
XtAppContext app;
+/* setenv("XFILESEARCHPATH", "/afs/athena/system/moira/lib/%N", 1); */
+ setenv("XFILESEARCHPATH", "/afs/athena/astaff/project/moiradev/src/clients/cluster/%N", 1);
if ((program_name = rindex(argv[0], '/')) == NULL)
program_name = argv[0];
else
XtGetApplicationResources(appShell, (caddr_t) &resources,
my_resources, XtNumber(my_resources),
NULL, (Cardinal) 0);
- WcRegisterCallback(app, "getClusters", getClusters, NULL);
- /* Register all Athena widget classes */
+ for (i = 0; i < sizeof(callbacks)/sizeof(XtActionsRec); i++)
+ WcRegisterCallback(app, callbacks[i].string, callbacks[i].proc, NULL);
+ /* Register all Motif widget classes */
AriRegisterAthena(app);
status = mr_connect(resources.server);
/* Create widget tree below toplevel shell using Xrm database */
WcWidgetCreation(appShell);
+ clist = WcFullNameToWidget(appShell, "*clusterlist");
+ XawMListChange(clist, clusters, 0, 0, False);
+ mlist = WcFullNameToWidget(appShell, "*machinelist");
+ XawMListChange(mlist, machines, 0, 0, False);
/*
* Realize the widget tree, finish up initializing,
* and enter the main application loop
*/
XtRealizeWidget(appShell);
mr_set_alternate_input(ConnectionNumber(dpy), mr_x_input);
+ set_com_err_hook(popup_error_hook);
XtMainLoop();
}
char **argv;
struct save_queue *sq;
{
- sq_save_args(argc, argv, sq);
+ char **argv_copy;
+ int i, n;
+
+ argv_copy = (char **)malloc((argc + 1) * sizeof (char *));
+ for (i = 0; i < argc; i++)
+ argv_copy[i] = strsave(argv[i]);
+ argv_copy[i] = NULL;
+
+ sq_save_data(sq, (char *)argv_copy);
return(MR_CONT);
}
+
+void deselectClusters()
+{
+ XawMListReturnStruct *ret;
+ int count;
+
+ ret = XawMListShowCurrent(clist, &count);
+ for (count--; count >= 0; count--)
+ XawMListUnhighlight(clist, ret[count].list_index);
+ free(ret);
+}
+
+
+void clearClusters()
+{
+ nclusters = 0;
+ deselectClusters();
+ clusters[0] = NULL;
+ XawMListChange(clist, clusters, 0, 0, False);
+}
+
+
+void addCluster(clu)
+char *clu;
+{
+ XawMListReturnStruct *ret;
+ int count, i, j, new, status;
+ char *argv[3], **nargv, buf[BUFSIZ], buf1[BUFSIZ];
+ struct save_queue *sq;
+
+ /* Get cluster data and assemble line */
+ sq = sq_create();
+ argv[0] = clu;
+ argv[1] = "*";
+ status = MoiraQuery("get_cluster_data", 2, argv, collect, sq);
+ if (status)
+ com_err(program_name, status, " while fetching cluster data");
+ if (status == MR_SUCCESS) {
+ sq_get_data(sq, &nargv);
+ sprintf(buf, "%-16s %s %s", clu, nargv[1], nargv[2]);
+ free_argv(nargv);
+ while (sq_get_data(sq, &nargv)) {
+ sprintf(buf1, "%s; %s %s", buf, nargv[1], nargv[2]);
+ strcpy(buf, buf1);
+ free_argv(nargv);
+ }
+ } else
+ strcpy(buf, clu);
+ sq_destroy(sq);
+
+ /* find out where in sorted list new item will go */
+ for (new = 0; new < nclusters; new++) {
+ if ((i = strmcmp(clusters[new], clu)) > 0)
+ break;
+ if (i == 0) {
+ free(clusters[new]);
+ clusters[new] = strsave(buf);
+ return;
+ }
+ }
+
+ /* unselect everything in list */
+ ret = XawMListShowCurrent(clist, &count);
+ for (i = 0; i < count; i++)
+ XawMListUnhighlight(clist, ret[i].list_index);
+
+ /* insert new item */
+ for (i = nclusters; i > new; i--)
+ clusters[i + 1] = clusters[i];
+
+ clusters[new] = strsave(buf);
+ nclusters++;
+ if (suppress_updates)
+ suppress_updates++;
+ else
+ XawMListChange(clist, clusters, nclusters, 0, True);
+
+ /* re-highlight (possibly moved) items */
+ for (i = 0; i < count; i++)
+ for (j = 0; j < nclusters; j++)
+ if (!strmcmp(ret[i].string, clusters[j]))
+ XawMListHighlight(clist, j);
+ free(ret);
+}
+
+
+void selectCluster(clu)
+char *clu;
+{
+ int i;
+
+ addCluster(clu);
+ for (i = 0; i < nclusters; i++)
+ if (!strmcmp(clusters[i], clu)) {
+ XawMListHighlight(clist, i);
+ return;
+ }
+}
+
+
void getClusters()
{
- Arg args[2];
- char *clu, **argv;
+ char clu[64], **argv, *p;
+ struct save_queue *sq;
+ int status;
+
+ sq = sq_create();
+ PromptUser("Cluster name:", clu, sizeof(clu));
+ p = clu;
+ status = MoiraQuery("get_cluster", 1, &p, collect, sq);
+ if (status)
+ com_err(program_name, status, " while fetching clusters");
+
+ suppress_updates = 1;
+ while (sq_get_data(sq, &argv)) {
+ addCluster(strsave(argv[0]));
+ free_argv(argv);
+ }
+ sq_destroy(sq);
+ if (suppress_updates > 1)
+ XawMListChange(clist, clusters, nclusters, 0, True);
+ suppress_updates = 0;
+}
+
+void selectClusters()
+{
+ char clu[64], **argv, *p;
+ struct save_queue *sq;
+ int status;
+
+ sq = sq_create();
+ PromptUser("Cluster name:", clu, sizeof(clu));
+ p = clu;
+ status = MoiraQuery("get_cluster", 1, &p, collect, sq);
+ if (status)
+ com_err(program_name, status, " while fetching clusters");
+
+ suppress_updates = 1;
+ while (sq_get_data(sq, &argv)) {
+ selectCluster(strsave(argv[0]));
+ free_argv(argv);
+ }
+ sq_destroy(sq);
+ if (suppress_updates > 1)
+ XawMListChange(clist, clusters, nclusters, 0, True);
+ suppress_updates = 0;
+}
+
+void getClusterMachine()
+{
+ char mach[64], **argv, *qargv[2];
+ struct save_queue *sq;
+ int status;
+
+ sq = sq_create();
+ PromptUser("Machine name:", mach, sizeof(mach));
+ qargv[0] = canonicalize_hostname(strsave(mach));
+ qargv[1] = "*";
+ status = MoiraQuery("get_machine_to_cluster_map", 2, qargv, collect, sq);
+ if (status)
+ com_err(program_name, status, " while fetching clusters");
+ free(qargv[0]);
+
+ suppress_updates = 1;
+ while (sq_get_data(sq, &argv)) {
+ addCluster(strsave(argv[1]));
+ free_argv(argv);
+ }
+ sq_destroy(sq);
+ if (suppress_updates > 1)
+ XawMListChange(clist, clusters, nclusters, 0, True);
+ suppress_updates = 0;
+}
+
+
+void selectClusterMachine()
+{
+ char mach[64], **argv, *qargv[2];
struct save_queue *sq;
int status;
sq = sq_create();
- XtSetArg(args[0], XtNstring, &clu);
- XtGetValues(WcFullNameToWidget(appShell, "*clufilter"), args, 1);
- status = MoiraQuery("get_cluster", 1, &clu, collect, sq);
+ PromptUser("Machine name:", mach, sizeof(mach));
+ qargv[0] = canonicalize_hostname(strsave(mach));
+ qargv[1] = "*";
+ status = MoiraQuery("get_machine_to_cluster_map", 2, qargv, collect, sq);
if (status)
com_err(program_name, status, " while fetching clusters");
+ free(qargv[0]);
+
+ suppress_updates = 1;
while (sq_get_data(sq, &argv)) {
-/* add_to_widget("*clusterlist", argv[0]); */
- clusters[nclusters++] = argv[0];
+ selectCluster(strsave(argv[1]));
+ free_argv(argv);
+ }
+ sq_destroy(sq);
+ if (suppress_updates > 1)
+ XawMListChange(clist, clusters, nclusters, 0, True);
+ suppress_updates = 0;
+}
+
+
+void getClusterServer()
+{
+ char buf[64], *mach, **argv, *qargs[3];
+ struct save_queue *fsq, *cluq, *sq;
+ int status;
+
+ fsq = sq_create();
+ PromptUser("Server name:", buf, sizeof(buf));
+ mach = canonicalize_hostname(strsave(buf));
+ status = MoiraQuery("get_filesys_by_machine", 1, &mach, collect, fsq);
+ if (status) {
+ com_err(program_name, status, " while fetching filesystems");
+ return;
+ }
+ free(mach);
+ cluq = sq_create();
+ qargs[0] = "*";
+ qargs[1] = "syslib";
+ status = MoiraQuery("get_cluster_data", 2, qargs, collect, cluq);
+ if (status) {
+ com_err(program_name, status, " while fetching cluster data");
+ return;
+ }
+ suppress_updates = 1;
+ while (sq_get_data(cluq, &argv)) {
+ mach = index(argv[2], ' ');
+ if (mach) *mach = 0;
+ printf("Searching for filsys %s\n", argv[2]);
+ for (sq = fsq->q_next; sq != fsq; sq = sq->q_next)
+ if (!strcmp(argv[2], ((char **)sq->q_data)[0]))
+ addCluster(strsave(argv[0]));
+ free_argv(argv);
+ }
+ if (suppress_updates > 1)
+ XawMListChange(clist, clusters, nclusters, 0, True);
+ suppress_updates = 0;
+ while (sq_get_data(fsq, &argv)) {
+ printf("filsys %s\n", argv[0]);
+ free_argv(argv);
+ }
+ sq_destroy(fsq);
+ sq_destroy(cluq);
+}
+
+
+void selectClusterData()
+{
+ char buf[64];
+ int i;
+
+ PromptUser("Data:", buf, sizeof(buf));
+
+ for (i = 0; i < nclusters; i++)
+ if (substr(buf, &clusters[i][CLULEN]))
+ XawMListHighlight(clist, i);
+}
+
+void selectAllCluster()
+{
+ int i;
+
+ for (i = 0; i < nclusters; i++)
+ XawMListHighlight(clist, i);
+}
+
+
+void deselectMachines()
+{
+ XawMListReturnStruct *ret;
+ int count;
+
+ ret = XawMListShowCurrent(mlist, &count);
+ for (count--; count >= 0; count--)
+ XawMListUnhighlight(mlist, ret[count].list_index);
+ free(ret);
+}
+
+
+void clearMachines()
+{
+ nmachines = 0;
+ deselectMachines();
+ machines[0] = NULL;
+ XawMListChange(mlist, machines, 0, 0, False);
+}
+
+
+void addMachine(mach, type)
+char *mach, *type;
+{
+ XawMListReturnStruct *ret;
+ int count, i, j, new, addr;
+ char buf[BUFSIZ];
+ struct hostent *he;
+
+ he = gethostbyname(mach);
+ if (he)
+ addr = *(int *)he->h_addr_list[0];
+ else
+ addr = 0L;
+ sprintf(buf, "%-32s %-8s %s", mach, type, inet_ntoa(addr));
+
+ /* find out where in sorted list new item will go */
+ for (new = 0; new < nmachines; new++) {
+ if ((i = strmcmp(machines[new], mach)) > 0)
+ break;
+ if (i == 0) {
+ if (strlen(mach) > strlen(machines[new])) {
+ free(machines[new]);
+ machines[new] = strsave(buf);
+ strcpy(machattr[new].type, type);
+ machattr[new].addr = addr;
+ }
+ if (suppress_updates)
+ suppress_updates++;
+ else
+ XawMListChange(mlist, machines, nmachines, 0, True);
+ return;
+ }
+ }
+
+ /* unselect everything in list */
+ ret = XawMListShowCurrent(mlist, &count);
+ for (i = 0; i < count; i++)
+ XawMListUnhighlight(mlist, ret[i].list_index);
+
+ /* insert new item */
+ for (i = nmachines; i > new; i--) {
+ machines[i] = machines[i - 1];
+ machattr[i] = machattr[i - 1];
}
- XawListChange(WcFullNameToWidget(appShell, "*clusterlist"),
- clusters, nclusters, 0, False);
+
+ machines[new] = strsave(buf);
+ strcpy(machattr[new].type, type);
+ machattr[new].addr = addr;
+ nmachines++;
+ if (suppress_updates)
+ suppress_updates++;
+ else
+ XawMListChange(mlist, machines, nmachines, 0, True);
+
+ /* re-highlight (possibly moved) items */
+ for (i = 0; i < count; i++)
+ for (j = 0; j < nmachines; j++)
+ if (!strmcmp(ret[i].string, machines[j]))
+ XawMListHighlight(mlist, j);
+ free(ret);
+}
+
+
+void selectMachine(mach, type)
+char *mach, *type;
+{
+ int i;
+
+ addMachine(mach, type);
+ for (i = 0; i < nmachines; i++)
+ if (!strmcmp(machines[i], mach)) {
+ XawMListHighlight(mlist, i);
+ return;
+ }
}
void getMachines()
{
+ char *mach, **argv, buf[BUFSIZ];
+ struct save_queue *sq;
+ int status;
+
+ sq = sq_create();
+ PromptUser("Machine name:", buf, sizeof(buf));
+ mach = canonicalize_hostname(strsave(buf));
+ status = MoiraQuery("get_machine", 1, &mach, collect, sq);
+ if (status)
+ com_err(program_name, status, " while fetching machines");
+ free(mach);
+
+ suppress_updates = 1;
+ while (sq_get_data(sq, &argv)) {
+ addMachine(argv[0], argv[1]);
+ free_argv(argv);
+ }
+ sq_destroy(sq);
+ if (suppress_updates > 1)
+ XawMListChange(mlist, machines, nmachines, 0, True);
+ suppress_updates = 0;
}
+
+void selectMachines()
+{
+ char *mach, **argv, buf[BUFSIZ];
+ struct save_queue *sq;
+ int status;
+
+ sq = sq_create();
+ PromptUser("Machine name:", buf, sizeof(buf));
+ mach = canonicalize_hostname(strsave(buf));
+ status = MoiraQuery("get_machine", 1, &mach, collect, sq);
+ if (status)
+ com_err(program_name, status, " while fetching machines");
+ free(mach);
+
+ suppress_updates = 1;
+ while (sq_get_data(sq, &argv)) {
+ selectMachine(argv[0], argv[1]);
+ free_argv(argv);
+ }
+ sq_destroy(sq);
+ if (suppress_updates > 1)
+ XawMListChange(mlist, machines, nmachines, 0, True);
+ suppress_updates = 0;
+
+}
+
+
+void getMachineCluster()
+{
+ char **argv, **argv1, *qargv[2], buf[256];
+ struct save_queue *sq, *sq1;
+ int status;
+
+ sq = sq_create();
+ qargv[0] = "*";
+ PromptUser("Cluster name:", buf, sizeof(buf));
+ qargv[1] = buf;
+ status = MoiraQuery("get_machine_to_cluster_map", 2, qargv, collect, sq);
+ if (status)
+ com_err(program_name, status, " while fetching clusters");
+
+ suppress_updates = 1;
+ while (sq_get_data(sq, &argv)) {
+ addMachine(strsave(argv[0]), "");
+#ifdef MACHTYPE
+ sq1 = sq_create();
+ status = MoiraQuery("get_machine", 1, argv, collect, sq1);
+ if (status)
+ com_err(program_name, status, " while fetching machine type");
+ sq_get_data(sq1, &argv1);
+ addMachine(argv1[0], argv1[1]);
+ sq_destroy(sq1);
+ free_argv(argv1);
+#endif
+ free_argv(argv);
+ }
+ sq_destroy(sq);
+ if (suppress_updates > 1)
+ XawMListChange(mlist, machines, nmachines, 0, True);
+ suppress_updates = 0;
+}
+
+
+void selectMachineCluster()
+{
+ char **argv, **argv1, *qargv[2], buf[256];
+ struct save_queue *sq, *sq1;
+ int status;
+
+ sq = sq_create();
+ qargv[0] = "*";
+ PromptUser("Cluster name:", buf, sizeof(buf));
+ qargv[1] = buf;
+ status = MoiraQuery("get_machine_to_cluster_map", 2, qargv, collect, sq);
+ if (status)
+ com_err(program_name, status, " while fetching clusters");
+
+ suppress_updates = 1;
+ while (sq_get_data(sq, &argv)) {
+ selectMachine(strsave(argv[0]), "");
+#ifdef MACHTYPE
+ sq1 = sq_create();
+ status = MoiraQuery("get_machine", 1, argv, collect, sq1);
+ if (status)
+ com_err(program_name, status, " while fetching machine type");
+ sq_get_data(sq1, &argv1);
+ selectMachine(argv1[0], argv1[1]);
+ free_argv(argv1);
+ sq_destroy(sq1);
+#endif
+ free_argv(argv);
+ }
+ sq_destroy(sq);
+ if (suppress_updates > 1)
+ XawMListChange(mlist, machines, nmachines, 0, True);
+ suppress_updates = 0;
+}
+
+
+void getMachineTypes()
+{
+ char *mach, **argv, buf[256], *p;
+ int i, changed = 0, status, addr;
+ struct save_queue *sq;
+ struct hostent *he;
+ sq = sq_create();
+
+ for (i = 0; i < nmachines; i++) {
+ if (strlen(machattr[i].type) == 0) {
+ mach = machines[i];
+ p = index(mach, ' ');
+ if (p) *p = 0;
+ status = MoiraQuery("get_machine", 1, &mach, collect, sq);
+ if (status)
+ com_err(program_name, status, " while fetching machine type");
+ sq_get_data(sq, &argv);
+ strcpy(machattr[i].type, argv[1]);
+ he = gethostbyname(mach);
+ if (he)
+ addr = *(int *)he->h_addr_list[0];
+ else
+ addr = 0L;
+ sprintf(buf, "%-32s %-8s %s", mach, argv[1], inet_ntoa(addr));
+ machines[i] = strsave(buf);
+ machattr[i].addr = addr;
+ free_argv(argv);
+ changed++;
+ }
+ }
+ if (changed)
+ XawMListChange(mlist, machines, nmachines, 0, True);
+ sq_destroy(sq);
+}
+
+
+void selectMachineType()
+{
+ char type[16];
+ int i;
+
+ PromptUser("Machine type:", type, sizeof(type));
+ getMachineTypes();
+
+ for (i = 0; i < nmachines; i++)
+ if (!strcasecmp(type, machattr[i].type))
+ XawMListHighlight(mlist, i);
+}
+
+
+void selectMachineSubnet()
+{
+ char buf[BUFSIZ];
+ int i, subnet;
+ struct hostent *he;
+
+ PromptUser("Machine's subnet:", buf, sizeof(buf));
+ subnet = atoi(buf);
+
+ for (i = 0; i < nmachines; i++) {
+ /* Here we go hardcoding the subnet mask.... */
+ if (subnet == ((ntohl(machattr[i].addr) >> 16) & 0xff))
+ XawMListHighlight(mlist, i);
+ }
+}
+
+
+void selectAllMachine()
+{
+ int i;
+
+ for (i = 0; i < nmachines; i++)
+ XawMListHighlight(mlist, i);
+}
+
+
+void addMachineCluster()
+{
+ XawMListReturnStruct *machs, *clus;
+ int mcount, ccount, status, c, m;
+ char *argv[2], *p;
+
+ machs = XawMListShowCurrent(mlist, &mcount);
+ clus = XawMListShowCurrent(clist, &ccount);
+ for (c = 0; c < ccount; c++) {
+ for (m = 0; m < mcount; m++) {
+ argv[0] = strsave(machines[machs[m].list_index]);
+ p = index(argv[0], ' ');
+ if (p) *p = 0;
+ argv[1] = strsave(clusters[clus[c].list_index]);
+ p = index(argv[1], ' ');
+ if (p) *p = 0;
+ status = MoiraQuery("add_machine_to_cluster", 2, argv,
+ collect, NULL);
+ if (status)
+ com_err(program_name, status, " while adding machines to clusters");
+ free(argv[0]);
+ free(argv[1]);
+ }
+ }
+ free(machs);
+ free(clus);
+}
+
+
+void removeMachineCluster()
+{
+ XawMListReturnStruct *machs, *clus;
+ int mcount, ccount, status, c, m;
+ char *argv[2], *p;
+
+ machs = XawMListShowCurrent(mlist, &mcount);
+ clus = XawMListShowCurrent(clist, &ccount);
+ for (c = 0; c < ccount; c++) {
+ for (m = 0; m < mcount; m++) {
+ argv[0] = strsave(machs[m].string);
+ p = index(argv[0], ' ');
+ if (p) *p = 0;
+ argv[1] = strsave(clus[c].string);
+ p = index(argv[1], ' ');
+ if (p) *p = 0;
+ status = MoiraQuery("delete_machine_from_cluster", 2, argv,
+ collect, NULL);
+ if (status)
+ com_err(program_name, status, " while deleting machines from clusters");
+ free(argv[0]);
+ free(argv[1]);
+ }
+ }
+ free(machs);
+ free(clus);
+}
+
+
+void removeMachineAllCluster()
+{
+ XawMListReturnStruct *machs;
+ int mcount, ccount, status, c, m;
+ char *argv[2], *p, **args;
+ struct save_queue *sq;
+
+ machs = XawMListShowCurrent(mlist, &mcount);
+
+ for (m = 0; m < mcount; m++) {
+ sq = sq_create();
+ argv[0] = strsave(machs[m].string);
+ p = index(argv[0], ' ');
+ if (p) *p = 0;
+ argv[1] = "*";
+ status = MoiraQuery("get_machine_to_cluster_map", 2, argv,
+ collect, sq);
+ if (status)
+ com_err(program_name, status, " while getting cluster mapping");
+ free(argv[0]);
+
+ while (sq_get_data(sq, &args)) {
+ status = MoiraQuery("delete_machine_from_cluster", 2, args,
+ collect, NULL);
+ if (status)
+ com_err(program_name, status, " while deleting machines from clusters");
+ }
+ sq_destroy(sq);
+ }
+}
+
+
+void saveCluster()
+{
+ char buf[512];
+ FILE *out;
+ int i;
+
+ PromptUser("Filename:", buf, sizeof(buf));
+ out = fopen(buf, "w");
+ if (out == NULL) {
+ com_err(program_name, errno, " while opening output file \"%s\"", buf);
+ return;
+ }
+ for (i = 0; i < nclusters; i++)
+ fprintf(out, "%s\n", clusters[i]);
+ if (fclose(out))
+ com_err(program_name, errno, " while closing output file \"%s\"", buf);
+}
+
+
+void saveMachine()
+{
+ char buf[512];
+ FILE *out;
+ int i;
+
+ PromptUser("Filename:", buf, sizeof(buf));
+ out = fopen(buf, "w");
+ if (out == NULL) {
+ com_err(program_name, errno, " while opening output file \"%s\"", buf);
+ return;
+ }
+ for (i = 0; i < nmachines; i++)
+ fprintf(out, "%s\n", machines[i]);
+ if (fclose(out))
+ com_err(program_name, errno, " while closing output file \"%s\"", buf);
+}
+
+
/* Called from within the toolkit */
void localErrorHandler(s)
String s;
{
int status;
-/* MakeWatchCursor(toplevel); */
+ MakeWatchCursor(appShell);
status = mr_query(query, argc, argv, callback, data);
if (status != MR_ABORTED && status != MR_NOT_CONNECTED) {
-/* MakeNormalCursor(toplevel); */
+ MakeNormalCursor(appShell);
return(status);
}
status = mr_connect(resources.server);
if (status) {
com_err(program_name, status, " while re-connecting to server %s",
resources.server);
-/* MakeNormalCursor(toplevel); */
+ MakeNormalCursor(appShell);
return(MR_ABORTED);
}
status = mr_auth("mmoira");
com_err(program_name, status, " while re-authenticating to server %s",
resources.server);
mr_disconnect();
-/* MakeNormalCursor(toplevel); */
+ MakeNormalCursor(appShell);
return(MR_ABORTED);
}
status = mr_query(query, argc, argv, callback, data);
-/* MakeNormalCursor(toplevel); */
+ MakeNormalCursor(appShell);
return(status);
}
-add_to_widget(wn, s)
-char *wn;
-char *s;
+MakeWatchCursor(w) {}
+MakeNormalCursor(w) {}
+
+static input_done_flag = 0;
+
+void inputDone()
+{
+ input_done_flag = 1;
+}
+
+
+PromptUser(msg, buf, bufsiz)
+char *msg, *buf;
+int bufsiz;
{
XawTextBlock tb;
- int ret, i;
- XawTextPosition size;
- Widget w;
Arg args[2];
- char buf[512];
+ XEvent e;
+ char *data;
- sprintf(buf, "%s\n", s);
- w = WcFullNameToWidget(appShell, wn);
- if (w == NULL)
- com_err(program_name, 0, " unable to find widget \"%s\"", wn);
tb.firstPos = 0;
- tb.length = strlen(s);
- tb.ptr = buf;
+ tb.ptr = msg;
+ tb.length = 0;
tb.format = FMT8BIT;
- XtSetArg(args[0], XtNlength, &size);
- XtGetValues(w, args, 1);
- ret = XawTextReplace(w, size, size, &tb);
- if (ret != XawEditDone)
- fprintf(stderr, "Text Edit failed: %d\n", ret);
+
+ XtSetArg(args[0], XtNlabel, msg);
+ XtSetValues(WcFullNameToWidget(appShell, "*query*prompt"), args, 1);
+
+ XawTextReplace(WcFullNameToWidget(appShell, "*query*input"),
+ 0, 65536, &tb);
+
+ XtManageChild(WcFullNameToWidget(appShell, "*query"));
+ XRaiseWindow(dpy, XtWindow(WcFullNameToWidget(appShell, "*query")));
+
+ /* repeat main_loop here so we can check status & return */
+ input_done_flag = 0;
+ while (!input_done_flag) {
+ XtAppNextEvent(_XtDefaultAppContext(), &e);
+ XtDispatchEvent(&e);
+ }
+
+ XtSetArg(args[0], XtNstring, &data);
+ XtGetValues(WcFullNameToWidget(appShell, "*query*input"), args, 1);
+ strncpy(buf, data, bufsiz);
+
+ XtUnmanageChild(WcFullNameToWidget(appShell, "*query"));
}
+
+void Help(w, s, unused)
+Widget w;
+char *s;
+{
+ XawTextBlock tb;
+
+ if (!strcmp(s, "moira"))
+ tb.ptr = moira_help;
+ else if (!strcmp(s, "program"))
+ tb.ptr = program_help;
+ else if (!strcmp(s, "author"))
+ tb.ptr = author_help;
+ else tb.ptr = unknown_help;
+
+ tb.firstPos = 0;
+ tb.length = strlen(tb.ptr);
+ tb.format = FMT8BIT;
+
+ XawTextReplace(WcFullNameToWidget(appShell, "*msg"),
+ 0, 65536, &tb);
+
+ XtPopup(WcFullNameToWidget(appShell, "*help"), XtGrabNone);
+}
+
+
+free_argv(argv)
+char **argv;
+{
+ int i;
+
+ for (i = 0; argv[i]; i++)
+ free(argv[i]);
+ free(argv);
+}
+
+
+/* compare machine strings. This is a separate routine instead of strcmp()
+ * so that we can deal with the optional machine type after the space
+ * padding. Usage is just like strcmp().
+ */
+
+int strmcmp(s1, s2)
+char *s1, *s2;
+{
+ if ((*s1 == ' ' || *s1 == 0) &&
+ (*s2 == ' ' || *s2 == 0))
+ return(0);
+ if (*s1 == *s2)
+ return(strmcmp(s1+1, s2+1));
+ if (*s1 < *s2)
+ return(-1);
+ return(1);
+}
+
+
+/* search for a substring. Will scan string s looking for substring
+ * f contained within it. Will return a pointer to the start of the
+ * contained substring, or NULL if not found.
+ */
+
+char *substr(f, s)
+char *f, *s;
+{
+ char *p;
+
+ while (p = index(s, *f)) {
+ if (!strncmp(f, p, strlen(f)))
+ return(p);
+ s++;
+ }
+ return(NULL);
+}
+
+
+
+void popup_error_hook(who, code, fmt, arg1, arg2, arg3, arg4, arg5)
+char *who;
+long code;
+char *fmt;
+caddr_t arg1, arg2, arg3, arg4, arg5;
+{
+ char buf[BUFSIZ], *cp;
+ XawTextBlock tb;
+ XEvent e;
+
+ (void) strcpy(buf, who);
+ for (cp = buf; *cp; cp++);
+ *cp++ = ':';
+ *cp++ = ' ';
+ if (code) {
+ (void) strcpy(cp, error_message(code));
+ while (*cp)
+ cp++;
+ }
+ sprintf(cp, fmt, arg1, arg2, arg3, arg4, arg5);
+
+ tb.firstPos = 0;
+ tb.ptr = buf;
+ tb.length = strlen(tb.ptr);
+ tb.format = FMT8BIT;
+
+ XawTextReplace(WcFullNameToWidget(appShell, "*errmsg"),
+ 0, 65536, &tb);
+ XtCallActionProc(WcFullNameToWidget(appShell, "*errmsg"),
+ "form-paragraph", &e, NULL, 0);
+
+ XtPopup(WcFullNameToWidget(appShell, "*error"), XtGrabNone);
+}