/* $OpenBSD: root.c,v 1.49 2017/06/01 08:08:24 joris Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "cvs.h" extern char *cvs_rootstr; /* keep these ordered with the defines */ const char *cvs_methods[] = { "", "local", "ssh", "pserver", "kserver", "gserver", "ext", "fork", }; #define CVS_NBMETHODS (sizeof(cvs_methods)/sizeof(cvs_methods[0])) /* * cvsroot_parse() * * Parse a CVS root string (as found in CVS/Root files or the CVSROOT * environment variable) and store the fields in a dynamically * allocated cvs_root structure. The format of the string is as follows: * [:method:][[user[:pass]@]host[:port]:]path * Returns a pointer to the allocated information on success, or NULL * on failure. */ 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); } /* find the start of the actual path */ 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; /* stop here, it's just a path */ return (root); } if (*(sp - 1) != ':') fatal("missing host/path delimiter in CVSROOT"); *(sp - 1) = '\0'; /* * looks like we have more than just a directory path, so * attempt to split it into user and host parts */ sp = strchr(cp, '@'); if (sp != NULL) { *(sp++) = '\0'; /* password ? */ 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) { /* no method found from start of CVSROOT, guess */ if (root->cr_host != NULL) root->cr_method = CVS_METHOD_SERVER; else root->cr_method = CVS_METHOD_LOCAL; } return (root); } /* * cvsroot_get() * * Get the CVSROOT information for a specific directory . The * value is taken from one of 3 possible sources (in order of precedence): * * 1) the `-d' command-line option * 2) the CVS/Root file found in checked-out trees * 3) the CVSROOT environment variable */ 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) { /* try env as a last resort */ 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); }