summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/expand_path.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src/expand_path.c')
-rw-r--r--contrib/cvs/src/expand_path.c112
1 files changed, 93 insertions, 19 deletions
diff --git a/contrib/cvs/src/expand_path.c b/contrib/cvs/src/expand_path.c
index 9898051..7d0bc39 100644
--- a/contrib/cvs/src/expand_path.c
+++ b/contrib/cvs/src/expand_path.c
@@ -81,10 +81,12 @@ variable_set (nameval)
}
/* This routine will expand the pathname to account for ~ and $
- characters as described above. If an error occurs, an error
- message is printed via error() and NULL is returned. FILE and
- LINE are the filename and linenumber to include in the error
- message. */
+ characters as described above. Returns a pointer to a newly
+ malloc'd string. If an error occurs, an error message is printed
+ via error() and NULL is returned. FILE and LINE are the filename
+ and linenumber to include in the error message. FILE must point
+ to something; LINE can be zero to indicate the line number is not
+ known. */
char *
expand_path (name, file, line)
char *name;
@@ -93,40 +95,82 @@ expand_path (name, file, line)
{
char *s;
char *d;
- /* FIXME: arbitrary limit. */
- char mybuf[PATH_MAX];
- char buf[PATH_MAX];
+
+ char *mybuf = NULL;
+ size_t mybuf_size = 0;
+ char *buf = NULL;
+ size_t buf_size = 0;
+
+ size_t doff;
+
char *result;
+
+ /* Sorry this routine is so ugly; it is a head-on collision
+ between the `traditional' unix *d++ style and the need to
+ dynamically allocate. It would be much cleaner (and probably
+ faster, not that this is a bottleneck for CVS) with more use of
+ strcpy & friends, but I haven't taken the effort to rewrite it
+ thusly. */
+
+ /* First copy from NAME to MYBUF, expanding $<foo> as we go. */
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;
- *--d = 0;
+ 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
/* expand_variable has already printed an error message. */
- return NULL;
+ goto error_exit;
}
- *d = 0;
+ 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';
+
+ /* Then copy from MYBUF to BUF, expanding ~. */
s = mybuf;
d = buf;
/* If you don't want ~username ~/ to be expanded simply remove
@@ -156,8 +200,15 @@ expand_path (name, file, line)
}
t = ps->pw_dir;
}
+ 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 = '/'; /* always add / */
@@ -166,12 +217,35 @@ expand_path (name, file, line)
else
--s;
/* Kill up to here */
+ doff = d - buf;
+ expand_string (&buf, &buf_size, doff + 1);
+ d = buf + doff;
while ((*d++ = *s++))
- ;
- *d=0;
- result = xmalloc (sizeof(char) * strlen(buf)+1);
- strcpy (result, buf);
+ {
+ 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';
+
+ /* OK, buf contains the value we want to return. Clean up and return
+ it. */
+ free (mybuf);
+ /* Save a little memory with xstrdup; buf will tend to allocate
+ more than it needs to. */
+ result = xstrdup (buf);
+ free (buf);
return result;
+
+ error_exit:
+ if (mybuf != NULL)
+ free (mybuf);
+ if (buf != NULL)
+ free (buf);
+ return NULL;
}
static char *
@@ -181,7 +255,7 @@ expand_variable (name, file, line)
int line;
{
if (strcmp (name, CVSROOT_ENV) == 0)
- return CVSroot;
+ return CVSroot_original;
else if (strcmp (name, RCSBIN_ENV) == 0)
return Rcsbin;
else if (strcmp (name, EDITOR1_ENV) == 0)
@@ -231,10 +305,10 @@ expand_variable (name, file, line)
that various crazy syntaxes might be invented for inserting
information about revisions, branches, etc. */
if (line != 0)
- error (0, 0, "%s:%d: unrecognized varaible syntax %s",
+ error (0, 0, "%s:%d: unrecognized variable syntax %s",
file, line, name);
else
- error (0, 0, "%s: unrecognized varaible syntax %s",
+ error (0, 0, "%s: unrecognized variable syntax %s",
file, name);
return NULL;
}
OpenPOWER on IntegriCloud