2 * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
4 * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
7 * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8 * Portions Copyright (C) 1989-1992, Brian Berliner
10 * You may distribute under the terms of the GNU General Public License as
11 * specified in the README file that comes with the CVS source distribution.
21 extern char *logHistory;
24 * Parse the INFOFILE file for the specified REPOSITORY. Invoke CALLPROC for
25 * the first line in the file that matches the REPOSITORY, or if ALL != 0, any
26 * lines matching "ALL", or if no lines match, the last line matching
29 * Return 0 for success, -1 if there was not an INFOFILE, and >0 for failure.
32 Parse_Info (infofile, repository, callproc, all)
34 const char *repository;
42 size_t line_allocated = 0;
43 char *default_value = NULL;
46 int callback_done, line_number;
47 char *cp, *exp, *value;
49 const char *regex_err;
53 if (current_parsed_root == NULL)
55 /* XXX - should be error maybe? */
56 error (0, 0, "CVSROOT variable not set");
60 /* find the info file and open it */
61 infopath = xmalloc (strlen (current_parsed_root->directory)
65 (void) sprintf (infopath, "%s/%s/%s", current_parsed_root->directory,
66 CVSROOTADM, infofile);
67 fp_info = CVS_FOPEN (infopath, "r");
70 /* If no file, don't do anything special. */
71 if (!existence_error (errno))
72 error (0, errno, "cannot open %s", infopath);
77 /* strip off the CVSROOT if repository was absolute */
78 srepos = Short_Repository (repository);
81 (void) fprintf (stderr, "%s-> Parse_Info (%s, %s, %s)\n",
83 server_active ? "S" : " ",
87 infopath, srepos, all ? "ALL" : "not ALL");
89 /* search the info file for lines that match */
90 callback_done = line_number = 0;
91 while (getline (&line, &line_allocated, fp_info) >= 0)
95 /* skip lines starting with # */
99 /* skip whitespace at beginning of line */
100 for (cp = line; *cp && isspace ((unsigned char) *cp); cp++)
103 /* if *cp is null, the whole line was blank */
107 /* the regular expression is everything up to the first space */
108 for (exp = cp; *cp && !isspace ((unsigned char) *cp); cp++)
113 /* skip whitespace up to the start of the matching value */
114 while (*cp && isspace ((unsigned char) *cp))
117 /* no value to match with the regular expression is an error */
120 error (0, 0, "syntax error at line %d file %s; ignored",
121 line_number, infofile);
126 /* strip the newline off the end of the value */
127 if ((cp = strrchr (value, '\n')) != NULL)
131 * At this point, exp points to the regular expression, and value
132 * points to the value to call the callback routine with. Evaluate
133 * the regular expression against srepos and callback with the value
137 /* save the default value so we have it later if we need it */
138 if (strcmp (exp, "DEFAULT") == 0)
140 if (default_value != NULL)
142 error (0, 0, "Multiple `DEFAULT' lines (%d and %d) in %s file",
143 default_line, line_number, infofile);
144 free (default_value);
146 default_value = xstrdup(value);
147 default_line = line_number;
152 * For a regular expression of "ALL", do the callback always We may
153 * execute lots of ALL callbacks in addition to *one* regular matching
154 * callback or default
156 if (strcmp (exp, "ALL") == 0)
159 error(0, 0, "Keyword `ALL' is ignored at line %d in %s file",
160 line_number, infofile);
161 else if ((expanded_value = expand_path (value, infofile,
162 line_number)) != NULL)
164 err += callproc (repository, expanded_value);
165 free (expanded_value);
173 /* only first matching, plus "ALL"'s */
176 /* see if the repository matched this regular expression */
177 if ((regex_err = re_comp (exp)) != NULL)
179 error (0, 0, "bad regular expression at line %d file %s: %s",
180 line_number, infofile, regex_err);
183 if (re_exec (srepos) == 0)
184 continue; /* no match */
186 /* it did, so do the callback and note that we did one */
187 if ((expanded_value = expand_path (value, infofile, line_number)) != NULL)
189 err += callproc (repository, expanded_value);
190 free (expanded_value);
196 if (ferror (fp_info))
197 error (0, errno, "cannot read %s", infopath);
198 if (fclose (fp_info) < 0)
199 error (0, errno, "cannot close %s", infopath);
201 /* if we fell through and didn't callback at all, do the default */
202 if (callback_done == 0 && default_value != NULL)
204 if ((expanded_value = expand_path (default_value, infofile, default_line)) != NULL)
206 err += callproc (repository, expanded_value);
207 free (expanded_value);
213 /* free up space if necessary */
214 if (default_value != NULL)
215 free (default_value);
224 /* Parse the CVS config file. The syntax right now is a bit ad hoc
225 but tries to draw on the best or more common features of the other
226 *info files and various unix (or non-unix) config file syntaxes.
227 Lines starting with # are comments. Settings are lines of the form
228 KEYWORD=VALUE. There is currently no way to have a multi-line
229 VALUE (would be nice if there was, probably).
231 CVSROOT is the $CVSROOT directory
232 (current_parsed_root->directory might not be set yet, so this
233 function takes the cvsroot as a function argument).
235 Returns 0 for success, negative value for failure. Call
236 error(0, ...) on errors in addition to the return value. */
238 parse_config (cvsroot)
244 size_t line_allocated = 0;
247 /* FIXME-reentrancy: If we do a multi-threaded server, this would need
248 to go to the per-connection data structures. */
249 static int parsed = 0;
251 /* Authentication code and serve_root might both want to call us.
252 Let this happen smoothly. */
257 infopath = xmalloc (strlen (cvsroot)
258 + sizeof (CVSROOTADM_CONFIG)
259 + sizeof (CVSROOTADM)
261 if (infopath == NULL)
263 error (0, 0, "out of memory; cannot allocate infopath");
267 strcpy (infopath, cvsroot);
268 strcat (infopath, "/");
269 strcat (infopath, CVSROOTADM);
270 strcat (infopath, "/");
271 strcat (infopath, CVSROOTADM_CONFIG);
273 fp_info = CVS_FOPEN (infopath, "r");
276 /* If no file, don't do anything special. */
277 if (!existence_error (errno))
279 /* Just a warning message; doesn't affect return
280 value, currently at least. */
281 error (0, errno, "cannot open %s", infopath);
283 goto set_defaults_and_return;
286 while (getline (&line, &line_allocated, fp_info) >= 0)
292 /* At least for the moment we don't skip whitespace at the start
293 of the line. Too picky? Maybe. But being insufficiently
294 picky leads to all sorts of confusion, and it is a lot easier
295 to start out picky and relax it than the other way around.
297 Is there any kind of written standard for the syntax of this
298 sort of config file? Anywhere in POSIX for example (I guess
299 makefiles are sort of close)? Red Hat Linux has a bunch of
300 these too (with some GUI tools which edit them)...
302 Along the same lines, we might want a table of keywords,
303 with various types (boolean, string, &c), as a mechanism
304 for making sure the syntax is consistent. Any good examples
305 to follow there (Apache?)? */
307 /* Strip the trailing newline. There will be one unless we
308 read a partial line without a newline, and then got end of
311 len = strlen (line) - 1;
312 if (line[len] == '\n')
315 /* Skip blank lines. */
319 /* The first '=' separates keyword from value. */
320 p = strchr (line, '=');
323 /* Probably should be printing line number. */
324 error (0, 0, "syntax error in %s: line '%s' is missing '='",
331 if (strcmp (line, "RCSBIN") == 0)
333 /* This option used to specify the directory for RCS
334 executables. But since we don't run them any more,
335 this is a noop. Silently ignore it so that a
336 repository can work with either new or old CVS. */
339 else if (strcmp (line, "SystemAuth") == 0)
341 if (strcmp (p, "no") == 0)
342 #ifdef AUTH_SERVER_SUPPORT
345 /* Still parse the syntax but ignore the
346 option. That way the same config file can
347 be used for local and server. */
350 else if (strcmp (p, "yes") == 0)
351 #ifdef AUTH_SERVER_SUPPORT
358 error (0, 0, "unrecognized value '%s' for SystemAuth", p);
362 else if (strcmp (line, "tag") == 0) {
365 else if (strcmp (line, "umask") == 0) {
366 cvsumask = (mode_t)(strtol(p, NULL, 8) & 0777);
368 else if (strcmp (line, "dlimit") == 0) {
370 #include <sys/resource.h>
373 if (getrlimit(RLIMIT_DATA, &rl) != -1) {
374 rl.rlim_cur = atoi(p);
377 (void) setrlimit(RLIMIT_DATA, &rl);
381 else if (strcmp (line, "PreservePermissions") == 0)
383 if (strcmp (p, "no") == 0)
385 else if (strcmp (p, "yes") == 0)
387 #ifdef PRESERVE_PERMISSIONS_SUPPORT
391 warning: this CVS does not support PreservePermissions");
396 error (0, 0, "unrecognized value '%s' for PreservePermissions",
401 else if (strcmp (line, "TopLevelAdmin") == 0)
403 if (strcmp (p, "no") == 0)
405 else if (strcmp (p, "yes") == 0)
409 error (0, 0, "unrecognized value '%s' for TopLevelAdmin", p);
413 else if (strcmp (line, "LockDir") == 0)
415 if (lock_dir != NULL)
417 lock_dir = xstrdup (p);
418 /* Could try some validity checking, like whether we can
419 opendir it or something, but I don't see any particular
420 reason to do that now rather than waiting until lock.c. */
422 else if (strcmp (line, "LogHistory") == 0)
424 if (strcmp (p, "all") != 0)
426 if (logHistory) free (logHistory);
427 logHistory = xstrdup (p);
430 else if (strcmp (line, "RereadLogAfterVerify") == 0)
432 if (strcmp (p, "no") == 0 || strcmp (p, "never") == 0)
433 RereadLogAfterVerify = LOGMSG_REREAD_NEVER;
434 else if (strcmp (p, "yes") == 0 || strcmp (p, "always") == 0)
435 RereadLogAfterVerify = LOGMSG_REREAD_ALWAYS;
436 else if (strcmp (p, "stat") == 0)
437 RereadLogAfterVerify = LOGMSG_REREAD_STAT;
439 else if (strcmp(line, "LocalKeyword") == 0)
441 /* Recognize cvs-1.12-style keyword control rather than erroring out. */
444 else if (strcmp(line, "KeywordExpand") == 0)
446 /* Recognize cvs-1.12-style keyword control rather than erroring out. */
451 /* We may be dealing with a keyword which was added in a
452 subsequent version of CVS. In that case it is a good idea
453 to complain, as (1) the keyword might enable a behavior like
454 alternate locking behavior, in which it is dangerous and hard
455 to detect if some CVS's have it one way and others have it
456 the other way, (2) in general, having us not do what the user
457 had in mind when they put in the keyword violates the
458 principle of least surprise. Note that one corollary is
459 adding new keywords to your CVSROOT/config file is not
460 particularly recommended unless you are planning on using
462 error (0, 0, "%s: unrecognized keyword '%s'",
467 if (ferror (fp_info))
469 error (0, errno, "cannot read %s", infopath);
472 if (fclose (fp_info) < 0)
474 error (0, errno, "cannot close %s", infopath);
477 set_defaults_and_return:
479 logHistory = xstrdup (ALL_HISTORY_REC_TYPES);
487 logHistory = xstrdup (ALL_HISTORY_REC_TYPES);
488 if (infopath != NULL)