source: git/kernel/feResource.cc @ 98938c

spielwiese
Last change on this file since 98938c was df4c47, checked in by Hans Schönemann <hannes@…>, 20 years ago
*hannes: fixed idx git-svn-id: file:///usr/local/Singular/svn/trunk@7260 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 19.3 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: feResource.cc,v 1.2 2004-07-12 15:02:08 Singular Exp $ */
5/*
6* ABSTRACT: management of resources
7*/
8
9#include <stdlib.h>
10#include <unistd.h>
11#include <string.h>
12
13#include "mod2.h"
14#ifdef AIX_4
15#define HAVE_PUTENV 1
16#endif
17
18#include "distrib.h"
19#include "dError.h"
20#if !defined(ESINGULAR) && !defined(TSINGULAR)
21#include "febase.h"
22#include "omalloc.h"
23#else
24char* feResource(const char id, int warn = -1);
25char* feResource(const char* key, int warn = -1);
26#include "dError.c"
27#endif
28
29// define RESOURCE_DEBUG for chattering about resource management
30// #define RESOURCE_DEBUG
31
32#if defined(MAKE_DISTRIBUTION)
33#if defined(ix86_Win) && ! defined(__CYGWIN__)
34#define SINGULAR_DEFAULT_DIR "/Singular/"S_VERSION1
35#elif defined(macintosh)
36#define SINGULAR_DEFAULT_DIR "Macintosh HD:Singular:"S_VERSION1
37#else // unix
38#define SINGULAR_DEFAULT_DIR "/usr/local/Singular/"S_VERSION1
39#endif
40#else // ! defined(MAKE_DISTRIBUTION)
41#define SINGULAR_DEFAULT_DIR S_ROOT_DIR
42#endif // defined(MAKE_DISTRIBUTION)
43
44/*****************************************************************
45 *
46 * Declarations: Data  structures
47 *
48 *****************************************************************/
49typedef enum {feResUndef = 0, feResBinary, feResDir, feResFile, feResUrl, feResPath} feResourceType;
50
51typedef struct feResourceConfig_s
52{
53  char*           key;   // key to identify resource
54  char            id;    // char id to identify resource
55  feResourceType  type;  // type of Resource
56  char*           env;   // env variable to look for
57  char*           fmt;   // format string -- see below for epxlaination
58  char*                        value; // what it was set to
59} feResourceConfig_s;
60typedef feResourceConfig_s * feResourceConfig;
61
62// feSprintf transforms format strings as follows:
63// 1.) substrings of the form %c (c being a letter) are replaced by respective resource value
64// 2.) substrings of the form $string are replaced by value of resp. env variable
65
66// feCleanResource makes furthermore  the following transformations (except for URL resources)
67// 1.) '/' characters are replaced by respective directory - separators
68// 2.) ';' characters are replaced by respective path separators
69static feResourceConfig_s feResourceConfigs[25] =
70{
71  {"SearchPath",    's',     feResPath,  NULL,
72   "$SINGULARPATH;"
73   "%b/LIB;"
74   "%r/LIB;"
75   "%r/../LIB;"
76   "%d/LIB;"
77   "%d/../LIB"
78   ""},
79  {"Singular",  'S',    feResBinary,"SINGULAR_EXECUTABLE",  "%d/"S_UNAME"/Singular",""},
80  {"BinDir",    'b',    feResDir,   "SINGULAR_BIN_DIR",     "%d/"S_UNAME            ""},
81  {"RootDir",   'r',    feResDir,   "SINGULAR_ROOT_DIR",    "%b/..",                ""},
82  {"DefaultDir",'d',    feResDir,   "SINGULAR_DEFAULT_DIR",  SINGULAR_DEFAULT_DIR,  ""},
83  {"InfoFile",  'i',    feResFile,  "SINGULAR_INFO_FILE",   "%r/info/singular.hlp", ""},
84  {"IdxFile",   'x',    feResFile,  "SINGULAR_IDX_FILE",    "%r/doc/singular.idx",  ""},
85  {"HtmlDir",   'h',    feResDir,   "SINGULAR_HTML_DIR",    "%r/html",              ""},
86  {"ManualUrl", 'u',    feResUrl,   "SINGULAR_URL",         "http://www.singular.uni-kl.de/Manual/"S_VERSION1,    ""},
87  {"ExDir",      'm',   feResDir,   "SINGULAR_EXAMPLES_DIR","%r/examples",              ""},
88#if !defined(macintosh)
89  {"netscape",  'N',    feResBinary,"NETSCAPE",             "%b/netscape",          ""},
90  {"info",      'I',    feResBinary,"INFO",                 "%b/info",              ""},
91  {"tkinfo",    'T',    feResBinary,"TKINFO",               "%b/tkinfo",            ""},
92#ifdef ix86_Win
93  {"rxvt",     'X',    feResBinary,"RXVT",                "%b/rxvt",             ""},
94#else
95  {"xterm",     'X',    feResBinary,"XTERM",                "%b/xterm",             ""},
96#endif
97  {"Path",      'p',    feResPath,  NULL,                   "%b;$PATH",         ""},
98#endif // ! defined(macintosh)
99
100#ifdef ESINGULAR
101  {"emacs",    'E',    feResBinary, "ESINGULAR_EMACS",      "%b/emacs",              ""},
102  {"xemacs",    'A',    feResBinary, "ESINGULAR_EMACS",      "%b/xemacs",              ""},
103  {"SingularEmacs",'M',feResBinary, "ESINGULAR_SINGULAR",    "%b/Singular",           ""},
104  {"EmacsLoad",'l',    feResFile,   "ESINGULAR_EMACS_LOAD",  "%e/.emacs-singular",             ""},
105  {"EmacsDir",  'e',    feResDir,   "ESINGULAR_EMACS_DIR",   "%r/emacs",             ""},
106#elif defined(TSINGULAR)
107  {"SingularXterm",'M',feResBinary, "TSINGULAR_SINGULAR",    "%b/Singular",           ""},
108#else
109  {"EmacsDir",  'e',    feResDir,   "SINGULAR_EMACS_DIR",   "%r/emacs",             ""},
110#endif
111  {NULL, 0, feResUndef, NULL, NULL, NULL}, // must be the last record
112};
113
114
115/*****************************************************************
116 *
117 * Declarations: Local variables / functions
118 *
119 *****************************************************************/
120char* feArgv0=NULL;
121#define MAXRESOURCELEN 5*MAXPATHLEN
122
123char fePathSep =
124#if defined(ix86_Win)
125';'
126#elif defined(macintosh)
127','
128#else
129':'
130#endif
131;
132
133static feResourceConfig feGetResourceConfig(const char id);
134static feResourceConfig feGetResourceConfig(const char* key);
135static char* feResource(feResourceConfig config, int warn);
136static char* feResourceDefault(feResourceConfig config);
137static char* feInitResource(feResourceConfig config, int warn);
138static char* feGetExpandedExecutable();
139static BOOLEAN feVerifyResourceValue(feResourceType type, char* value);
140static char* feCleanResourceValue(feResourceType type, char* value);
141static char* feCleanUpFile(char* fname);
142static char* feCleanUpPath(char* path);
143static void mystrcpy(char* d, char* s);
144static char* feSprintf(char* s, const char* fmt, int warn = -1);
145#if defined(ix86_Win) && defined(__GNUC__)
146// utility function of Cygwin32:
147extern "C" int cygwin32_posix_path_list_p (const char *path);
148#endif
149
150/*****************************************************************
151 *
152 * Public functions
153 *
154 *****************************************************************/
155char* feResource(const char* key, int warn)
156{
157  return feResource(feGetResourceConfig(key), warn);
158}
159
160char* feGetResource(const char id)
161{
162  return feResource(feGetResourceConfig(id), -1);
163}
164
165char* feResource(const char id, int warn)
166{
167  return feResource(feGetResourceConfig(id), warn);
168}
169
170char* feResourceDefault(const char id)
171{
172  return feResourceDefault(feGetResourceConfig(id));
173}
174
175char* feResourceDefault(const char* key)
176{
177  return feResourceDefault(feGetResourceConfig(key));
178}
179
180void feInitResources(char* argv0)
181{
182#if defined(ix86_Win) && defined(__GNUC__)
183  if (cygwin32_posix_path_list_p (getenv("PATH")))
184    fePathSep = ':';
185#endif
186  feArgv0 = omStrDup(argv0);
187#ifdef RESOURCE_DEBUG
188  printf("feInitResources: entering with argv0=%s=\n", argv0);
189#endif
190  // init some Resources
191  feResource('b');
192  feResource('r');
193  // don't complain about stuff when initializing SingularPath
194  feResource('s',0);
195
196#if defined(HAVE_SETENV) || defined(HAVE_PUTENV)
197  char* path = feResource('p');
198#ifdef RESOURCE_DEBUG
199  printf("feInitResources: setting path with argv0=%s=\n", path);
200#endif
201#ifdef HAVE_PUTENV
202  if (path != NULL) { char *s=(char *)omAlloc0(strlen(path)+6);
203                      sprintf(s,"PATH=%s",path);
204                      putenv(s);
205                    }
206#else
207  if (path != NULL) setenv("PATH", path, 1);
208#endif
209#endif
210}
211
212void feReInitResources()
213{
214  int i = 0;
215  while (feResourceConfigs[i].key != NULL)
216  {
217    if (feResourceConfigs[i].value != "")
218    {
219      if (feResourceConfigs[i].value != NULL)
220        omFree(feResourceConfigs[i].value);
221      feResourceConfigs[i].value = "";
222    }
223    i++;
224  }
225#ifdef RESOURCE_DEBUG
226  printf("feInitResources: entering with argv0=%s=\n", feArgv0);
227#endif
228  // init some Resources
229  feResource('b');
230  feResource('r');
231  // don't complain about stuff when initializing SingularPath
232  feResource('s',0);
233}
234
235/*****************************************************************
236 *
237 * Local functions
238 *
239 *****************************************************************/
240static feResourceConfig feGetResourceConfig(const char id)
241{
242  int i = 0;
243  while (feResourceConfigs[i].key != NULL)
244  {
245    if (feResourceConfigs[i].id == id) return &(feResourceConfigs[i]);
246    i++;
247  }
248  return NULL;
249}
250
251static feResourceConfig feGetResourceConfig(const char* key)
252{
253  int i = 0;
254  while (feResourceConfigs[i].key != NULL)
255  {
256    if (strcmp(feResourceConfigs[i].key, key) == 0)
257      return &(feResourceConfigs[i]);
258    i++;
259  }
260  return NULL;
261}
262
263static char* feResource(feResourceConfig config, int warn)
264{
265  if (config == NULL) return NULL;
266  if (config->value != NULL && *(config->value) != '\0') return config->value;
267  return feInitResource(config, warn);
268}
269
270static char* feResourceDefault(feResourceConfig config)
271{
272  if (config == NULL) return NULL;
273  char* value = (char*) omAlloc(MAXRESOURCELEN);
274  feSprintf(value, config->fmt, -1);
275  return value;
276}
277
278static char* feInitResource(feResourceConfig config, int warn)
279{
280  assume(config != NULL);
281#ifdef RESOURCE_DEBUG
282  printf("feInitResource: entering for %s\n", config->key);
283#endif
284
285  char value[MAXRESOURCELEN];
286  // now we have to work
287  // First, check Environment variable
288  if (config->env != NULL)
289  {
290    char* evalue = getenv(config->env);
291    if (evalue != NULL)
292    {
293#ifdef RESOURCE_DEBUG
294      printf("feInitResource: Found value from env:%s\n", evalue);
295#endif
296      strcpy(value, evalue);
297      if (config->type == feResBinary  // do not verify binaries
298          ||
299          feVerifyResourceValue(config->type,
300                                feCleanResourceValue(config->type, value)))
301      {
302#ifdef RESOURCE_DEBUG
303        printf("feInitResource: Set value of %s to =%s=\n", config->key, value);
304#endif
305        config->value = omStrDup(value);
306        return config->value;
307      }
308    }
309  }
310
311  *value = '\0';
312  // Special treatment of executable
313  if (config->id == 'S')
314  {
315    char* executable = feGetExpandedExecutable();
316    if (executable != NULL)
317    {
318#ifdef RESOURCE_DEBUG
319      printf("exec:%s\n", executable);
320#endif
321      strcpy(value, executable);
322#ifdef RESOURCE_DEBUG
323      printf("value:%s\n", value);
324#endif
325      omFree(executable);
326    }
327  }
328  // and bindir
329  else if (config->id == 'b')
330  {
331    char* executable = feResource('S');
332#ifdef RESOURCE_DEBUG
333      printf("feInitResource: Get %s from %s\n", config->key, executable);
334#endif
335    if (executable != NULL)
336    {
337      strcpy(value, executable);
338      executable = strrchr(value, DIR_SEP);
339      if (executable != NULL) *executable = '\0';
340    }
341  }
342
343#ifdef RESOURCE_DEBUG
344  printf("value:%s\n", value);
345#endif
346
347  if (*value == '\0' && config->fmt != NULL )
348  {
349    feSprintf(value, config->fmt, warn);
350  }
351  else if (config->fmt == NULL)
352  {
353    sprintf(value, "Wrong Resource Specification of %s", config->key);
354    dReportBug(value);
355    return NULL;
356  }
357
358  // Clean and verify
359  if (feVerifyResourceValue(config->type,
360                            feCleanResourceValue(config->type, value)))
361  {
362#ifdef RESOURCE_DEBUG
363    printf("feInitResource: Set value of %s to =%s=\n", config->key, value);
364#endif
365    config->value = omStrDup(value);
366    return config->value;
367  }
368  else if (config->type == feResBinary)
369  {
370    // for binaries, search through PATH once more
371    char* executable = omFindExec(config->key, value);
372    if (executable != NULL)
373    {
374      if (feVerifyResourceValue(config->type,
375                                feCleanResourceValue(config->type, value)))
376      {
377        config->value = omStrDup(value);
378#ifdef RESOURCE_DEBUG
379        printf("feInitResource: Set value of %s to =%s=\n", config->key, config->value);
380#endif
381        return config->value;
382      }
383    }
384  }
385
386  // issue warning if explicitely requested, or if
387  // this value is gotten for the first time
388  if (warn > 0 || (warn < 0 && config->value != NULL))
389  {
390    Warn("Could not get %s. ", config->key);
391    Warn("Either set environment variable %s to %s,",
392         config->env, config->key);
393    feSprintf(value, config->fmt, warn);
394    Warn("or make sure that %s is at %s", config->key, value);
395  }
396#ifdef RESOURCE_DEBUG
397      printf("feInitResource: Set value of %s to NULL", config->key);
398#endif
399  config->value = NULL;
400  return NULL;
401}
402
403static char* feGetExpandedExecutable()
404{
405  if (feArgv0 == NULL || *feArgv0 == '\0')
406  {
407    if (feArgv0 == NULL) dReportBug("feArgv0 == NULL");
408    else dReportBug("feArgv0 == ''");
409    return NULL;
410  }
411#ifndef macintosh
412#ifdef ix86_Win // stupid WINNT sometimes gives you argv[0] within ""
413  if (*feArgv0 == '"')
414  {
415    int l = strlen(feArgv0);
416    if (feArgv0[l-1] == '"')
417    {
418      feArgv0[l-1] = '\0';
419      feArgv0++;
420    }
421  }
422#endif
423#ifdef RESOURCE_DEBUG
424  printf("feGetExpandedExecutable: calling find_exec with =%s=\n", feArgv0);
425#endif
426  char executable[MAXRESOURCELEN];
427  char* value = omFindExec(feArgv0, executable);
428#ifdef RESOURCE_DEBUG
429  printf("feGetExpandedExecutable: find_exec exited with =%s=%d\n", executable, access(executable, X_OK));
430#endif
431  if (value == NULL)
432  {
433    char message[MAXRESOURCELEN];
434    sprintf(message, "Could not get expanded executable from %s", feArgv0);
435    dReportBug(message);
436    return NULL;
437  }
438  return omStrDup(value);
439#else // macintosh
440  return feArgv0;
441#endif
442}
443
444
445static BOOLEAN feVerifyResourceValue(feResourceType type, char* value)
446{
447#ifdef RESOURCE_DEBUG
448  printf("feVerifyResourceValue: entering with =%s=\n", value);
449  printf("%d:%d\n", access(value, R_OK), access(value, X_OK));
450#endif
451  switch(type)
452  {
453      case feResUrl:
454      case feResPath:
455        return TRUE;
456
457      case feResFile:
458        return ! access(value, R_OK);
459
460      case feResBinary:
461      case feResDir:
462        return ! access(value, X_OK);
463
464      default:
465        return FALSE;
466  }
467}
468
469/*****************************************************************
470 *
471 * Cleaning/Transformations of resource values
472 *
473 *****************************************************************/
474
475static char* feCleanResourceValue(feResourceType type, char* value)
476{
477  if (value == NULL || *value == '\0') return value;
478#ifdef RESOURCE_DEBUG
479      printf("Clean value:%s\n", value);
480#endif
481#ifdef ix86_Win
482#ifdef RESOURCE_DEBUG
483      printf("Clean WINNT value:%s\n", value);
484#endif
485  if (type == feResBinary)
486  {
487    int l = strlen(value);
488    if (l < 4 || (strcmp(&value[l-4], ".exe") != 0 &&
489                  strcmp(&value[l-4], ".EXE") != 0))
490      strcat(value, ".exe");
491  }
492#endif
493  if (type == feResFile || type == feResBinary || type == feResDir)
494    return feCleanUpFile(value);
495  if (type == feResPath)
496    return feCleanUpPath(value);
497  return value;
498}
499
500static char* feCleanUpFile(char* fname)
501{
502  char* fn, *s;
503
504#ifdef RESOURCE_DEBUG
505  printf("feCleanUpFile: entering with =%s=\n", fname);
506#endif
507  // Remove unnecessary .. and //
508  for (fn = fname; *fn != '\0'; fn++)
509  {
510    if (*fn == '/')
511    {
512      if (*(fn+1) == '\0')
513      {
514        if (fname != fn) *fn = '\0';
515        break;
516      }
517      if (*(fn + 1) == '/' && (fname != fn))
518      {
519        mystrcpy(fn, fn+1);
520        fn--;
521      }
522      else if (*(fn+1) == '.')
523      {
524        if (*(fn+2) == '.' && (*(fn + 3) == '/' || *(fn + 3) == '\0'))
525        {
526          *fn = '\0';
527          s = strrchr(fname, '/');
528          if (s != NULL)
529          {
530            mystrcpy(s+1, fn + (*(fn + 3) != '\0' ? 4 : 3));
531            fn = s-1;
532          }
533          else
534          {
535            *fn = '/';
536          }
537        }
538        else if (*(fn+2) == '/' || *(fn+2) == '\0')
539        {
540          mystrcpy(fn+1, fn+3);
541          fn--;
542        }
543      }
544    }
545  }
546
547#ifdef macintosh
548  // replace / and .. by DIR_SEP and UP_DIR
549  fn = fname;
550  while (*fn != NULL)
551  {
552    if (*fn == '.' && *(fn + 1) == '.')
553    {
554      mystrcpy(fn , fn + 2);
555    }
556    else
557    {
558      if (*fn == '/') *fn = DIR_SEP;
559      fn++;
560    }
561  }
562#endif
563
564#ifdef RESOURCE_DEBUG
565  printf("feCleanUpFile: leaving with =%s=\n", fname);
566#endif
567  return fname;
568}
569
570// remove duplicates dir resp. those which do not exist
571static char* feCleanUpPath(char* path)
572{
573#ifdef RESOURCE_DEBUG
574  printf("feCleanUpPath: entering with: =%s=\n", path);
575#endif
576  if (path == NULL) return path;
577
578  int n_comps = 1, i, j;
579  char* opath = path;
580  char** path_comps;
581
582  for (; *path != '\0'; path++)
583  {
584    if (*path == fePathSep) n_comps++;
585    if (*path == ';')
586    {
587      *path = fePathSep;
588      n_comps++;
589    }
590  }
591
592  path_comps = (char**) omAlloc(n_comps*sizeof(char*));
593  path_comps[0]=opath;
594  path=opath;
595  i = 1;
596
597  if (i < n_comps)
598  {
599    while (1)
600    {
601      if (*path == fePathSep)
602      {
603        *path = '\0';
604        path_comps[i] = path+1;
605        i++;
606        if (i == n_comps) break;
607      }
608      path++;
609    }
610  }
611
612  for (i=0; i<n_comps; i++)
613    path_comps[i] = feCleanUpFile(path_comps[i]);
614#ifdef RESOURCE_DEBUG
615  PrintS("feCleanUpPath: after CleanUpName: ");
616  for (i=0; i<n_comps; i++)
617    Print("%s:", path_comps[i]);
618  Print("\n");
619#endif
620
621  for (i=0; i<n_comps;)
622  {
623#ifdef RESOURCE_DEBUG
624    if (access(path_comps[i], X_OK | R_OK))
625      Print("feCleanUpPath: remove %d:%s -- can not access\n", i, path_comps[i]);
626#endif
627    if ( ! access(path_comps[i], X_OK | R_OK))
628    {
629      // x- permission is granted -- we assume that it is a dir
630      for (j=0; j<i; j++)
631      {
632        if (strcmp(path_comps[j], path_comps[i]) == 0)
633        {
634          // found a duplicate
635#ifdef RESOURCE_DEBUG
636          Print("feCleanUpPath: remove %d:%s -- equal to %d:%s\n", j, path_comps[j], i, path_comps[i]);
637#endif
638          j = i+1;
639          break;
640        }
641      }
642      if (j == i)
643      {
644        i++;
645        continue;
646      }
647    }
648    // now we can either not access or found a duplicate
649    path_comps[i] = NULL;
650    for (j=i+1; j<n_comps; j++)
651        path_comps[j-1] = path_comps[j];
652    n_comps--;
653  }
654
655
656  // assemble everything again
657  for (path=opath, i=0;i<n_comps-1;i++)
658  {
659    strcpy(path, path_comps[i]);
660    path += strlen(path);
661    *path = fePathSep;
662    path++;
663  }
664  if (n_comps)
665  {
666    strcpy(path, path_comps[i]);
667  }
668  else
669  {
670    *opath = '\0';
671  }
672  omFree(path_comps);
673#ifdef RESOURCE_DEBUG
674  Print("feCleanUpPath: leaving with path=%s=\n", opath);
675#endif
676  return opath;
677}
678
679// strcpy where source and destination may overlap
680static void mystrcpy(char* d, char* s)
681{
682  assume(d != NULL && s != NULL);
683  while (*s != '\0')
684  {
685    *d = *s;
686    d++;
687    s++;
688  }
689  *d = '\0';
690}
691
692/*****************************************************************
693 *
694 * feSprintf
695 *
696 *****************************************************************/
697static char* feSprintf(char* s, const char* fmt, int warn)
698{
699  char* s_in = s;
700  if (fmt == NULL) return NULL;
701
702  while (*fmt != '\0')
703  {
704    *s = *fmt;
705
706    if (*fmt == '%' && *(fmt + 1) != '\0')
707    {
708      fmt++;
709      char* r = feResource(*fmt, warn);
710      if (r != NULL)
711      {
712        strcpy(s, r);
713        s += strlen(r) - 1;
714      }
715      else
716      {
717        s++;
718        *s = *fmt;
719      }
720    }
721    else if (*fmt == '$' && *(fmt + 1) != '\0')
722    {
723      fmt++;
724      char* v = s + 1;
725      while (*fmt == '_' ||
726             (*fmt >= 'A' && *fmt <= 'Z') ||
727             (*fmt >= 'a' && *fmt <= 'z'))
728      {
729        *v = *fmt;
730        v++;
731        fmt++;
732      }
733      fmt--;
734      *v = '\0';
735      v = getenv(s + 1);
736      if (v != NULL) strcpy(s, v);
737      s += strlen(s) - 1;
738    }
739    s++;
740    fmt++;
741  }
742  *s = '\0';
743  return s_in;
744}
745
746void feStringAppendResources(int warn)
747{
748  int i = 0;
749  char* r;
750  StringAppend("%-10s:\t%s\n", "argv[0]", feArgv0);
751  while (feResourceConfigs[i].key != NULL)
752  {
753    r = feResource(feResourceConfigs[i].key, warn);
754    StringAppend("%-10s:\t%s\n", feResourceConfigs[i].key,
755                 (r != NULL ? r : ""));
756    i++;
757  }
758}
Note: See TracBrowser for help on using the repository browser.