/* find_home_tildeexpand.c -- library function to do sh-like ~ expansion */
/* (C) 2002 by Matthias Andree <matthias.andree@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details, it is in the file named
* COPYING.
*/
#include "common.h"
#include <string.h>
#include <stdlib.h>
#include "find_home.h"
#include "xmalloc.h"
#include "xstrdup.h"
#ifndef __riscos__
static bool tilde_expand = true;
#else
static bool tilde_expand = false;
#endif
/*
* tildeexpand tries to expand the first tilde argument, similar, but
* not identical, to the way a POSIX sh does. It does not support
* multiple tildes, and does not search for a slash, but for the longest
* count of characters in the POSIX portable file name character set.
*/
/*@only@*/
char *tildeexpand(const char *name)
{
char *tmp;
const char *home;
size_t l, tl;
if (!tilde_expand)
return xstrdup(name);
if (name[0] != '~')
return xstrdup(name);
/* figure length of user name */
l = strspn(&name[1],
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789._-"); /* Portable Filename Character Set */
if (l > 0) {
/* got a parameter to the tilde */
tmp = (char *)xmalloc(l + 1);
memcpy(tmp, &name[1], l);
/* we want exactly the first l characters but as C string,
* so stuff the NUL byte */
tmp[l] = '\0';
home = find_home_user(tmp);
xfree(tmp);
} else {
/* plain tilde */
home = find_home(false);
}
if (home == NULL) {
return xstrdup(name);
}
tl = strlen(name) + strlen(home) - l + 1;
tmp = (char *)xmalloc(tl);
(void)strlcpy(tmp, home, tl);
/* no need to insert a slash here, name[l] contains one */
if (strlcat(tmp, name + l + 1, tl) >= tl)
internal_error;
return tmp;
}