/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2009,
2010, 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
. */
#if HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
char *
mu_get_homedir (void)
{
char *homedir = getenv ("HOME");
if (homedir)
homedir = strdup (homedir);
else
{
struct mu_auth_data *auth = mu_get_auth_by_uid (geteuid ());
if (!auth)
return NULL;
homedir = strdup (auth->dir);
mu_auth_data_free (auth);
}
return homedir;
}
char *
mu_get_full_path (const char *file)
{
char *p = NULL;
if (!file)
p = mu_getcwd ();
else if (*file != '/')
{
char *cwd = mu_getcwd ();
if (cwd)
{
p = mu_make_file_name (cwd, file);
free (cwd);
}
}
else
p = strdup (file);
return p;
}
/* mu_normalize_path: convert pathname containig relative paths specs (../)
into an equivalent absolute path. Strip trailing delimiter if present,
unless it is the only character left. E.g.:
/home/user/../smith --> /home/smith
/home/user/../.. --> /
*/
char *
mu_normalize_path (char *path)
{
int len;
char *p;
if (!path)
return path;
len = strlen (path);
/* Empty string is returned as is */
if (len == 0)
return path;
/* delete trailing delimiter if any */
if (len && path[len-1] == '/')
path[len-1] = 0;
/* Eliminate any /../ */
for (p = strchr (path, '.'); p; p = strchr (p, '.'))
{
if (p > path && p[-1] == '/')
{
if (p[1] == '.' && (p[2] == 0 || p[2] == '/'))
/* found */
{
char *q, *s;
/* Find previous delimiter */
for (q = p-2; *q != '/' && q >= path; q--)
;
if (q < path)
break;
/* Copy stuff */
s = p + 2;
p = q;
while ((*q++ = *s++))
;
continue;
}
}
p++;
}
if (path[0] == 0)
{
path[0] = '/';
path[1] = 0;
}
return path;
}
/* Expand a PATTERN to the pathname. PATTERN may contain the following
macro-notations:
---------+------------
notation | expands to
---------+------------
%u user name
%h user's home dir
~ Likewise
---------+------------
Allocates memory.
*/
char *
mu_expand_path_pattern (const char *pattern, const char *username)
{
const char *p;
char *q;
char *path;
size_t len = 0;
struct mu_auth_data *auth = NULL;
for (p = pattern; *p; p++)
{
if (*p == '~')
{
if (!auth)
{
auth = mu_get_auth_by_name (username);
if (!auth)
return NULL;
}
len += strlen (auth->dir);
}
else if (*p == '%')
switch (*++p)
{
case 'u':
len += strlen (username);
break;
case 'h':
if (!auth)
{
auth = mu_get_auth_by_name (username);
if (!auth)
return NULL;
}
len += strlen (auth->dir);
break;
case '%':
len++;
break;
default:
len += 2;
}
else
len++;
}
path = malloc (len + 1);
if (!path)
return NULL;
p = pattern;
q = path;
while (*p)
{
size_t off = strcspn (p, "~%");
memcpy (q, p, off);
q += off;
p += off;
if (*p == '~')
{
strcpy (q, auth->dir);
q += strlen (auth->dir);
p++;
}
else if (*p == '%')
{
switch (*++p)
{
case 'u':
strcpy (q, username);
q += strlen (username);
break;
case 'h':
strcpy (q, auth->dir);
q += strlen (auth->dir);
break;
case '%':
*q++ = '%';
break;
default:
*q++ = '%';
*q++ = *p;
}
p++;
}
}
*q = 0;
if (auth)
mu_auth_data_free (auth);
return path;
}