source: git/Singular/feResource.cc @ 6e56de

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