source: git/resources/feResource.cc @ d34978

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