source: git/resources/feResource.cc @ a0a5d0

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