source: git/Singular/feResource.cc @ 2c694a2

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