source: git/libpolys/resources/feResource.cc @ bd795d

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