source: trunk/athena/bin/dash/dash.c @ 16488

Revision 16488, 41.9 KB checked in by ghudson, 23 years ago (diff)
Add function to reenable gnome.
Line 
1/*
2 * $Id: dash.c,v 1.4 2001-08-01 13:43:20 ghudson Exp $
3 *
4 * Copyright 1990, 1991 by the Massachusetts Institute of Technology.
5 *
6 * For copying and distribution information, please see the file
7 * <mit-copyright.h>.
8 *
9 */
10
11#if  (!defined(lint))  &&  (!defined(SABER))
12static char *rcsid =
13"$Id: dash.c,v 1.4 2001-08-01 13:43:20 ghudson Exp $";
14#endif
15
16#include "mit-copyright.h"
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <ctype.h>
21#include <errno.h>
22#include <signal.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <sys/wait.h>
26#include <sys/time.h>
27#include <sys/resource.h>
28#include <sys/param.h>
29#include <fcntl.h>
30#include <athdir.h>
31#include <X11/Xlib.h>
32#include <X11/Xutil.h>
33#include <X11/Xatom.h>
34#include <X11/Xmu/WinUtil.h>
35#include <Jets/Jets.h>
36#include <Jets/Window.h>
37#include <Jets/Button.h>
38#include <Jets/Label.h>
39#include <Jets/Menu.h>
40#include <Jets/DClock.h>
41#include <Jets/AClock.h>
42#include <Jets/Form.h>
43#include <Jets/Tree.h>
44/* #include <StripChart.h> */
45/* #include <List.h> */
46#include <Jets/warn.h>
47#include "dash.h"
48
49
50extern int DEBUG;
51
52#define LOADST "/usr/athena/lib/gnuemacs/etc/loadst"
53
54#define DASH "Dash"
55#define DASH_NOP (char)0x00
56#define DASH_DEBUG (char)0x01
57#define DASH_KILL (char)0x02
58#define DASH_CREATE (char)0x03
59#define DASH_DESTROY (char)0x04
60#define DASH_MAP (char)0x05
61#define DASH_UNMAP (char)0x06
62#define DASH_CREATEORMAP (char)0x07
63#define DASH_RESTART (char)0x08
64
65Atom dashAtom, nameAtom;
66#define DASH_ATOM "_ATHENA_DASH"
67
68
69
70Jet root;
71/*
72 * These definitions are needed by the tree jet
73 */
74JetClass *jetClasses[] =
75{ &treeJetClass, &windowJetClass, &buttonJetClass, &labelJetClass,
76    &menuJetClass, &dClockJetClass,
77    &aClockJetClass, &formJetClass,
78    /* &stripChartJetClass, */
79    /* &listJetClass, */};
80
81int numJetClasses = XjNumber(jetClasses);
82
83static XrmOptionDescRec opTable[] = {
84{"+rv",         "*reverseVideo", XrmoptionNoArg,        (caddr_t) "off"},
85{"-background", "*background",  XrmoptionSepArg,        (caddr_t) NULL},
86{"-bd",         "*borderColor", XrmoptionSepArg,        (caddr_t) NULL},
87{"-bg",         "*background",  XrmoptionSepArg,        (caddr_t) NULL},
88{"-bordercolor","*borderColor", XrmoptionSepArg,        (caddr_t) NULL},
89{"-borderwidth",".borderWidth", XrmoptionSepArg,        (caddr_t) NULL},
90{"-bw",         ".borderWidth", XrmoptionSepArg,        (caddr_t) NULL},
91{"-display",    ".display",     XrmoptionSepArg,        (caddr_t) NULL},
92{"-fg",         "*foreground",  XrmoptionSepArg,        (caddr_t) NULL},
93{"-fn",         "*font",        XrmoptionSepArg,        (caddr_t) NULL},
94{"-font",       "*font",        XrmoptionSepArg,        (caddr_t) NULL},
95{"-foreground", "*foreground",  XrmoptionSepArg,        (caddr_t) NULL},
96{"-geometry",   "*menuTree.window.geometry",    XrmoptionSepArg,
97   (caddr_t) NULL},
98{"-reverse",    "*reverseVideo", XrmoptionNoArg,        (caddr_t) "on"},
99{"-rv",         "*reverseVideo", XrmoptionNoArg,        (caddr_t) "on"},
100{"+rude",       "*rude",        XrmoptionNoArg,         (caddr_t) "off"},
101{"-rude",       "*rude",        XrmoptionNoArg,         (caddr_t) "on"},
102{"+verify",     "*verify",      XrmoptionNoArg,         (caddr_t) "off"},
103{"-verify",     "*verify",      XrmoptionNoArg,         (caddr_t) "on"},
104{"-xrm",        NULL,           XrmoptionResArg,        (caddr_t) NULL},
105{"-name",       ".name",        XrmoptionSepArg,        (caddr_t) NULL},
106{"-appdefs",    ".appDefs",     XrmoptionSepArg,        (caddr_t) NULL},
107{"-f",          ".appDefs",     XrmoptionSepArg,        (caddr_t) NULL},
108{"-userdefs",   ".userDefs",    XrmoptionSepArg,        (caddr_t) NULL},
109{"-menus",      "*Menu.file",   XrmoptionSepArg,        (caddr_t) NULL},
110{"-send",       ".send",        XrmoptionNoArg,         (caddr_t) "true"},
111{"-kill",       ".kill",        XrmoptionNoArg,         (caddr_t) "true"},
112{"-run",        ".run",         XrmoptionNoArg,         (caddr_t) "true"},
113{"-restart",    ".restart",     XrmoptionNoArg,         (caddr_t) "true"},
114{"-debug",      ".debug",       XrmoptionNoArg,         (caddr_t) "true"},
115{"-nofork",     ".nofork",      XrmoptionNoArg,         (caddr_t) "true"},
116{"-nosession",  "*showCommand", XrmoptionNoArg,         (caddr_t) "false"},
117#ifdef HAVE_KRB4
118{"-nochecktickets",  ".checkTickets",  XrmoptionNoArg,  (caddr_t) "false"},
119#endif /* HAVE_KRB4 */
120};
121
122MyResources parms;
123
124#define offset(field) XjOffset(MyResourcesPtr,field)
125
126static XjResource appResources[] =
127{
128  { "verify", "Verify", XjRBoolean, sizeof(Boolean),
129      offset(verifyOn), XjRBoolean, (caddr_t) True },
130  { "notify", "Notify", XjRBoolean, sizeof(Boolean),
131      offset(notifyOn), XjRBoolean, (caddr_t) True },
132  { "startString", "StartString", XjRString, sizeof(char *),
133      offset(startString), XjRString, (caddr_t) NULL },
134  { "run", "Run", XjRBoolean, sizeof(Boolean),
135      offset(run), XjRBoolean, (caddr_t) False },
136  { "send", "Send", XjRBoolean, sizeof(Boolean),
137      offset(send), XjRBoolean, (caddr_t) False },
138  { "kill", "Kill", XjRBoolean, sizeof(Boolean),
139      offset(kill), XjRBoolean, (caddr_t) False },
140  { "restart", "Restart", XjRBoolean, sizeof(Boolean),
141      offset(restart), XjRBoolean, (caddr_t) False },
142  { "debug", "Debug", XjRBoolean, sizeof(Boolean),
143      offset(debug), XjRBoolean, (caddr_t) False },
144  { "nofork", "Nofork", XjRBoolean, sizeof(Boolean),
145      offset(nofork), XjRBoolean, (caddr_t) False },
146#ifdef HAVE_KRB4
147  { "checkTickets", "CheckTickets", XjRBoolean, sizeof(Boolean),
148      offset(checkTickets), XjRBoolean, (caddr_t) True },
149#endif /* HAVE_KRB4 */
150};
151
152#undef offset
153
154
155/*
156 *  setenv() doesn't exist on some systems...  it's putenv instead.
157 *  So, we write our own setenv routine, and use it instead.
158 *
159 *  Arguments:  (same as setenv in BSD Unix)
160 *      char *name;     name of environment variable to set or change.
161 *      char *value;    value to set or change environment variable to.
162 *      int overwrite;  if non-zero, force variable to value.
163 *                      if zero, and variable does not exist, add variable
164 *                              to environment.
165 *                      else, do nothing.
166 *
167 *  Returns:   (same as setenv in bsd Unix)
168 *      -1              if unsuccessful (unable to malloc enough space for
169 *                              an expanded environment).
170 *      0               otherwise.
171 *
172 */
173static int psetenv(name, value, overwrite)
174     char *name, *value;
175     int overwrite;
176{
177  char *string;
178
179  if ((overwrite) ||
180      ( (char *) getenv(name) == NULL))
181    {
182      string = (char *) malloc((strlen(name) + strlen(value) + 2)
183                               * sizeof(char));
184                                        /* add 1 for the null and 1 for "=" */
185      if (string == NULL)
186        return(-1);
187      strcpy(string, name);
188      strcat(string, "=");
189      strcat(string, value);
190      if (! putenv(string) )
191        return(-1);
192    }
193  return(0);
194}
195
196
197/*
198 * Set utilities
199 */
200
201typedef struct _Set
202{
203  struct _Set *next;
204  char *name;
205} Set;
206
207Set *setCache[100];
208int cacheSize = 0;
209
210/*
211 * Single level expansion of name
212 */
213Set *expandName(name)
214     char *name;
215{
216  char *type;
217  XrmValue value;
218  Set *tmp, *list;
219  char *start, *end, *more;
220  char n[50], c[50];
221  int i;
222
223  if (!strcasecmp("NULL", name))
224    return NULL;
225
226  for (i = 0; i < cacheSize; i++)
227    if (!strcmp(name, setCache[i]->name))
228      return setCache[i]->next;
229
230  sprintf(n, "%s.set.%s", programName, name);
231  sprintf(c, "%s.Set.%s", programClass, name);
232
233  if (XrmGetResource(rdb, n, c, &type, &value))
234    start = (char *)(value.addr);
235  else
236    {
237      char errtext[100];
238
239      sprintf(errtext, "no set %s exists", name);
240      XjWarning(errtext);
241      return NULL;
242    }
243
244  list = (Set *)XjMalloc((unsigned) sizeof(Set));
245  list->name = XjNewString(name);
246  list->next = NULL;
247
248  while (isspace(*start)) start++;
249  while (*start != '\0')
250    {
251      end = start;
252      while (!isspace(*end) && *end != '\0') end++;
253      more = end;
254      if (*end != '\0') more++;
255      *end = '\0';
256
257      tmp = (Set *)XjMalloc((unsigned) sizeof(Set));
258      tmp->name = start;
259      tmp->next = list->next;
260      list->next = tmp;
261         
262      start = more;
263    }
264
265  setCache[cacheSize++] = list;
266  return list->next;
267}
268
269Set *resolveName(name, list)
270     char *name;
271     Set *list;
272{
273  Set *e, *tmp;
274
275  e = expandName(name);
276  while (e != NULL)
277    {
278      if (*(e->name) == '_')
279        {
280          tmp = (Set *)XjMalloc((unsigned) sizeof(Set));
281          tmp->name = e->name + 1;
282          tmp->next = list;
283          list = tmp;
284        }
285      else
286        list = resolveName(e->name, list);
287      e = e->next;
288    }
289
290  return list;
291}
292
293void freeSet(set)
294     Set *set;
295{
296  Set *back;
297
298  while (set)
299    {
300      back = set;
301      set = set->next;
302      XjFree((char *) back);
303    }
304}
305
306/*
307 * Tree callbacks...
308 */
309
310int printTree(fromJet, what, data)
311     Jet fromJet;
312     char *what;
313     caddr_t data;
314{
315  Jet j;
316
317  for (j = root->core.child; j != NULL; j = j->core.sibling)
318    fprintf(stdout, "%s\n", j->core.name);
319  return 0;
320}
321
322int mapTree(fromJet, what, data)
323     Jet fromJet;
324     char *what;
325     caddr_t data;
326{
327  Jet w;
328
329  w = XjFindJet(what, root);
330
331  if (w != NULL)
332    {
333      w = w->core.child;
334      while (w)
335        {
336          MapWindow(w, True);
337          w = w->core.sibling;
338        }
339      return 0;
340    }
341  else
342    {
343      char errtext[100];
344
345      sprintf(errtext, "couldn't find %s to map it", what);
346      XjWarning(errtext);
347      return 1;
348    }
349}
350
351int mapSet(fromJet, what, data)
352     Jet fromJet;
353     char *what;
354     caddr_t data;
355{
356  Set *set, *ptr;
357
358  set = resolveName(what, NULL);
359  if (set)
360    {
361      for (ptr = set; ptr != NULL; ptr = ptr->next)
362        (void)mapTree(fromJet, ptr->name, data);
363      freeSet(set);
364    }
365  return 0;
366}
367
368int unmapTree(fromJet, what, data)
369     Jet fromJet;
370     char *what;
371     caddr_t data;
372{
373  Jet w;
374
375  w = XjFindJet(what, root);
376
377  if (w != NULL)
378    {
379      w = w->core.child;
380      while (w)
381        {
382          UnmapWindow(w);
383          w = w->core.sibling;
384        }
385      return 0;
386    }
387  else
388    {
389      char errtext[100];
390
391      sprintf(errtext, "couldn't find %s to unmap it", what);
392      XjWarning(errtext);
393      return 1;
394    }
395}
396
397int unmapSet(fromJet, what, data)
398     Jet fromJet;
399     char *what;
400     caddr_t data;
401{
402  Set *set, *ptr;
403
404  set = resolveName(what, NULL);
405  if (set)
406    {
407      for (ptr = set; ptr != NULL; ptr = ptr->next)
408        (void)unmapTree(fromJet, ptr->name, data);
409      freeSet(set);
410    }
411  return 0;
412}
413
414int createTree(fromJet, what, data)
415     Jet fromJet;
416     char *what;
417     caddr_t data;
418{
419  if (NULL == XjFindJet(what, root))
420    XjRealizeJet(XjVaCreateJet(what, treeJetClass, root, NULL, NULL));
421  return 0;
422}
423
424int createSet(fromJet, what, data)
425     Jet fromJet;
426     char *what;
427     caddr_t data;
428{
429  Set *set, *ptr;
430
431  set = resolveName(what, NULL);
432  if (set)
433    {
434      for (ptr = set; ptr != NULL; ptr = ptr->next)
435        (void)createTree(fromJet, ptr->name, data);
436      freeSet(set);
437    }
438  return 0;
439}
440
441int createMapTree(fromJet, what, data)
442     Jet fromJet;
443     char *what;
444     caddr_t data;
445{
446  if (NULL == XjFindJet(what, root))
447    XjRealizeJet(XjVaCreateJet(what, treeJetClass, root, NULL, NULL));
448  else
449    mapTree(fromJet, what, data);
450
451  return 0;
452}
453
454int createMapSet(fromJet, what, data)
455     Jet fromJet;
456     char *what;
457     caddr_t data;
458{
459  Set *set, *ptr;
460
461  set = resolveName(what, NULL);
462  if (set)
463    {
464      for (ptr = set; ptr != NULL; ptr = ptr->next)
465        (void)createMapTree(fromJet, ptr->name, data);
466      freeSet(set);
467    }
468  return 0;
469}
470
471int destroyTree(fromJet, what, data)
472     Jet fromJet;
473     char *what;
474     caddr_t data;
475{
476  Jet w;
477
478  w = XjFindJet(what, root);
479  if (w != NULL)
480    {
481      XjDestroyJet(w);
482      return 0;
483    }
484  else
485    {
486      char errtext[100];
487
488      sprintf(errtext, "couldn't find %s to destroy it", what);
489      XjWarning(errtext);
490      return 1;
491    }
492}
493
494int destroySet(fromJet, what, data)
495     Jet fromJet;
496     char *what;
497     caddr_t data;
498{
499  Set *set, *ptr;
500
501  set = resolveName(what, NULL);
502  if (set)
503    {
504      for (ptr = set; ptr != NULL; ptr = ptr->next)
505        (void)destroyTree(fromJet, ptr->name, data);
506      freeSet(set);
507    }
508  return 0;
509}
510
511int warpTree(fromJet, what, data)
512     Jet fromJet;
513     char *what;
514     caddr_t data;
515{
516  Jet w;
517
518  w = XjFindJet(what, root);
519
520  if (w != NULL)
521    {
522      w = w->core.child;
523      if (w != NULL)
524        XWarpPointer(w->core.display,
525                     None,
526                     w->core.window,
527                     0, 0, 0, 0,
528                     w->core.width / 2,
529                     w->core.height / 2);
530      return 0;
531    }
532  else
533    {
534      char errtext[100];
535
536      sprintf(errtext, "couldn't find %s to warp there", what);
537      XjWarning(errtext);
538      return 1;
539    }
540}
541
542int warpSet(fromJet, what, data)
543     Jet fromJet;
544     char *what;
545     caddr_t data;
546{
547  Set *set;
548
549  set = resolveName(what, NULL);
550  if (set)
551    {
552      (void)warpTree(fromJet, set->name, data);
553      freeSet(set);
554    }
555  return 0;
556}
557
558/*
559 * Exec related callbacks
560 */
561int sh(fromJet, what, data)
562     Jet fromJet;
563     char *what;
564     caddr_t data;
565{
566  if (127 == system(what))
567    {
568      XjWarning("couldn't execute shell");
569      return 1;
570    }
571  return 0;
572}
573
574/*
575 * Translate the string "what," expanding %M, %S, etc, and place
576 * it into the string "where."
577 */
578void expand(what, where)
579     char *what, *where;
580{
581  static int initialized = 0;
582  static char sys[20], bin[20], sysdir[50], bindir[50], home[100];
583  char *start, *wherestart, *tmp, **found;
584  struct stat bdir;
585
586  if (initialized == 0)
587    {
588      initialized++;
589
590      tmp = getenv("HOME");
591      if (tmp != NULL)
592        strncpy(home, tmp, sizeof(home)/sizeof(char));
593      else
594        sprintf(home, "nohome");
595
596      tmp = getenv("ATHENA_SYS");
597      if (tmp != NULL)
598        strncpy(sys, tmp, sizeof(sys)/sizeof(char));
599      else
600        sprintf(sys, "@sys");
601
602      tmp = getenv("HOSTTYPE");
603      if (tmp != NULL)
604        strncpy(bin, tmp, sizeof(bin)/sizeof(char));
605      else
606        strcpy(bin, HOSTTYPE);
607
608      sprintf(sysdir, "arch/%s/bin", sys);
609      sprintf(bindir, "%sbin", bin);
610    }
611
612  while (isspace(*what)) what++;
613  start = what;
614  wherestart = where;
615
616  while (*what != '\0')
617    {
618      while (*what != '\0' && *what != '%' && *what != '~')
619        *where++ = *what++;
620
621      if (*what == '~' && what == start)
622        {
623          strncpy(where, home, strlen(home));
624          where += strlen(home);
625          what++;
626        }
627      else
628        if (*what == '%')
629          {
630            what++;
631            switch(*what)
632              {
633              case '%':
634                *where++ = '%';
635                what++;
636                break;
637              case 'M':
638                strncpy(where, bin, strlen(bin));
639                where += strlen(bin);
640                what++;
641                break;
642              case 'S':
643                strncpy(where, sys, strlen(sys));
644                where += strlen(sys);
645                what++;
646                break;
647              case 'B':
648                /* Make tmp point to the beginning of the path we're
649                 * looking for binary directories under, and null
650                 * terminate it.
651                 */
652                tmp = where;
653                if (where != wherestart)
654                  {
655                    tmp--;
656                    while (*tmp != ' ' && tmp > wherestart)
657                      tmp--;
658                    if (*tmp == ' ') tmp++;
659                  }
660                *where = '\0';
661
662                /* Let athdir do the work... */
663                found = athdir_get_paths(tmp, "bin",
664                                         NULL, NULL, NULL, NULL, 0);
665                if (found)
666                  {
667                    /* Replace partially constructed path ending with
668                     * %B with the path athdir returned.
669                     */
670                    strcpy(tmp, *found);
671                    where = tmp + strlen(*found);
672                    athdir_free_paths(found);
673                  }
674                else
675                  {
676                    /* If we found nothing to substitute, don't. */
677                    strcpy(where, "%B");
678                    where += 2;
679                  }
680
681                what++;
682                break;
683              default:
684                *where++ = '%';
685                what++;
686              }
687          }
688    }
689  *where = '\0';
690}
691
692static char *cwd = NULL; /* working directory for exec'ed programs */
693static char *subject = NULL;
694static char buf[MAXPATHLEN];
695static char addpath[MAXPATHLEN];
696
697int setup(fromJet, what, data)
698caddr_t fromJet;
699char *what;
700caddr_t data;
701{
702  subject = what;
703  return 0;
704}
705
706int cd(fromJet, what, data)
707caddr_t fromJet;
708char *what;
709caddr_t data;
710{
711  cwd = what;
712  return 0;
713}
714
715void setupEnvironment()
716{
717  char *path, *space;
718
719  if (displayName != NULL)
720    psetenv("DISPLAY", displayName, True);
721
722  if (cwd != NULL)
723    {
724      expand(cwd, buf);
725      if (-1 == chdir(buf))
726        {
727          char errtext[100];
728
729          sprintf(errtext, "cd to %s failed with error %d",
730                  cwd, errno);
731          XjWarning(errtext);
732        }
733    }
734
735  if (subject != NULL)
736    psetenv("SUBJECT", subject, True);
737
738  if (*addpath != '\0')
739    {
740      path = (char *) getenv("PATH");
741      if (path == NULL)
742        {
743          space = XjMalloc((unsigned) MAXPATHLEN);
744          space[0] = '\0';
745        }
746      else
747        {
748          space = XjMalloc((unsigned) (MAXPATHLEN + strlen(path)));
749          strcpy(space, path);
750          strcat(space, ":");
751        }
752
753      strcat(addpath, "/%B");
754      expand(addpath, &space[strlen(space)]);
755      psetenv("PATH", space, True);
756    }
757}
758
759
760int add(fromJet, what, data)
761     Jet fromJet;
762     char *what;
763     caddr_t data;
764{
765  int err;
766  FILE *a;
767  int l;
768  sigset_t set, oset;
769  char line1[100], line2[100];
770
771  line2[0] = '\0';
772  sprintf(addpath, "attach -p %s", what);
773  (void) sigemptyset(&set);
774  (void) sigaddset(&set, SIGCHLD);
775  (void) sigprocmask(SIG_BLOCK, &set, &oset);
776  if (NULL != (a = popen(addpath, "r")))
777    {
778      fgets(addpath, MAXPATHLEN, a);
779      err = pclose(a);
780      (void) sigprocmask(SIG_SETMASK, &oset, NULL);
781
782      if (err != 0)
783        sprintf(line2, "Attach failed with error %d", err/256);
784      else
785        {
786          l = strlen(addpath);
787          if (l > 0)
788            if (addpath[l - 1] == '\n')
789              addpath[l - 1] = '\0';
790          return 0;
791        }
792    }
793  (void) sigprocmask(SIG_SETMASK, &oset, NULL);
794  sprintf(line1, "Could not attach %s", what);
795  XjUserWarning(root, NULL, True, line1, line2);
796
797  return 1;
798}
799
800int attach(fromJet, what, data)
801     Jet fromJet;
802     char *what;
803     caddr_t data;
804{
805  int err;
806
807  err = add(fromJet, what, data);
808  addpath[0] = '\0';
809
810  return err;
811}
812
813typedef struct _Child
814{
815  struct _Child *next;
816  int pid;
817  char *title;
818} Child;
819
820static Child *firstChild = NULL;
821
822
823/*
824 * Avoid zombies
825 */
826void checkChildren(sig)
827     int sig;
828{
829  Boolean found;
830  Child *ch, **last;
831  int child, status;
832
833  while ((child = waitpid(-1, &status, WNOHANG)) > 0)
834    {
835      found = False;
836      last = &firstChild;
837      for (ch = firstChild;
838           ch != NULL && !found;
839           last = &ch->next, ch = ch->next)
840        if (ch->pid == child)
841          {
842            found = True;
843            *last = ch->next;
844
845            if (WIFEXITED(status) && WEXITSTATUS(status))
846              {
847                char line1[100];
848
849                sprintf(line1, "%s exited with status %d",
850                        ch->title, WEXITSTATUS(status));
851                XjUserWarning(root, NULL, True, line1, "");
852              }
853            if (WIFSIGNALED(status) && WTERMSIG(status))
854              {
855                char line1[100], line2[100];
856
857                sprintf(line1, "%s exited with signal %d",
858                        ch->title, WTERMSIG(status));
859                if (WCOREDUMP(status))
860                  strcpy(line2, "(core dumped!)");
861                else
862                  line2[0] = '\0';
863                XjUserWarning(root, NULL, True, line1, line2);
864              }
865
866            XjFree((char *) ch);
867          }
868    }
869}
870
871char *NAME; /* oh no! a global variable! */
872
873
874input(fd, name)
875     int fd;
876     char *name;
877{
878  char buf[MAXPATHLEN];
879  char buf2[MAXPATHLEN + 7]; /* add some in for the length of errno */
880  int n;
881
882  if (read(fd, buf2, MAXPATHLEN + 7))
883    {
884      char line1[100], line2[100];
885
886      sscanf(buf2, "%s %d", buf, &n);
887      sprintf(line1, "Could not start %s:", name);
888      sprintf(line2, "%s: %s", buf, strerror(n));
889      XjUserWarning(root, NULL, True, line1, line2);
890    }
891  XjReadCallback((XjCallbackProc)NULL, fd, &fd);
892  close(fd);
893}
894
895
896int exec(info, what, data)
897     MenuInfo *info;
898     char *what;
899     caddr_t data;
900{
901  int pid;
902  char *ptr;
903  int argc = 0;
904  char *argv[100];
905  Child *ch;
906  char *name;
907  int fd[2];
908  int pipes;
909  int num_fds;
910
911
912  if (info != NULL &&           /* exec through menu item */
913      info->null == NULL)
914    name = info->menu->title;
915  else
916    if (NAME != NULL)           /* exec through verify, because verify */
917      {                         /* can't pass the menuinfo structure */
918        name = NAME;            /* it got, since the menus may have */
919        NAME = NULL;            /* rearranged by now. There _is_ a better */
920      }                         /* solution, but if I had time to do it, you */
921  else                          /* wouldn't be reading this! */
922    name = what;                /* exec through non-menu item */
923
924  if ((pipes = pipe(fd)))
925    {
926      char line1[100], line2[100];
927
928      sprintf(line1, "Could not set up pipe:  %s", strerror(errno));
929      sprintf(line2, "There will be no warning if `%s' can't be started.",
930              name);
931      XjUserWarning(root, NULL, True, line1, line2);
932    }
933  pipes = !pipes;
934
935  pid = fork();                 /* vfork will block indefinitely... :-( */
936
937  if (pid == -1)
938    {
939      char line1[100], line2[100];
940
941      sprintf(line1, "Could not start %s:", name);
942      sprintf(line2, "Fork - %s", strerror(errno));
943      XjUserWarning(root, NULL, True, line1, line2);
944      if (pipes)
945        {
946          close(fd[0]);
947          close(fd[1]);
948        }
949      return 1;
950    }
951
952  if (pid != 0)                 /* We're in the parent... */
953    {
954      addpath[0] = '\0';
955      cwd = NULL;
956      subject = NULL;
957
958      ch = (Child *)XjMalloc((unsigned) sizeof(Child));
959      ch->pid = pid;
960      ch->title = name;
961      ch->next = firstChild;
962      firstChild = ch;
963
964      if (pipes)
965        {
966          close(fd[1]);         /* Parent reads on fd[0] */
967          XjReadCallback((XjCallbackProc)input, fd[0], name);
968        }
969      return 0;
970    }
971
972  setupEnvironment();
973
974  expand(what, buf);
975  ptr = buf;
976
977  while (*ptr != '\0')
978    {
979      while (isspace(*ptr))
980        ptr++;
981
982      argv[argc++] = ptr;
983
984      while (!isspace(*ptr) && *ptr != '\0')
985        ptr++;
986
987      if (*ptr != '\0')
988        {
989          *ptr = '\0';
990          ptr++;
991        }
992
993    }
994
995  argv[argc] = NULL;
996
997  for (num_fds = 3; num_fds < getdtablesize(); num_fds++)
998    fcntl(num_fds, F_SETFD, 1);
999
1000  if (-1 == execvp(argv[0], argv))
1001    {
1002      char buf2[MAXPATHLEN + 7]; /* add some in for the length of errno */
1003      int n;
1004
1005      /* Child writes on the wall with crayon...  just kidding - fd[1] */
1006      if (pipes)
1007        {
1008          sprintf(buf2, "%s %d", buf, errno);
1009          n = strlen(buf2);
1010          if (write(fd[1], buf2, n) == n)
1011            _exit(0);
1012        }
1013      _exit(42);
1014    }
1015  return 42;                    /* never reached, but makes saber happy... */
1016}
1017
1018int restart(info, what, data)
1019     MenuInfo *info;
1020     char *what;
1021     caddr_t data;
1022{
1023  char *ptr;
1024  int argc = 0;
1025  char *argv[100];
1026  char line1[100], line2[100];
1027
1028  setupEnvironment();
1029
1030  if (what != NULL &&
1031      *what != '\0')
1032    {
1033      expand(what, buf);
1034      ptr = buf;
1035
1036      while (*ptr != '\0')
1037        {
1038          while (isspace(*ptr))
1039            ptr++;
1040
1041          argv[argc++] = ptr;
1042
1043          while (!isspace(*ptr) && *ptr != '\0')
1044            ptr++;
1045
1046          if (*ptr != '\0')
1047            {
1048              *ptr = '\0';
1049              ptr++;
1050            }
1051        }
1052      execvp(argv[0], argv);
1053    }
1054  else
1055    execvp(global_argv[0], global_argv);
1056
1057  sprintf(line1, "Attempt to restart failed with error %d", errno);
1058  sprintf(line2, "%s: %s", global_argv[0], strerror(errno));
1059  XjUserWarning(root, NULL, True, line1, line2);
1060  return 1;
1061}
1062
1063int addMenus(info, file, data)
1064     MenuInfo *info;
1065     char *file;
1066     caddr_t data;
1067{
1068  if (info->null != NULL) /* we weren't called by menu code */
1069    return 1;
1070
1071  return loadNewMenus(info->menubar, file);
1072}
1073
1074/*
1075 * Danger Will Robinson!
1076 * This mechanism makes it possible for callbacks to
1077 * be called after the calling jet has already been
1078 * destroyed. Ain't that special?
1079 */
1080typedef struct _vstruct {
1081  Jet top;
1082  Jet yes;
1083  XjCallback me;
1084  Menu *menu;
1085  char *string;
1086  char *title;
1087} Verify;
1088
1089int yesorno(who, v, data)
1090     Jet who;
1091     Verify *v;
1092     caddr_t data;
1093{
1094  XUnmapWindow(v->top->core.display, XjWindow(v->top));
1095  XFlush(v->top->core.display);
1096
1097  if (v->yes == who)
1098    {
1099      NAME = v->title;
1100      XjCallCallbacks((caddr_t) who, v->menu->activateProc, NULL);
1101    }
1102
1103  XjDestroyJet(v->top);
1104  XjFree(v->string);
1105  XjFree((char *) v);
1106  return 0;
1107}
1108
1109int verify(info, foo, data)
1110     MenuInfo *info;
1111     int foo;
1112     caddr_t data;
1113{
1114  Verify *v;
1115  Jet lqtop, lqform, logo, lqlabel, lqybutton, lqnbutton,
1116  lqnwindow, lqywindow, lqylabel, lqnlabel;
1117
1118  if (info->null != NULL) /* we weren't called by menu code */
1119    return 1;
1120
1121  if (!parms.verifyOn)
1122    {
1123      XjCallCallbacks((caddr_t) info, info->menu->activateProc, NULL);
1124      return 0;
1125    }
1126
1127  v = (Verify *)XjMalloc((unsigned) sizeof(Verify));
1128
1129  v->me.next = NULL;
1130  v->me.argType = argPtr;
1131  v->me.passPtr = v;
1132  v->me.proc = yesorno;
1133  v->menu = info->menu;
1134
1135  lqtop =  XjVaCreateJet("lqWindow", windowJetClass, root, NULL, NULL);
1136  lqform = XjVaCreateJet("lqForm", formJetClass, lqtop, NULL, NULL);
1137
1138  /* in this structure because that widget may need it forever, long
1139     after it's off the stack and we have returned */
1140  v->title = info->menu->title;
1141  v->string = XjMalloc((unsigned) (strlen(info->menu->title) + 1
1142                                   + strlen(parms.startString)));
1143  sprintf(v->string, parms.startString, info->menu->title);
1144
1145  logo = XjVaCreateJet("dashLogo", labelJetClass, lqform,
1146                       NULL, NULL);
1147  lqlabel = XjVaCreateJet("lqLabel", labelJetClass, lqform,
1148                          XjNlabel, v->string, NULL, NULL);
1149  lqywindow = XjVaCreateJet("lqYWindow", windowJetClass, lqform, NULL, NULL);
1150  lqnwindow = XjVaCreateJet("lqNWindow", windowJetClass, lqform, NULL, NULL);
1151  lqybutton = XjVaCreateJet("lqYButton", buttonJetClass, lqywindow,
1152                            XjNactivateProc, &(v->me), NULL, NULL);
1153  lqnbutton = XjVaCreateJet("lqNButton", buttonJetClass, lqnwindow,
1154                            XjNactivateProc, &(v->me), NULL, NULL);
1155  lqylabel = XjVaCreateJet("lqYLabel", labelJetClass, lqybutton, NULL, NULL);
1156  lqnlabel = XjVaCreateJet("lqNLabel", labelJetClass, lqnbutton, NULL, NULL);
1157
1158  v->top = lqtop;
1159  v->yes = lqybutton;
1160
1161  XjRealizeJet(lqtop);
1162  return 0;
1163}
1164
1165
1166int toggleVerify(info, otherName, data)
1167MenuInfo *info;
1168char *otherName;
1169caddr_t data;
1170{
1171  static int initialized = 0;
1172  static char *onName, *offName;
1173
1174  if (info->null != NULL) /* we weren't called by menu code */
1175    return 1;
1176
1177  if (initialized == 0)
1178    {
1179      char *ptr = otherName;
1180
1181      initialized = 1;
1182
1183                                /* Deal with star BS... */
1184      if (ptr[0] == ' '  &&  ptr[1] == ' '  &&  ptr[2] == ' ')
1185        ptr += 3;
1186      if (ptr[0] == '*'  &&  ptr[1] == ' ')
1187        ptr += 2;
1188                                /* Rip this code out in a future */
1189                                /* release... */
1190
1191      if (parms.verifyOn)
1192        {
1193          onName = info->menu->title;
1194          offName = ptr;
1195        }
1196      else
1197        {
1198          onName = ptr;
1199          offName = info->menu->title;
1200        }
1201    }
1202
1203  if (parms.verifyOn)
1204    info->menu->title = offName;
1205  else
1206    info->menu->title = onName;
1207
1208  parms.verifyOn = !parms.verifyOn;
1209
1210  computeMenuSize(info->menubar, info->menu);
1211  computeMenuSize(info->menubar, info->menu->parent); /* bug */
1212  return 0;
1213}
1214
1215int toggleHelp(info, otherName, data)
1216MenuInfo *info;
1217char *otherName;
1218caddr_t data;
1219{
1220  static int initialized = 0;
1221  static char *onName, *offName;
1222  XjSize size;
1223
1224  if (info->null != NULL) /* we weren't called by menu code */
1225    return 1;
1226
1227  if (initialized == 0)
1228    {
1229      char *ptr = otherName;
1230
1231      initialized = 1;
1232
1233                                /* Deal with star BS... */
1234      if (ptr[0] == ' '  &&  ptr[1] == ' '  &&  ptr[2] == ' ')
1235        ptr += 3;
1236      if (ptr[0] == '*'  &&  ptr[1] == ' ')
1237        ptr += 2;
1238                                /* Rip this code out in a future */
1239                                /* release... */
1240
1241      if (info->menubar->menu.showHelp == 1)
1242        {
1243          onName = info->menu->title;
1244          offName = ptr;
1245        }
1246      else
1247        {
1248          onName = ptr;
1249          offName = info->menu->title;
1250        }
1251    }
1252
1253  if (info->menubar->menu.showHelp == 1)
1254    info->menu->title = offName;
1255  else
1256    info->menu->title = onName;
1257
1258  info->menubar->menu.showHelp = !info->menubar->menu.showHelp;
1259
1260  computeAllMenuSizes(info->menubar, info->menubar->menu.rootMenu);
1261  computeRootMenuSize(info->menubar, &size);
1262  return 0;
1263}
1264
1265int quit(fromJet, what, data)
1266caddr_t fromJet;
1267int what;
1268caddr_t data;
1269{
1270  XjExit(what);
1271  return 0;                             /* For linting... */
1272}
1273
1274int enableGnome(fromJet, what, data)
1275caddr_t fromJet;
1276int what;
1277caddr_t data;
1278{
1279  system("rm -f $HOME/.athena_dash_interface");
1280  return 0;                             /* For linting... */
1281}
1282
1283int debug(fromJet, what, data)
1284caddr_t fromJet;
1285char *what;
1286caddr_t data;
1287{
1288  fprintf(stdout, "malloced %d\n", malloced);
1289  return 0;
1290}
1291
1292int usage(fromJet, what, data)
1293caddr_t fromJet;
1294char *what;
1295caddr_t data;
1296{
1297  XjUsage(what);
1298  return 0;
1299}
1300
1301int printMenu(info, what, data)
1302     MenuInfo *info;
1303     char *what;
1304     caddr_t data;
1305{
1306  if (info->null != NULL)               /* we weren't called by menu code */
1307    return 1;
1308
1309  PrintMenu(info->menubar); /* call only from a menu item. :-) */
1310  return 0;
1311}
1312
1313/* when the menu works without being overrideRedirect, this should
1314   be made ICCCM compliant. */
1315int lowerMenu(info, what, data)
1316     MenuInfo *info;
1317     char *what;
1318     caddr_t data;
1319{
1320#ifndef sgi
1321  if (info->null != NULL)
1322    return 1;
1323
1324  XLowerWindow(info->menubar->core.display,
1325               info->menubar->core.window);
1326  return 0;
1327#else
1328  /* HACK HACK HACK
1329   * If fam is running with icons on the background, it puts a window
1330   * up in front of the root window but behind everything else,
1331   * override redirect, but the full size of the screen. The code in
1332   * the other half of this ifdef pushes dash behind that window
1333   * where you can't see it. This is clearly not satisfactory.
1334   */
1335  Window rooter, parent, *list;
1336  WindowJet menuWindow;
1337  int i;
1338  unsigned int num;
1339  XWindowAttributes win;
1340  XWindowChanges config;
1341
1342  if (info->null != NULL)
1343    return 1;
1344
1345  /*
1346   * If the menu bar is not override redirect, we're ok.
1347   * If XQueryTree fails, just lower ourselves.
1348   */
1349  menuWindow = (WindowJet)info->menubar->core.parent;
1350  if (menuWindow->window.overrideRedirect == False ||
1351      !XQueryTree(root->core.display, root->core.window,
1352                  &rooter, &parent, &list, &num))
1353    {
1354      XLowerWindow(info->menubar->core.display,
1355                   info->menubar->core.window);
1356      return 0;
1357    }
1358
1359  /*
1360   * Start examining the children of the root from back to font.
1361   */
1362  for (i = 0; i < num; i++)
1363    {
1364      /* Ignore ourselves. */
1365      if (list[i] == info->menubar->core.window)
1366        continue;
1367
1368      if (XGetWindowAttributes(root->core.display, list[i], &win))
1369        {
1370          /* Is this the fam window? A fine heuristic. It's override
1371             redirect, we can see it, and it takes up the whole
1372             screen. */
1373          if (win.override_redirect == True &&
1374              win.map_state == IsViewable &&
1375              win.x == 0 && win.y == 0 &&
1376              win.width == root->core.width &&
1377              win.height == root->core.height)
1378            break;
1379
1380          /* Is this a normal viewable window? Then we're safe putting
1381             ourselves behind it. (Or, in front of the window behind
1382             it.) This catches the case where fam isn't actually
1383             running. */
1384          if (win.override_redirect == False &&
1385              win.map_state == IsViewable)
1386            {
1387              if (i > 0)
1388                i--; /* bug; we should probably really change
1389                        to Below, below, for this case */
1390              break;
1391            }
1392        }
1393
1394      /* We didn't find the fam window or any viewable windows at all.
1395         So we simply lower ourselves to the bottom. We could probably
1396         just as well do nothing at all. */
1397      if (i == num)
1398        {
1399          XLowerWindow(info->menubar->core.display,
1400                       info->menubar->core.window);
1401          XFree(list);
1402          return 0;
1403        }
1404    }
1405
1406  config.sibling = list[i];
1407  config.stack_mode = Above;
1408  XConfigureWindow(root->core.display, info->menubar->core.window,
1409                   CWSibling | CWStackMode, &config);
1410
1411  XFree(list);
1412  return 0;
1413#endif
1414}
1415
1416int logout(fromJet, what, data)
1417caddr_t fromJet;
1418char *what;
1419caddr_t data;
1420{
1421  char *pid_string;
1422  int pid_int;
1423
1424  if (pid_string = (char *) getenv("XSESSION"))
1425    if (pid_int = atoi(pid_string))
1426      if (!kill(pid_int, SIGHUP))
1427        return 0;
1428
1429  NAME = "logout";
1430  /*return exec(NULL, "/usr/athena/end_session", NULL);*/
1431  return exec(NULL, "end_session", NULL);
1432}
1433
1434fatal(display)
1435     Display *display;
1436{
1437  XjExit(-1);
1438}
1439
1440static int (*def_handler)();
1441
1442static int handler(display, error)
1443     Display *display;
1444     XErrorEvent *error;
1445{
1446  if (error->error_code == BadWindow  ||  error->error_code == BadAtom)
1447    return 0;
1448
1449  def_handler(display, error);
1450  return 0;                     /* it'll never get this far anyway... */
1451}
1452
1453
1454
1455Window findDASH(display)
1456     Display *display;
1457{
1458  char *atom_name;
1459  Atom actual_type;
1460  int actual_format;
1461  unsigned long nitems;
1462  unsigned long bytes_after;
1463  Window *prop;
1464  unsigned char *name;
1465/*  unsigned char *prop; */
1466  int status;
1467
1468#ifdef TIME_STARTUP
1469  struct timeval start, end;
1470
1471  gettimeofday(&start, NULL);
1472  printf("findDASH: - %d.%d + \n", start.tv_sec, start.tv_usec);
1473#endif
1474
1475  atom_name = (char *) XjMalloc(strlen(programName) + strlen(DASH_ATOM)
1476                                + 2);
1477  sprintf(atom_name, "%s_%s", DASH_ATOM, programName);
1478  nameAtom = XInternAtom(display, atom_name, False);
1479  XjFree(atom_name);
1480
1481  status = XGetWindowProperty(display, RootWindow(display, 0),
1482                              nameAtom, 0, 1,
1483                              False, AnyPropertyType, &actual_type,
1484                              &actual_format, &nitems, &bytes_after,
1485                              (unsigned char **) &prop);
1486  if (status==BadWindow)
1487    XjFatalError("rootWindow does not exist!");
1488  if (status!=Success)
1489    return (Window) NULL;
1490  if (! prop)
1491    return (Window) NULL;
1492
1493  def_handler = XSetErrorHandler(handler);
1494  status = XGetWindowProperty(display, *prop,
1495                              dashAtom, 0, 1,
1496                              False, AnyPropertyType, &actual_type,
1497                              &actual_format, &nitems, &bytes_after,
1498                              &name);
1499  (void) XSetErrorHandler(def_handler);
1500
1501  if (status==BadWindow)
1502    {
1503      XjFatalError("rootWindow does not exist!");
1504    }
1505  if (status!=Success)
1506    {
1507      return (Window) NULL;
1508    }
1509
1510#ifdef TIME_STARTUP
1511          gettimeofday(&end, NULL);
1512          printf("findDASH: %d.%d = %d.%06.6d\n", end.tv_sec, end.tv_usec,
1513                 (end.tv_usec > start.tv_usec)
1514                 ? end.tv_sec - start.tv_sec
1515                 : end.tv_sec - start.tv_sec - 1,
1516                 (end.tv_usec > start.tv_usec)
1517                 ? end.tv_usec - start.tv_usec
1518                 : end.tv_usec + 1000000 - start.tv_usec );
1519#endif
1520 
1521  if (!strcmp((char *)name, programName))
1522    {
1523      XjFree(name);
1524      return *prop;
1525    }
1526
1527  XjFree(name);
1528  return (Window) NULL;
1529}
1530
1531
1532
1533Status sendEvent(display, window, opcode, data)
1534     Display *display;
1535     Window window;
1536     char opcode;
1537     char *data;
1538{
1539  Status s;
1540  XEvent e;
1541
1542  e.xclient.type = ClientMessage;
1543  e.xclient.window = window;
1544  e.xclient.message_type = dashAtom;
1545  e.xclient.format = 8;
1546  memset(e.xclient.data.b, 0, sizeof(e.xclient.data.b));
1547  e.xclient.data.b[0] = opcode;
1548  if (data)
1549    strcpy(&e.xclient.data.b[1], data);
1550
1551  if (s = XSendEvent(display, window, False, NoEventMask, &e))
1552    XFlush(display);
1553
1554  return s;
1555}
1556
1557int delete(fromJet, what, data)
1558     Jet fromJet;
1559     char *what;
1560     caddr_t data;
1561{
1562  XjDestroyJet(fromJet);
1563  return 0;
1564}
1565
1566int deleteParent(fromJet, what, data)
1567     Jet fromJet;
1568     char *what;
1569     caddr_t data;
1570{
1571  XjDestroyJet(XjParent(fromJet));
1572  return 0;
1573}
1574
1575int message(info, zilch, data)
1576     WindowInfo *info;
1577     char *zilch;
1578     caddr_t data;
1579{
1580  char errtext[100];
1581  info->event->xclient.data.b[19] = '\0'; /* just in case */
1582
1583  if (info->event->xclient.message_type == dashAtom)
1584    switch(info->event->xclient.data.b[0])
1585      {
1586      case DASH_NOP:
1587        break;
1588      case DASH_DEBUG:
1589        DEBUG = !DEBUG;
1590        printTree(NULL, NULL, NULL);
1591        break;
1592      case DASH_KILL:
1593        XjExit(0);
1594        break;
1595      case DASH_CREATE:
1596        createSet(NULL, &info->event->xclient.data.b[1], NULL);
1597        break;
1598      case DASH_DESTROY:
1599        destroySet(NULL, &info->event->xclient.data.b[1], NULL);
1600        break;
1601      case DASH_MAP:
1602        mapSet(NULL, &info->event->xclient.data.b[1], NULL);
1603        break;
1604      case DASH_UNMAP:
1605        unmapSet(NULL, &info->event->xclient.data.b[1], NULL);
1606        break;
1607      case DASH_CREATEORMAP:
1608        createMapSet(NULL, &info->event->xclient.data.b[1], NULL);
1609        break;
1610      case DASH_RESTART:
1611        restart(NULL, NULL, NULL);
1612        break;
1613      default:
1614        sprintf(errtext, "unknown ClientMessage opcode: %d\n",
1615                (int)info->event->xclient.data.b[0]);
1616        break;
1617      }
1618  else
1619    {
1620      sprintf(errtext, "unrecognized ClientMessage: %d\n",
1621              info->event->xclient.message_type);
1622      XjWarning(errtext);
1623      return 1;
1624    }
1625
1626  return 0;
1627}
1628
1629/*
1630struct loadInfo {
1631  FILE *f;
1632  StripChartJet who;
1633};
1634
1635void getLoad(fd, info)
1636     int fd;
1637     struct loadInfo *info;
1638{
1639  char s[40];
1640  int l1, l2, l3;
1641
1642  fscanf(info->f, "%s %d.%d[%d]\n", s, &l1, &l2, &l3);
1643  XjStripChartData(info->who, 100*l1+l2);
1644}
1645
1646int load(init, foo, data)
1647     StripChartInit *init;
1648     int foo;
1649     caddr_t data;
1650{
1651  FILE *loadFile;
1652  char command[80];
1653  struct loadInfo *info;
1654
1655  sprintf(command, "%s %d", LOADST, init->interval/1000);
1656  loadFile = popen(command, "r");
1657  info = (struct loadInfo *)XjMalloc(sizeof(struct loadInfo));
1658  info->who = init->j;
1659  info->f = loadFile;
1660
1661  XjReadCallback((XjCallbackProc)getLoad, fileno(loadFile), info);
1662  return 0;
1663}
1664
1665int cpu(where)
1666     int *where;
1667{
1668  double l;
1669
1670  getcpu(NULL, NULL, &l);
1671  *where = (int)(l * 100.0);
1672  return 0;
1673}
1674
1675int pstat(where)
1676     int *where;
1677{
1678  FILE *ps;
1679  static int Pused, Ptext, Pfree, Pwasted, Pmissing;
1680  static int Pnum[6], Psize[6];
1681  static struct timeval last = { 0, 0 };
1682  struct timeval now;
1683
1684  gettimeofday(&now, NULL);
1685  if (now.tv_sec - last.tv_sec > 60)
1686    {
1687      last = now;
1688
1689      ps = popen("/etc/pstat -s", "r");
1690
1691      fscanf(ps, "%dk used (%dk text), %dk free, %dk wasted, %dk missing\n",
1692             &Pused, &Ptext, &Pfree, &Pwasted, &Pmissing);
1693      fscanf(ps, "avail: %d*%dk %d*%dk %d*%dk %d*%dk %d*%dk %d*%dk\n",
1694             &Pnum[0], &Psize[0], &Pnum[1], &Psize[1], &Pnum[2], &Psize[2],
1695             &Pnum[3], &Psize[3], &Pnum[4], &Psize[4], &Pnum[5], &Psize[5]);
1696
1697      pclose(ps);
1698    }
1699
1700  *where = 100 * Pused / (Pused + Pfree + Pwasted + Pmissing);
1701
1702  return 0;
1703}
1704*/
1705
1706
1707int std_out(fromJet, what, data)
1708     Jet fromJet;
1709     char *what;
1710     caddr_t data;
1711{
1712  printf(what);
1713  fflush(stdout);
1714  return 0;                             /* For linting... */
1715}
1716
1717int std_err(fromJet, what, data)
1718     Jet fromJet;
1719     char *what;
1720     caddr_t data;
1721{
1722  fprintf(stderr, what);
1723  fflush(stderr);
1724  return 0;                             /* For linting... */
1725}
1726
1727
1728XjCallbackRec callbacks[] =
1729{
1730  /* tree operations */
1731  { "createTree", createTree },
1732  { "createMapTree", createMapTree },
1733  { "destroyTree", destroyTree },
1734  { "warpTree", warpTree },
1735  { "mapTree", mapTree },
1736  { "unmapTree", unmapTree },
1737  { "printTree", printTree },
1738  /* set operations */
1739  { "createSet", createSet },
1740  { "createMapSet", createMapSet },
1741  { "destroySet", destroySet },
1742  { "warpSet", warpSet },
1743  { "mapSet", mapSet },
1744  { "unmapSet", unmapSet },
1745  /* misc */
1746  { "quit", quit },
1747  { "exec", exec },
1748  { "sh", sh },
1749  { "toggleHelp", toggleHelp },
1750  { "toggleVerify", toggleVerify },
1751  { "debug", debug },
1752  { "usage", usage },
1753  { "logout", logout },
1754  { "delete", delete },
1755  { "deleteParent", deleteParent },
1756  { "printMenu", printMenu },
1757  { "lowerMenu", lowerMenu },
1758  { "cd", cd },
1759  { "attach", attach },
1760  { "add", add },
1761  { "setup", setup },
1762  { "addMenus", addMenus },
1763  { "verify", verify },
1764  { "restart", restart },
1765  { "message", message },
1766  { "stdout", std_out },
1767  { "stderr", std_err },
1768  { "enableGnome", enableGnome },
1769/*
1770  { "load", load },
1771  { "cpu", cpu },
1772  { "pstat", pstat },
1773*/
1774};
1775
1776main(argc, argv)
1777int argc;
1778char **argv;
1779{
1780  Display *display;
1781  char *home;
1782  char userFile[100];
1783  Window handle = (Window) NULL;
1784  int cd[50];
1785  Set *tmp, *list;
1786  char *nameOptions[50];
1787  int i, numOptions = 0;
1788  int count, sign = 1;
1789  Status e;
1790  Jet handlejet;
1791  struct sigaction act;
1792  sigemptyset(&act.sa_mask);
1793  act.sa_flags = 0;
1794
1795  expand("~/.dashrc", userFile); /* Also guarantees expand() is initialized
1796                                    in this process, not multiple times in
1797                                    children. */
1798
1799  (void)XSetIOErrorHandler(fatal);
1800
1801  root = XjCreateRoot(&argc, argv, DASH, userFile,
1802                      opTable, XjNumber(opTable));
1803
1804  XjLoadFromResources(NULL,
1805                      NULL,
1806                      programClass,
1807                      programName,
1808                      appResources,
1809                      XjNumber(appResources),
1810                      (caddr_t) &parms);
1811  display = root->core.display;
1812
1813  dashAtom = XInternAtom(display, DASH_ATOM, False);
1814
1815  /*
1816   * Parse special creation options out of command line.
1817   */
1818  argv++;
1819  while (*argv)
1820    {
1821      if (!strcmp(*argv, "-show"))
1822        sign = 1;
1823      else
1824        {
1825          if (!strcmp(*argv, "-hide"))
1826            sign = 0;
1827          else
1828            {
1829              if (**argv == '+' || **argv == '-')
1830                {
1831                  cd[numOptions] = (**argv) == '+' ? 0 : 1;
1832                  nameOptions[numOptions++] = *argv + 1;
1833                }
1834              else
1835                {
1836                  cd[numOptions] = sign;
1837                  nameOptions[numOptions++] = *argv;
1838                }
1839            }
1840        }
1841      argv++;
1842    }
1843
1844  if (numOptions == 0)
1845    {
1846      nameOptions[0] = "default";
1847      cd[0] = 1;
1848      numOptions = 1;
1849    }
1850
1851  if (!parms.run) /* don't get a handle if we don't care */
1852    handle = findDASH(display);
1853
1854  if (!handle && (parms.send || parms.kill))
1855    {
1856      /* try harder... */
1857      count = 3;
1858      while (!handle && count)
1859        {
1860          sleep(10);
1861          handle = findDASH(display);
1862          count--;
1863        }
1864
1865      if (!handle)
1866        {
1867          char errtext[100];
1868
1869          sprintf(errtext, "couldn't find a running %s", programName);
1870          XjWarning(errtext);
1871          XjExit(1);
1872        }
1873    }
1874
1875  /*
1876   * -kill
1877   */
1878  if (handle && parms.kill)
1879    {
1880      if (sendEvent(display, handle, DASH_KILL, NULL))
1881        XjExit(0);
1882      else
1883        XjFatalError("sendEvent failed");
1884    }
1885
1886  /*
1887   * -restart
1888   */
1889  if (handle && parms.restart)
1890    {
1891      if (sendEvent(display, handle, DASH_RESTART, NULL))
1892        XjExit(0);
1893      else
1894        XjFatalError("sendEvent failed");
1895    }
1896
1897  /*
1898   * -debug
1899   */
1900  if (handle && parms.debug)
1901    {
1902      if (sendEvent(display, handle, DASH_DEBUG, NULL))
1903        XjExit(0);
1904      else
1905        XjFatalError("sendEvent failed");
1906    }
1907
1908  /*
1909   * Either -send, or a dash exists and not -run
1910   */
1911  if (handle)
1912    {
1913      for (i = 0; i < numOptions; i++)
1914        {
1915          if (cd[i] == 0)
1916            e = sendEvent(display, handle, DASH_UNMAP, nameOptions[i]);
1917          else
1918            e = sendEvent(display, handle, DASH_CREATEORMAP, nameOptions[i]);
1919          if (!e)
1920            XjFatalError("sendEvent failed");
1921        }
1922      XjExit(0);
1923    }
1924
1925  /*
1926   * Now we deal with the rest of the command line args...
1927   */
1928  if (!parms.nofork)
1929    {
1930      switch (fork())
1931        {
1932        case 0:                 /* child */
1933          break;
1934        case -1:                /* error */
1935          perror ("Can't fork");
1936          XjExit(-1);
1937        default:                /* parent */
1938          XjExit(0);
1939        }
1940    }
1941
1942  if (parms.startString == NULL)
1943    parms.startString = "Start %s?";
1944
1945  DEBUG = parms.debug;
1946
1947  XjRegisterCallbacks(callbacks, XjNumber(callbacks));
1948
1949  for (i = 0; i < numOptions; i++)
1950    {
1951      tmp = resolveName(nameOptions[i], NULL);
1952      if (cd[i] == 1)
1953        for (list = tmp; list != NULL; list = list->next)
1954          (void)XjVaCreateJet(list->name, treeJetClass, root, NULL, NULL);
1955      freeSet(tmp);
1956    }
1957
1958  XjRealizeJet(root);
1959  /*
1960   * Okay, so there is no handle...  we'll create one and install the
1961   * property on the root.
1962   */
1963  handlejet = XjVaCreateJet("handleWindow", windowJetClass, root,
1964                            XjNoverrideRedirect, True,
1965                            XjNmapped, False,
1966                            XjNx, -100,
1967                            XjNy, -100,
1968                            XjNwidth, 1,
1969                            XjNheight, 1,
1970                            XjNtitle, DASH_ATOM,
1971                            NULL, NULL);
1972  XjRealizeJet(handlejet);
1973  handle = XjWindow(handlejet);
1974  XChangeProperty(display, handle, dashAtom,
1975                  XA_STRING, 8, PropModeReplace,
1976                  (unsigned char *) programName, strlen(programName));
1977  XChangeProperty(display, RootWindow(display, 0), nameAtom,
1978                  XA_WINDOW, 32, PropModeReplace,
1979                  (unsigned char *) &handle, 1);
1980  XFlush(display);
1981
1982
1983
1984   act.sa_handler= (void (*)())checkChildren;
1985   (void) sigaction(SIGCHLD, &act, NULL);
1986
1987#ifdef HAVE_KRB4
1988  if (parms.checkTickets)
1989    checkTkts(0,0);
1990#endif /* HAVE_KRB4 */
1991
1992  XjEventLoop(root);
1993}
Note: See TracBrowser for help on using the repository browser.