]> andersk Git - moira.git/commitdiff
finish writing program; use MList widget
authormar <mar>
Thu, 21 Oct 1993 15:02:27 +0000 (15:02 +0000)
committermar <mar>
Thu, 21 Oct 1993 15:02:27 +0000 (15:02 +0000)
clients/cluster/cluster.c

index ea7f1abbbc9d5772d7f2b3bc57938a939e6d5058..ee907c15f1f6698b5b5aae360f8fd0a9ba9cd66a 100644 (file)
@@ -1,13 +1,17 @@
 /* $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;
@@ -26,29 +30,99 @@ static XtResource my_resources[] = {
 
 #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
@@ -69,8 +143,9 @@ char* argv[];
     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);
@@ -103,12 +178,17 @@ char* argv[];
 
     /* 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();
 }
 
@@ -118,35 +198,712 @@ int argc;
 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;
@@ -174,17 +931,17 @@ caddr_t data;
 {
     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");
@@ -192,38 +949,169 @@ caddr_t data;
        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);
+}
This page took 0.223412 seconds and 5 git commands to generate.