source: git/Singular/feResource.cc @ ce3f53e

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