diff options
author | peter <peter@FreeBSD.org> | 1996-08-20 23:46:10 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1996-08-20 23:46:10 +0000 |
commit | 8982e501c77217c860f79bba431f46a62b607a21 (patch) | |
tree | 70187fdf5be4cbefd0baf46bddac7e5e32c13c24 /contrib/cvs/src/expand_path.c | |
parent | 01ee40fd6a76f6ff7ef247fc1b2cf6e337f216c5 (diff) | |
download | FreeBSD-src-8982e501c77217c860f79bba431f46a62b607a21.zip FreeBSD-src-8982e501c77217c860f79bba431f46a62b607a21.tar.gz |
Import of slightly trimmed cvs-1.8 distribution. Generated files
and non-unix code has been left out.
Diffstat (limited to 'contrib/cvs/src/expand_path.c')
-rw-r--r-- | contrib/cvs/src/expand_path.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/contrib/cvs/src/expand_path.c b/contrib/cvs/src/expand_path.c new file mode 100644 index 0000000..9898051 --- /dev/null +++ b/contrib/cvs/src/expand_path.c @@ -0,0 +1,241 @@ +/* expand_path.c -- expand environmental variables in passed in string + * + * The main routine is expand_path(), it is the routine that handles + * the '~' character in four forms: + * ~name + * ~name/ + * ~/ + * ~ + * and handles environment variables contained within the pathname + * which are defined by: + * ${var_name} (var_name is the name of the environ variable) + * $var_name (var_name ends w/ non-alphanumeric char other than '_') + */ + +#include "cvs.h" +#include <sys/types.h> + +static char *expand_variable PROTO((char *env, char *file, int line)); + + +/* User variables. */ + +List *variable_list = NULL; + +static void variable_delproc PROTO ((Node *)); + +static void +variable_delproc (node) + Node *node; +{ + free (node->data); +} + +/* Currently used by -s option; we might want a way to set user + variables in a file in the $CVSROOT/CVSROOT directory too. */ + +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'; + /* Make p point to the value. */ + ++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 + { + /* Replace the old value. For example, this means that -s + options on the command line override ones from .cvsrc. */ + free (node->data); + node->data = xstrdup (p); + free (name); + } +} + +/* 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. */ +char * +expand_path (name, file, line) + char *name; + char *file; + int line; +{ + char *s; + char *d; + /* FIXME: arbitrary limit. */ + char mybuf[PATH_MAX]; + char buf[PATH_MAX]; + char *result; + s = name; + d = mybuf; + while ((*d++ = *s)) + if (*s++ == '$') + { + char *p = d; + char *e; + int flag = (*s == '{'); + + for (; (*d++ = *s); s++) + if (flag + ? *s =='}' + : isalnum (*s) == 0 && *s != '_') + break; + *--d = 0; + e = expand_variable (&p[flag], file, line); + + if (e) + { + for (d = &p[-1]; (*d++ = *e++);) + ; + --d; + if (flag && *s) + s++; + } + else + /* expand_variable has already printed an error message. */ + return NULL; + } + *d = 0; + s = mybuf; + d = buf; + /* If you don't want ~username ~/ to be expanded simply remove + * This entire if statement including the else portion + */ + if (*s++ == '~') + { + char *t; + char *p=s; + if (*s=='/' || *s==0) + t = get_homedir (); + 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; + } + while ((*d++ = *t++)) + ; + --d; + if (*p == 0) + *p = '/'; /* always add / */ + s=p; + } + else + --s; + /* Kill up to here */ + while ((*d++ = *s++)) + ; + *d=0; + result = xmalloc (sizeof(char) * strlen(buf)+1); + strcpy (result, buf); + return result; +} + +static char * +expand_variable (name, file, line) + char *name; + char *file; + int line; +{ + if (strcmp (name, CVSROOT_ENV) == 0) + return CVSroot; + else if (strcmp (name, RCSBIN_ENV) == 0) + return Rcsbin; + 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])) + { + /* These names are reserved for future versions of CVS, + so that is why it is an error. */ + 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; + /* Crazy syntax for a user variable. But we want + *something* that lets the user name a user variable + anything he wants, without interference from + (existing or future) internal variables. */ + 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 + { + /* It is an unrecognized character. We return an error to + reserve these for future versions of CVS; it is plausible + 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", + file, line, name); + else + error (0, 0, "%s: unrecognized varaible syntax %s", + file, name); + return NULL; + } +} |