GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/cvs/root.c Lines: 33 81 40.7 %
Date: 2017-11-07 Branches: 16 56 28.6 %

Line Branch Exec Source
1
/*	$OpenBSD: root.c,v 1.49 2017/06/01 08:08:24 joris Exp $	*/
2
/*
3
 * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. The name of the author may not be used to endorse or promote products
13
 *    derived from this software without specific prior written permission.
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
24
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#include <errno.h>
28
#include <stdlib.h>
29
#include <string.h>
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
47
#define CVS_NBMETHODS	(sizeof(cvs_methods)/sizeof(cvs_methods[0]))
48
49
/*
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:
55
 *	[:method:][[user[:pass]@]host[:port]:]path
56
 * Returns a pointer to the allocated information on success, or NULL
57
 * on failure.
58
 */
59
static struct cvsroot *
60
cvsroot_parse(const char *str)
61
{
62
	u_int i;
63
	char *cp, *sp, *pp;
64
82
	const char *errstr;
65
	static struct cvsroot *root = NULL;
66
67
41
	if (root != NULL)
68
		return (root);
69
70
41
	root = xcalloc(1, sizeof(*root));
71
41
	root->cr_method = CVS_METHOD_NONE;
72
41
	root->cr_str = xstrdup(str);
73
41
	root->cr_buf = xstrdup(str);
74
75
41
	sp = root->cr_buf;
76
	cp = root->cr_buf;
77
41
	if (*sp == ':') {
78
		sp++;
79
		if ((cp = strchr(sp, ':')) == NULL)
80
			fatal("failed to parse CVSROOT: unterminated method");
81
82
		*(cp++) = '\0';
83
84
		for (i = 0; i < CVS_NBMETHODS; i++) {
85
			if (strcmp(sp, cvs_methods[i]) == 0) {
86
				root->cr_method = i;
87
				break;
88
			}
89
		}
90
		if (i == CVS_NBMETHODS)
91
			fatal("cvsroot_parse: unknown method `%s'", sp);
92
	}
93
94
	/* find the start of the actual path */
95
41
	if ((sp = strchr(cp, '/')) == NULL)
96
		fatal("no path specification in CVSROOT");
97
98
41
	root->cr_dir = sp;
99

123
	STRIP_SLASH(root->cr_dir);
100
41
	if (sp == cp) {
101
41
		if (root->cr_method == CVS_METHOD_NONE)
102
41
			root->cr_method = CVS_METHOD_LOCAL;
103
		/* stop here, it's just a path */
104
41
		return (root);
105
	}
106
107
	if (*(sp - 1) != ':')
108
		fatal("missing host/path delimiter in CVSROOT");
109
110
	*(sp - 1) = '\0';
111
112
	/*
113
	 * looks like we have more than just a directory path, so
114
	 * attempt to split it into user and host parts
115
	 */
116
	sp = strchr(cp, '@');
117
	if (sp != NULL) {
118
		*(sp++) = '\0';
119
120
		/* password ? */
121
		pp = strchr(cp, ':');
122
		if (pp != NULL) {
123
			*(pp++) = '\0';
124
			root->cr_pass = pp;
125
		}
126
127
		root->cr_user = cp;
128
	} else
129
		sp = cp;
130
131
	pp = strchr(sp, ':');
132
	if (pp != NULL) {
133
		*(pp++) = '\0';
134
		root->cr_port = strtonum(pp, 1, 65535, &errstr);
135
		if (errstr != NULL)
136
			fatal("port specification in CVSROOT is %s", errstr);
137
138
	}
139
140
	root->cr_host = sp;
141
142
	if (root->cr_method == CVS_METHOD_NONE) {
143
		/* no method found from start of CVSROOT, guess */
144
		if (root->cr_host != NULL)
145
			root->cr_method = CVS_METHOD_SERVER;
146
		else
147
			root->cr_method = CVS_METHOD_LOCAL;
148
	}
149
150
	return (root);
151
41
}
152
153
/*
154
 * cvsroot_get()
155
 *
156
 * Get the CVSROOT information for a specific directory <dir>.  The
157
 * value is taken from one of 3 possible sources (in order of precedence):
158
 *
159
 * 1) the `-d' command-line option
160
 * 2) the CVS/Root file found in checked-out trees
161
 * 3) the CVSROOT environment variable
162
 */
163
struct cvsroot *
164
cvsroot_get(const char *dir)
165
{
166
82
	char rootpath[PATH_MAX], *rootstr, line[128];
167
	FILE *fp;
168
169
41
	if (cvs_rootstr != NULL)
170
17
		return cvsroot_parse(cvs_rootstr);
171
172
24
	if (cvs_server_active == 1)
173
		return cvsroot_parse(dir);
174
175
24
	if (cvs_cmdop == CVS_OP_IMPORT) {
176
		if ((rootstr = getenv("CVSROOT")) != NULL)
177
			return (cvsroot_parse(rootstr));
178
		return (NULL);
179
	}
180
181
24
	(void)xsnprintf(rootpath, PATH_MAX, "%s/%s", dir, CVS_PATH_ROOTSPEC);
182
183
24
	if ((fp = fopen(rootpath, "r")) == NULL) {
184
		if (errno == ENOENT) {
185
			/* try env as a last resort */
186
			if ((rootstr = getenv("CVSROOT")) != NULL)
187
				return cvsroot_parse(rootstr);
188
			else
189
				return (NULL);
190
		} else {
191
			fatal("cvsroot_get: fopen: `%s': %s",
192
			    CVS_PATH_ROOTSPEC, strerror(errno));
193
		}
194
	}
195
196
24
	if (fgets(line, (int)sizeof(line), fp) == NULL)
197
		fatal("cvsroot_get: fgets: `%s'", CVS_PATH_ROOTSPEC);
198
199
24
	(void)fclose(fp);
200
201
24
	line[strcspn(line, "\n")] = '\0';
202
24
	if (line[0] == '\0')
203
		cvs_log(LP_ERR, "empty %s file", CVS_PATH_ROOTSPEC);
204
205
24
	return cvsroot_parse(line);
206
41
}
207
208
int
209
cvsroot_is_local(void)
210
{
211
328
	if (current_cvsroot == NULL)
212
		fatal("cvsroot_is_local: no CVSROOT");
213
214
164
	return (current_cvsroot->cr_method == CVS_METHOD_LOCAL);
215
}
216
217
int
218
cvsroot_is_remote(void)
219
{
220
548
	if (current_cvsroot == NULL)
221
		fatal("cvsroot_is_remote: no CVSROOT");
222
223
274
	return (current_cvsroot->cr_method != CVS_METHOD_LOCAL);
224
}