#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "cvs.h"
extern char *cvs_rootstr;
const char *cvs_methods[] = {
"",
"local",
"ssh",
"pserver",
"kserver",
"gserver",
"ext",
"fork",
};
#define CVS_NBMETHODS (sizeof(cvs_methods)/sizeof(cvs_methods[0]))
static struct cvsroot *
cvsroot_parse(const char *str)
{
u_int i;
char *cp, *sp, *pp;
const char *errstr;
static struct cvsroot *root = NULL;
if (root != NULL)
return (root);
root = xcalloc(1, sizeof(*root));
root->cr_method = CVS_METHOD_NONE;
root->cr_str = xstrdup(str);
root->cr_buf = xstrdup(str);
sp = root->cr_buf;
cp = root->cr_buf;
if (*sp == ':') {
sp++;
if ((cp = strchr(sp, ':')) == NULL)
fatal("failed to parse CVSROOT: unterminated method");
*(cp++) = '\0';
for (i = 0; i < CVS_NBMETHODS; i++) {
if (strcmp(sp, cvs_methods[i]) == 0) {
root->cr_method = i;
break;
}
}
if (i == CVS_NBMETHODS)
fatal("cvsroot_parse: unknown method `%s'", sp);
}
if ((sp = strchr(cp, '/')) == NULL)
fatal("no path specification in CVSROOT");
root->cr_dir = sp;
STRIP_SLASH(root->cr_dir);
if (sp == cp) {
if (root->cr_method == CVS_METHOD_NONE)
root->cr_method = CVS_METHOD_LOCAL;
return (root);
}
if (*(sp - 1) != ':')
fatal("missing host/path delimiter in CVSROOT");
*(sp - 1) = '\0';
sp = strchr(cp, '@');
if (sp != NULL) {
*(sp++) = '\0';
pp = strchr(cp, ':');
if (pp != NULL) {
*(pp++) = '\0';
root->cr_pass = pp;
}
root->cr_user = cp;
} else
sp = cp;
pp = strchr(sp, ':');
if (pp != NULL) {
*(pp++) = '\0';
root->cr_port = strtonum(pp, 1, 65535, &errstr);
if (errstr != NULL)
fatal("port specification in CVSROOT is %s", errstr);
}
root->cr_host = sp;
if (root->cr_method == CVS_METHOD_NONE) {
if (root->cr_host != NULL)
root->cr_method = CVS_METHOD_SERVER;
else
root->cr_method = CVS_METHOD_LOCAL;
}
return (root);
}
struct cvsroot *
cvsroot_get(const char *dir)
{
char rootpath[PATH_MAX], *rootstr, line[128];
FILE *fp;
if (cvs_rootstr != NULL)
return cvsroot_parse(cvs_rootstr);
if (cvs_server_active == 1)
return cvsroot_parse(dir);
if (cvs_cmdop == CVS_OP_IMPORT) {
if ((rootstr = getenv("CVSROOT")) != NULL)
return (cvsroot_parse(rootstr));
return (NULL);
}
(void)xsnprintf(rootpath, PATH_MAX, "%s/%s", dir, CVS_PATH_ROOTSPEC);
if ((fp = fopen(rootpath, "r")) == NULL) {
if (errno == ENOENT) {
if ((rootstr = getenv("CVSROOT")) != NULL)
return cvsroot_parse(rootstr);
else
return (NULL);
} else {
fatal("cvsroot_get: fopen: `%s': %s",
CVS_PATH_ROOTSPEC, strerror(errno));
}
}
if (fgets(line, (int)sizeof(line), fp) == NULL)
fatal("cvsroot_get: fgets: `%s'", CVS_PATH_ROOTSPEC);
(void)fclose(fp);
line[strcspn(line, "\n")] = '\0';
if (line[0] == '\0')
cvs_log(LP_ERR, "empty %s file", CVS_PATH_ROOTSPEC);
return cvsroot_parse(line);
}
int
cvsroot_is_local(void)
{
if (current_cvsroot == NULL)
fatal("cvsroot_is_local: no CVSROOT");
return (current_cvsroot->cr_method == CVS_METHOD_LOCAL);
}
int
cvsroot_is_remote(void)
{
if (current_cvsroot == NULL)
fatal("cvsroot_is_remote: no CVSROOT");
return (current_cvsroot->cr_method != CVS_METHOD_LOCAL);
}