source: git/resource/feResource.cc @ ac554b

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