source: git/Singular/feResource.cc @ b29464

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