source: git/Singular/feResource.cc @ 8654b5

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