summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src/client.c')
-rw-r--r--contrib/cvs/src/client.c167
1 files changed, 129 insertions, 38 deletions
diff --git a/contrib/cvs/src/client.c b/contrib/cvs/src/client.c
index eafe916..3119613 100644
--- a/contrib/cvs/src/client.c
+++ b/contrib/cvs/src/client.c
@@ -1,3 +1,5 @@
+/* JT thinks BeOS is worth the trouble. */
+
/* CVS client-related stuff.
This program is free software; you can redistribute it and/or modify
@@ -64,7 +66,6 @@ extern char *strerror ();
#if HAVE_KERBEROS
#define CVS_PORT 1999
-#if HAVE_KERBEROS
#include <krb.h>
extern char *krb_realmofhost ();
@@ -78,8 +79,6 @@ static Key_schedule sched;
#endif /* HAVE_KERBEROS */
-#endif /* HAVE_KERBEROS */
-
#ifdef HAVE_GSSAPI
#ifdef HAVE_GSSAPI_H
@@ -1119,7 +1118,7 @@ call_in_directory (pathname, func, data)
strcpy (r, "/.");
Create_Admin (".", ".", repo, (char *) NULL,
- (char *) NULL, 0, 1);
+ (char *) NULL, 0, 1, 1);
free (repo);
}
@@ -1256,7 +1255,7 @@ warning: server is not creating directories one at a time");
strcpy (r, reposdirname);
Create_Admin (dir, dir, repo,
- (char *)NULL, (char *)NULL, 0, 0);
+ (char *)NULL, (char *)NULL, 0, 0, 1);
free (repo);
b = strrchr (dir, '/');
@@ -1764,6 +1763,7 @@ update_entries (data_arg, ent_list, short_pathname, filename)
}
free (mode_string);
+ free (scratch_entries);
free (entries_line);
/* The Mode, Mod-time, and Checksum responses should not carry
@@ -1851,7 +1851,8 @@ update_entries (data_arg, ent_list, short_pathname, filename)
if (use_gzip)
{
- if (gunzip_and_write (fd, short_pathname, buf, size))
+ if (gunzip_and_write (fd, short_pathname,
+ (unsigned char *) buf, size))
error (1, 0, "aborting due to compression error");
}
else if (write (fd, buf, size) != size)
@@ -2029,6 +2030,8 @@ update_entries (data_arg, ent_list, short_pathname, filename)
free (mode_string);
free (buf);
+ free (scratch_entries);
+ free (entries_line);
return;
}
@@ -2127,8 +2130,8 @@ update_entries (data_arg, ent_list, short_pathname, filename)
if (file_timestamp)
free (file_timestamp);
- free (scratch_entries);
}
+ free (scratch_entries);
free (entries_line);
}
@@ -2494,7 +2497,11 @@ handle_set_checkin_prog (args, len)
{
char *prog;
struct save_prog *p;
+
read_line (&prog);
+ if (strcmp (command_name, "export") == 0)
+ return;
+
p = (struct save_prog *) xmalloc (sizeof (struct save_prog));
p->next = checkin_progs;
p->dir = xstrdup (args);
@@ -2509,7 +2516,11 @@ handle_set_update_prog (args, len)
{
char *prog;
struct save_prog *p;
+
read_line (&prog);
+ if (strcmp (command_name, "export") == 0)
+ return;
+
p = (struct save_prog *) xmalloc (sizeof (struct save_prog));
p->next = update_progs;
p->dir = xstrdup (args);
@@ -2687,7 +2698,7 @@ send_repository (dir, repos, update_dir)
{
Node *n;
n = getnode ();
- n->type = UNKNOWN;
+ n->type = NT_UNKNOWN;
n->key = xstrdup (update_dir);
n->data = NULL;
@@ -3598,19 +3609,15 @@ get_responses_and_close ()
&& waitpid (rsh_pid, (int *) 0, 0) == -1)
error (1, errno, "waiting for process %d", rsh_pid);
+ buf_free (to_server);
+ buf_free (from_server);
server_started = 0;
- /* see if we need to sleep before returning */
+ /* see if we need to sleep before returning to avoid time-stamp races */
if (last_register_time)
{
- time_t now;
-
- for (;;)
- {
- (void) time (&now);
- if (now != last_register_time) break;
- sleep (1); /* to avoid time-stamp races */
- }
+ while (time ((time_t *) NULL) == last_register_time)
+ sleep (1);
}
return errs;
@@ -3778,6 +3785,7 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
int port_number;
struct sockaddr_in client_sai;
struct hostent *hostinfo;
+ char no_passwd = 0; /* gets set if no password found */
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock == -1)
@@ -3822,6 +3830,14 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
/* Get the password, probably from ~/.cvspass. */
password = get_cvs_password ();
+
+ /* Send the empty string by default. This is so anonymous CVS
+ access doesn't require client to have done "cvs login". */
+ if (password == NULL)
+ {
+ no_passwd = 1;
+ password = scramble ("");
+ }
/* Announce that we're starting the authorization protocol. */
if (send (sock, begin, strlen (begin), 0) < 0)
@@ -3845,8 +3861,8 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
if (send (sock, end, strlen (end), 0) < 0)
error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
- /* Paranoia. */
- memset (password, 0, strlen (password));
+ /* Paranoia. */
+ memset (password, 0, strlen (password));
}
{
@@ -3939,20 +3955,28 @@ connect_to_pserver (tofdp, fromfdp, verify_only, do_gssapi)
return;
rejected:
+ error (0, 0,
+ "authorization failed: server %s rejected access to %s for user %s",
+ CVSroot_hostname, CVSroot_directory, CVSroot_username);
+
+ /* Output a special error message if authentication was attempted
+ with no password -- the user should be made aware that they may
+ have missed a step. */
+ if (no_passwd)
+ {
+ error (0, 0,
+ "used empty password; try \"cvs login\" with a real password");
+ }
+
if (shutdown (sock, 2) < 0)
{
- error (0, 0,
- "authorization failed: server %s rejected access",
- CVSroot_hostname);
- error (1, 0,
+ error (0, 0,
"shutdown() failed (server %s): %s",
CVSroot_hostname,
SOCK_STRERROR (SOCK_ERRNO));
}
- error (1, 0,
- "authorization failed: server %s rejected access",
- CVSroot_hostname);
+ error_exit();
}
#endif /* AUTH_CLIENT_SUPPORT */
@@ -4115,9 +4139,16 @@ connect_to_gserver (sock, hostinfo)
if (stat_maj != GSS_S_COMPLETE && stat_maj != GSS_S_CONTINUE_NEEDED)
{
OM_uint32 message_context;
+ OM_uint32 new_stat_min;
+
+ message_context = 0;
+ gss_display_status (&new_stat_min, stat_maj, GSS_C_GSS_CODE,
+ GSS_C_NULL_OID, &message_context, &tok_out);
+ error (0, 0, "GSSAPI authentication failed: %s",
+ (char *) tok_out.value);
message_context = 0;
- gss_display_status (&stat_min, stat_maj, GSS_C_GSS_CODE,
+ gss_display_status (&new_stat_min, stat_min, GSS_C_MECH_CODE,
GSS_C_NULL_OID, &message_context, &tok_out);
error (1, 0, "GSSAPI authentication failed: %s",
(char *) tok_out.value);
@@ -4141,7 +4172,29 @@ connect_to_gserver (sock, hostinfo)
recv_bytes (sock, cbuf, 2);
need = ((cbuf[0] & 0xff) << 8) | (cbuf[1] & 0xff);
- assert (need <= sizeof buf);
+
+ if (need > sizeof buf)
+ {
+ int got;
+
+ /* This usually means that the server sent us an error
+ message. Read it byte by byte and print it out.
+ FIXME: This is a terrible error handling strategy.
+ However, even if we fix the server, we will still
+ want to do this to work with older servers. */
+ buf[0] = cbuf[0];
+ buf[1] = cbuf[1];
+ got = recv (sock, buf + 2, sizeof buf - 2, 0);
+ if (got < 0)
+ error (1, 0, "recv() from server %s: %s",
+ CVSroot_hostname, SOCK_STRERROR (SOCK_ERRNO));
+ buf[got + 2] = '\0';
+ if (buf[got + 1] == '\n')
+ buf[got + 1] = '\0';
+ error (1, 0, "error from server %s: %s", CVSroot_hostname,
+ buf);
+ }
+
recv_bytes (sock, buf, need);
tok_in.length = need;
}
@@ -4175,7 +4228,7 @@ send_variable_proc (node, closure)
void
start_server ()
{
- int tofd, fromfd;
+ int tofd, fromfd, rootless;
char *log = getenv ("CVS_CLIENT_LOG");
@@ -4354,7 +4407,8 @@ the :server: access method is not supported by this port of CVS");
stored_mode = NULL;
}
- if (strcmp (command_name, "init") != 0)
+ rootless = (strcmp (command_name, "init") == 0);
+ if (!rootless)
{
send_to_server ("Root ", 0);
send_to_server (CVSroot_directory, 0);
@@ -4478,7 +4532,7 @@ the :server: access method is not supported by this port of CVS");
}
}
- if (cvsencrypt)
+ if (cvsencrypt && !rootless)
{
#ifdef ENCRYPTION
/* Turn on encryption before turning on compression. We do
@@ -4525,7 +4579,7 @@ the :server: access method is not supported by this port of CVS");
#endif /* ! ENCRYPTION */
}
- if (gzip_level)
+ if (gzip_level && !rootless)
{
if (supported_request ("Gzip-stream"))
{
@@ -4567,7 +4621,7 @@ the :server: access method is not supported by this port of CVS");
}
}
- if (cvsauthenticate && ! cvsencrypt)
+ if (cvsauthenticate && ! cvsencrypt && !rootless)
{
/* Turn on authentication after turning on compression, so
that we can compress the authentication information. We
@@ -4598,7 +4652,7 @@ the :server: access method is not supported by this port of CVS");
}
#ifdef FILENAMES_CASE_INSENSITIVE
- if (supported_request ("Case"))
+ if (supported_request ("Case") && !rootless)
send_to_server ("Case\012", 0);
#endif
@@ -4968,6 +5022,7 @@ struct send_data
int build_dirs;
int force;
int no_contents;
+ int backup_modified;
};
static int send_fileproc PROTO ((void *callerdat, struct file_info *finfo));
@@ -5089,6 +5144,18 @@ warning: ignoring -k options due to server limitations");
}
else
send_modified (filename, finfo->fullname, vers);
+
+ if (args->backup_modified)
+ {
+ char *bakname;
+ bakname = backup_file (filename, vers->vn_user);
+ /* This behavior is sufficiently unexpected to
+ justify overinformativeness, I think. */
+ if (! really_quiet)
+ printf ("(Locally modified %s moved to %s)\n",
+ filename, bakname);
+ free (bakname);
+ }
}
else
{
@@ -5197,9 +5264,6 @@ send_dirent_proc (callerdat, dir, repository, update_dir, entries)
dir_exists = isdir (cvsadm_name);
free (cvsadm_name);
- /* initialize the ignore list for this directory */
- ignlist = getlist ();
-
/*
* If there is an empty directory (e.g. we are doing `cvs add' on a
* newly-created directory), the server still needs to know about it.
@@ -5215,6 +5279,9 @@ send_dirent_proc (callerdat, dir, repository, update_dir, entries)
char *repos = Name_Repository (dir, update_dir);
send_a_repository (dir, repos, update_dir);
free (repos);
+
+ /* initialize the ignore list for this directory */
+ ignlist = getlist ();
}
else
{
@@ -5239,6 +5306,29 @@ send_dirent_proc (callerdat, dir, repository, update_dir, entries)
return (dir_exists ? R_PROCESS : R_SKIP_ALL);
}
+static int send_dirleave_proc PROTO ((void *, char *, int, char *, List *));
+
+/*
+ * send_dirleave_proc () is called back by the recursion code upon leaving
+ * a directory. All it does is delete the ignore list if it hasn't already
+ * been done (by send_filesdone_proc).
+ */
+/* ARGSUSED */
+static int
+send_dirleave_proc (callerdat, dir, err, update_dir, entries)
+ void *callerdat;
+ char *dir;
+ int err;
+ char *update_dir;
+ List *entries;
+{
+
+ /* Delete the ignore list if it hasn't already been done. */
+ if (ignlist)
+ dellist (&ignlist);
+ return err;
+}
+
/*
* Send each option in a string to the server, one by one.
* This assumes that the options are separated by spaces, for example
@@ -5430,9 +5520,10 @@ send_files (argc, argv, local, aflag, flags)
args.build_dirs = flags & SEND_BUILD_DIRS;
args.force = flags & SEND_FORCE;
args.no_contents = flags & SEND_NO_CONTENTS;
+ args.backup_modified = flags & BACKUP_MODIFIED_FILES;
err = start_recursion
(send_fileproc, send_filesdoneproc,
- send_dirent_proc, (DIRLEAVEPROC)NULL, (void *) &args,
+ send_dirent_proc, send_dirleave_proc, (void *) &args,
argc, argv, local, W_LOCAL, aflag, 0, (char *)NULL, 0);
if (err)
error_exit ();
OpenPOWER on IntegriCloud