#include "cvs.h"
#include "getline.h"
char *method_names[] = {
"local", "server (rsh)", "pserver", "kserver", "gserver", "ext"
};
#ifndef DEBUG
char *
Name_Root (dir, update_dir)
char *dir;
char *update_dir;
{
FILE *fpin;
char *ret, *xupdate_dir;
char *root = NULL;
size_t root_allocated = 0;
char *tmp;
char *cvsadm;
char *cp;
if (update_dir && *update_dir)
xupdate_dir = update_dir;
else
xupdate_dir = ".";
if (dir != NULL)
{
cvsadm = xmalloc (strlen (dir) + sizeof (CVSADM) + 10);
(void) sprintf (cvsadm, "%s/%s", dir, CVSADM);
tmp = xmalloc (strlen (dir) + sizeof (CVSADM_ROOT) + 10);
(void) sprintf (tmp, "%s/%s", dir, CVSADM_ROOT);
}
else
{
cvsadm = xstrdup (CVSADM);
tmp = xstrdup (CVSADM_ROOT);
}
if ((!isdir (cvsadm)) || (!isreadable (tmp)))
{
ret = NULL;
goto out;
}
fpin = open_file (tmp, "r");
if (getline (&root, &root_allocated, fpin) < 0)
{
error (0, 0, "in directory %s:", xupdate_dir);
error (0, errno, "cannot read %s", CVSADM_ROOT);
error (0, 0, "please correct this problem");
ret = NULL;
goto out;
}
(void) fclose (fpin);
if ((cp = strrchr (root, '\n')) != NULL)
*cp = '\0';
if (
#ifdef CLIENT_SUPPORT
(strchr (root, ':') == NULL) &&
#endif
! isabsolute (root))
{
error (0, 0, "in directory %s:", xupdate_dir);
error (0, 0,
"ignoring %s because it does not contain an absolute pathname.",
CVSADM_ROOT);
ret = NULL;
goto out;
}
#ifdef CLIENT_SUPPORT
if ((strchr (root, ':') == NULL) && !isdir (root))
#else
if (!isdir (root))
#endif
{
error (0, 0, "in directory %s:", xupdate_dir);
error (0, 0,
"ignoring %s because it specifies a non-existent repository %s",
CVSADM_ROOT, root);
ret = NULL;
goto out;
}
strip_trailing_slashes (root);
ret = xstrdup (root);
out:
free (cvsadm);
free (tmp);
if (root != NULL)
free (root);
return (ret);
}
void
Create_Root (dir, rootdir)
char *dir;
char *rootdir;
{
FILE *fout;
char *tmp;
if (noexec)
return;
if (rootdir != NULL)
{
if (dir != NULL)
{
tmp = xmalloc (strlen (dir) + sizeof (CVSADM_ROOT) + 10);
(void) sprintf (tmp, "%s/%s", dir, CVSADM_ROOT);
}
else
tmp = xstrdup (CVSADM_ROOT);
fout = open_file (tmp, "w+");
if (fprintf (fout, "%s\n", rootdir) < 0)
error (1, errno, "write to %s failed", tmp);
if (fclose (fout) == EOF)
error (1, errno, "cannot close %s", tmp);
free (tmp);
}
}
#endif
static unsigned int root_allow_count;
static char **root_allow_vector;
static unsigned int root_allow_size;
void
root_allow_add (arg)
char *arg;
{
char *p;
if (root_allow_size <= root_allow_count)
{
if (root_allow_size == 0)
{
root_allow_size = 1;
root_allow_vector =
(char **) malloc (root_allow_size * sizeof (char *));
}
else
{
root_allow_size *= 2;
root_allow_vector =
(char **) realloc (root_allow_vector,
root_allow_size * sizeof (char *));
}
if (root_allow_vector == NULL)
{
no_memory:
printf ("E Fatal server error, aborting.\n\
error ENOMEM Virtual memory exhausted.\n");
#ifdef SYSTEM_CLEANUP
SYSTEM_CLEANUP ();
#endif
exit (EXIT_FAILURE);
}
}
p = malloc (strlen (arg) + 1);
if (p == NULL)
goto no_memory;
strcpy (p, arg);
root_allow_vector[root_allow_count++] = p;
}
void
root_allow_free ()
{
if (root_allow_vector != NULL)
free (root_allow_vector);
root_allow_count = 0;
root_allow_size = 0;
}
int
root_allow_ok (arg)
char *arg;
{
unsigned int i;
if (root_allow_count == 0)
{
printf ("\
error 0 Server configuration missing --allow-root in inetd.conf\n");
error_exit ();
}
for (i = 0; i < root_allow_count; ++i)
if (strcmp (root_allow_vector[i], arg) == 0)
return 1;
return 0;
}
char *CVSroot_original = NULL;
int client_active;
CVSmethod CVSroot_method;
char *CVSroot_username;
char *CVSroot_hostname;
char *CVSroot_directory;
#ifdef AUTH_SERVER_SUPPORT
static void
check_root_consistent ()
{
if ((Pserver_Repos != NULL) && (CVSroot_directory != NULL))
if (strcmp (Pserver_Repos, CVSroot_directory) != 0)
error (1, 0, "repository mismatch: \"%s\" vs \"%s\"",
Pserver_Repos, CVSroot_directory);
}
#endif
int
parse_cvsroot (CVSroot)
char *CVSroot;
{
static int cvsroot_parsed = 0;
char *cvsroot_copy, *p;
int check_hostname;
if (cvsroot_parsed)
{
error (0, 0, "WARNING (parse_cvsroot): someone called me twice!\n");
return 0;
}
CVSroot_original = xstrdup (CVSroot);
cvsroot_copy = xstrdup (CVSroot);
if ((*cvsroot_copy == ':'))
{
char *method = ++cvsroot_copy;
if (! (p = strchr (method, ':')))
{
error (0, 0, "bad CVSroot: %s", CVSroot);
return 1;
}
*p = '\0';
cvsroot_copy = ++p;
if (strcmp (method, "local") == 0)
CVSroot_method = local_method;
else if (strcmp (method, "pserver") == 0)
CVSroot_method = pserver_method;
else if (strcmp (method, "kserver") == 0)
CVSroot_method = kserver_method;
else if (strcmp (method, "gserver") == 0)
CVSroot_method = gserver_method;
else if (strcmp (method, "server") == 0)
CVSroot_method = server_method;
else if (strcmp (method, "ext") == 0)
CVSroot_method = ext_method;
else
{
error (0, 0, "unknown method in CVSroot: %s", CVSroot);
return 1;
}
}
else
{
CVSroot_method = ((strchr (cvsroot_copy, ':'))
#ifdef RSH_NOT_TRANSPARENT
? server_method
#else
? ext_method
#endif
: local_method);
}
client_active = (CVSroot_method != local_method);
CVSroot_username = NULL;
CVSroot_hostname = NULL;
if (CVSroot_method != local_method)
{
if ((p = strchr (cvsroot_copy, '@')))
{
CVSroot_username = cvsroot_copy;
*p = '\0';
cvsroot_copy = ++p;
if (*CVSroot_username == '\0')
CVSroot_username = NULL;
}
if ((p = strchr (cvsroot_copy, ':')))
{
CVSroot_hostname = cvsroot_copy;
*p = '\0';
cvsroot_copy = ++p;
if (*CVSroot_hostname == '\0')
CVSroot_hostname = NULL;
}
}
CVSroot_directory = cvsroot_copy;
#ifdef AUTH_SERVER_SUPPORT
check_root_consistent ();
#endif
#if ! defined (CLIENT_SUPPORT) && ! defined (DEBUG)
if (CVSroot_method != local_method)
{
error (0, 0, "Your CVSROOT is set for a remote access method");
error (0, 0, "but your CVS executable doesn't support it");
error (0, 0, "(%s)", CVSroot);
return 1;
}
#endif
if (CVSroot_username && ! CVSroot_hostname)
{
error (0, 0, "missing hostname in CVSROOT: %s", CVSroot);
return 1;
}
check_hostname = 0;
switch (CVSroot_method)
{
case local_method:
if (CVSroot_username || CVSroot_hostname)
{
error (0, 0, "can't specify hostname and username in CVSROOT");
error (0, 0, "when using local access method");
error (0, 0, "(%s)", CVSroot);
return 1;
}
if (!isabsolute (CVSroot_directory))
error (1, 0, "CVSROOT %s must be an absolute pathname",
CVSroot_directory);
break;
case kserver_method:
#ifndef HAVE_KERBEROS
error (0, 0, "Your CVSROOT is set for a kerberos access method");
error (0, 0, "but your CVS executable doesn't support it");
error (0, 0, "(%s)", CVSroot);
return 1;
#endif
check_hostname = 1;
break;
case gserver_method:
#ifndef HAVE_GSSAPI
error (0, 0, "Your CVSROOT is set for a GSSAPI access method");
error (0, 0, "but your CVS executable doesn't support it");
error (0, 0, "(%s)", CVSroot);
return 1;
#endif
check_hostname = 1;
break;
case server_method:
case ext_method:
case pserver_method:
check_hostname = 1;
break;
}
if (check_hostname)
{
if (! CVSroot_hostname)
{
error (0, 0, "didn't specify hostname in CVSROOT: %s", CVSroot);
return 1;
}
}
if (*CVSroot_directory == '\0')
{
error (0, 0, "missing directory in CVSROOT: %s", CVSroot);
return 1;
}
return 0;
}
void
set_local_cvsroot (dir)
char *dir;
{
CVSroot_original = xstrdup (dir);
CVSroot_method = local_method;
CVSroot_directory = CVSroot_original;
#ifdef AUTH_SERVER_SUPPORT
check_root_consistent ();
#endif
CVSroot_username = NULL;
CVSroot_hostname = NULL;
client_active = 0;
}
#ifdef DEBUG
#include <stdio.h>
char *CVSroot;
char *program_name = "testing";
char *command_name = "parse_cvsroot";
void
main (argc, argv)
int argc;
char *argv[];
{
program_name = argv[0];
if (argc != 2)
{
fprintf (stderr, "Usage: %s <CVSROOT>\n", program_name);
exit (2);
}
if (parse_cvsroot (argv[1]))
{
fprintf (stderr, "%s: Parsing failed.", program_name);
exit (1);
}
printf ("CVSroot: %s\n", argv[1]);
printf ("CVSroot_method: %s\n", method_names[CVSroot_method]);
printf ("CVSroot_username: %s\n",
CVSroot_username ? CVSroot_username : "NULL");
printf ("CVSroot_hostname: %s\n",
CVSroot_hostname ? CVSroot_hostname : "NULL");
printf ("CVSroot_directory: %s\n", CVSroot_directory);
exit (0);
}
#endif