PIPS
file.c
Go to the documentation of this file.
1 /*
2 
3  $Id: file.c 23583 2019-07-12 06:17:23Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 
28 #include <unistd.h>
29 #include <stdlib.h>
30 
31 #include <stdio.h>
32 #include <string.h>
33 #include <limits.h>
34 #include <errno.h>
35 #include <ctype.h>
36 
37 #include <sys/stat.h>
38 #include <sys/param.h>
39 #include <sys/types.h>
40 #include <sys/wait.h>
41 
42 #include <dirent.h>
43 #include <regex.h>
44 
45 #include "genC.h"
46 #include "misc.h"
47 
48 /* FC 2015-07-20: yuk, moved out to prevent an include cycle dependency
49  * #include "properties.h"
50  */
51 extern bool get_bool_property(const string);
52 extern char* get_string_property(const char*);
53 
54 /* @return a file descriptor.
55  */
56 FILE * check_fopen(const char * file, const char * mode)
57 {
58  FILE * fd = fopen(file, mode);
59  if (fd==(FILE*)NULL)
60  {
61  pips_user_warning("fopen failed on file \"%s\" (mode \"%s\")\n%s\n",
62  file, mode, strerror(errno));
63  }
64  return fd;
65 }
66 
67 FILE * safe_fopen(const char *filename, const char *what)
68 {
69  FILE * f;
70  if((f = fopen( filename, what)) == (FILE *) NULL) {
71  pips_internal_error("fopen failed on file %s\n%s",
72  filename, strerror(errno));
73  }
74  return f;
75 }
76 
77 int safe_fclose(FILE * stream, const char *filename)
78 {
79  if(fclose(stream) == EOF) {
80  if(errno==ENOSPC)
81  pips_user_irrecoverable_error("fclose failed on file %s (%s)\n",
82  filename, strerror(errno));
83  else
84  pips_internal_error("fclose failed on file %s (%s)",
85  filename, strerror(errno));
86  }
87  return 0;
88 }
89 
90 int safe_fflush(FILE * stream, char *filename)
91 {
92  if (fflush(stream) == EOF)
93  pips_internal_error("fflush failed on file %s (%s)",
94  filename,
95  strerror(errno));
96  return 0;
97 }
98 
99 FILE * safe_freopen(char *filename, char *what, FILE * stream)
100 {
101  FILE *f;
102 
103  if((f = freopen( filename, what, stream)) == (FILE *) NULL) {
104  pips_internal_error("freopen failed on file %s (%s)",
105  filename,
106  strerror(errno));
107  }
108  return f;
109 }
110 
111 int
112 safe_fseek(FILE * stream, long int offset, int wherefrom, char *filename)
113 {
114  if( fseek( stream, offset, wherefrom) != 0) {
115  pips_internal_error("fseek failed on file %s (%s)",
116  filename,
117  strerror(errno));
118  }
119  return(0);
120 }
121 
122 long int
123 safe_ftell(FILE * stream, char *filename)
124 {
125  long int pt;
126  pt = ftell( stream);
127  if((pt == -1L) && (errno != 0)) {
128  pips_internal_error("ftell failed on file %s (%s)",
129  filename,
130  strerror(errno));
131  }
132  return(pt);
133 }
134 
135 void
136 safe_rewind(FILE * stream, char *filename)
137 {
138  rewind( stream );
139  if(errno != 0) {
140  pips_internal_error("rewind failed on file %s (%s)",
141  filename,
142  strerror(errno));
143  }
144 }
145 
146 int
147 safe_fgetc(FILE * stream, char *filename)
148 {
149  int value;
150  if((value = fgetc( stream)) == EOF) {
151  pips_internal_error("fgetc failed on file %s (%s)",
152  filename, strerror(errno));
153  }
154  return(value);
155 }
156 
157 int
158 safe_getc(FILE * stream, char *filename)
159 {
160  int value;
161  if((value = getc( stream)) == EOF ) {
162  pips_internal_error("getc failed on file %s (%s)",
163  filename,
164  strerror(errno));
165  }
166  return(value);
167 }
168 
169 char*
170 safe_fgets(char* s, int n, FILE* stream, char* filename)
171 {
172  if (fgets(s, n, stream) == (char *) NULL) {
173  pips_internal_error("gets failed on file %s (%s)",
174  filename, strerror(errno));
175  }
176  return s;
177 }
178 
179 int safe_fputc( c, stream, filename)
180 char c;
181 FILE * stream;
182 char * filename;
183 {
184  if(fputc( c, stream) == EOF) {
185  pips_internal_error("fputc failed on file %s (%s)",
186  filename, strerror(errno));
187  }
188  return(c);
189 }
190 
191 int safe_putc( c, stream, filename)
192 char c;
193 FILE * stream;
194 char * filename;
195 {
196  if(putc( c, stream) == EOF) {
197  pips_internal_error("putc failed on file %s (%s)",
198  filename, strerror(errno));
199  }
200  return(c);
201 }
202 
203 int safe_fputs( s, stream, filename)
204 char * s, * filename;
205 FILE * stream;
206 {
207  if(fputs( s, stream) == EOF) {
208  pips_internal_error("fputs failed on file %s (%s)",
209  filename, strerror(errno));
210  }
211  return(1);
212 }
213 
214 int safe_fread( ptr, element_size, count, stream, filename)
215 char * ptr, * filename;
216 int element_size;
217 int count;
218 FILE * stream;
219 {
220  if(((int)fread(ptr, element_size, count, stream)) != count) {
221  pips_internal_error("fread failed on file %s (%s)",
222  filename, strerror(errno));
223  }
224  return(count);
225 }
226 
227 int safe_fwrite( ptr, element_size, count, stream, filename)
228 char * ptr, * filename;
229 int element_size;
230 int count;
231 FILE * stream;
232 {
233  if(((int)fwrite(ptr, element_size, count, stream)) != count) {
234  pips_internal_error("fwrite failed on file %s (%s)",
235  filename,
236  strerror(errno));
237  }
238  return(count);
239 }
240 
241 /* returns a sorted arg list of files matching regular expression re
242  in directory 'dir' and with file_name_predicate() returning true on
243  the file name (for example use directory_exists_p to select
244  directories, of file_exists_p to select regular files). re has the
245  ed syntax.
246 
247  Return 0 on success, -1 on directory openning error.
248  */
249 int
251  gen_array_t files, /* an allocated array */
252  string dir, /* the directory we're interested in */
253  string re, /* regular expression */
254  bool (*file_name_predicate)(const char *) /* condition to list a file */)
255 {
256  DIR * dirp;
257  struct dirent * dp;
258  int index = 0;
259 
260  pips_assert("some dir", strcmp(dir, "") != 0);
261 
262  dirp = opendir(dir);
263 
264  if (dirp != NULL)
265  {
266  regex_t re_compiled;
267 
268  if (regcomp(&re_compiled, re, REG_ICASE))
269  pips_user_error("regcomp() failed to compile \"%s\".\n", re);
270 
271  while((dp = readdir(dirp)) != NULL) {
272  if (!regexec(&re_compiled, dp->d_name, 0, NULL, 0))
273  {
274  char * full_file_name =
275  strdup(concatenate(dir, "/", dp->d_name, NULL));
276  if (file_name_predicate(full_file_name))
277  gen_array_dupaddto(files, index++, dp->d_name);
278  free(full_file_name);
279  }
280  }
281 
282  regfree(&re_compiled);
283 
284  closedir(dirp);
285  }
286  else
287  return -1;
288 
289  gen_array_sort(files);
290  return 0;
291 }
292 
293 
294 /* The same as the previous safe_list_files_in_directory() but with no
295  return code and a call to user error if it cannot open the
296  directory.
297  */
298 void
300  gen_array_t files,
301  string dir,
302  string re,
303  bool (* file_name_predicate)(const char *))
304 {
305  int return_code =
306  safe_list_files_in_directory(files, dir, re, file_name_predicate);
307 
308  if (return_code == -1)
309  pips_user_error("opendir() failed on directory \"%s\", %s.\n",
310  dir, strerror(errno));
311 }
312 
313 bool
314 directory_exists_p(const char * name)
315 {
316  struct stat buf;
317  return (stat(name, &buf) == 0) && S_ISDIR(buf.st_mode);
318 }
319 
320 bool
321 file_exists_p(const char * name)
322 {
323  struct stat buf;
324  return (stat(name, &buf) == 0) && S_ISREG(buf.st_mode);
325 }
326 
327 #define to_escape(c) \
328  !isalnum(c) && c != '_' && c != '/' && c != '.'
329 
330 /* protect a string, for example for use in a system call
331  * list of non escaped characters in the macro above.
332  */
333 char *
334 strescape (const char *source)
335 {
336  size_t new_size = 1; // for \0
337  for (const char *iter=source; *iter; ++iter,++new_size)
338  if (to_escape(*iter)) ++new_size;
339  char *escaped = malloc(sizeof(char)*new_size);
340  char *eiter = escaped;
341  for (const char *iter=source; *iter; ++iter,++eiter) {
342  if (to_escape(*iter)) *eiter++ = '\\';
343  *eiter = *iter;
344  }
345  *eiter=0;
346  return escaped;
347 }
348 
349 #define COLON ':'
350 /* Returns the allocated nth path from colon-separated path string.
351 
352  @param path_list the string that contains a colon-separated path
353 
354  @param n the n-th instance to extract
355 
356  @return an allocated string with the n-th part name
357 
358  If the path is empty or if n is out-of-bound, NULL is returned.
359  The resulting string is *not*escaped, and can contain spaces
360 */
361 string
362 nth_path(const char * path_list, int n)
363 {
364  int len;
365 
366  if (path_list == NULL)
367  return NULL;
368 
369  /* Find the n-th part: */
370  while (*path_list && n > 0)
371  if (*path_list++ == COLON)
372  n--;
373 
374  if (!*path_list)
375  /* Out-of-bound... */
376  return NULL;
377 
378  /* Compute the length up to the COLON or the end of string: */
379  for(len = 0; path_list[len] && path_list[len] != COLON; len++)
380  ;
381 
382  char *unescaped = strndup(path_list, len);
383  return unescaped;
384 }
385 
386 
387 static char *
388 relative_name_if_necessary(const char * name)
389 {
390  if (name[0]=='/' || name[0]=='.') return strdup(name);
391  else return strdup(concatenate("./", name, NULL));
392 }
393 
394 /* returns an allocated string pointing to the file, possibly
395  * with an additional path taken from colon-separated dir_path.
396  * returns NULL if no file was found.
397  */
398 char *
399 find_file_in_directories(const char *file_name, const char *dir_path)
400 {
401  char *path;
402  int n=0;
403  pips_assert("some file name", file_name);
404 
407 
408  if (!dir_path || file_name[0]=='/')
409  return (string) NULL;
410 
411  /* looks for the file with an additional path ahead.
412  */
413  while ((path=nth_path(dir_path, n++)))
414  {
415  char *name = strdup(concatenate(path, "/", file_name, NULL)),
416  *res=NULL;
417  free(path);
418  if (file_exists_p(name))
419  res = relative_name_if_necessary(name);
420  free(name);
421  if (res) return res;
422  }
423 
424  return (string) NULL;
425 }
426 
427 bool
428 file_readable_p(char * name)
429 {
430  struct stat buf;
431  return !stat(name, &buf) && (S_IRUSR & buf.st_mode);
432 }
433 
434 bool
435 create_directory(char *name)
436 {
437  bool success = true;
438 
439  if (directory_exists_p(name)) {
440  pips_internal_error("existing directory: %s", name);
441  }
442 
443  if (mkdir(name, 0777) == -1) {
444  pips_user_warning("cannot create directory: %s (%s)\n",
445  name, strerror(errno));
446  success = false;
447  }
448 
449  return success;
450 }
451 
452 bool
453 purge_directory(char *name)
454 {
455  bool success = true;
456 
457  if (directory_exists_p(name)) {
458  if(system(concatenate("/bin/rm -r ", name, (char*) NULL))) {
459  // FI: this warning should be emitted by a higher-level routine!
460  pips_user_warning("cannot purge directory %s. Check owner rights\n", name);
461  success = false;
462  }
463  else {
464  success = true;
465  }
466  }
467  else {
468  // Well, it's purged if it does not exist...
469  success = true;
470  }
471 
472  return success;
473 }
474 
475 #if !defined(PATH_MAX)
476 #if defined(_POSIX_PATH_MAX)
477 #define PATH_MAX _POSIX_PATH_MAX
478 #else
479 #define PATH_MAX 255
480 #endif
481 #endif
482 
483 /* returns the current working directory name.
484  */
485 char *
486 get_cwd(void)
487 {
488  static char cwd[PATH_MAX]; /* argh */
489  cwd[PATH_MAX-1] = '\0';
490  return getcwd(cwd, PATH_MAX);
491 }
492 
493 /* returns the allocated line read, whatever its length.
494  * returns NULL on EOF. also some asserts. FC 09/97.
495  */
496 char *
497 safe_readline(FILE * file)
498 {
499  int i=0, size = 20, c;
500  char * buf = (char*) malloc(sizeof(char)*size), * res;
501  pips_assert("malloc ok", buf);
502  while((c=getc(file)) && c!=EOF && c!='\n')
503  {
504  if (i==size-1) /* larger for trailing '\0' */
505  {
506  size+=20; buf = (char*) realloc((char*) buf, sizeof(char)*size);
507  pips_assert("realloc ok", buf);
508  }
509  buf[i++] = (char) c;
510  }
511  if (c==EOF && i==0) { res = NULL; free(buf); }
512  else { buf[i++] = '\0'; res = strdup(buf); free(buf); }
513  return res;
514 }
515 
516 /* Assumes "fn" is the name of a text file, opens it, and returns
517  * its nth line (starting with 1) in a newly allocated buffer,
518  * whatever the line length. Returns NULL if it does not exist.
519  *
520  * This function is used by the PIPS preprocessor and its parsers to
521  * print out the line where an error has been detected.
522  */
523 string safe_read_nth_line(string fn, int n)
524 {
525  FILE * fd = safe_fopen(fn, "r");
526  int i = 0;
527 #define MAX_INPUT_LINE_SIZE (200)
529  // Skip n-1 lines
530  for(i=0; i<n-1; i++)
532  string nth_line = safe_readline(fd);
533  safe_fclose(fd, fn);
534  return nth_line;
535 }
536 
537 /* return lines f-l from file fn as a string
538  */
539 string safe_get_line_interval(const string fn, int f, int l)
540 {
541  pips_assert("positive lines", 1 <= f && 1 <= l);
542 
543  if (l < f) {
544  // ooops, empty interval...
545  // TODO: generate an internal error instead
546  // however there are some impact on the validation...
547  string msg;
548  asprintf(&msg, "<empty interval on \"%s\": %d-%d>\n", fn, f, l);
549  return msg;
550  }
551 
552  FILE * fd = safe_fopen(fn, "r");
554 
555  // skip first lines
556  int i;
557  for (i = 1; i < f ; i++) {
558  char * line = safe_readline(fd);
559  pips_assert("expecting a line", line != NULL);
560  free(line);
561  }
562 
563  // keep next lines, although without preprocessor stuff
564  for (i = f; i <= l; i++)
565  {
566  char * line = safe_readline(fd);
567  // pips_assert("expecting a line", line != NULL);
568  if (line == NULL) break;
569 
570  // ??? skip preprocessor #... lines?
571  // I'm not sure that it really works (FC)
572  char * c = line;
573  while (*c && (*c == ' ' || *c == '\t')) c++;
574  if (*c == '#') // ??? preprocessor line?
575  i--;
576  else {
578  string_buffer_append(sb, "\n");
579  }
580 
581  free(line);
582  }
583 
584  // we are done
585  safe_fclose(fd, fn);
586 
587  string extract = string_buffer_to_string(sb);
589 
590  return extract;
591 }
592 
593 /* Assumes "fn" is the name of a text file, opens it, and copies the
594  * lines whose number belongs to [f..l] into file descriptor "out",
595  * except if they have been generated by a C preprocessor. Line
596  * starting with '#' are counted but not copied.
597  *
598  * This function is used by the PIPS preprocessor and its parsers to
599  * print out the lines where an error has been detected.
600  */
601 void safe_copy_line_interval(string fn, int f, int l, FILE * out)
602 {
603  FILE * fd = safe_fopen(fn, "r");
604  int i = 0;
605 #define MAX_INPUT_LINE_SIZE (200)
607 
608  pips_assert("The interval is strictly positive and non empty",
609  f>=1 && l>=f);
610 
611  // Skip f-1 lines
612  for(i=0; i<f-1; i++)
614 
615  // Copy l-f+1 lines
616  int c = l - f + 1;
617  while(c>0) {
618  int n = fgetc(fd);
619  if(n==EOF)
620  break;
621  else {
622  if((char) n == '#') {
623  /* Do not reproduce this line as it was generated by an
624  external preprocessor whose behavior is not controlled */
625  while(c>0) {
626  n = fgetc(fd);
627  if(n==EOF)
628  c = -1; // stop
629  else if((char) n == '\n') {
630  c--; // One useless line has been read
631  break;
632  }
633  }
634  }
635  else {
636  fputc(n, out);
637  if((char) n == '\n')
638  c--;
639  }
640  }
641  }
642 
643  safe_fclose(fd, fn);
644 }
645 
646 /* returns the file as an allocated string.
647  * \n is dropped at the time.
648  */
649 char *
650 safe_readfile(FILE * file)
651 {
652  char * line, * buf=NULL;
653  while ((line=safe_readline(file)))
654  {
655  if (buf)
656  {
657  buf = (char*)
658  realloc(buf, sizeof(char)*(strlen(buf)+strlen(line)+2));
659  strcat(buf, " ");
660  strcat(buf, line);
661  free(line);
662  }
663  else buf = line;
664  }
665  return buf;
666 }
667 
668 void
669 safe_cat(FILE * out, FILE * in)
670 {
671  int c;
672  while ((c=getc(in))!=EOF)
673  if (putc(c, out)==EOF)
674  pips_internal_error("cat failed");
675  safe_fflush(out, "<probably stdout>");
676 }
677 
678 void
680  FILE * out /* where to output the file content */,
681  char *file /* the content of which is appended */,
682  int margin /* number of spaces for shifting */ ,
683  bool but_comments /* do not shift F77 comment lines */)
684 {
685  FILE * in = safe_fopen(file, "r");
686  bool first = true;
687  int c, i;
688  while ((c=getc(in))!=EOF)
689  {
690  if (first && (!but_comments || (c!='C' && c!='c' && c!='*' && c!='!')))
691  {
692  for (i=0; i<margin; i++)
693  if (putc(' ', out)==EOF)
694  pips_internal_error("append failed");
695  first = false;
696  }
697  if (c=='\n')
698  first = true;
699  if (putc(c, out)==EOF)
700  pips_internal_error("append failed");
701  }
702  safe_fclose(in, file);
703 }
704 
705 void
706 safe_copy(char *source, char *target)
707 {
708  FILE * in, * out;
709  in = safe_fopen(source, "r");
710  out = safe_fopen(target, "w");
711  safe_cat(out, in);
712  safe_fclose(out, target);
713  safe_fclose(in, source);
714 }
715 
716 /* Display a file through $PIPS_MORE (or $PAGER) if stdout is a TTY,
717  on stdout otherwise.
718 
719  Return false if the file couldn't be displayed.
720  */
721 int
722 safe_display(char *fname)
723 {
724  if (!file_exists_p(fname))
725  {
726  pips_user_error("View file \"%s\" not found\n", fname);
727  return 0;
728  }
729 
730  if (isatty(fileno(stdout)))
731  {
732  int pgpid = fork();
733  if (pgpid)
734  {
735  int status;
736  waitpid(pgpid, &status, 0);
737  return WIFEXITED(status) && WEXITSTATUS(status) == 0;
738  }
739  else
740  {
741  char *pager = getenv("PIPS_MORE");
742  if (!pager)
743  pager = getenv("PAGER");
744  if (!pager)
745  pager = "more";
746  execlp(pager, pager, fname, NULL);
747  pips_internal_error("running %s %s: %s",
748  pager, fname, strerror(errno));
749  exit(127);
750  }
751  }
752  else
753  {
754  FILE * in = safe_fopen(fname, "r");
755  safe_cat(stdout, in);
756  safe_fclose(in, fname);
757  return 1;
758  }
759 }
760 
761 ␌
762 /* Some OS do not define basename and dirname. Others like DEC OSF1
763  do. So define them and use another name for them:
764 
765  /some/path/to/file.suffix -> file
766 
767  This may create conflicting file names, when the same source
768  filename is used in different subdirectory as in:
769 
770  create foo mod.c src/mod.c src/init/mod.c src/close/mod.c
771 
772  To avoid the problem a larger part of the access path should be
773  preserved. This can be done by substituting / by another character.
774  */
775 char * pips_filename(char *fullpath, char *suffix, bool short_p)
776 {
777  int len = strlen(fullpath)-1, i, j;
778  char *result;
779 
780  if (suffix) /* Drop the suffix */
781  {
782  int ls = strlen(suffix) - 1, le = len;
783  while (suffix[ls] == fullpath[le]) {
784  ls--;
785  le--;
786  if (ls < 0 || le < 0)
787  break;
788  }
789  if (ls < 0) /* ok */
790  len = le;
791  }
792 
793  if(short_p) {
794  /* Keep the basename only */
795  for (i=len; i>=0; i--) if (fullpath[i]=='/') break;
796  /* fullpath[i+1:len] */
797  result = (char*) malloc(sizeof(char)*(len-i+1));
798  for (i++, j=0; i<=len; i++, j++)
799  result[j] = fullpath[i];
800  result[j++] = '\0';
801  }
802  else {
803  /* Or substitute slashes by a neutral character */
804  char * cc;
805 
806  if(fullpath[0]=='.' && fullpath[1]=='/')
807  result = strndup(fullpath+2, len-1);
808  else
809  result = strndup(fullpath, len+1);
810 
811 
812 #define SLASH_SUBSTITUTION_CHARACTER '_'
813 
814  for(cc=result; *cc!='\000'; cc++) {
815  if(*cc=='/')
817  }
818  }
819  return result;
820 }
821 
822 char * pips_basename(char *fullpath, char *suffix)
823 {
824  return pips_filename(fullpath, suffix, true);
825 }
826 
827 /* The source file name access path is shortened or not depending on
828  the property. It is shorten if the name conflicts are not managed. */
829 char * pips_initial_filename(char *fullpath, char *suffix)
830 {
831  return pips_filename(fullpath, suffix,
832  !get_bool_property("PREPROCESSOR_FILE_NAME_CONFLICT_HANDLING"));
833 }
834 
835 /* /some/path/to/file.suffix -> /some/path/to
836  */
837 char * pips_dirname(char *fullpath)
838 {
839  char *result = strdup(fullpath);
840  int len = strlen(result);
841  while (result[--len]!='/' && len>=0);
842  result[len] = '\0';
843  return result;
844 }
845 
846 ␌
847 /* Delete the given file.
848 
849  Throw a pips_internal_error() if it fails.
850 */
851 void
852 safe_unlink(const char *file_name)
853 {
854  if (unlink(file_name))
855  {
856  perror("[safe_unlink] ");
857  pips_internal_error("unlink %s failed", file_name);
858  }
859 }
860 
861 void
862 safe_symlink(const char *topath, const char *frompath)
863 {
864  if (symlink(topath, frompath))
865  {
866  perror("[safe_symlink] ");
867  pips_internal_error("symlink(%s, %s) failed", topath, frompath);
868  }
869 }
870 
871 
872 /* Create a hard link to topath. That means that the file is accessible
873  with the new name frompath too.
874 
875  Throw a pips_internal_error() if it fails.
876 */
877 void
878 safe_link(const char *topath, const char *frompath)
879 {
880  if (link(frompath, topath))
881  {
882  perror("[safe_link] ");
883  pips_internal_error("link(%s,%s) failed", frompath, topath);
884  }
885 }
886 
887 /* attempt shell substitutions to what. returns NULL on errors.
888  */
889 char *
890 safe_system_output(char * what)
891 {
892  char * result;
893  FILE * in;
894 
895  in = popen(what, "r");
896 
897  if (in==NULL) {
898  perror("[safe_system_output] ");
899  pips_internal_error("popen failed: %s", what);
900  }
901 
902  result = safe_readfile(in);
903 
904  if (pclose(in)) {
905  /* on failures, do not stop it anyway...
906  */
907  perror("[safe_system_output] ");
908  pips_user_warning("\n pclose failed: %s\n", what);
909  if (result) free(result), result = NULL;
910  }
911 
912  return result;
913 }
914 
915 /* returns what after variable, command and file substitutions.
916  * the returned string is newly allocated. it's NULL on errors.
917  */
918 char *
920 {
921  return safe_system_output(concatenate("echo ", what, NULL));
922 }
923 
924 /* SunOS forgets to declare this one.
925  */
926 /* extern char * mktemp(char *); */
927 
928 /* @return a new temporary file name, starting with "prefix".
929  * the name is freshly allocated.
930  *
931  * FI: mkstemp() is being deprecated and it returns an integer, usable as
932  * file descriptor, not a character string.
933  *
934  */
935 char * safe_new_tmp_file(char * prefix)
936 {
937  string name = strdup(concatenate(prefix, ".XXXXXX", NULL));
938  int desc = mkstemp(name);
939  pips_assert("could create temporary name", desc!=-1);
940  return name;
941 }
942 
943 /* utility to open configuration file, (read only!)
944  * its name can be found using various ways
945  * property and env can be NULL (and ignored)
946  * if the file if not found a pips_error is generated
947  * canonical_name should be a file name, not a path
948  */
949 #define DEFAULT_CONFIG_DIR "etc"
950 #define CONFIG_DEFAULT_RIGHT "r"
951 FILE *
952 fopen_config(const char* canonical_name,
953  const char* cproperty,
954  const char* cenv)
955 {
956  FILE * fconf;
957 
958  // try various combinaison :
959  // pips property
960  if (cproperty) {
961  const string sproperty = get_string_property(cproperty);
962  if (sproperty && (fconf = fopen(sproperty, CONFIG_DEFAULT_RIGHT)))
963  return fconf;
964  }
965 
966  // then pips env var
967  if (cenv) {
968  string senv = getenv(cenv);
969  if (senv && (fconf = fopen(senv, CONFIG_DEFAULT_RIGHT)))
970  return fconf;
971  }
972 
973  // then default, with PIPS_ROOT if set
974  string pipsenv = getenv("PIPS_ROOT");
975  string sdefault;
976  if(pipsenv)
977  sdefault =
978  concatenate(pipsenv,"/" DEFAULT_CONFIG_DIR "/" , canonical_name, NULL);
979  else
980  sdefault = concatenate(CONFIG_DIR "/", canonical_name, NULL);
981 
982  return safe_fopen(sdefault, CONFIG_DEFAULT_RIGHT);
983 }
static int count
Definition: SDG.c:519
static FILE * out
Definition: alias_check.c:128
void gen_array_dupaddto(gen_array_t a, size_t i, void *what)
Definition: array.c:111
void gen_array_sort(gen_array_t a)
Definition: array.c:164
struct _newgen_struct_status_ * status
Definition: database.h:31
static Value offset
Definition: translation.c:283
void safe_copy(char *source, char *target)
Definition: file.c:706
#define to_escape(c)
Definition: file.c:327
char * pips_filename(char *fullpath, char *suffix, bool short_p)
Some OS do not define basename and dirname.
Definition: file.c:775
char * safe_fgets(char *s, int n, FILE *stream, char *filename)
Definition: file.c:170
bool create_directory(char *name)
Definition: file.c:435
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
#define CONFIG_DEFAULT_RIGHT
Definition: file.c:950
bool file_exists_p(const char *name)
Definition: file.c:321
char * get_string_property(const char *)
char * pips_initial_filename(char *fullpath, char *suffix)
The source file name access path is shortened or not depending on the property.
Definition: file.c:829
int safe_fputc(char c, FILE *stream, char *filename)
Definition: file.c:179
string nth_path(const char *path_list, int n)
Returns the allocated nth path from colon-separated path string.
Definition: file.c:362
#define DEFAULT_CONFIG_DIR
utility to open configuration file, (read only!) its name can be found using various ways property an...
Definition: file.c:949
void safe_symlink(const char *topath, const char *frompath)
Definition: file.c:862
char * find_file_in_directories(const char *file_name, const char *dir_path)
returns an allocated string pointing to the file, possibly with an additional path taken from colon-s...
Definition: file.c:399
int safe_fread(char *ptr, int element_size, int count, FILE *stream, char *filename)
Definition: file.c:214
int safe_display(char *fname)
Display a file through $PIPS_MORE (or $PAGER) if stdout is a TTY, on stdout otherwise.
Definition: file.c:722
string safe_get_line_interval(const string fn, int f, int l)
return lines f-l from file fn as a string
Definition: file.c:539
char * get_cwd(void)
returns the current working directory name.
Definition: file.c:486
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
int safe_fseek(FILE *stream, long int offset, int wherefrom, char *filename)
Definition: file.c:112
bool file_readable_p(char *name)
Definition: file.c:428
char * safe_readfile(FILE *file)
returns the file as an allocated string.
Definition: file.c:650
static char * relative_name_if_necessary(const char *name)
Definition: file.c:388
void list_files_in_directory(gen_array_t files, string dir, string re, bool(*file_name_predicate)(const char *))
The same as the previous safe_list_files_in_directory() but with no return code and a call to user er...
Definition: file.c:299
bool directory_exists_p(const char *name)
Definition: file.c:314
int safe_fflush(FILE *stream, char *filename)
Definition: file.c:90
char * strescape(const char *source)
protect a string, for example for use in a system call list of non escaped characters in the macro ab...
Definition: file.c:334
#define COLON
Definition: file.c:349
int safe_fputs(char *s, FILE *stream, char *filename)
Definition: file.c:203
some path to file suffix some path to *char * pips_dirname(char *fullpath)
Definition: file.c:837
void safe_append(FILE *out, char *file, int margin, bool but_comments)
Definition: file.c:679
#define MAX_INPUT_LINE_SIZE
int safe_fgetc(FILE *stream, char *filename)
Definition: file.c:147
char * safe_new_tmp_file(char *prefix)
SunOS forgets to declare this one.
Definition: file.c:935
char * safe_readline(FILE *file)
returns the allocated line read, whatever its length.
Definition: file.c:497
int safe_list_files_in_directory(gen_array_t files, string dir, string re, bool(*file_name_predicate)(const char *))
returns a sorted arg list of files matching regular expression re in directory 'dir' and with file_na...
Definition: file.c:250
int safe_getc(FILE *stream, char *filename)
Definition: file.c:158
char * pips_basename(char *fullpath, char *suffix)
Definition: file.c:822
FILE * fopen_config(const char *canonical_name, const char *cproperty, const char *cenv)
Definition: file.c:952
void safe_link(const char *topath, const char *frompath)
Create a hard link to topath.
Definition: file.c:878
char * safe_system_substitute(char *what)
returns what after variable, command and file substitutions.
Definition: file.c:919
long int safe_ftell(FILE *stream, char *filename)
Definition: file.c:123
FILE * check_fopen(const char *file, const char *mode)
file.c
Definition: file.c:56
int safe_putc(char c, FILE *stream, char *filename)
Definition: file.c:191
void safe_rewind(FILE *stream, char *filename)
Definition: file.c:136
bool purge_directory(char *name)
Definition: file.c:453
#define PATH_MAX
Definition: file.c:479
FILE * safe_freopen(char *filename, char *what, FILE *stream)
Definition: file.c:99
void safe_unlink(const char *file_name)
Delete the given file.
Definition: file.c:852
char * safe_system_output(char *what)
attempt shell substitutions to what.
Definition: file.c:890
int safe_fwrite(char *ptr, int element_size, int count, FILE *stream, char *filename)
Definition: file.c:227
#define SLASH_SUBSTITUTION_CHARACTER
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void safe_copy_line_interval(string fn, int f, int l, FILE *out)
Assumes "fn" is the name of a text file, opens it, and copies the lines whose number belongs to [f....
Definition: file.c:601
void safe_cat(FILE *out, FILE *in)
Definition: file.c:669
string safe_read_nth_line(string fn, int n)
Assumes "fn" is the name of a text file, opens it, and returns its nth line (starting with 1) in a ne...
Definition: file.c:523
void * malloc(YYSIZE_T)
void free(void *)
bool success
Definition: gpips-local.h:59
static int current_line
Poor attempt at associating physical line numbers to statement.
Definition: statement.c:2405
#define pips_user_warning
Definition: misc-local.h:146
#define asprintf
Definition: misc-local.h:225
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define exit(code)
Definition: misc-local.h:54
#define pips_user_error
Definition: misc-local.h:147
#define pips_user_irrecoverable_error
Definition: misc-local.h:148
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
void string_buffer_append(string_buffer, const string)
append string s (if non empty) to string buffer sb, the duplication is done if needed according to th...
string string_buffer_to_string(const string_buffer)
return malloc'ed string from string buffer sb
void string_buffer_free(string_buffer *)
free string buffer structure, also free string contents according to the dup field
Definition: string_buffer.c:82
string_buffer string_buffer_make(bool dup)
allocate a new string buffer
Definition: string_buffer.c:58
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
static const char * prefix
struct _newgen_struct_value_ * value
Definition: ri.h:455
char * strdup()
static int line
FLEX_SCANNER.
Definition: scanner.c:852
static char buf[BSZ]
Definition: split_file.c:157
char * strndup(char const *s, size_t n)
A replacement function, for systems that lack strndup.
Definition: strndup.c:26
internally defined structure.
Definition: string_buffer.c:47
Definition: statement.c:4047
static string file_name