Annotation of src/usr.bin/cvs/root.c, Revision 1.45
1.45 ! tobias 1: /* $OpenBSD: root.c,v 1.44 2007/10/05 19:28:23 gilles Exp $ */
1.1 jfb 2: /*
3: * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
1.13 tedu 4: * All rights reserved.
1.1 jfb 5: *
1.13 tedu 6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
1.1 jfb 9: *
1.13 tedu 10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
1.1 jfb 12: * 2. The name of the author may not be used to endorse or promote products
1.13 tedu 13: * derived from this software without specific prior written permission.
1.1 jfb 14: *
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
1.13 tedu 24: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1 jfb 25: */
26:
1.36 otto 27: #include <errno.h>
28: #include <stdlib.h>
29: #include <string.h>
1.1 jfb 30:
31: #include "cvs.h"
32:
33: extern char *cvs_rootstr;
34:
35: /* keep these ordered with the defines */
36: const char *cvs_methods[] = {
37: "",
38: "local",
39: "ssh",
40: "pserver",
41: "kserver",
42: "gserver",
43: "ext",
44: "fork",
45: };
46:
1.20 xsa 47: #define CVS_NBMETHODS (sizeof(cvs_methods)/sizeof(cvs_methods[0]))
1.6 jfb 48:
49: /*
1.1 jfb 50: * cvsroot_parse()
51: *
52: * Parse a CVS root string (as found in CVS/Root files or the CVSROOT
53: * environment variable) and store the fields in a dynamically
54: * allocated cvs_root structure. The format of the string is as follows:
1.39 xsa 55: * [:method:][[user[:pass]@]host[:port]:]path
1.1 jfb 56: * Returns a pointer to the allocated information on success, or NULL
57: * on failure.
58: */
1.40 joris 59: static struct cvsroot *
1.1 jfb 60: cvsroot_parse(const char *str)
61: {
62: u_int i;
63: char *cp, *sp, *pp;
1.37 xsa 64: const char *errstr;
1.40 joris 65: static struct cvsroot *root = NULL;
1.1 jfb 66:
1.40 joris 67: if (root != NULL)
68: return (root);
1.6 jfb 69:
1.31 ray 70: root = xcalloc(1, sizeof(*root));
1.1 jfb 71: root->cr_method = CVS_METHOD_NONE;
1.10 jfb 72: CVS_RSTVR(root);
1.1 jfb 73:
1.26 joris 74: root->cr_str = xstrdup(str);
75: root->cr_buf = xstrdup(str);
1.1 jfb 76:
77: sp = root->cr_buf;
78: cp = root->cr_buf;
79: if (*sp == ':') {
80: sp++;
1.27 xsa 81: if ((cp = strchr(sp, ':')) == NULL)
82: fatal("failed to parse CVSROOT: unterminated method");
83:
1.1 jfb 84: *(cp++) = '\0';
85:
86: for (i = 0; i < CVS_NBMETHODS; i++) {
87: if (strcmp(sp, cvs_methods[i]) == 0) {
88: root->cr_method = i;
89: break;
90: }
1.14 jfb 91: }
1.27 xsa 92: if (i == CVS_NBMETHODS)
93: fatal("cvsroot_parse: unknown method `%s'", sp);
1.1 jfb 94: }
95:
96: /* find the start of the actual path */
1.27 xsa 97: if ((sp = strchr(cp, '/')) == NULL)
98: fatal("no path specification in CVSROOT");
1.1 jfb 99:
100: root->cr_dir = sp;
1.32 joris 101: STRIP_SLASH(root->cr_dir);
1.1 jfb 102: if (sp == cp) {
103: if (root->cr_method == CVS_METHOD_NONE)
104: root->cr_method = CVS_METHOD_LOCAL;
105: /* stop here, it's just a path */
106: return (root);
107: }
108:
1.27 xsa 109: if (*(sp - 1) != ':')
110: fatal("missing host/path delimiter in CVSROOT");
111:
1.1 jfb 112: *(sp - 1) = '\0';
113:
114: /*
115: * looks like we have more than just a directory path, so
116: * attempt to split it into user and host parts
117: */
118: sp = strchr(cp, '@');
119: if (sp != NULL) {
120: *(sp++) = '\0';
121:
122: /* password ? */
123: pp = strchr(cp, ':');
124: if (pp != NULL) {
125: *(pp++) = '\0';
126: root->cr_pass = pp;
127: }
128:
129: root->cr_user = cp;
1.12 deraadt 130: } else
1.11 jfb 131: sp = cp;
1.1 jfb 132:
133: pp = strchr(sp, ':');
134: if (pp != NULL) {
135: *(pp++) = '\0';
1.43 joris 136: root->cr_port = strtonum(pp, 1, 65535, &errstr);
1.37 xsa 137: if (errstr != NULL)
138: fatal("port specification in CVSROOT is %s", errstr);
1.1 jfb 139:
140: }
141:
142: root->cr_host = sp;
143:
144: if (root->cr_method == CVS_METHOD_NONE) {
145: /* no method found from start of CVSROOT, guess */
146: if (root->cr_host != NULL)
147: root->cr_method = CVS_METHOD_SERVER;
148: else
149: root->cr_method = CVS_METHOD_LOCAL;
150: }
151:
152: return (root);
1.25 joris 153: }
1.1 jfb 154:
155: /*
156: * cvsroot_get()
157: *
158: * Get the CVSROOT information for a specific directory <dir>. The
159: * value is taken from one of 3 possible sources (in order of precedence):
160: *
161: * 1) the `-d' command-line option
162: * 2) the CVS/Root file found in checked-out trees
163: * 3) the CVSROOT environment variable
164: */
1.21 xsa 165: struct cvsroot *
1.1 jfb 166: cvsroot_get(const char *dir)
167: {
1.5 jfb 168: char rootpath[MAXPATHLEN], *rootstr, line[128];
1.1 jfb 169: FILE *fp;
170:
171: if (cvs_rootstr != NULL)
172: return cvsroot_parse(cvs_rootstr);
1.41 tobias 173:
174: if (cvs_server_active == 1)
175: return cvsroot_parse(dir);
1.45 ! tobias 176:
! 177: if (cvs_cmdop == CVS_OP_IMPORT)
! 178: return NULL;
1.1 jfb 179:
1.35 xsa 180: (void)xsnprintf(rootpath, MAXPATHLEN, "%s/%s", dir, CVS_PATH_ROOTSPEC);
1.16 xsa 181:
1.27 xsa 182: if ((fp = fopen(rootpath, "r")) == NULL) {
1.1 jfb 183: if (errno == ENOENT) {
184: /* try env as a last resort */
185: if ((rootstr = getenv("CVSROOT")) != NULL)
186: return cvsroot_parse(rootstr);
187: else
1.32 joris 188: return (NULL);
1.12 deraadt 189: } else {
1.27 xsa 190: fatal("cvsroot_get: fopen: `%s': %s",
191: CVS_PATH_ROOTSPEC, strerror(errno));
1.1 jfb 192: }
193: }
194:
1.27 xsa 195: if (fgets(line, (int)sizeof(line), fp) == NULL)
196: fatal("cvsroot_get: fgets: `%s'", CVS_PATH_ROOTSPEC);
197:
1.5 jfb 198: (void)fclose(fp);
1.1 jfb 199:
1.44 gilles 200: line[strcspn(line, "\n")] = '\0';
201: if (line[0] == '\0')
1.32 joris 202: cvs_log(LP_ERR, "empty %s file", CVS_PATH_ROOTSPEC);
1.1 jfb 203:
1.5 jfb 204: return cvsroot_parse(line);
1.1 jfb 205: }