source: git/resources/feResource.cc @ 394d507

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