source: git/Singular/feResource.cc @ 48aa42

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