Esempio n. 1
0
/*.......................................................................
 * Append a string to a pathname, increasing the size of the pathname
 * buffer if needed.
 *
 * Input:
 *  path        PathName *  The pathname container.
 *  string    const char *  The string to be appended to the pathname.
 *                          Note that regardless of the slen argument,
 *                          this should be a '\0' terminated string.
 *  slen             int    The maximum number of characters to append
 *                          from string[], or -1 to append the whole
 *                          string.
 *  remove_escapes   int    If true, remove the backslashes that escape
 *                          spaces, tabs, backslashes etc..
 * Output:
 *  return          char *  The pathname string path->name[], which may
 *                          have been reallocated, or NULL if there was
 *                          insufficient memory to extend the pathname.
 */
char *_pn_append_to_path(PathName *path, const char *string, int slen,
			int remove_escapes)
{
  int pathlen;     /* The length of the pathname */
  int i;
/*
 * Check the arguments.
 */
  if(!path || !string) {
    errno = EINVAL;
    return NULL;
  };
/*
 * Get the current length of the pathname.
 */
  pathlen = strlen(path->name);
/*
 * How many characters should be appended?
 */
  if(slen < 0 || slen > strlen(string))
    slen = strlen(string);
/*
 * Resize the pathname if needed.
 */
  if(!_pn_resize_path(path, pathlen + slen))
    return NULL;
/*
 * Append the string to the output pathname, removing any escape
 * characters found therein.
 */
  if(remove_escapes) {
    int is_escape = 0;
    for(i=0; i<slen; i++) {
      is_escape = !is_escape && string[i] == '\\';
      if(!is_escape)
	path->name[pathlen++] = string[i];
    };
/*
 * Terminate the string.
 */
    path->name[pathlen] = '\0';
  } else {
/*
 * Append the string directly to the pathname.
 */
    memcpy(path->name + pathlen, string, slen);
    path->name[pathlen + slen] = '\0';
  };
  return path->name;
}
Esempio n. 2
0
/*.......................................................................
 * Preprocess a path, expanding ~/, ~user/ and $envvar references, using
 * ef->path as a work buffer, then copy the result into a cache entry,
 * and return a pointer to this copy.
 *
 * Input:
 *  ef    ExpandFile *  The resource object of the file matcher.
 *  pathlen      int    The length of the prefix of path[] to be expanded.
 * Output:
 *  return      char *  A pointer to a copy of the output path in the
 *                      cache. On error NULL is returned, and a description
 *                      of the error is left in ef->errmsg[].
 */
