source: git/Singular/feResource.cc @ c06a32

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