#include "cvs.h"
#include <sys/types.h>
static char *expand_variable PROTO((char *env, char *file, int line));
List *variable_list = NULL;
static void variable_delproc PROTO ((Node *));
static void
variable_delproc (node)
Node *node;
{
free (node->data);
}
void
variable_set (nameval)
char *nameval;
{
char *p;
char *name;
Node *node;
p = nameval;
while (isalnum (*p) || *p == '_')
++p;
if (*p != '=')
error (1, 0, "illegal character in user variable name in %s", nameval);
if (p == nameval)
error (1, 0, "empty user variable name in %s", nameval);
name = xmalloc (p - nameval + 1);
strncpy (name, nameval, p - nameval);
name[p - nameval] = '\0';
++p;
if (strchr (p, '\012') != NULL)
error (1, 0, "linefeed in user variable value in %s", nameval);
if (variable_list == NULL)
variable_list = getlist ();
node = findnode (variable_list, name);
if (node == NULL)
{
node = getnode ();
node->type = VARIABLE;
node->delproc = variable_delproc;
node->key = name;
node->data = xstrdup (p);
(void) addnode (variable_list, node);
}
else
{
free (node->data);
node->data = xstrdup (p);
free (name);
}
}
char *
expand_path (name, file, line)
char *name;
char *file;
int line;
{
char *s;
char *d;
char *mybuf = NULL;
size_t mybuf_size = 0;
char *buf = NULL;
size_t buf_size = 0;
size_t doff;
char *result;
s = name;
d = mybuf;
doff = d - mybuf;
expand_string (&mybuf, &mybuf_size, doff + 1);
d = mybuf + doff;
while ((*d++ = *s))
{
if (*s++ == '$')
{
char *p = d;
char *e;
int flag = (*s == '{');
doff = d - mybuf;
expand_string (&mybuf, &mybuf_size, doff + 1);
d = mybuf + doff;
for (; (*d++ = *s); s++)
{
if (flag
? *s =='}'
: isalnum (*s) == 0 && *s != '_')
break;
doff = d - mybuf;
expand_string (&mybuf, &mybuf_size, doff + 1);
d = mybuf + doff;
}
*--d = '\0';
e = expand_variable (&p[flag], file, line);
if (e)
{
doff = d - mybuf;
expand_string (&mybuf, &mybuf_size, doff + 1);
d = mybuf + doff;
for (d = &p[-1]; (*d++ = *e++);)
{
doff = d - mybuf;
expand_string (&mybuf, &mybuf_size, doff + 1);
d = mybuf + doff;
}
--d;
if (flag && *s)
s++;
}
else
goto error_exit;
}
doff = d - mybuf;
expand_string (&mybuf, &mybuf_size, doff + 1);
d = mybuf + doff;
}
doff = d - mybuf;
expand_string (&mybuf, &mybuf_size, doff + 1);
d = mybuf + doff;
*d = '\0';
s = mybuf;
d = buf;
if (*s++ == '~')
{
char *t;
char *p=s;
if (*s=='/' || *s==0)
t = get_homedir ();
else
{
#ifdef GETPWNAM_MISSING
for (; *p!='/' && *p; p++)
;
*p = 0;
if (line != 0)
error (0, 0,
"%s:%d:tilde expansion not supported on this system",
file, line);
else
error (0, 0, "%s:tilde expansion not supported on this system",
file);
return NULL;
#else
struct passwd *ps;
for (; *p!='/' && *p; p++)
;
*p = 0;
ps = getpwnam (s);
if (ps == 0)
{
if (line != 0)
error (0, 0, "%s:%d: no such user %s",
file, line, s);
else
error (0, 0, "%s: no such user %s", file, s);
return NULL;
}
t = ps->pw_dir;
#endif
}
doff = d - buf;
expand_string (&buf, &buf_size, doff + 1);
d = buf + doff;
while ((*d++ = *t++))
{
doff = d - buf;
expand_string (&buf, &buf_size, doff + 1);
d = buf + doff;
}
--d;
if (*p == 0)
*p = '/';
s=p;
}
else
--s;
doff = d - buf;
expand_string (&buf, &buf_size, doff + 1);
d = buf + doff;
while ((*d++ = *s++))
{
doff = d - buf;
expand_string (&buf, &buf_size, doff + 1);
d = buf + doff;
}
doff = d - buf;
expand_string (&buf, &buf_size, doff + 1);
d = buf + doff;
*d = '\0';
free (mybuf);
result = xstrdup (buf);
free (buf);
return result;
error_exit:
if (mybuf != NULL)
free (mybuf);
if (buf != NULL)
free (buf);
return NULL;
}
static char *
expand_variable (name, file, line)
char *name;
char *file;
int line;
{
if (strcmp (name, CVSROOT_ENV) == 0)
return CVSroot_original;
else if (strcmp (name, "RCSBIN") == 0)
{
error (0, 0, "RCSBIN internal variable is no longer supported");
return NULL;
}
else if (strcmp (name, EDITOR1_ENV) == 0)
return Editor;
else if (strcmp (name, EDITOR2_ENV) == 0)
return Editor;
else if (strcmp (name, EDITOR3_ENV) == 0)
return Editor;
else if (strcmp (name, "USER") == 0)
return getcaller ();
else if (isalpha (name[0]))
{
if (line != 0)
error (0, 0, "%s:%d: no such internal variable $%s",
file, line, name);
else
error (0, 0, "%s: no such internal variable $%s",
file, name);
return NULL;
}
else if (name[0] == '=')
{
Node *node;
node = findnode (variable_list, name + 1);
if (node == NULL)
{
if (line != 0)
error (0, 0, "%s:%d: no such user variable ${%s}",
file, line, name);
else
error (0, 0, "%s: no such user variable ${%s}",
file, name);
return NULL;
}
return node->data;
}
else
{
if (line != 0)
error (0, 0, "%s:%d: unrecognized variable syntax %s",
file, line, name);
else
error (0, 0, "%s: unrecognized variable syntax %s",
file, name);
return NULL;
}
}