static char *ef_expand_special(ExpandFile *ef, const char *path, int pathlen)
{
  int spos;      /* The index of the start of the path segment that needs */
                 /*  to be copied from path[] to the output pathname. */
  int ppos;      /* The index of a character in path[] */
  char *pptr;    /* A pointer into the output path */
  int escaped;   /* True if the previous character was a '\' */
  int i;
/*
 * Clear the pathname buffer.
 */
  _pn_clear_path(ef->path);
/*
 * We need to perform two passes, one to expand environment variables
 * and a second to do tilde expansion. This caters for the case
 * where an initial dollar expansion yields a tilde expression.
 */
  escaped = 0;
  for(spos=ppos=0; ppos < pathlen; ppos++) {
    int c = path[ppos];
    if(escaped) {
      escaped = 0;
    } else if(c == '\\') {
      escaped = 1;
    } else if(c == '$') {
      int envlen;   /* The length of the environment variable */
      char *value;  /* The value of the environment variable */
/*
 * Record the preceding unrecorded part of the pathname.
 */
      if(spos < ppos && _pn_append_to_path(ef->path, path + spos, ppos-spos, 0)
	 == NULL) {
	strncpy(ef->errmsg, "Insufficient memory to expand path", sizeof(ef->errmsg));
	return NULL;
      };
/*
 * Skip the dollar.
 */
      ppos++;
/*
 * Copy the environment variable name that follows the dollar into
 * ef->envnam[], stopping if a directory separator or end of string
 * is seen.
 */
      for(envlen=0; envlen<ENV_LEN && ppos < pathlen &&
	  strncmp(path + ppos, FS_DIR_SEP, FS_DIR_SEP_LEN); envlen++)
	ef->envnam[envlen] = path[ppos++];
/*
 * If the username overflowed the buffer, treat it as invalid (note that
 * on most unix systems only 8 characters are allowed in a username,
 * whereas our ENV_LEN is much bigger than that.
 */
      if(envlen >= ENV_LEN) {
	strncpy(ef->errmsg, "Environment variable name too long", sizeof(ef->errmsg));
	return NULL;
      };
/*
 * Terminate the environment variable name.
 */
      ef->envnam[envlen] = '\0';
/*
 * Lookup the value of the environment variable.
 */
      value = getenv(ef->envnam);
      if(!value) {
	const char *fmt = "No expansion found for: $%.*s";
	snprintf(ef->errmsg, sizeof(ef->errmsg), fmt, ERRLEN - strlen(fmt),
		 ef->envnam);
	return NULL;
      };
/*
 * Copy the value of the environment variable into the output pathname.
 */
      if(_pn_append_to_path(ef->path, value, -1, 0) == NULL) {
	strncpy(ef->errmsg, "Insufficient memory to expand path", sizeof(ef->errmsg));
	return NULL;
      };
/*
 * Record the start of the uncopied tail of the input pathname.
 */
      spos = ppos;
    };
  };
/*
 * Record the uncopied tail of the pathname.
 */
  if(spos < ppos && _pn_append_to_path(ef->path, path + spos, ppos-spos, 0)
     == NULL) {
    strncpy(ef->errmsg, "Insufficient memory to expand path", sizeof(ef->errmsg));
    return NULL;
  };
/*
 * If the first character of the resulting pathname is a tilde,
 * then attempt to substitute the home directory of the specified user.
 */
  pptr = ef->path->name;
  if(*pptr == '~' && path[0] != '\\') {
    int usrlen;           /* The length of the username following the tilde */
    const char *homedir;  /* The home directory of the user */
    int homelen;          /* The length of the home directory string */
    int plen;             /* The current length of the path */
    int skip=0;           /* The number of characters to skip after the ~user */
/*
 * Get the current length of the output path.
 */
    plen = strlen(ef->path->name);
/*
 * Skip the tilde.
 */
    pptr++;
/*
 * Copy the optional username that follows the tilde into ef->usrnam[].
 */
    for(usrlen=0; usrlen<USR_LEN && *pptr &&
	strncmp(pptr, FS_DIR_SEP, FS_DIR_SEP_LEN); usrlen++)
      ef->usrnam[usrlen] = *pptr++;
/*
 * If the username overflowed the buffer, treat it as invalid (note that
 * on most unix systems only 8 characters are allowed in a username,
 * whereas our USR_LEN is much bigger than that.
 */
    if(usrlen >= USR_LEN) {
      strncpy(ef->errmsg, "Username too long", sizeof(ef->errmsg));
      return NULL;
    };
/*
 * Terminate the username string.
 */
    ef->usrnam[usrlen] = '\0';
/*
 * Lookup the home directory of the user.
 */
    homedir = _hd_lookup_home_dir(ef->home, ef->usrnam);
    if(!homedir) {
      strncpy(ef->errmsg, _hd_last_home_dir_error(ef->home), ERRLEN);
      ef->errmsg[ERRLEN] = '\0';
      return NULL;
    };
    homelen = strlen(homedir);
/*
 * ~user and ~ are usually followed by a directory separator to
 * separate them from the file contained in the home directory.
 * If the home directory is the root directory, then we don't want
 * to follow the home directory by a directory separator, so we must
 * erase it.
 */
    if(strcmp(homedir, FS_ROOT_DIR) == 0 &&
       strncmp(pptr, FS_DIR_SEP, FS_DIR_SEP_LEN) == 0) {
      skip = FS_DIR_SEP_LEN;
    };
/*
 * If needed, increase the size of the pathname buffer to allow it
 * to accomodate the home directory instead of the tilde expression.
 * Note that pptr may not be valid after this call.
 */
    if(_pn_resize_path(ef->path, plen - usrlen - 1 - skip + homelen)==NULL) {
      strncpy(ef->errmsg, "Insufficient memory to expand filename", sizeof(ef->errmsg));
      return NULL;
    };
/*
 * Move the part of the pathname that follows the tilde expression to
 * the end of where the home directory will need to be inserted.
 */
    memmove(ef->path->name + homelen,
	    ef->path->name + 1 + usrlen + skip, plen - usrlen - 1 - skip+1);
/*
 * Write the home directory at the beginning of the string.
 */
    for(i=0; i<homelen; i++)
      ef->path->name[i] = homedir[i];
  };
/*
 * Copy the result into the cache, and return a pointer to the copy.
 */
  return ef_cache_pathname(ef, ef->path->name, 0);
}
Esempio n. 3
0
/*.......................................................................
 * Prepend a string to a pathname, increasing the size of the pathname
 * buffer if needed.
 *
 * Input:
 *  path        PathName *  The pathname container.
 *  string    const char *  The string to be prepended to the pathname.
 *                          Note that regardless of the slen argument,
 *                          this should be a '\0' terminated string.
 *  slen             int    The maximum number of characters to prepend
 *                          from string[], or -1 to append the whole
 *                          string.
 *  remove_escapes   int    If true, remove the backslashes that escape
 *                          spaces, tabs, backslashes etc..
 * Output:
 *  return          char *  The pathname string path->name[], which may
 *                          have been reallocated, or NULL if there was
 *                          insufficient memory to extend the pathname.
 */
char *_pn_prepend_to_path(PathName *path, const char *string, int slen,
			  int remove_escapes)
{
  int pathlen;     /* The length of the pathname */
  int shift;       /* The number of characters to shift the suffix by */
  int i,j;
/*
 * Check the arguments.
 */
  if(!path || !string) {
    errno = EINVAL;
    return NULL;
  };
/*
 * Get the current length of the pathname.
 */
  pathlen = strlen(path->name);
/*
 * How many characters should be appended?
 */
  if(slen < 0 || slen > strlen(string))
    slen = strlen(string);
/*
 * Work out how far we need to shift the original path string to make
 * way for the new prefix. When removing escape characters, we need
 * final length of the new prefix, after unescaped backslashes have
 * been removed.
 */
  if(remove_escapes) {
    int is_escape = 0;
    for(shift=0,i=0; i<slen; i++) {
      is_escape = !is_escape && string[i] == '\\';
      if(!is_escape)
	shift++;
    };
  } else {
    shift = slen;
  };
/*
 * Resize the pathname if needed.
 */
  if(!_pn_resize_path(path, pathlen + shift))
    return NULL;
/*
 * Make room for the prefix at the beginning of the string.
 */
  memmove(path->name + shift, path->name, pathlen+1);
/*
 * Copy the new prefix into the vacated space at the beginning of the
 * output pathname, removing any escape characters if needed.
 */
  if(remove_escapes) {
    int is_escape = 0;
    for(i=j=0; i<slen; i++) {
      is_escape = !is_escape && string[i] == '\\';
      if(!is_escape)
	path->name[j++] = string[i];
    };
  } else {
    memcpy(path->name, string, slen);
  };
  return path->name;
}