source: git/Singular/feResource.cc @ b39d4d

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