#define _POSIX_SOURCE #define _POSIX_C_SOURCE 199309L #include #include #include #include #include /* POSIX */ #include #include "utils.h" #include "error.h" #include "types.h" static char * ReadAll (FILE * f, int offset) { char buf [10*1024] ; size_t iRead, nRead ; char * ret ; clearerr (f) ; iRead = 0 ; nRead = 0 ; while (iRead < sizeof buf) { nRead = fread (buf+iRead, 1, (sizeof buf)-iRead, f) ; if (nRead <= 0) break ; iRead += nRead ; } if (nRead > 0) { assert (iRead == sizeof buf) ; ret = ReadAll (f, offset+iRead) ; } else if (ferror (f) != 0) { error ("read file: %s", strerror (errno)) ; ret = NULL ; } else { ret = malloc (offset+iRead+1) ; if (ret == NULL) error ("failed to allocate memory") ; ret[offset+iRead] = EOS ; } memcpy (ret+offset, buf, iRead) ; return ret ; } extern char * File_ReadAll (FILE * f) { assert (f != NULL) ; return ReadAll (f, 0) ; } static const char * getHome (void) { static char homeDir [80] = "" ; static int initialized = 0 ; if (! initialized) { const char * env ; env = getenv ("HOME") ; if (env != NULL && env[0] != EOS) { sprintf (homeDir, "%.*s", (int)(sizeof homeDir)-1, env) ; } initialized = 1 ; } return homeDir[0] != EOS ? homeDir : NULL ; } extern bool File_FindInPath (char * out, int outSz, const char * path, const char * basename) { char name [FILENAME_MAX] ; int len ; assert (path != NULL) ; assert (basename != NULL) ; assert (out != NULL) ; /* regular path */ if (access (basename, F_OK) == 0) { sprintf (out, "%.*s", outSz-1, basename) ; return true ; } else /* relative to home directory */ if (strncmp (basename, "~/", 2) == 0 && getHome () != NULL) { sprintf (name, "%s%s", getHome (), basename+1) ; if (access (name, F_OK) == 0) { sprintf (out, "%.*s", outSz-1, name) ; return true ; } else { return false ; } } else /* forbid relative to PATH just like shell */ /* NB: absolute non-existent files also drop here */ if (strchr (basename, '/') != NULL) { return false ; } else { while (*path != EOS) { len = strcspn (path, ":") ; if (strncmp (path, "~/", 2) == 0) { sprintf (name, "%s%.*s/%s", getHome (), len-1, path+1, basename) ; } else { sprintf (name, "%.*s/%s", len, path, basename) ; } if (access (name, F_OK) == 0) { sprintf (out, "%.*s", outSz-1, name) ; return true ; } path += len ; while (*path == ':') path++ ; } return false ; } } extern char * File_ReadOutputFromCommand (const char * cmd) { FILE * out ; char * ret ; if ((out = popen (cmd, "r")) == NULL) { error ("when calling command: %s, error: ", cmd, strerror (errno)) ; ret = NULL ; } else { ret = File_ReadAll (out) ; pclose (out) ; /* if return value is correct, remove trailing whitespace */ if (ret != NULL) { char *lastNotWhite, *cursor ; char c ; cursor = lastNotWhite = ret ; while ((c = *cursor++) != EOS) { if (strchr (" \t\n", c) == NULL) { lastNotWhite = cursor ; } } *lastNotWhite = EOS ; } } return ret ; }