summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/expand_path.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-08-20 23:46:10 +0000
committerpeter <peter@FreeBSD.org>1996-08-20 23:46:10 +0000
commit8982e501c77217c860f79bba431f46a62b607a21 (patch)
tree70187fdf5be4cbefd0baf46bddac7e5e32c13c24 /contrib/cvs/src/expand_path.c
parent01ee40fd6a76f6ff7ef247fc1b2cf6e337f216c5 (diff)
downloadFreeBSD-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.c241
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;
+ }
+}
OpenPOWER on IntegriCloud