source: git/Singular/feResource.cc @ f413ec5

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