diff options
author | Jean-Francois Brousseau <jfb@cvs.openbsd.org> | 2004-12-21 18:48:00 +0000 |
---|---|---|
committer | Jean-Francois Brousseau <jfb@cvs.openbsd.org> | 2004-12-21 18:48:00 +0000 |
commit | 7e9b38a197f22d07535747f999adcd870da7eb31 (patch) | |
tree | 87344939776097527c61eb9fa1b20ea1549c29e9 /usr.bin/cvs | |
parent | 3d46960173efa81ae236b33be993ba399a6f0b38 (diff) |
gnu CVS has an undocumented -s command-line option to set a variable,
so let's support it too. This will also be required to implement the
`Set' request handler.
Diffstat (limited to 'usr.bin/cvs')
-rw-r--r-- | usr.bin/cvs/cvs.c | 133 | ||||
-rw-r--r-- | usr.bin/cvs/cvs.h | 15 |
2 files changed, 144 insertions, 4 deletions
diff --git a/usr.bin/cvs/cvs.c b/usr.bin/cvs/cvs.c index 92d813a0837..840dcb70d5a 100644 --- a/usr.bin/cvs/cvs.c +++ b/usr.bin/cvs/cvs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cvs.c,v 1.26 2004/12/21 18:15:55 xsa Exp $ */ +/* $OpenBSD: cvs.c,v 1.27 2004/12/21 18:47:58 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -31,6 +31,7 @@ #include <pwd.h> #include <errno.h> #include <stdio.h> +#include <ctype.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> @@ -69,6 +70,8 @@ char *cvs_msg = NULL; CVSFILE *cvs_files; +static TAILQ_HEAD(, cvs_var) cvs_variables; + /* * Command dispatch table * ---------------------- @@ -318,7 +321,8 @@ void usage(void) { fprintf(stderr, - "Usage: %s [-flQqtv] [-d root] [-e editor] [-z level] command [...]\n", __progname); + "Usage: %s [-flQqtv] [-d root] [-e editor] [-s var=val] [-z level] " + "command [...]\n", __progname); } @@ -329,6 +333,8 @@ main(int argc, char **argv) int i, ret, cmd_argc; struct cvs_cmd *cmdp; + TAILQ_INIT(&cvs_variables); + if (cvs_log_init(LD_STD, 0) < 0) err(1, "failed to initialize logging"); @@ -437,7 +443,7 @@ cvs_getopt(int argc, char **argv) int ret; char *ep; - while ((ret = getopt(argc, argv, "b:d:e:fHlnQqrtvz:")) != -1) { + while ((ret = getopt(argc, argv, "b:d:e:fHlnQqrs:tvz:")) != -1) { switch (ret) { case 'b': /* @@ -472,6 +478,16 @@ cvs_getopt(int argc, char **argv) case 'r': cvs_readonly = 1; break; + case 's': + ep = strchr(optarg, '='); + if (ep == NULL) { + cvs_log(LP_ERR, "no = in variable assignment"); + exit(EX_USAGE); + } + *(ep++) = '\0'; + if (cvs_var_set(optarg, ep) < 0) + exit(EX_USAGE); + break; case 't': (void)cvs_log_filter(LP_FILTER_UNSET, LP_TRACE); cvs_trace = 1; @@ -623,3 +639,114 @@ cvs_read_rcfile(void) (void)fclose(fp); } + + +/* + * cvs_var_set() + * + * Set the value of the variable <var> to <val>. If there is no such variable, + * a new entry is created, otherwise the old value is overwritten. + * Returns 0 on success, or -1 on failure. + */ +int +cvs_var_set(const char *var, const char *val) +{ + char *valcp; + const char *cp; + struct cvs_var *vp; + + if ((var == NULL) || (*var == '\0')) { + cvs_log(LP_ERR, "no variable name"); + return (-1); + } + + /* sanity check on the name */ + for (cp = var; *cp != '\0'; cp++) + if (!isalnum(*cp) && (*cp != '_')) { + cvs_log(LP_ERR, + "variable name `%s' contains invalid characters", + var); + return (-1); + } + + TAILQ_FOREACH(vp, &cvs_variables, cv_link) + if (strcmp(vp->cv_name, var) == 0) + break; + + valcp = strdup(val); + if (valcp == NULL) { + cvs_log(LP_ERRNO, "failed to allocate variable"); + return (-1); + } + + if (vp == NULL) { + vp = (struct cvs_var *)malloc(sizeof(*vp)); + if (vp == NULL) { + cvs_log(LP_ERRNO, "failed to allocate variable"); + free(valcp); + return (-1); + } + memset(vp, 0, sizeof(*vp)); + + vp->cv_name = strdup(var); + if (vp->cv_name == NULL) { + cvs_log(LP_ERRNO, "failed to allocate variable"); + free(valcp); + free(vp); + return (-1); + } + + TAILQ_INSERT_TAIL(&cvs_variables, vp, cv_link); + + } else /* free the previous value */ + free(vp->cv_val); + + vp->cv_val = valcp; + + return (0); +} + + +/* + * cvs_var_set() + * + * Remove any entry for the variable <var>. + * Returns 0 on success, or -1 on failure. + */ +int +cvs_var_unset(const char *var) +{ + struct cvs_var *vp; + + TAILQ_FOREACH(vp, &cvs_variables, cv_link) + if (strcmp(vp->cv_name, var) == 0) { + TAILQ_REMOVE(&cvs_variables, vp, cv_link); + free(vp->cv_name); + free(vp->cv_val); + free(vp); + return (0); + } + + return (-1); + +} + + +/* + * cvs_var_get() + * + * Get the value associated with the variable <var>. Returns a pointer to the + * value string on success, or NULL if the variable does not exist. + */ + +const char* +cvs_var_get(const char *var) +{ + struct cvs_var *vp; + + TAILQ_FOREACH(vp, &cvs_variables, cv_link) + if (strcmp(vp->cv_name, var) == 0) + return (vp->cv_val); + + return (NULL); +} diff --git a/usr.bin/cvs/cvs.h b/usr.bin/cvs/cvs.h index 984c7c9d221..4ba776e7184 100644 --- a/usr.bin/cvs/cvs.h +++ b/usr.bin/cvs/cvs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cvs.h,v 1.40 2004/12/21 18:15:55 xsa Exp $ */ +/* $OpenBSD: cvs.h,v 1.41 2004/12/21 18:47:59 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -119,6 +119,14 @@ struct cvs_file; struct cvs_dir; struct cvs_flist; +struct cvs_var { + char *cv_name; + char *cv_val; + TAILQ_ENTRY(cvs_var) cv_link; +}; + + + struct cvs_op { u_int co_op; uid_t co_uid; /* user performing the operation */ @@ -257,6 +265,11 @@ int cvs_update (int, char **); int cvs_version (int, char **); +int cvs_var_set (const char *, const char *); +int cvs_var_unset (const char *); +const char* cvs_var_get (const char *); + + /* from root.c */ struct cvsroot* cvsroot_parse (const char *); void cvsroot_free (struct cvsroot *); |