]>
Commit | Line | Data |
---|---|---|
c9104dd4 | 1 | /* $Header$ */ |
2 | ||
3 | #include <stdio.h> | |
2ddfd00a | 4 | #include <Wc/WcCreate.h> |
c9104dd4 | 5 | #include <X11/StringDefs.h> |
6 | #include <X11/Xaw/Text.h> | |
2ddfd00a | 7 | #include <netdb.h> |
8 | #include "MList.h" | |
c9104dd4 | 9 | #include <moira.h> |
10 | #include <moira_site.h> | |
2ddfd00a | 11 | #include <strings.h> |
c9104dd4 | 12 | |
13 | extern void AriRegisterAthena(); | |
2ddfd00a | 14 | extern int errno; |
c9104dd4 | 15 | |
16 | typedef struct _ClusterResources { | |
17 | char *server; | |
18 | } ClusterResources; | |
19 | ||
20 | static XrmOptionDescRec options[] = { | |
21 | {"-server", "*moiraServer", XrmoptionSepArg, NULL}, | |
22 | }; | |
23 | ||
24 | #define Offset(field) (XtOffset(ClusterResources *, field)) | |
25 | ||
26 | static XtResource my_resources[] = { | |
27 | {"moiraServer", XtCString, XtRString, sizeof(String), | |
28 | Offset(server), XtRImmediate, "" }, | |
29 | }; | |
30 | ||
31 | #undef Offset | |
32 | ||
2ddfd00a | 33 | char *substr(); |
34 | void localErrorHandler(), mr_x_input(), inputDone(), Help(), popup_error_hook(); | |
35 | void getClusters(), getClusterMachine(); | |
36 | void selectClusters(), selectClusterMachine(), selectClusterData(); | |
37 | void deselectClusters(), clearClusters(); | |
38 | void getMachines(), getMachineCluster(); | |
39 | void selectMachines(), selectMachineCluster(); | |
40 | void deselectMachines(), clearMachines(), getMachineTypes(); | |
41 | void selectMachineType(), selectMachineSubnet(), getClusterServer(); | |
42 | void addMachineCluster(), removeMachineCluster(), removeMachineAllCluster(); | |
43 | void selectAllCluster(), selectAllMachine(); | |
44 | void saveCluster(), saveMachine(); | |
c9104dd4 | 45 | |
46 | XtActionsRec actions[] = { | |
2ddfd00a | 47 | { "inputDone", inputDone }, |
48 | }; | |
49 | ||
50 | XtActionsRec callbacks[] = { | |
51 | { "HelpCB", Help }, | |
c9104dd4 | 52 | { "getClusters", getClusters }, |
2ddfd00a | 53 | { "getClusterMachine", getClusterMachine }, |
54 | { "selectClusters", selectClusters }, | |
55 | { "selectClusterData", selectClusterData }, | |
56 | { "selectAllCluster", selectAllCluster }, | |
57 | { "selectClusterMachine", selectClusterMachine }, | |
58 | { "deselectClusters", deselectClusters }, | |
59 | { "clearClusters", clearClusters }, | |
60 | { "getClusterServer", getClusterServer }, | |
c9104dd4 | 61 | { "getMachines", getMachines }, |
2ddfd00a | 62 | { "getMachineCluster", getMachineCluster }, |
63 | { "selectMachines", selectMachines }, | |
64 | { "selectAllMachine", selectAllMachine }, | |
65 | { "selectMachineCluster", selectMachineCluster }, | |
66 | { "deselectMachines", deselectMachines }, | |
67 | { "clearMachines", clearMachines }, | |
68 | { "getMachineTypes", getMachineTypes }, | |
69 | { "selectMachineType", selectMachineType }, | |
70 | { "selectMachineSubnet", selectMachineSubnet }, | |
71 | { "addMachineCluster", addMachineCluster }, | |
72 | { "removeMachineCluster", removeMachineCluster }, | |
73 | { "removeMachineAllCluster", removeMachineAllCluster }, | |
74 | { "saveCluster", saveCluster }, | |
75 | { "saveMachine", saveMachine }, | |
c9104dd4 | 76 | }; |
77 | ||
2ddfd00a | 78 | char *moira_help = "Moira is the Athena configuration management system."; |
79 | ||
80 | char *program_help = | |
81 | "This program allows you to manipulate machine/cluster mappings. To\n\ | |
82 | create or delete machines or clusters, use one of the other moira\n\ | |
83 | clients.\n\ | |
84 | \n\ | |
85 | You can fetch from the database clusters and machines, which will be\n\ | |
86 | listed in the two scrolling windows. They may be fetched by name\n\ | |
87 | (wildcards are allowed), machine<->cluster mappings, or fileservers\n\ | |
88 | used.\n\ | |
89 | \n\ | |
90 | The machines and clusters you are going to change must be selected.\n\ | |
91 | You can do this by mousing on them or using operations similar ton\n\ | |
92 | those that fetched them from the database. Then you can use the\n\ | |
93 | commands in the Mappings menu."; | |
94 | char *author_help = "Written by Mark Rosenstein <mar@MIT.EDU>, MIT Project Athena."; | |
95 | char *unknown_help = "Sorry, help is not available on that topic."; | |
96 | ||
97 | #define MACHLEN 32 | |
98 | #define CLULEN 16 | |
99 | ||
100 | typedef struct _mattr { | |
101 | char type[9]; | |
102 | long addr; | |
103 | } mattr; | |
104 | ||
105 | Widget appShell, clist, mlist; | |
c9104dd4 | 106 | ClusterResources resources; |
107 | Display *dpy; | |
108 | char *program_name; | |
2ddfd00a | 109 | char *clusters[256], *machines[1000]; |
110 | mattr machattr[1000]; | |
c9104dd4 | 111 | int nclusters = 0, nmachines = 0; |
2ddfd00a | 112 | int suppress_updates = 0; |
113 | ||
c9104dd4 | 114 | |
115 | void | |
116 | main(argc, argv) | |
117 | int argc; | |
118 | char* argv[]; | |
119 | { | |
2ddfd00a | 120 | int status, i; |
c9104dd4 | 121 | char *motd; |
122 | XtAppContext app; | |
123 | ||
2ddfd00a | 124 | /* setenv("XFILESEARCHPATH", "/afs/athena/system/moira/lib/%N", 1); */ |
125 | setenv("XFILESEARCHPATH", "/afs/athena/astaff/project/moiradev/src/clients/cluster/%N", 1); | |
c9104dd4 | 126 | if ((program_name = rindex(argv[0], '/')) == NULL) |
127 | program_name = argv[0]; | |
128 | else | |
129 | program_name++; | |
130 | program_name = strsave(program_name); | |
131 | ||
132 | /* | |
133 | * Intialize Toolkit creating the application shell, and get | |
134 | * application resources. | |
135 | */ | |
136 | appShell = XtInitialize("cluster", "Cluster", | |
137 | options, XtNumber(options), | |
138 | &argc, argv); | |
139 | app = XtWidgetToApplicationContext(appShell); | |
140 | XtAppSetErrorHandler(app, localErrorHandler); | |
141 | dpy = XtDisplay(appShell); | |
142 | XtAppAddActions(app, actions, XtNumber(actions)); | |
143 | XtGetApplicationResources(appShell, (caddr_t) &resources, | |
144 | my_resources, XtNumber(my_resources), | |
145 | NULL, (Cardinal) 0); | |
2ddfd00a | 146 | for (i = 0; i < sizeof(callbacks)/sizeof(XtActionsRec); i++) |
147 | WcRegisterCallback(app, callbacks[i].string, callbacks[i].proc, NULL); | |
148 | /* Register all Motif widget classes */ | |
c9104dd4 | 149 | AriRegisterAthena(app); |
150 | ||
151 | status = mr_connect(resources.server); | |
152 | if (status) { | |
153 | com_err(program_name, status, " connecting to server"); | |
154 | exit(1); | |
155 | } | |
156 | ||
157 | status = mr_motd(&motd); | |
158 | if (status) { | |
159 | com_err(program_name, status, " connecting to server"); | |
160 | exit(1); | |
161 | } | |
162 | if (motd) { | |
163 | fprintf(stderr, "The Moira server is currently unavailable:\n%s\n", | |
164 | motd); | |
165 | mr_disconnect(); | |
166 | exit(1); | |
167 | } | |
168 | ||
169 | status = mr_auth("cluster"); | |
170 | if (status == MR_USER_AUTH) { | |
171 | char buf[BUFSIZ]; | |
172 | com_err(program_name, status, "\nPress [RETURN] to continue"); | |
173 | gets(buf); | |
174 | } else if (status) { | |
175 | com_err(program_name, status, "; authorization failed - may need to run kinit"); | |
176 | exit(1); | |
177 | } | |
178 | ||
179 | /* Create widget tree below toplevel shell using Xrm database */ | |
180 | WcWidgetCreation(appShell); | |
2ddfd00a | 181 | clist = WcFullNameToWidget(appShell, "*clusterlist"); |
182 | XawMListChange(clist, clusters, 0, 0, False); | |
183 | mlist = WcFullNameToWidget(appShell, "*machinelist"); | |
184 | XawMListChange(mlist, machines, 0, 0, False); | |
c9104dd4 | 185 | /* |
186 | * Realize the widget tree, finish up initializing, | |
187 | * and enter the main application loop | |
188 | */ | |
189 | XtRealizeWidget(appShell); | |
190 | mr_set_alternate_input(ConnectionNumber(dpy), mr_x_input); | |
2ddfd00a | 191 | set_com_err_hook(popup_error_hook); |
c9104dd4 | 192 | XtMainLoop(); |
193 | } | |
194 | ||
195 | ||
196 | int collect(argc, argv, sq) | |
197 | int argc; | |
198 | char **argv; | |
199 | struct save_queue *sq; | |
200 | { | |
2ddfd00a | 201 | char **argv_copy; |
202 | int i, n; | |
203 | ||
204 | argv_copy = (char **)malloc((argc + 1) * sizeof (char *)); | |
205 | for (i = 0; i < argc; i++) | |
206 | argv_copy[i] = strsave(argv[i]); | |
207 | argv_copy[i] = NULL; | |
208 | ||
209 | sq_save_data(sq, (char *)argv_copy); | |
c9104dd4 | 210 | return(MR_CONT); |
211 | } | |
212 | ||
2ddfd00a | 213 | |
214 | void deselectClusters() | |
215 | { | |
216 | XawMListReturnStruct *ret; | |
217 | int count; | |
218 | ||
219 | ret = XawMListShowCurrent(clist, &count); | |
220 | for (count--; count >= 0; count--) | |
221 | XawMListUnhighlight(clist, ret[count].list_index); | |
222 | free(ret); | |
223 | } | |
224 | ||
225 | ||
226 | void clearClusters() | |
227 | { | |
228 | nclusters = 0; | |
229 | deselectClusters(); | |
230 | clusters[0] = NULL; | |
231 | XawMListChange(clist, clusters, 0, 0, False); | |
232 | } | |
233 | ||
234 | ||
235 | void addCluster(clu) | |
236 | char *clu; | |
237 | { | |
238 | XawMListReturnStruct *ret; | |
239 | int count, i, j, new, status; | |
240 | char *argv[3], **nargv, buf[BUFSIZ], buf1[BUFSIZ]; | |
241 | struct save_queue *sq; | |
242 | ||
243 | /* Get cluster data and assemble line */ | |
244 | sq = sq_create(); | |
245 | argv[0] = clu; | |
246 | argv[1] = "*"; | |
247 | status = MoiraQuery("get_cluster_data", 2, argv, collect, sq); | |
248 | if (status) | |
249 | com_err(program_name, status, " while fetching cluster data"); | |
250 | if (status == MR_SUCCESS) { | |
251 | sq_get_data(sq, &nargv); | |
252 | sprintf(buf, "%-16s %s %s", clu, nargv[1], nargv[2]); | |
253 | free_argv(nargv); | |
254 | while (sq_get_data(sq, &nargv)) { | |
255 | sprintf(buf1, "%s; %s %s", buf, nargv[1], nargv[2]); | |
256 | strcpy(buf, buf1); | |
257 | free_argv(nargv); | |
258 | } | |
259 | } else | |
260 | strcpy(buf, clu); | |
261 | sq_destroy(sq); | |
262 | ||
263 | /* find out where in sorted list new item will go */ | |
264 | for (new = 0; new < nclusters; new++) { | |
265 | if ((i = strmcmp(clusters[new], clu)) > 0) | |
266 | break; | |
267 | if (i == 0) { | |
268 | free(clusters[new]); | |
269 | clusters[new] = strsave(buf); | |
270 | return; | |
271 | } | |
272 | } | |
273 | ||
274 | /* unselect everything in list */ | |
275 | ret = XawMListShowCurrent(clist, &count); | |
276 | for (i = 0; i < count; i++) | |
277 | XawMListUnhighlight(clist, ret[i].list_index); | |
278 | ||
279 | /* insert new item */ | |
280 | for (i = nclusters; i > new; i--) | |
281 | clusters[i + 1] = clusters[i]; | |
282 | ||
283 | clusters[new] = strsave(buf); | |
284 | nclusters++; | |
285 | if (suppress_updates) | |
286 | suppress_updates++; | |
287 | else | |
288 | XawMListChange(clist, clusters, nclusters, 0, True); | |
289 | ||
290 | /* re-highlight (possibly moved) items */ | |
291 | for (i = 0; i < count; i++) | |
292 | for (j = 0; j < nclusters; j++) | |
293 | if (!strmcmp(ret[i].string, clusters[j])) | |
294 | XawMListHighlight(clist, j); | |
295 | free(ret); | |
296 | } | |
297 | ||
298 | ||
299 | void selectCluster(clu) | |
300 | char *clu; | |
301 | { | |
302 | int i; | |
303 | ||
304 | addCluster(clu); | |
305 | for (i = 0; i < nclusters; i++) | |
306 | if (!strmcmp(clusters[i], clu)) { | |
307 | XawMListHighlight(clist, i); | |
308 | return; | |
309 | } | |
310 | } | |
311 | ||
312 | ||
c9104dd4 | 313 | void getClusters() |
314 | { | |
2ddfd00a | 315 | char clu[64], **argv, *p; |
316 | struct save_queue *sq; | |
317 | int status; | |
318 | ||
319 | sq = sq_create(); | |
320 | PromptUser("Cluster name:", clu, sizeof(clu)); | |
321 | p = clu; | |
322 | status = MoiraQuery("get_cluster", 1, &p, collect, sq); | |
323 | if (status) | |
324 | com_err(program_name, status, " while fetching clusters"); | |
325 | ||
326 | suppress_updates = 1; | |
327 | while (sq_get_data(sq, &argv)) { | |
328 | addCluster(strsave(argv[0])); | |
329 | free_argv(argv); | |
330 | } | |
331 | sq_destroy(sq); | |
332 | if (suppress_updates > 1) | |
333 | XawMListChange(clist, clusters, nclusters, 0, True); | |
334 | suppress_updates = 0; | |
335 | } | |
336 | ||
337 | void selectClusters() | |
338 | { | |
339 | char clu[64], **argv, *p; | |
340 | struct save_queue *sq; | |
341 | int status; | |
342 | ||
343 | sq = sq_create(); | |
344 | PromptUser("Cluster name:", clu, sizeof(clu)); | |
345 | p = clu; | |
346 | status = MoiraQuery("get_cluster", 1, &p, collect, sq); | |
347 | if (status) | |
348 | com_err(program_name, status, " while fetching clusters"); | |
349 | ||
350 | suppress_updates = 1; | |
351 | while (sq_get_data(sq, &argv)) { | |
352 | selectCluster(strsave(argv[0])); | |
353 | free_argv(argv); | |
354 | } | |
355 | sq_destroy(sq); | |
356 | if (suppress_updates > 1) | |
357 | XawMListChange(clist, clusters, nclusters, 0, True); | |
358 | suppress_updates = 0; | |
359 | } | |
360 | ||
361 | void getClusterMachine() | |
362 | { | |
363 | char mach[64], **argv, *qargv[2]; | |
364 | struct save_queue *sq; | |
365 | int status; | |
366 | ||
367 | sq = sq_create(); | |
368 | PromptUser("Machine name:", mach, sizeof(mach)); | |
369 | qargv[0] = canonicalize_hostname(strsave(mach)); | |
370 | qargv[1] = "*"; | |
371 | status = MoiraQuery("get_machine_to_cluster_map", 2, qargv, collect, sq); | |
372 | if (status) | |
373 | com_err(program_name, status, " while fetching clusters"); | |
374 | free(qargv[0]); | |
375 | ||
376 | suppress_updates = 1; | |
377 | while (sq_get_data(sq, &argv)) { | |
378 | addCluster(strsave(argv[1])); | |
379 | free_argv(argv); | |
380 | } | |
381 | sq_destroy(sq); | |
382 | if (suppress_updates > 1) | |
383 | XawMListChange(clist, clusters, nclusters, 0, True); | |
384 | suppress_updates = 0; | |
385 | } | |
386 | ||
387 | ||
388 | void selectClusterMachine() | |
389 | { | |
390 | char mach[64], **argv, *qargv[2]; | |
c9104dd4 | 391 | struct save_queue *sq; |
392 | int status; | |
393 | ||
394 | sq = sq_create(); | |
2ddfd00a | 395 | PromptUser("Machine name:", mach, sizeof(mach)); |
396 | qargv[0] = canonicalize_hostname(strsave(mach)); | |
397 | qargv[1] = "*"; | |
398 | status = MoiraQuery("get_machine_to_cluster_map", 2, qargv, collect, sq); | |
c9104dd4 | 399 | if (status) |
400 | com_err(program_name, status, " while fetching clusters"); | |
2ddfd00a | 401 | free(qargv[0]); |
402 | ||
403 | suppress_updates = 1; | |
c9104dd4 | 404 | while (sq_get_data(sq, &argv)) { |
2ddfd00a | 405 | selectCluster(strsave(argv[1])); |
406 | free_argv(argv); | |
407 | } | |
408 | sq_destroy(sq); | |
409 | if (suppress_updates > 1) | |
410 | XawMListChange(clist, clusters, nclusters, 0, True); | |
411 | suppress_updates = 0; | |
412 | } | |
413 | ||
414 | ||
415 | void getClusterServer() | |
416 | { | |
417 | char buf[64], *mach, **argv, *qargs[3]; | |
418 | struct save_queue *fsq, *cluq, *sq; | |
419 | int status; | |
420 | ||
421 | fsq = sq_create(); | |
422 | PromptUser("Server name:", buf, sizeof(buf)); | |
423 | mach = canonicalize_hostname(strsave(buf)); | |
424 | status = MoiraQuery("get_filesys_by_machine", 1, &mach, collect, fsq); | |
425 | if (status) { | |
426 | com_err(program_name, status, " while fetching filesystems"); | |
427 | return; | |
428 | } | |
429 | free(mach); | |
430 | cluq = sq_create(); | |
431 | qargs[0] = "*"; | |
432 | qargs[1] = "syslib"; | |
433 | status = MoiraQuery("get_cluster_data", 2, qargs, collect, cluq); | |
434 | if (status) { | |
435 | com_err(program_name, status, " while fetching cluster data"); | |
436 | return; | |
437 | } | |
438 | suppress_updates = 1; | |
439 | while (sq_get_data(cluq, &argv)) { | |
440 | mach = index(argv[2], ' '); | |
441 | if (mach) *mach = 0; | |
442 | printf("Searching for filsys %s\n", argv[2]); | |
443 | for (sq = fsq->q_next; sq != fsq; sq = sq->q_next) | |
444 | if (!strcmp(argv[2], ((char **)sq->q_data)[0])) | |
445 | addCluster(strsave(argv[0])); | |
446 | free_argv(argv); | |
447 | } | |
448 | if (suppress_updates > 1) | |
449 | XawMListChange(clist, clusters, nclusters, 0, True); | |
450 | suppress_updates = 0; | |
451 | while (sq_get_data(fsq, &argv)) { | |
452 | printf("filsys %s\n", argv[0]); | |
453 | free_argv(argv); | |
454 | } | |
455 | sq_destroy(fsq); | |
456 | sq_destroy(cluq); | |
457 | } | |
458 | ||
459 | ||
460 | void selectClusterData() | |
461 | { | |
462 | char buf[64]; | |
463 | int i; | |
464 | ||
465 | PromptUser("Data:", buf, sizeof(buf)); | |
466 | ||
467 | for (i = 0; i < nclusters; i++) | |
468 | if (substr(buf, &clusters[i][CLULEN])) | |
469 | XawMListHighlight(clist, i); | |
470 | } | |
471 | ||
472 | void selectAllCluster() | |
473 | { | |
474 | int i; | |
475 | ||
476 | for (i = 0; i < nclusters; i++) | |
477 | XawMListHighlight(clist, i); | |
478 | } | |
479 | ||
480 | ||
481 | void deselectMachines() | |
482 | { | |
483 | XawMListReturnStruct *ret; | |
484 | int count; | |
485 | ||
486 | ret = XawMListShowCurrent(mlist, &count); | |
487 | for (count--; count >= 0; count--) | |
488 | XawMListUnhighlight(mlist, ret[count].list_index); | |
489 | free(ret); | |
490 | } | |
491 | ||
492 | ||
493 | void clearMachines() | |
494 | { | |
495 | nmachines = 0; | |
496 | deselectMachines(); | |
497 | machines[0] = NULL; | |
498 | XawMListChange(mlist, machines, 0, 0, False); | |
499 | } | |
500 | ||
501 | ||
502 | void addMachine(mach, type) | |
503 | char *mach, *type; | |
504 | { | |
505 | XawMListReturnStruct *ret; | |
506 | int count, i, j, new, addr; | |
507 | char buf[BUFSIZ]; | |
508 | struct hostent *he; | |
509 | ||
510 | he = gethostbyname(mach); | |
511 | if (he) | |
512 | addr = *(int *)he->h_addr_list[0]; | |
513 | else | |
514 | addr = 0L; | |
515 | sprintf(buf, "%-32s %-8s %s", mach, type, inet_ntoa(addr)); | |
516 | ||
517 | /* find out where in sorted list new item will go */ | |
518 | for (new = 0; new < nmachines; new++) { | |
519 | if ((i = strmcmp(machines[new], mach)) > 0) | |
520 | break; | |
521 | if (i == 0) { | |
522 | if (strlen(mach) > strlen(machines[new])) { | |
523 | free(machines[new]); | |
524 | machines[new] = strsave(buf); | |
525 | strcpy(machattr[new].type, type); | |
526 | machattr[new].addr = addr; | |
527 | } | |
528 | if (suppress_updates) | |
529 | suppress_updates++; | |
530 | else | |
531 | XawMListChange(mlist, machines, nmachines, 0, True); | |
532 | return; | |
533 | } | |
534 | } | |
535 | ||
536 | /* unselect everything in list */ | |
537 | ret = XawMListShowCurrent(mlist, &count); | |
538 | for (i = 0; i < count; i++) | |
539 | XawMListUnhighlight(mlist, ret[i].list_index); | |
540 | ||
541 | /* insert new item */ | |
542 | for (i = nmachines; i > new; i--) { | |
543 | machines[i] = machines[i - 1]; | |
544 | machattr[i] = machattr[i - 1]; | |
c9104dd4 | 545 | } |
2ddfd00a | 546 | |
547 | machines[new] = strsave(buf); | |
548 | strcpy(machattr[new].type, type); | |
549 | machattr[new].addr = addr; | |
550 | nmachines++; | |
551 | if (suppress_updates) | |
552 | suppress_updates++; | |
553 | else | |
554 | XawMListChange(mlist, machines, nmachines, 0, True); | |
555 | ||
556 | /* re-highlight (possibly moved) items */ | |
557 | for (i = 0; i < count; i++) | |
558 | for (j = 0; j < nmachines; j++) | |
559 | if (!strmcmp(ret[i].string, machines[j])) | |
560 | XawMListHighlight(mlist, j); | |
561 | free(ret); | |
562 | } | |
563 | ||
564 | ||
565 | void selectMachine(mach, type) | |
566 | char *mach, *type; | |
567 | { | |
568 | int i; | |
569 | ||
570 | addMachine(mach, type); | |
571 | for (i = 0; i < nmachines; i++) | |
572 | if (!strmcmp(machines[i], mach)) { | |
573 | XawMListHighlight(mlist, i); | |
574 | return; | |
575 | } | |
c9104dd4 | 576 | } |
577 | ||
578 | void getMachines() | |
579 | { | |
2ddfd00a | 580 | char *mach, **argv, buf[BUFSIZ]; |
581 | struct save_queue *sq; | |
582 | int status; | |
583 | ||
584 | sq = sq_create(); | |
585 | PromptUser("Machine name:", buf, sizeof(buf)); | |
586 | mach = canonicalize_hostname(strsave(buf)); | |
587 | status = MoiraQuery("get_machine", 1, &mach, collect, sq); | |
588 | if (status) | |
589 | com_err(program_name, status, " while fetching machines"); | |
590 | free(mach); | |
591 | ||
592 | suppress_updates = 1; | |
593 | while (sq_get_data(sq, &argv)) { | |
594 | addMachine(argv[0], argv[1]); | |
595 | free_argv(argv); | |
596 | } | |
597 | sq_destroy(sq); | |
598 | if (suppress_updates > 1) | |
599 | XawMListChange(mlist, machines, nmachines, 0, True); | |
600 | suppress_updates = 0; | |
c9104dd4 | 601 | } |
602 | ||
2ddfd00a | 603 | |
604 | void selectMachines() | |
605 | { | |
606 | char *mach, **argv, buf[BUFSIZ]; | |
607 | struct save_queue *sq; | |
608 | int status; | |
609 | ||
610 | sq = sq_create(); | |
611 | PromptUser("Machine name:", buf, sizeof(buf)); | |
612 | mach = canonicalize_hostname(strsave(buf)); | |
613 | status = MoiraQuery("get_machine", 1, &mach, collect, sq); | |
614 | if (status) | |
615 | com_err(program_name, status, " while fetching machines"); | |
616 | free(mach); | |
617 | ||
618 | suppress_updates = 1; | |
619 | while (sq_get_data(sq, &argv)) { | |
620 | selectMachine(argv[0], argv[1]); | |
621 | free_argv(argv); | |
622 | } | |
623 | sq_destroy(sq); | |
624 | if (suppress_updates > 1) | |
625 | XawMListChange(mlist, machines, nmachines, 0, True); | |
626 | suppress_updates = 0; | |
627 | ||
628 | } | |
629 | ||
630 | ||
631 | void getMachineCluster() | |
632 | { | |
633 | char **argv, **argv1, *qargv[2], buf[256]; | |
634 | struct save_queue *sq, *sq1; | |
635 | int status; | |
636 | ||
637 | sq = sq_create(); | |
638 | qargv[0] = "*"; | |
639 | PromptUser("Cluster name:", buf, sizeof(buf)); | |
640 | qargv[1] = buf; | |
641 | status = MoiraQuery("get_machine_to_cluster_map", 2, qargv, collect, sq); | |
642 | if (status) | |
643 | com_err(program_name, status, " while fetching clusters"); | |
644 | ||
645 | suppress_updates = 1; | |
646 | while (sq_get_data(sq, &argv)) { | |
647 | addMachine(strsave(argv[0]), ""); | |
648 | #ifdef MACHTYPE | |
649 | sq1 = sq_create(); | |
650 | status = MoiraQuery("get_machine", 1, argv, collect, sq1); | |
651 | if (status) | |
652 | com_err(program_name, status, " while fetching machine type"); | |
653 | sq_get_data(sq1, &argv1); | |
654 | addMachine(argv1[0], argv1[1]); | |
655 | sq_destroy(sq1); | |
656 | free_argv(argv1); | |
657 | #endif | |
658 | free_argv(argv); | |
659 | } | |
660 | sq_destroy(sq); | |
661 | if (suppress_updates > 1) | |
662 | XawMListChange(mlist, machines, nmachines, 0, True); | |
663 | suppress_updates = 0; | |
664 | } | |
665 | ||
666 | ||
667 | void selectMachineCluster() | |
668 | { | |
669 | char **argv, **argv1, *qargv[2], buf[256]; | |
670 | struct save_queue *sq, *sq1; | |
671 | int status; | |
672 | ||
673 | sq = sq_create(); | |
674 | qargv[0] = "*"; | |
675 | PromptUser("Cluster name:", buf, sizeof(buf)); | |
676 | qargv[1] = buf; | |
677 | status = MoiraQuery("get_machine_to_cluster_map", 2, qargv, collect, sq); | |
678 | if (status) | |
679 | com_err(program_name, status, " while fetching clusters"); | |
680 | ||
681 | suppress_updates = 1; | |
682 | while (sq_get_data(sq, &argv)) { | |
683 | selectMachine(strsave(argv[0]), ""); | |
684 | #ifdef MACHTYPE | |
685 | sq1 = sq_create(); | |
686 | status = MoiraQuery("get_machine", 1, argv, collect, sq1); | |
687 | if (status) | |
688 | com_err(program_name, status, " while fetching machine type"); | |
689 | sq_get_data(sq1, &argv1); | |
690 | selectMachine(argv1[0], argv1[1]); | |
691 | free_argv(argv1); | |
692 | sq_destroy(sq1); | |
693 | #endif | |
694 | free_argv(argv); | |
695 | } | |
696 | sq_destroy(sq); | |
697 | if (suppress_updates > 1) | |
698 | XawMListChange(mlist, machines, nmachines, 0, True); | |
699 | suppress_updates = 0; | |
700 | } | |
701 | ||
702 | ||
703 | void getMachineTypes() | |
704 | { | |
705 | char *mach, **argv, buf[256], *p; | |
706 | int i, changed = 0, status, addr; | |
707 | struct save_queue *sq; | |
708 | struct hostent *he; | |
709 | sq = sq_create(); | |
710 | ||
711 | for (i = 0; i < nmachines; i++) { | |
712 | if (strlen(machattr[i].type) == 0) { | |
713 | mach = machines[i]; | |
714 | p = index(mach, ' '); | |
715 | if (p) *p = 0; | |
716 | status = MoiraQuery("get_machine", 1, &mach, collect, sq); | |
717 | if (status) | |
718 | com_err(program_name, status, " while fetching machine type"); | |
719 | sq_get_data(sq, &argv); | |
720 | strcpy(machattr[i].type, argv[1]); | |
721 | he = gethostbyname(mach); | |
722 | if (he) | |
723 | addr = *(int *)he->h_addr_list[0]; | |
724 | else | |
725 | addr = 0L; | |
726 | sprintf(buf, "%-32s %-8s %s", mach, argv[1], inet_ntoa(addr)); | |
727 | machines[i] = strsave(buf); | |
728 | machattr[i].addr = addr; | |
729 | free_argv(argv); | |
730 | changed++; | |
731 | } | |
732 | } | |
733 | if (changed) | |
734 | XawMListChange(mlist, machines, nmachines, 0, True); | |
735 | sq_destroy(sq); | |
736 | } | |
737 | ||
738 | ||
739 | void selectMachineType() | |
740 | { | |
741 | char type[16]; | |
742 | int i; | |
743 | ||
744 | PromptUser("Machine type:", type, sizeof(type)); | |
745 | getMachineTypes(); | |
746 | ||
747 | for (i = 0; i < nmachines; i++) | |
748 | if (!strcasecmp(type, machattr[i].type)) | |
749 | XawMListHighlight(mlist, i); | |
750 | } | |
751 | ||
752 | ||
753 | void selectMachineSubnet() | |
754 | { | |
755 | char buf[BUFSIZ]; | |
756 | int i, subnet; | |
757 | struct hostent *he; | |
758 | ||
759 | PromptUser("Machine's subnet:", buf, sizeof(buf)); | |
760 | subnet = atoi(buf); | |
761 | ||
762 | for (i = 0; i < nmachines; i++) { | |
763 | /* Here we go hardcoding the subnet mask.... */ | |
764 | if (subnet == ((ntohl(machattr[i].addr) >> 16) & 0xff)) | |
765 | XawMListHighlight(mlist, i); | |
766 | } | |
767 | } | |
768 | ||
769 | ||
770 | void selectAllMachine() | |
771 | { | |
772 | int i; | |
773 | ||
774 | for (i = 0; i < nmachines; i++) | |
775 | XawMListHighlight(mlist, i); | |
776 | } | |
777 | ||
778 | ||
779 | void addMachineCluster() | |
780 | { | |
781 | XawMListReturnStruct *machs, *clus; | |
782 | int mcount, ccount, status, c, m; | |
783 | char *argv[2], *p; | |
784 | ||
785 | machs = XawMListShowCurrent(mlist, &mcount); | |
786 | clus = XawMListShowCurrent(clist, &ccount); | |
787 | for (c = 0; c < ccount; c++) { | |
788 | for (m = 0; m < mcount; m++) { | |
789 | argv[0] = strsave(machines[machs[m].list_index]); | |
790 | p = index(argv[0], ' '); | |
791 | if (p) *p = 0; | |
792 | argv[1] = strsave(clusters[clus[c].list_index]); | |
793 | p = index(argv[1], ' '); | |
794 | if (p) *p = 0; | |
795 | status = MoiraQuery("add_machine_to_cluster", 2, argv, | |
796 | collect, NULL); | |
797 | if (status) | |
798 | com_err(program_name, status, " while adding machines to clusters"); | |
799 | free(argv[0]); | |
800 | free(argv[1]); | |
801 | } | |
802 | } | |
803 | free(machs); | |
804 | free(clus); | |
805 | } | |
806 | ||
807 | ||
808 | void removeMachineCluster() | |
809 | { | |
810 | XawMListReturnStruct *machs, *clus; | |
811 | int mcount, ccount, status, c, m; | |
812 | char *argv[2], *p; | |
813 | ||
814 | machs = XawMListShowCurrent(mlist, &mcount); | |
815 | clus = XawMListShowCurrent(clist, &ccount); | |
816 | for (c = 0; c < ccount; c++) { | |
817 | for (m = 0; m < mcount; m++) { | |
818 | argv[0] = strsave(machs[m].string); | |
819 | p = index(argv[0], ' '); | |
820 | if (p) *p = 0; | |
821 | argv[1] = strsave(clus[c].string); | |
822 | p = index(argv[1], ' '); | |
823 | if (p) *p = 0; | |
824 | status = MoiraQuery("delete_machine_from_cluster", 2, argv, | |
825 | collect, NULL); | |
826 | if (status) | |
827 | com_err(program_name, status, " while deleting machines from clusters"); | |
828 | free(argv[0]); | |
829 | free(argv[1]); | |
830 | } | |
831 | } | |
832 | free(machs); | |
833 | free(clus); | |
834 | } | |
835 | ||
836 | ||
837 | void removeMachineAllCluster() | |
838 | { | |
839 | XawMListReturnStruct *machs; | |
840 | int mcount, ccount, status, c, m; | |
841 | char *argv[2], *p, **args; | |
842 | struct save_queue *sq; | |
843 | ||
844 | machs = XawMListShowCurrent(mlist, &mcount); | |
845 | ||
846 | for (m = 0; m < mcount; m++) { | |
847 | sq = sq_create(); | |
848 | argv[0] = strsave(machs[m].string); | |
849 | p = index(argv[0], ' '); | |
850 | if (p) *p = 0; | |
851 | argv[1] = "*"; | |
852 | status = MoiraQuery("get_machine_to_cluster_map", 2, argv, | |
853 | collect, sq); | |
854 | if (status) | |
855 | com_err(program_name, status, " while getting cluster mapping"); | |
856 | free(argv[0]); | |
857 | ||
858 | while (sq_get_data(sq, &args)) { | |
859 | status = MoiraQuery("delete_machine_from_cluster", 2, args, | |
860 | collect, NULL); | |
861 | if (status) | |
862 | com_err(program_name, status, " while deleting machines from clusters"); | |
863 | } | |
864 | sq_destroy(sq); | |
865 | } | |
866 | } | |
867 | ||
868 | ||
869 | void saveCluster() | |
870 | { | |
871 | char buf[512]; | |
872 | FILE *out; | |
873 | int i; | |
874 | ||
875 | PromptUser("Filename:", buf, sizeof(buf)); | |
876 | out = fopen(buf, "w"); | |
877 | if (out == NULL) { | |
878 | com_err(program_name, errno, " while opening output file \"%s\"", buf); | |
879 | return; | |
880 | } | |
881 | for (i = 0; i < nclusters; i++) | |
882 | fprintf(out, "%s\n", clusters[i]); | |
883 | if (fclose(out)) | |
884 | com_err(program_name, errno, " while closing output file \"%s\"", buf); | |
885 | } | |
886 | ||
887 | ||
888 | void saveMachine() | |
889 | { | |
890 | char buf[512]; | |
891 | FILE *out; | |
892 | int i; | |
893 | ||
894 | PromptUser("Filename:", buf, sizeof(buf)); | |
895 | out = fopen(buf, "w"); | |
896 | if (out == NULL) { | |
897 | com_err(program_name, errno, " while opening output file \"%s\"", buf); | |
898 | return; | |
899 | } | |
900 | for (i = 0; i < nmachines; i++) | |
901 | fprintf(out, "%s\n", machines[i]); | |
902 | if (fclose(out)) | |
903 | com_err(program_name, errno, " while closing output file \"%s\"", buf); | |
904 | } | |
905 | ||
906 | ||
c9104dd4 | 907 | /* Called from within the toolkit */ |
908 | void localErrorHandler(s) | |
909 | String s; | |
910 | { | |
911 | fprintf(stderr, "Moira X error: %s\n", s); | |
912 | exit(1); | |
913 | } | |
914 | ||
915 | ||
916 | void mr_x_input() | |
917 | { | |
918 | XEvent event; | |
919 | ||
920 | XtAppNextEvent(_XtDefaultAppContext(), &event); | |
921 | XtDispatchEvent(&event); | |
922 | } | |
923 | ||
924 | ||
925 | int MoiraQuery(query, argc, argv, callback, data) | |
926 | char *query; | |
927 | int argc; | |
928 | char **argv; | |
929 | int (*callback)(); | |
930 | caddr_t data; | |
931 | { | |
932 | int status; | |
933 | ||
2ddfd00a | 934 | MakeWatchCursor(appShell); |
c9104dd4 | 935 | status = mr_query(query, argc, argv, callback, data); |
936 | if (status != MR_ABORTED && status != MR_NOT_CONNECTED) { | |
2ddfd00a | 937 | MakeNormalCursor(appShell); |
c9104dd4 | 938 | return(status); |
939 | } | |
940 | status = mr_connect(resources.server); | |
941 | if (status) { | |
942 | com_err(program_name, status, " while re-connecting to server %s", | |
943 | resources.server); | |
2ddfd00a | 944 | MakeNormalCursor(appShell); |
c9104dd4 | 945 | return(MR_ABORTED); |
946 | } | |
947 | status = mr_auth("mmoira"); | |
948 | if (status) { | |
949 | com_err(program_name, status, " while re-authenticating to server %s", | |
950 | resources.server); | |
951 | mr_disconnect(); | |
2ddfd00a | 952 | MakeNormalCursor(appShell); |
c9104dd4 | 953 | return(MR_ABORTED); |
954 | } | |
955 | status = mr_query(query, argc, argv, callback, data); | |
2ddfd00a | 956 | MakeNormalCursor(appShell); |
c9104dd4 | 957 | return(status); |
958 | } | |
959 | ||
960 | ||
2ddfd00a | 961 | MakeWatchCursor(w) {} |
962 | MakeNormalCursor(w) {} | |
963 | ||
964 | static input_done_flag = 0; | |
965 | ||
966 | void inputDone() | |
967 | { | |
968 | input_done_flag = 1; | |
969 | } | |
970 | ||
971 | ||
972 | PromptUser(msg, buf, bufsiz) | |
973 | char *msg, *buf; | |
974 | int bufsiz; | |
c9104dd4 | 975 | { |
976 | XawTextBlock tb; | |
c9104dd4 | 977 | Arg args[2]; |
2ddfd00a | 978 | XEvent e; |
979 | char *data; | |
c9104dd4 | 980 | |
c9104dd4 | 981 | tb.firstPos = 0; |
2ddfd00a | 982 | tb.ptr = msg; |
983 | tb.length = 0; | |
c9104dd4 | 984 | tb.format = FMT8BIT; |
2ddfd00a | 985 | |
986 | XtSetArg(args[0], XtNlabel, msg); | |
987 | XtSetValues(WcFullNameToWidget(appShell, "*query*prompt"), args, 1); | |
988 | ||
989 | XawTextReplace(WcFullNameToWidget(appShell, "*query*input"), | |
990 | 0, 65536, &tb); | |
991 | ||
992 | XtManageChild(WcFullNameToWidget(appShell, "*query")); | |
993 | XRaiseWindow(dpy, XtWindow(WcFullNameToWidget(appShell, "*query"))); | |
994 | ||
995 | /* repeat main_loop here so we can check status & return */ | |
996 | input_done_flag = 0; | |
997 | while (!input_done_flag) { | |
998 | XtAppNextEvent(_XtDefaultAppContext(), &e); | |
999 | XtDispatchEvent(&e); | |
1000 | } | |
1001 | ||
1002 | XtSetArg(args[0], XtNstring, &data); | |
1003 | XtGetValues(WcFullNameToWidget(appShell, "*query*input"), args, 1); | |
1004 | strncpy(buf, data, bufsiz); | |
1005 | ||
1006 | XtUnmanageChild(WcFullNameToWidget(appShell, "*query")); | |
c9104dd4 | 1007 | } |
1008 | ||
2ddfd00a | 1009 | |
1010 | void Help(w, s, unused) | |
1011 | Widget w; | |
1012 | char *s; | |
1013 | { | |
1014 | XawTextBlock tb; | |
1015 | ||
1016 | if (!strcmp(s, "moira")) | |
1017 | tb.ptr = moira_help; | |
1018 | else if (!strcmp(s, "program")) | |
1019 | tb.ptr = program_help; | |
1020 | else if (!strcmp(s, "author")) | |
1021 | tb.ptr = author_help; | |
1022 | else tb.ptr = unknown_help; | |
1023 | ||
1024 | tb.firstPos = 0; | |
1025 | tb.length = strlen(tb.ptr); | |
1026 | tb.format = FMT8BIT; | |
1027 | ||
1028 | XawTextReplace(WcFullNameToWidget(appShell, "*msg"), | |
1029 | 0, 65536, &tb); | |
1030 | ||
1031 | XtPopup(WcFullNameToWidget(appShell, "*help"), XtGrabNone); | |
1032 | } | |
1033 | ||
1034 | ||
1035 | free_argv(argv) | |
1036 | char **argv; | |
1037 | { | |
1038 | int i; | |
1039 | ||
1040 | for (i = 0; argv[i]; i++) | |
1041 | free(argv[i]); | |
1042 | free(argv); | |
1043 | } | |
1044 | ||
1045 | ||
1046 | /* compare machine strings. This is a separate routine instead of strcmp() | |
1047 | * so that we can deal with the optional machine type after the space | |
1048 | * padding. Usage is just like strcmp(). | |
1049 | */ | |
1050 | ||
1051 | int strmcmp(s1, s2) | |
1052 | char *s1, *s2; | |
1053 | { | |
1054 | if ((*s1 == ' ' || *s1 == 0) && | |
1055 | (*s2 == ' ' || *s2 == 0)) | |
1056 | return(0); | |
1057 | if (*s1 == *s2) | |
1058 | return(strmcmp(s1+1, s2+1)); | |
1059 | if (*s1 < *s2) | |
1060 | return(-1); | |
1061 | return(1); | |
1062 | } | |
1063 | ||
1064 | ||
1065 | /* search for a substring. Will scan string s looking for substring | |
1066 | * f contained within it. Will return a pointer to the start of the | |
1067 | * contained substring, or NULL if not found. | |
1068 | */ | |
1069 | ||
1070 | char *substr(f, s) | |
1071 | char *f, *s; | |
1072 | { | |
1073 | char *p; | |
1074 | ||
1075 | while (p = index(s, *f)) { | |
1076 | if (!strncmp(f, p, strlen(f))) | |
1077 | return(p); | |
1078 | s++; | |
1079 | } | |
1080 | return(NULL); | |
1081 | } | |
1082 | ||
1083 | ||
1084 | ||
1085 | void popup_error_hook(who, code, fmt, arg1, arg2, arg3, arg4, arg5) | |
1086 | char *who; | |
1087 | long code; | |
1088 | char *fmt; | |
1089 | caddr_t arg1, arg2, arg3, arg4, arg5; | |
1090 | { | |
1091 | char buf[BUFSIZ], *cp; | |
1092 | XawTextBlock tb; | |
1093 | XEvent e; | |
1094 | ||
1095 | (void) strcpy(buf, who); | |
1096 | for (cp = buf; *cp; cp++); | |
1097 | *cp++ = ':'; | |
1098 | *cp++ = ' '; | |
1099 | if (code) { | |
1100 | (void) strcpy(cp, error_message(code)); | |
1101 | while (*cp) | |
1102 | cp++; | |
1103 | } | |
1104 | sprintf(cp, fmt, arg1, arg2, arg3, arg4, arg5); | |
1105 | ||
1106 | tb.firstPos = 0; | |
1107 | tb.ptr = buf; | |
1108 | tb.length = strlen(tb.ptr); | |
1109 | tb.format = FMT8BIT; | |
1110 | ||
1111 | XawTextReplace(WcFullNameToWidget(appShell, "*errmsg"), | |
1112 | 0, 65536, &tb); | |
1113 | XtCallActionProc(WcFullNameToWidget(appShell, "*errmsg"), | |
1114 | "form-paragraph", &e, NULL, 0); | |
1115 | ||
1116 | XtPopup(WcFullNameToWidget(appShell, "*error"), XtGrabNone); | |
1117 | } |