summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/cvs/Makefile11
-rw-r--r--usr.bin/cvs/checkout.c100
-rw-r--r--usr.bin/cvs/client.c585
-rw-r--r--usr.bin/cvs/cmd.c4
-rw-r--r--usr.bin/cvs/commit.c24
-rw-r--r--usr.bin/cvs/cvs.c36
-rw-r--r--usr.bin/cvs/cvs.h11
-rw-r--r--usr.bin/cvs/diff.c47
-rw-r--r--usr.bin/cvs/diff_internals.c6
-rw-r--r--usr.bin/cvs/fatal.c6
-rw-r--r--usr.bin/cvs/file.c4
-rw-r--r--usr.bin/cvs/getlog.c69
-rw-r--r--usr.bin/cvs/log.c11
-rw-r--r--usr.bin/cvs/remote.c209
-rw-r--r--usr.bin/cvs/remote.h92
-rw-r--r--usr.bin/cvs/server.c455
-rw-r--r--usr.bin/cvs/status.c26
-rw-r--r--usr.bin/cvs/update.c38
-rw-r--r--usr.bin/cvs/util.c8
19 files changed, 1641 insertions, 101 deletions
diff --git a/usr.bin/cvs/Makefile b/usr.bin/cvs/Makefile
index 5f7582413e5..5f3bcab384c 100644
--- a/usr.bin/cvs/Makefile
+++ b/usr.bin/cvs/Makefile
@@ -1,13 +1,14 @@
-# $OpenBSD: Makefile,v 1.29 2006/06/12 13:56:00 xsa Exp $
+# $OpenBSD: Makefile,v 1.30 2006/07/07 17:37:17 joris Exp $
PROG= opencvs
MAN= cvs.1 cvsignore.5 cvsrc.5 cvswrappers.5 cvsintro.7
CPPFLAGS+=-I${.CURDIR}
-SRCS= cvs.c add.c commit.c config.c checkout.c buf.c cmd.c date.y diff.c \
- diff3.c diff_internals.c entries.c fatal.c file.c getlog.c log.c \
- import.c init.c remove.c repository.c rcs.c rcsnum.c rcstime.c root.c \
- status.c tag.c worklist.c util.c update.c xmalloc.c
+SRCS= cvs.c add.c commit.c config.c checkout.c client.c buf.c cmd.c date.y \
+ diff.c diff3.c diff_internals.c entries.c fatal.c file.c getlog.c \
+ log.c import.c init.c remove.c repository.c rcs.c rcsnum.c rcstime.c \
+ remote.c root.c server.c status.c tag.c worklist.c util.c \
+ update.c xmalloc.c
CFLAGS+=-Wall
CFLAGS+=-Wstrict-prototypes -Wmissing-prototypes
diff --git a/usr.bin/cvs/checkout.c b/usr.bin/cvs/checkout.c
index ce59cb2c704..5f6534067e8 100644
--- a/usr.bin/cvs/checkout.c
+++ b/usr.bin/cvs/checkout.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: checkout.c,v 1.65 2006/07/01 20:30:46 reyk Exp $ */
+/* $OpenBSD: checkout.c,v 1.66 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -20,6 +20,7 @@
#include "cvs.h"
#include "log.h"
#include "diff.h"
+#include "remote.h"
int cvs_checkout(int, char **);
int cvs_export(int, char **);
@@ -167,56 +168,67 @@ cvs_checkout_file(struct cvs_file *cf, RCSNUM *rnum, BUF *bp, int flags)
time_t rcstime;
CVSENTRIES *ent;
struct timeval tv[2];
- char *entry, rev[16], timebuf[64], tbuf[32], stickytag[32];
+ char *p, *entry, rev[16], timebuf[64], tbuf[32], stickytag[32];
rcsnum_tostr(rnum, rev, sizeof(rev));
- cvs_log(LP_TRACE, "cvs_checkout_file(%s, %s, %d)",
- cf->file_path, rev, flags);
+ cvs_log(LP_TRACE, "cvs_checkout_file(%s, %s, %d) -> %s",
+ cf->file_path, rev, flags,
+ (cvs_server_active) ? "to client" : "to disk");
nbp = rcs_kwexp_buf(bp, cf->file_rcs, rnum);
if (flags & CO_DUMP) {
- if (cvs_buf_write_fd(nbp, STDOUT_FILENO) == -1)
- fatal("cvs_checkout_file: %s", strerror(errno));
+ if (cvs_server_active) {
+ cvs_printf("dump file %s to client\n", cf->file_path);
+ } else {
+ if (cvs_buf_write_fd(nbp, STDOUT_FILENO) == -1)
+ fatal("cvs_checkout_file: %s", strerror(errno));
+ }
+
cvs_buf_free(nbp);
return;
}
- oflags = O_WRONLY | O_TRUNC;
- if (cf->fd != -1) {
- exists = 1;
- (void)close(cf->fd);
- } else {
- exists = 0;
- oflags |= O_CREAT;
- }
+ if (cvs_server_active == 0) {
+ oflags = O_WRONLY | O_TRUNC;
+ if (cf->fd != -1) {
+ exists = 1;
+ (void)close(cf->fd);
+ } else {
+ exists = 0;
+ oflags |= O_CREAT;
+ }
- cf->fd = open(cf->file_path, oflags);
- if (cf->fd == -1)
- fatal("cvs_checkout_file: open: %s", strerror(errno));
+ cf->fd = open(cf->file_path, oflags);
+ if (cf->fd == -1)
+ fatal("cvs_checkout_file: open: %s", strerror(errno));
- if (cvs_buf_write_fd(nbp, cf->fd) == -1)
- fatal("cvs_checkout_file: %s", strerror(errno));
+ if (cvs_buf_write_fd(nbp, cf->fd) == -1)
+ fatal("cvs_checkout_file: %s", strerror(errno));
- cvs_buf_free(nbp);
+ cvs_buf_free(nbp);
- if (fchmod(cf->fd, 0644) == -1)
- fatal("cvs_checkout_file: fchmod: %s", strerror(errno));
+ if (fchmod(cf->fd, 0644) == -1)
+ fatal("cvs_checkout_file: fchmod: %s", strerror(errno));
+
+ if (exists == 0) {
+ rcstime = rcs_rev_getdate(cf->file_rcs, rnum);
+ rcstime = cvs_hack_time(rcstime, 0);
+ } else {
+ time(&rcstime);
+ }
- if (exists == 0) {
- rcstime = rcs_rev_getdate(cf->file_rcs, rnum);
- rcstime = cvs_hack_time(rcstime, 0);
+ tv[0].tv_sec = rcstime;
+ tv[0].tv_usec = 0;
+ tv[1] = tv[0];
+ if (futimes(cf->fd, tv) == -1)
+ fatal("cvs_checkout_file: futimes: %s",
+ strerror(errno));
} else {
time(&rcstime);
}
- tv[0].tv_sec = rcstime;
- tv[0].tv_usec = 0;
- tv[1] = tv[0];
- if (futimes(cf->fd, tv) == -1)
- fatal("cvs_checkout_file: futimes: %s", strerror(errno));
-
rcstime = cvs_hack_time(rcstime, 1);
ctime_r(&rcstime, tbuf);
@@ -244,9 +256,29 @@ cvs_checkout_file(struct cvs_file *cf, RCSNUM *rnum, BUF *bp, int flags)
l = snprintf(entry, CVS_ENT_MAXLINELEN, "/%s/%s/%s//%s", cf->file_name,
rev, timebuf, stickytag);
- ent = cvs_ent_open(cf->file_wd);
- cvs_ent_add(ent, entry);
- cvs_ent_close(ent, ENT_SYNC);
+ if (cvs_server_active == 0) {
+ ent = cvs_ent_open(cf->file_wd);
+ cvs_ent_add(ent, entry);
+ cvs_ent_close(ent, ENT_SYNC);
+ } else {
+ if ((p = strrchr(cf->file_rpath, ',')) != NULL)
+ *p = '\0';
+
+ cvs_server_send_response("Updated %s/", cf->file_wd);
+ cvs_remote_output(cf->file_rpath);
+ cvs_remote_output(entry);
+ cvs_remote_output("u=rw,g=rw,o=rw");
+
+ /* XXX */
+ printf("%ld\n", cvs_buf_len(nbp));
+
+ if (cvs_buf_write_fd(nbp, STDOUT_FILENO) == -1)
+ fatal("cvs_checkout_file: failed to send file");
+ cvs_buf_free(nbp);
+
+ if (p != NULL)
+ *p = ',';
+ }
xfree(entry);
}
diff --git a/usr.bin/cvs/client.c b/usr.bin/cvs/client.c
new file mode 100644
index 00000000000..0ef1f5fb4ad
--- /dev/null
+++ b/usr.bin/cvs/client.c
@@ -0,0 +1,585 @@
+/* $OpenBSD: client.c,v 1.9 2006/07/07 17:37:17 joris Exp $ */
+/*
+ * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include "cvs.h"
+#include "log.h"
+#include "diff.h"
+#include "remote.h"
+
+struct cvs_req cvs_requests[] = {
+ /* this is what our client will use, the server should support it */
+ { "Root", 1, cvs_server_root, REQ_NEEDED },
+ { "Valid-responses", 1, cvs_server_validresp, REQ_NEEDED },
+ { "valid-requests", 1, cvs_server_validreq, REQ_NEEDED },
+ { "Global_option", 0, cvs_server_globalopt, REQ_NEEDED },
+ { "Directory", 0, cvs_server_directory, REQ_NEEDED },
+ { "Entry", 0, cvs_server_entry, REQ_NEEDED },
+ { "Modified", 0, cvs_server_modified, REQ_NEEDED },
+ { "UseUnchanged", 0, cvs_server_useunchanged, REQ_NEEDED },
+ { "Unchanged", 0, cvs_server_unchanged, REQ_NEEDED },
+ { "Questionable", 0, cvs_server_questionable, REQ_NEEDED },
+ { "Argument", 0, cvs_server_argument, REQ_NEEDED },
+
+ /*
+ * used to tell the server what is going on in our
+ * working copy, unsupported until we are told otherwise
+ */
+ { "Max-dotdot", 0, NULL, 0 },
+ { "Static-directory", 0, NULL, 0 },
+ { "Sticky", 0, NULL, 0 },
+ { "Checkin-prog", 0, NULL, 0 },
+ { "Update-prog", 0, NULL, 0 },
+ { "Kopt", 0, NULL, 0 },
+ { "Checkin-time", 0, NULL, 0 },
+ { "Is-modified", 0, NULL, 0 },
+ { "Notify", 0, NULL, 0 },
+ { "Case", 0, NULL, 0 },
+ { "Argumentx", 0, NULL, 0 },
+ { "Gzip-stream", 0, NULL, 0 },
+ { "Kerberos-encrypt", 0, NULL, 0 },
+ { "Gssapi-encrypt", 0, NULL, 0 },
+ { "Gssapi-authenticate", 0, NULL, 0 },
+ { "Set", 0, NULL, 0 },
+ { "expand-modules", 0, NULL, 0 },
+
+ /* commands that might be supported */
+ { "ci", 0, cvs_server_commit, 0 },
+ { "co", 0, NULL, 0 },
+ { "diff", 0, cvs_server_diff, 0 },
+ { "tag", 0, NULL, 0 },
+ { "status", 0, cvs_server_status, 0 },
+ { "admin", 0, NULL, 0 },
+ { "history", 0, NULL, 0 },
+ { "watchers", 0, NULL, 0 },
+ { "editors", 0, NULL, 0 },
+ { "annotate", 0, NULL, 0 },
+ { "log", 0, cvs_server_log, 0 },
+ { "export", 0, NULL, 0 },
+ { "rdiff", 0, NULL, 0 },
+ { "rtag", 0, NULL, 0 },
+ { "init", 0, NULL, 0 },
+ { "update", 0, cvs_server_update, 0 },
+ { "import", 0, NULL, 0 },
+ { "add", 0, NULL, 0 },
+ { "remove", 0, NULL, 0 },
+ { "watch-on", 0, NULL, 0 },
+ { "watch-off", 0, NULL, 0 },
+ { "watch-add", 0, NULL, 0 },
+ { "watch-remove", 0, NULL, 0 },
+ { "release", 0, NULL, 0 },
+ { "noop", 0, NULL, 0 },
+ { "update-patches", 0, NULL, 0 },
+ { "gzip-file-contents", 0, NULL, 0 },
+ { "wrapper-sendme-rcsOptions", 0, NULL, 0 },
+ { "", -1, NULL, 0 }
+};
+
+static char *client_get_supported_responses(void);
+static char *lastdir = NULL;
+static int end_of_response = 0;
+
+static char *
+client_get_supported_responses(void)
+{
+ BUF *bp;
+ char *d;
+ int i, first;
+
+ first = 0;
+ bp = cvs_buf_alloc(512, BUF_AUTOEXT);
+ for (i = 0; cvs_responses[i].supported != -1; i++) {
+ if (cvs_responses[i].hdlr == NULL)
+ continue;
+
+ if (first != 0)
+ cvs_buf_append(bp, " ", 1);
+ else
+ first++;
+ cvs_buf_append(bp, cvs_responses[i].name,
+ strlen(cvs_responses[i].name));
+ }
+
+ cvs_buf_putc(bp, '\0');
+ d = cvs_buf_release(bp);
+ return (d);
+}
+
+void
+cvs_client_connect_to_server(void)
+{
+ char *cmd, *argv[9], *resp;
+ int ifd[2], ofd[2], argc;
+
+ switch (current_cvsroot->cr_method) {
+ case CVS_METHOD_PSERVER:
+ case CVS_METHOD_KSERVER:
+ case CVS_METHOD_GSERVER:
+ case CVS_METHOD_FORK:
+ case CVS_METHOD_EXT:
+ fatal("the specified connection method is not support");
+ default:
+ break;
+ }
+
+ if (pipe(ifd) == -1)
+ fatal("cvs_client_connect: %s", strerror(errno));
+ if (pipe(ofd) == -1)
+ fatal("cvs_client_connect: %s", strerror(errno));
+
+ switch (fork()) {
+ case -1:
+ fatal("cvs_client_connect: fork failed: %s", strerror(errno));
+ case 0:
+ if (dup2(ifd[0], STDIN_FILENO) == -1)
+ fatal("cvs_client_connect: %s", strerror(errno));
+ if (dup2(ofd[1], STDOUT_FILENO) == -1)
+ fatal("cvs_client_connect: %s", strerror(errno));
+
+ close(ifd[1]);
+ close(ofd[0]);
+
+ if ((cmd = getenv("CVS_SERVER")) == NULL)
+ cmd = CVS_SERVER_DEFAULT;
+
+ argc = 0;
+ argv[argc++] = cvs_rsh;
+
+ if (current_cvsroot->cr_user != NULL) {
+ argv[argc++] = "-l";
+ argv[argc++] = current_cvsroot->cr_user;
+ }
+
+ argv[argc++] = current_cvsroot->cr_host;
+ argv[argc++] = cmd;
+ argv[argc++] = "server";
+ argv[argc] = NULL;
+
+ cvs_log(LP_TRACE, "connecting to server %s",
+ current_cvsroot->cr_host);
+
+ execvp(argv[0], argv);
+ fatal("cvs_client_connect: failed to execute cvs server");
+ default:
+ break;
+ }
+
+ close(ifd[0]);
+ close(ofd[1]);
+
+ if ((current_cvsroot->cr_srvin = fdopen(ifd[1], "w")) == NULL)
+ fatal("cvs_client_connect: %s", strerror(errno));
+ if ((current_cvsroot->cr_srvout = fdopen(ofd[0], "r")) == NULL)
+ fatal("cvs_client_connect: %s", strerror(errno));
+
+ setvbuf(current_cvsroot->cr_srvin, NULL,_IOLBF, 0);
+ setvbuf(current_cvsroot->cr_srvout, NULL, _IOLBF, 0);
+
+ cvs_client_send_request("Root %s", current_cvsroot->cr_dir);
+
+ resp = client_get_supported_responses();
+ cvs_client_send_request("Valid-responses %s", resp);
+ xfree(resp);
+
+ cvs_client_send_request("valid-requests");
+ cvs_client_get_responses();
+
+ if (cvs_trace)
+ cvs_client_send_request("Global_option -t");
+
+ if (verbosity == 2)
+ cvs_client_send_request("Global_option -V");
+
+ cvs_client_send_request("UseUnchanged");
+}
+
+void
+cvs_client_send_request(char *fmt, ...)
+{
+ va_list ap;
+ char *data, *s;
+ struct cvs_req *req;
+
+ va_start(ap, fmt);
+ vasprintf(&data, fmt, ap);
+ va_end(ap);
+
+ if ((s = strchr(data, ' ')) != NULL)
+ *s = '\0';
+
+ req = cvs_remote_get_request_info(data);
+ if (req == NULL)
+ fatal("'%s' is an unknown request", data);
+
+ if (req->supported != 1)
+ fatal("remote cvs server does not support '%s'", data);
+
+ if (s != NULL)
+ *s = ' ';
+
+ cvs_remote_output(data);
+ xfree(data);
+}
+
+void
+cvs_client_read_response(void)
+{
+ char *cmd, *data;
+ struct cvs_resp *resp;
+
+ cmd = cvs_remote_input();
+ if ((data = strchr(cmd, ' ')) != NULL)
+ (*data++) = '\0';
+
+ resp = cvs_remote_get_response_info(cmd);
+ if (resp == NULL)
+ fatal("response '%s' is not supported by our client", cmd);
+
+ if (resp->hdlr == NULL)
+ fatal("opencvs client does not support '%s'", cmd);
+
+ (*resp->hdlr)(data);
+ xfree(cmd);
+}
+
+void
+cvs_client_get_responses(void)
+{
+ while (end_of_response != 1)
+ cvs_client_read_response();
+
+ end_of_response = 0;
+}
+
+void
+cvs_client_senddir(const char *dir)
+{
+ char *repo;
+
+ cvs_log(LP_TRACE, "cvs_client_senddir(%s)", dir);
+
+ if (lastdir != NULL && !strcmp(dir, lastdir))
+ return;
+
+ cvs_client_send_request("Directory %s", dir);
+
+ repo = xmalloc(MAXPATHLEN);
+ cvs_get_repository_path(dir, repo, MAXPATHLEN);
+ cvs_remote_output(repo);
+ xfree(repo);
+
+ if (lastdir != NULL)
+ xfree(lastdir);
+ lastdir = xstrdup(dir);
+}
+
+void
+cvs_client_sendfile(struct cvs_file *cf)
+{
+ int l;
+ size_t len;
+ char rev[16], timebuf[64], sticky[32];
+
+ if (cf->file_type != CVS_FILE)
+ return;
+
+ cvs_client_senddir(cf->file_wd);
+
+ cvs_log(LP_TRACE, "cvs_client_sendfile(%s)", cf->file_path);
+ cvs_remote_classify_file(cf);
+
+ if (cf->file_ent != NULL) {
+ if (cf->file_status == FILE_ADDED) {
+ len = strlcpy(rev, "0", sizeof(rev));
+ if (len >= sizeof(rev))
+ fatal("cvs_client_sendfile: truncation");
+
+ len = strlcpy(timebuf, "Initial ", sizeof(timebuf));
+ if (len >= sizeof(timebuf))
+ fatal("cvs_client_sendfile: truncation");
+
+ len = strlcat(timebuf, cf->file_name, sizeof(timebuf));
+ if (len >= sizeof(timebuf))
+ fatal("cvs_client_sendfile: truncation");
+ } else {
+ rcsnum_tostr(cf->file_ent->ce_rev, rev, sizeof(rev));
+ ctime_r(&cf->file_ent->ce_mtime, timebuf);
+ }
+
+ if (cf->file_ent->ce_conflict == NULL) {
+ if (timebuf[strlen(timebuf) - 1] == '\n')
+ timebuf[strlen(timebuf) - 1] = '\0';
+ } else {
+ len = strlcpy(timebuf, cf->file_ent->ce_conflict,
+ sizeof(timebuf));
+ if (len >= sizeof(timebuf))
+ fatal("cvs_client_sendfile: truncation");
+ }
+
+ sticky[0] = '\0';
+ if (cf->file_ent->ce_tag != NULL) {
+ l = snprintf(sticky, sizeof(sticky), "T%s",
+ cf->file_ent->ce_tag);
+ if (l == -1 || l >= (int)sizeof(sticky))
+ fatal("cvs_client_sendfile: overflow");
+ }
+
+ cvs_client_send_request("Entry /%s/%s%s/%s/%s/",
+ cf->file_name, (cf->file_status == FILE_REMOVED) ? "-" : "",
+ rev, timebuf, sticky);
+ }
+
+ switch (cf->file_status) {
+ case FILE_UNKNOWN:
+ if (cf->fd != -1)
+ cvs_client_send_request("Questionable %s",
+ cf->file_name);
+ break;
+ case FILE_ADDED:
+ case FILE_MODIFIED:
+ cvs_client_send_request("Modified %s", cf->file_name);
+ cvs_remote_send_file(cf->file_path);
+ break;
+ case FILE_UPTODATE:
+ cvs_client_send_request("Unchanged %s", cf->file_name);
+ break;
+ }
+}
+
+void
+cvs_client_send_files(char **argv, int argc)
+{
+ int i;
+
+ for (i = 0; i < argc; i++)
+ cvs_client_send_request("Argument %s", argv[i]);
+}
+
+void
+cvs_client_ok(char *data)
+{
+ cvs_log(LP_TRACE, "cvs_client_ok()");
+ end_of_response = 1;
+}
+
+void
+cvs_client_error(char *data)
+{
+ cvs_log(LP_TRACE, "cvs_client_error()");
+ end_of_response = 1;
+}
+
+void
+cvs_client_validreq(char *data)
+{
+ int i;
+ char *sp, *ep;
+ struct cvs_req *req;
+
+ sp = data;
+ do {
+ if ((ep = strchr(sp, ' ')) != NULL)
+ *ep = '\0';
+
+ req = cvs_remote_get_request_info(sp);
+ if (req != NULL)
+ req->supported = 1;
+
+ if (ep != NULL)
+ sp = ep + 1;
+ } while (ep != NULL);
+
+ for (i = 0; cvs_requests[i].supported != -1; i++) {
+ req = &cvs_requests[i];
+ if ((req->flags & REQ_NEEDED) &&
+ req->supported != 1) {
+ fatal("server does not support required '%s'",
+ req->name);
+ }
+ }
+}
+
+void
+cvs_client_e(char *data)
+{
+ cvs_printf("%s\n", data);
+}
+
+void
+cvs_client_m(char *data)
+{
+ cvs_printf("%s\n", data);
+}
+
+void
+cvs_client_checkedin(char *data)
+{
+ int l;
+ CVSENTRIES *entlist;
+ struct cvs_ent *ent, *newent;
+ char *dir, *entry, rev[16], timebuf[64], sticky[16];
+
+ cvs_log(LP_TRACE, "cvs_client_checkedin(%s)", data);
+
+ dir = cvs_remote_input();
+ entry = cvs_remote_input();
+ xfree(dir);
+
+ entlist = cvs_ent_open(data);
+ newent = cvs_ent_parse(entry);
+ ent = cvs_ent_get(entlist, newent->ce_name);
+ xfree(entry);
+
+ entry = xmalloc(CVS_ENT_MAXLINELEN);
+
+ rcsnum_tostr(newent->ce_rev, rev, sizeof(rev));
+ ctime_r(&ent->ce_mtime, timebuf);
+ if (timebuf[strlen(timebuf) - 1] == '\n')
+ timebuf[strlen(timebuf) - 1] = '\0';
+
+ sticky[0] = '\0';
+ if (ent->ce_tag != NULL) {
+ l = snprintf(sticky, sizeof(sticky), "T%s", ent->ce_tag);
+ if (l == -1 || l >= (int)sizeof(sticky))
+ fatal("cvs_client_checkedin: overflow");
+ }
+
+ l = snprintf(entry, CVS_ENT_MAXLINELEN, "/%s/%s/%s//%s/",
+ newent->ce_name, rev, timebuf, sticky);
+ if (l == -1 || l >= CVS_ENT_MAXLINELEN)
+ fatal("cvs_client_checkedin: overflow");
+
+ cvs_ent_free(ent);
+ cvs_ent_free(newent);
+ cvs_ent_add(entlist, entry);
+ cvs_ent_close(entlist, ENT_SYNC);
+
+ xfree(entry);
+}
+
+void
+cvs_client_updated(char *data)
+{
+ BUF *bp;
+ int l, fd;
+ time_t now;
+ mode_t fmode;
+ size_t flen;
+ CVSENTRIES *ent;
+ struct cvs_ent *e;
+ const char *errstr;
+ struct timeval tv[2];
+ char timebuf[32], *repo, *rpath, *entry, *mode;
+ char revbuf[32], *len, *fpath, *wdir;
+
+ cvs_log(LP_TRACE, "cvs_client_updated(%s)", data);
+
+ rpath = cvs_remote_input();
+ entry = cvs_remote_input();
+ mode = cvs_remote_input();
+ len = cvs_remote_input();
+
+ repo = xmalloc(MAXPATHLEN);
+ cvs_get_repository_path(".", repo, MAXPATHLEN);
+
+ if (strlen(repo) + 1 > strlen(rpath))
+ fatal("received a repository path that is too short");
+
+ fpath = rpath + strlen(repo) + 1;
+ if ((wdir = dirname(fpath)) == NULL)
+ fatal("cvs_client_updated: dirname: %s", strerror(errno));
+ xfree(repo);
+
+ flen = strtonum(len, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ fatal("cvs_client_updated: %s: %s", len, errstr);
+ xfree(len);
+
+ cvs_strtomode(mode, &fmode);
+ xfree(mode);
+
+ time(&now);
+ now = cvs_hack_time(now, 0);
+ ctime_r(&now, timebuf);
+ if (timebuf[strlen(timebuf) - 1] == '\n')
+ timebuf[strlen(timebuf) - 1] = '\0';
+
+ e = cvs_ent_parse(entry);
+ xfree(entry);
+ rcsnum_tostr(e->ce_rev, revbuf, sizeof(revbuf));
+ entry = xmalloc(CVS_ENT_MAXLINELEN);
+ l = snprintf(entry, CVS_ENT_MAXLINELEN, "/%s/%s/%s//", e->ce_name,
+ revbuf, timebuf);
+ if (l == -1 || l >= CVS_ENT_MAXLINELEN)
+ fatal("cvs_client_updated: overflow");
+
+ cvs_ent_free(e);
+ ent = cvs_ent_open(wdir);
+ cvs_ent_add(ent, entry);
+ cvs_ent_close(ent, ENT_SYNC);
+ xfree(entry);
+
+ bp = cvs_remote_receive_file(flen);
+ if ((fd = open(fpath, O_CREAT | O_WRONLY | O_TRUNC)) == -1)
+ fatal("cvs_client_updated: open: %s: %s",
+ fpath, strerror(errno));
+
+ if (cvs_buf_write_fd(bp, fd) == -1)
+ fatal("cvs_client_updated: cvs_buf_write_fd failed for %s",
+ fpath);
+
+ cvs_buf_free(bp);
+
+ now = cvs_hack_time(now, 0);
+ tv[0].tv_sec = now;
+ tv[0].tv_usec = 0;
+ tv[1] = tv[0];
+
+ if (futimes(fd, tv) == -1)
+ fatal("cvs_client_updated: futimes: %s", strerror(errno));
+
+ if (fchmod(fd, fmode) == -1)
+ fatal("cvs_client_updated: fchmod: %s", strerror(errno));
+
+ (void)close(fd);
+
+ xfree(rpath);
+}
+
+void
+cvs_client_merged(char *data)
+{
+ cvs_log(LP_TRACE, "cvs_client_merged(%s)", data);
+}
+
+void
+cvs_client_removed(char *data)
+{
+ cvs_log(LP_TRACE, "cvs_client_removed(%s)", data);
+}
+
+void
+cvs_client_remove_entry(char *data)
+{
+ char *dir;
+
+ cvs_log(LP_TRACE, "cvs_client_remove_entry(%s)", data);
+
+ dir = cvs_remote_input();
+ xfree(dir);
+}
diff --git a/usr.bin/cvs/cmd.c b/usr.bin/cvs/cmd.c
index b6304e81fbf..2629892e0e0 100644
--- a/usr.bin/cvs/cmd.c
+++ b/usr.bin/cvs/cmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd.c,v 1.51 2006/06/12 13:56:00 xsa Exp $ */
+/* $OpenBSD: cmd.c,v 1.52 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2005 Joris Vink <joris@openbsd.org>
* All rights reserved.
@@ -44,6 +44,7 @@ struct cvs_cmd *cvs_cdt[] = {
&cvs_cmd_status,
&cvs_cmd_tag,
&cvs_cmd_update,
+ &cvs_cmd_server,
#if 0
&cvs_cmd_admin,
&cvs_cmd_annotate,
@@ -59,7 +60,6 @@ struct cvs_cmd *cvs_cdt[] = {
&cvs_cmd_release,
&cvs_cmd_rlog,
&cvs_cmd_rtag,
- &cvs_cmd_server,
&cvs_cmd_unedit,
&cvs_cmd_update,
&cvs_cmd_version,
diff --git a/usr.bin/cvs/commit.c b/usr.bin/cvs/commit.c
index cf4c9fb8c90..9a66ddfb60d 100644
--- a/usr.bin/cvs/commit.c
+++ b/usr.bin/cvs/commit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: commit.c,v 1.79 2006/07/02 21:01:48 joris Exp $ */
+/* $OpenBSD: commit.c,v 1.80 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org>
@@ -21,8 +21,8 @@
#include "cvs.h"
#include "diff.h"
#include "log.h"
+#include "remote.h"
-int cvs_commit(int, char **);
void cvs_commit_local(struct cvs_file *);
void cvs_commit_check_conflicts(struct cvs_file *);
@@ -87,6 +87,26 @@ cvs_commit(int argc, char **argv)
if (logmsg == NULL)
fatal("please use -m or -F to specify a log message for now");
+ if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
+ cr.enterdir = NULL;
+ cr.leavedir = NULL;
+ cr.fileproc = cvs_client_sendfile;
+ cr.flags = flags;
+
+ if (argc > 0)
+ cvs_file_run(argc, argv, &cr);
+ else
+ cvs_file_run(1, &arg, &cr);
+
+ cvs_client_send_request("Argument -m%s", logmsg);
+
+ cvs_client_send_files(argv, argc);
+ cvs_client_senddir(".");
+ cvs_client_send_request("ci");
+ cvs_client_get_responses();
+ return (0);
+ }
+
TAILQ_INIT(&files_affected);
conflicts_found = 0;
diff --git a/usr.bin/cvs/cvs.c b/usr.bin/cvs/cvs.c
index 32ccbfb3e94..026e9c91200 100644
--- a/usr.bin/cvs/cvs.c
+++ b/usr.bin/cvs/cvs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cvs.c,v 1.105 2006/06/28 20:19:05 reyk Exp $ */
+/* $OpenBSD: cvs.c,v 1.106 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
@@ -31,6 +31,7 @@
#include "config.h"
#include "log.h"
#include "file.h"
+#include "remote.h"
extern char *__progname;
@@ -48,6 +49,7 @@ int cvs_noexec = 0; /* set to 1 to disable disk operations (-n option) */
int cvs_error = -1; /* set to the correct error code on failure */
int cvs_cmdop;
int cvs_umask = CVS_UMASK_DEFAULT;
+int cvs_server_active = 0;
char *cvs_tagname = NULL;
char *cvs_defargs; /* default global arguments from .cvsrc */
@@ -96,6 +98,14 @@ cvs_cleanup(void)
cvs_log(LP_TRACE, "cvs_cleanup: removing temp files");
cvs_worklist_run(&temp_files, cvs_worklist_unlink);
+
+ if (cvs_server_active) {
+ if (cvs_rmdir(cvs_server_path) == -1)
+ cvs_log(LP_ERR,
+ "warning: failed to remove server directory: %s",
+ cvs_server_path);
+ xfree(cvs_server_path);
+ }
}
void
@@ -115,6 +125,7 @@ main(int argc, char **argv)
struct passwd *pw;
struct stat st;
char fpath[MAXPATHLEN];
+ char *root, *rootp;
tzset();
@@ -217,14 +228,33 @@ main(int argc, char **argv)
cvs_file_init();
+ if (cvs_cmdop == CVS_OP_SERVER) {
+ setvbuf(stdin, NULL, _IOLBF, 0);
+ setvbuf(stdout, NULL, _IOLBF, 0);
+
+ cvs_server_active = 1;
+ root = cvs_remote_input();
+ if ((rootp = strchr(root, ' ')) == NULL)
+ fatal("bad Root request");
+ cvs_rootstr = xstrdup(rootp + 1);
+ xfree(root);
+ }
+
if ((current_cvsroot = cvsroot_get(".")) == NULL) {
cvs_log(LP_ERR,
"No CVSROOT specified! Please use the '-d' option");
fatal("or set the CVSROOT environment variable.");
}
- if (current_cvsroot->cr_method != CVS_METHOD_LOCAL)
- fatal("remote setups are not supported yet");
+ if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
+ if (cvs_server_active == 1)
+ fatal("remote Root while already running as server?");
+
+ cvs_client_connect_to_server();
+ cmdp->cmd(cmd_argc, cmd_argv);
+ cvs_cleanup();
+ return (0);
+ }
i = snprintf(fpath, sizeof(fpath), "%s/%s", current_cvsroot->cr_dir,
CVS_PATH_ROOT);
diff --git a/usr.bin/cvs/cvs.h b/usr.bin/cvs/cvs.h
index 381e35f80e8..e3c89d19db4 100644
--- a/usr.bin/cvs/cvs.h
+++ b/usr.bin/cvs/cvs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cvs.h,v 1.115 2006/07/01 20:30:46 reyk Exp $ */
+/* $OpenBSD: cvs.h,v 1.116 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -274,6 +274,7 @@ extern char *cvs_msg;
extern char *cvs_rsh;
extern char *cvs_tmpdir;
extern char *import_repository;
+extern char *cvs_server_path;
extern int cvs_umask;
extern int verbosity;
@@ -285,6 +286,7 @@ extern int cvs_nocase;
extern int cvs_noexec;
extern int cvs_readonly;
extern int cvs_error;
+extern int cvs_server_active;
extern struct cvs_cmd *cvs_cdt[];
@@ -358,4 +360,11 @@ int update_has_conflict_markers(struct cvs_file *);
#define CO_SETSTICKY 0x02
#define CO_DUMP 0x04
+/* commands */
+int cvs_commit(int, char **);
+int cvs_diff(int, char **);
+int cvs_status(int, char **);
+int cvs_update(int, char **);
+int cvs_getlog(int, char **);
+
#endif
diff --git a/usr.bin/cvs/diff.c b/usr.bin/cvs/diff.c
index 6d36121055e..af6ef52a97a 100644
--- a/usr.bin/cvs/diff.c
+++ b/usr.bin/cvs/diff.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: diff.c,v 1.107 2006/07/01 01:07:50 ray Exp $ */
+/* $OpenBSD: diff.c,v 1.108 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -20,8 +20,8 @@
#include "cvs.h"
#include "diff.h"
#include "log.h"
+#include "remote.h"
-int cvs_diff(int, char **);
void cvs_diff_local(struct cvs_file *);
static int Nflag = 0;
@@ -95,7 +95,41 @@ cvs_diff(int argc, char **argv)
cr.enterdir = NULL;
cr.leavedir = NULL;
- cr.fileproc = cvs_diff_local;
+
+ if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
+ cr.fileproc = cvs_client_sendfile;
+
+ if (!(flags & CR_RECURSE_DIRS))
+ cvs_client_send_request("Argument -l");
+
+ switch (diff_format) {
+ case D_CONTEXT:
+ cvs_client_send_request("Argument -c");
+ break;
+ case D_RCSDIFF:
+ cvs_client_send_request("Argument -n");
+ break;
+ case D_UNIFIED:
+ cvs_client_send_request("Argument -u");
+ break;
+ default:
+ break;
+ }
+
+ if (Nflag == 1)
+ cvs_client_send_request("Argument -N");
+
+ if (diff_pflag == 1)
+ cvs_client_send_request("Argument -p");
+
+ if (rev1 != NULL)
+ cvs_client_send_request("Argument -r%s", rev1);
+ if (rev2 != NULL)
+ cvs_client_send_request("Argument -r%s", rev2);
+ } else {
+ cr.fileproc = cvs_diff_local;
+ }
+
cr.flags = flags;
diff_rev1 = diff_rev2 = NULL;
@@ -105,6 +139,13 @@ cvs_diff(int argc, char **argv)
else
cvs_file_run(1, &arg, &cr);
+ if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
+ cvs_client_send_files(argv, argc);
+ cvs_client_senddir(".");
+ cvs_client_send_request("diff");
+ cvs_client_get_responses();
+ }
+
return (0);
}
diff --git a/usr.bin/cvs/diff_internals.c b/usr.bin/cvs/diff_internals.c
index 5a37ec4c86d..4c453d9ebda 100644
--- a/usr.bin/cvs/diff_internals.c
+++ b/usr.bin/cvs/diff_internals.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: diff_internals.c,v 1.2 2006/05/31 22:24:12 joris Exp $ */
+/* $OpenBSD: diff_internals.c,v 1.3 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (C) Caldera International Inc. 2001-2002.
* All rights reserved.
@@ -946,7 +946,7 @@ proceed:
diff_output("\t%s", buf);
}
- printf("\n");
+ diff_output("\n");
t = localtime(&stb2.st_mtime);
(void)strftime(buf, sizeof(buf),
@@ -961,7 +961,7 @@ proceed:
diff_output("\t%s", buf);
}
- printf("\n");
+ diff_output("\n");
anychange = 1;
} else if (a > context_vec_ptr->b + (2 * context) + 1 &&
c > context_vec_ptr->d + (2 * context) + 1) {
diff --git a/usr.bin/cvs/fatal.c b/usr.bin/cvs/fatal.c
index 8bf10f68cf4..159664d4777 100644
--- a/usr.bin/cvs/fatal.c
+++ b/usr.bin/cvs/fatal.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fatal.c,v 1.7 2006/05/27 03:30:30 joris Exp $ */
+/* $OpenBSD: fatal.c,v 1.8 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
@@ -27,6 +27,7 @@
#include "cvs.h"
#include "log.h"
+#include "remote.h"
/* Fatal messages. This function never returns. */
@@ -41,5 +42,8 @@ fatal(const char *fmt,...)
cvs_cleanup();
+ if (cvs_server_active)
+ cvs_server_send_response("error");
+
exit(1);
}
diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c
index d2755fac3f9..4bf40d725db 100644
--- a/usr.bin/cvs/file.c
+++ b/usr.bin/cvs/file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.c,v 1.161 2006/06/19 05:05:17 joris Exp $ */
+/* $OpenBSD: file.c,v 1.162 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
@@ -279,7 +279,7 @@ cvs_file_walklist(struct cvs_flisthead *fl, struct cvs_recursion *cr)
(void)close(fd);
goto next;
}
- } else {
+ } else if (current_cvsroot->cr_method == CVS_METHOD_LOCAL) {
if (stat(d, &st) == -1) {
cvs_log(LP_ERRNO, "%s", d);
goto next;
diff --git a/usr.bin/cvs/getlog.c b/usr.bin/cvs/getlog.c
index 2dc516f7a6b..c1912d5b78d 100644
--- a/usr.bin/cvs/getlog.c
+++ b/usr.bin/cvs/getlog.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getlog.c,v 1.64 2006/06/19 05:05:17 joris Exp $ */
+/* $OpenBSD: getlog.c,v 1.65 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -20,6 +20,7 @@
#include "cvs.h"
#include "diff.h"
#include "log.h"
+#include "remote.h"
#define LOG_REVSEP \
"----------------------------"
@@ -27,7 +28,6 @@
#define LOG_REVEND \
"============================================================================="
-int cvs_getlog(int, char **);
void cvs_log_local(struct cvs_file *);
char *logrev = NULL;
@@ -71,7 +71,19 @@ cvs_getlog(int argc, char **argv)
cr.enterdir = NULL;
cr.leavedir = NULL;
- cr.fileproc = cvs_log_local;
+
+ if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
+ cr.fileproc = cvs_client_sendfile;
+
+ if (!(flags & CR_RECURSE_DIRS))
+ cvs_client_send_request("Argument -l");
+
+ if (logrev != NULL)
+ cvs_client_send_request("Argument -r%s", logrev);
+ } else {
+ cr.fileproc = cvs_log_local;
+ }
+
cr.flags = flags;
if (argc > 0)
@@ -79,6 +91,13 @@ cvs_getlog(int argc, char **argv)
else
cvs_file_run(1, &arg, &cr);
+ if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
+ cvs_client_send_files(argv, argc);
+ cvs_client_senddir(".");
+ cvs_client_send_request("log");
+ cvs_client_get_responses();
+ }
+
return (0);
}
@@ -114,65 +133,65 @@ cvs_log_local(struct cvs_file *cf)
return;
}
- printf("\nRCS file: %s", cf->file_rpath);
- printf("\nWorking file: %s", cf->file_path);
- printf("\nhead:");
+ cvs_printf("\nRCS file: %s", cf->file_rpath);
+ cvs_printf("\nWorking file: %s", cf->file_path);
+ cvs_printf("\nhead:");
if (cf->file_rcs->rf_head != NULL)
- printf(" %s", rcsnum_tostr(cf->file_rcs->rf_head,
+ cvs_printf(" %s", rcsnum_tostr(cf->file_rcs->rf_head,
numb, sizeof(numb)));
- printf("\nbranch:");
+ cvs_printf("\nbranch:");
if (rcs_branch_get(cf->file_rcs) != NULL) {
- printf(" %s", rcsnum_tostr(rcs_branch_get(cf->file_rcs),
+ cvs_printf(" %s", rcsnum_tostr(rcs_branch_get(cf->file_rcs),
numb, sizeof(numb)));
}
- printf("\nlocks: %s", (cf->file_rcs->rf_flags & RCS_SLOCK)
+ cvs_printf("\nlocks: %s", (cf->file_rcs->rf_flags & RCS_SLOCK)
? "strict" : "");
TAILQ_FOREACH(lkp, &(cf->file_rcs->rf_locks), rl_list)
- printf("\n\t%s: %s", lkp->rl_name,
+ cvs_printf("\n\t%s: %s", lkp->rl_name,
rcsnum_tostr(lkp->rl_num, numb, sizeof(numb)));
- printf("\naccess list:\n");
+ cvs_printf("\naccess list:\n");
TAILQ_FOREACH(acp, &(cf->file_rcs->rf_access), ra_list)
- printf("\t%s\n", acp->ra_name);
+ cvs_printf("\t%s\n", acp->ra_name);
- printf("symbolic names:\n");
+ cvs_printf("symbolic names:\n");
TAILQ_FOREACH(sym, &(cf->file_rcs->rf_symbols), rs_list) {
- printf("\t%s: %s\n", sym->rs_name,
+ cvs_printf("\t%s: %s\n", sym->rs_name,
rcsnum_tostr(sym->rs_num, numb, sizeof(numb)));
}
- printf("keyword substitution: %s\n",
+ cvs_printf("keyword substitution: %s\n",
cf->file_rcs->rf_expand == NULL ? "kv" : cf->file_rcs->rf_expand);
- printf("total revisions: %u", cf->file_rcs->rf_ndelta);
+ cvs_printf("total revisions: %u", cf->file_rcs->rf_ndelta);
if (logrev != NULL)
nrev = cvs_revision_select(cf->file_rcs, logrev);
else
nrev = cf->file_rcs->rf_ndelta;
- printf(";\tselected revisions: %u", nrev);
- printf("\n");
- printf("description:\n%s", cf->file_rcs->rf_desc);
+ cvs_printf(";\tselected revisions: %u", nrev);
+ cvs_printf("\n");
+ cvs_printf("description:\n%s", cf->file_rcs->rf_desc);
TAILQ_FOREACH(rdp, &(cf->file_rcs->rf_delta), rd_list) {
if (logrev != NULL &&
!(rdp->rd_flags & RCS_RD_SELECT))
continue;
- printf("%s\n", LOG_REVSEP);
+ cvs_printf("%s\n", LOG_REVSEP);
rcsnum_tostr(rdp->rd_num, numb, sizeof(numb));
- printf("revision %s", numb);
+ cvs_printf("revision %s", numb);
strftime(timeb, sizeof(timeb), "%Y/%m/%d %H:%M:%S",
&rdp->rd_date);
- printf("\ndate: %s; author: %s; state: %s;\n", timeb,
+ cvs_printf("\ndate: %s; author: %s; state: %s;\n", timeb,
rdp->rd_author, rdp->rd_state);
- printf("%s", rdp->rd_log);
+ cvs_printf("%s", rdp->rd_log);
}
- printf("%s\n", LOG_REVEND);
+ cvs_printf("%s\n", LOG_REVEND);
}
diff --git a/usr.bin/cvs/log.c b/usr.bin/cvs/log.c
index 22064ec3548..1f46dc16e61 100644
--- a/usr.bin/cvs/log.c
+++ b/usr.bin/cvs/log.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.c,v 1.35 2006/05/27 03:30:30 joris Exp $ */
+/* $OpenBSD: log.c,v 1.36 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
@@ -31,7 +31,6 @@
#include "log.h"
extern char *__progname;
-
static int send_m = 1;
/*
@@ -85,8 +84,10 @@ cvs_vlog(u_int level, const char *fmt, va_list vap)
/* The cvs program appends the command name to the program name */
if (level == LP_TRACE) {
strlcpy(prefix, " -> ", sizeof(prefix));
- if (cvs_cmdop == CVS_OP_SERVER)
+ if (cvs_server_active)
prefix[0] = 'S';
+ else
+ prefix[0] = 'C';
} else if (cvs_command != NULL) {
if (level == LP_ABORT)
snprintf(prefix, sizeof(prefix), "%s [%s aborted]",
@@ -108,7 +109,7 @@ cvs_vlog(u_int level, const char *fmt, va_list vap)
else
out = stderr;
- if (cvs_cmdop == CVS_OP_SERVER) {
+ if (cvs_server_active) {
if (out == stdout)
putc('M', out);
else {
@@ -145,7 +146,7 @@ cvs_printf(const char *fmt, ...)
va_start(vap, fmt);
- if (cvs_cmdop == CVS_OP_SERVER) {
+ if (cvs_server_active) {
ret = vasprintf(&nstr, fmt, vap);
if (ret == -1)
fatal("cvs_printf: %s", strerror(errno));
diff --git a/usr.bin/cvs/remote.c b/usr.bin/cvs/remote.c
new file mode 100644
index 00000000000..4d00a12ed53
--- /dev/null
+++ b/usr.bin/cvs/remote.c
@@ -0,0 +1,209 @@
+/* $OpenBSD: remote.c,v 1.1 2006/07/07 17:37:17 joris Exp $ */
+/*
+ * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include "cvs.h"
+#include "log.h"
+#include "diff.h"
+#include "remote.h"
+
+struct cvs_resp *
+cvs_remote_get_response_info(const char *response)
+{
+ int i;
+
+ for (i = 0; cvs_responses[i].supported != -1; i++) {
+ if (!strcmp(cvs_responses[i].name, response))
+ return (&(cvs_responses[i]));
+ }
+
+ return (NULL);
+}
+
+struct cvs_req *
+cvs_remote_get_request_info(const char *request)
+{
+ int i;
+
+ for (i = 0; cvs_requests[i].supported != -1; i++) {
+ if (!strcmp(cvs_requests[i].name, request))
+ return (&(cvs_requests[i]));
+ }
+
+ return (NULL);
+}
+
+void
+cvs_remote_output(const char *data)
+{
+ FILE *out;
+
+ if (cvs_server_active)
+ out = stdout;
+ else
+ out = current_cvsroot->cr_srvin;
+
+ if (cvs_server_active == 0)
+ cvs_log(LP_TRACE, "cvs_remote_output(%s)", data);
+
+ fputs(data, out);
+ fputs("\n", out);
+}
+
+char *
+cvs_remote_input(void)
+{
+ FILE *in;
+ size_t len;
+ char *data, *ldata;
+
+ if (cvs_server_active)
+ in = stdin;
+ else
+ in = current_cvsroot->cr_srvout;
+
+ data = fgetln(in, &len);
+ if (data == NULL) {
+ if (sig_received != 0)
+ fatal("received signal %d", sig_received);
+
+ if (cvs_server_active) {
+ cvs_cleanup();
+ exit(0);
+ }
+
+ fatal("the connection has been closed by the server");
+ }
+
+ if (data[len - 1] == '\n') {
+ data[len - 1] = '\0';
+ } else {
+ ldata = xmalloc(len + 1);
+ if (strlcpy(ldata, data, len) >= len)
+ fatal("cvs_remote_input: truncation");
+ data = ldata;
+ }
+
+ ldata = xstrdup(data);
+ return (ldata);
+}
+
+BUF *
+cvs_remote_receive_file(size_t len)
+{
+ BUF *bp;
+ FILE *in;
+ size_t ret;
+ char *data;
+
+ if (cvs_server_active)
+ in = stdin;
+ else
+ in = current_cvsroot->cr_srvout;
+
+ cvs_log(LP_TRACE, "cvs_remote_receive_file(%ld)", len);
+
+ data = xmalloc(len);
+ ret = fread(data, sizeof(char), len, in);
+ if (ret != len)
+ fatal("length mismatch, expected %ld, got %ld", len, ret);
+
+ bp = cvs_buf_alloc(len, BUF_AUTOEXT);
+ cvs_buf_set(bp, data, len, 0);
+ xfree(data);
+ return (bp);
+}
+
+void
+cvs_remote_send_file(const char *path)
+{
+ BUF *bp;
+ int l, fd;
+ FILE *out;
+ size_t ret;
+ struct stat st;
+ char buf[16], *fcont;
+
+ if (cvs_server_active)
+ out = stdout;
+ else
+ out = current_cvsroot->cr_srvin;
+
+ cvs_log(LP_TRACE, "cvs_remote_send_file(%s)", path);
+
+ if ((fd = open(path, O_RDONLY)) == -1)
+ fatal("cvs_remote_send_file: %s: %s", path, strerror(errno));
+
+ if (fstat(fd, &st) == -1)
+ fatal("cvs_remote_send_file: %s: %s", path, strerror(errno));
+
+ cvs_modetostr(st.st_mode, buf, sizeof(buf));
+ cvs_remote_output(buf);
+
+ l = snprintf(buf, sizeof(buf), "%lld", st.st_size);
+ if (l == -1 || l >= (int)sizeof(buf))
+ fatal("cvs_remote_send_file: overflow");
+ cvs_remote_output(buf);
+
+ bp = cvs_buf_load_fd(fd, BUF_AUTOEXT);
+ fcont = cvs_buf_release(bp);
+ ret = fwrite(fcont, sizeof(char), st.st_size, out);
+ if (ret != st.st_size)
+ fatal("length mismatch, tried to write %lld only wrote %ld",
+ st.st_size, ret);
+
+ xfree(fcont);
+ (void)close(fd);
+}
+
+void
+cvs_remote_classify_file(struct cvs_file *cf)
+{
+ time_t mtime;
+ struct stat st;
+ CVSENTRIES *entlist;
+
+ cvs_log(LP_TRACE, "cvs_remote_classify_file(%s)", cf->file_path);
+
+ entlist = cvs_ent_open(cf->file_wd);
+ cf->file_ent = cvs_ent_get(entlist, cf->file_name);
+ cvs_ent_close(entlist, ENT_NOSYNC);
+
+ if (cf->file_ent != NULL && cf->file_ent->ce_status != CVS_ENT_REG) {
+ if (cf->file_ent->ce_status == CVS_ENT_ADDED)
+ cf->file_status = FILE_ADDED;
+ else
+ cf->file_status = FILE_REMOVED;
+ return;
+ }
+
+ if (cf->fd != -1 && cf->file_ent != NULL) {
+ if (fstat(cf->fd, &st) == -1)
+ fatal("cvs_remote_classify_file(%s): %s", cf->file_path,
+ strerror(errno));
+
+ mtime = cvs_hack_time(st.st_mtime, 1);
+ if (mtime != cf->file_ent->ce_mtime)
+ cf->file_status = FILE_MODIFIED;
+ else
+ cf->file_status = FILE_UPTODATE;
+ } else if (cf->fd == -1) {
+ cf->file_status = FILE_UNKNOWN;
+ }
+}
+
diff --git a/usr.bin/cvs/remote.h b/usr.bin/cvs/remote.h
new file mode 100644
index 00000000000..2d340d14408
--- /dev/null
+++ b/usr.bin/cvs/remote.h
@@ -0,0 +1,92 @@
+/* $OpenBSD: remote.h,v 1.1 2006/07/07 17:37:17 joris Exp $ */
+/*
+ * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef H_REMOTE
+#define H_REMOTE
+
+struct cvs_req {
+ char name[32];
+ int supported;
+
+ void (*hdlr)(char *);
+ int flags;
+};
+
+struct cvs_resp {
+ char name[32];
+ int supported;
+
+ void (*hdlr)(char *);
+ int flags;
+};
+
+#define REQ_NEEDED 0x01
+#define RESP_NEEDED 0x01
+
+void cvs_client_connect_to_server(void);
+void cvs_client_disconnect(void);
+void cvs_client_send_request(char *, ...);
+void cvs_client_read_response(void);
+void cvs_client_get_responses(void);
+
+void cvs_client_ok(char *);
+void cvs_client_error(char *);
+void cvs_client_validreq(char *);
+void cvs_client_e(char *);
+void cvs_client_m(char *);
+void cvs_client_checkedin(char *);
+void cvs_client_updated(char *);
+void cvs_client_merged(char *);
+void cvs_client_removed(char *);
+void cvs_client_remove_entry(char *);
+
+void cvs_client_senddir(const char *);
+void cvs_client_sendfile(struct cvs_file *);
+void cvs_client_send_files(char **, int);
+
+void cvs_server_root(char *);
+void cvs_server_send_response(char *, ...);
+void cvs_server_validresp(char *);
+void cvs_server_validreq(char *);
+void cvs_server_globalopt(char *);
+void cvs_server_directory(char *);
+void cvs_server_entry(char *);
+void cvs_server_modified(char *);
+void cvs_server_useunchanged(char *);
+void cvs_server_unchanged(char *);
+void cvs_server_questionable(char *);
+void cvs_server_argument(char *);
+
+void cvs_server_commit(char *);
+void cvs_server_diff(char *);
+void cvs_server_update(char *);
+void cvs_server_status(char *);
+void cvs_server_log(char *);
+
+void cvs_remote_classify_file(struct cvs_file *);
+void cvs_remote_output(const char *);
+char *cvs_remote_input(void);
+BUF *cvs_remote_receive_file(size_t len);
+void cvs_remote_send_file(const char *);
+
+extern struct cvs_req cvs_requests[];
+extern struct cvs_resp cvs_responses[];
+
+struct cvs_req *cvs_remote_get_request_info(const char *);
+struct cvs_resp *cvs_remote_get_response_info(const char *);
+
+#endif
diff --git a/usr.bin/cvs/server.c b/usr.bin/cvs/server.c
new file mode 100644
index 00000000000..b4ce702a00e
--- /dev/null
+++ b/usr.bin/cvs/server.c
@@ -0,0 +1,455 @@
+/* $OpenBSD: server.c,v 1.29 2006/07/07 17:37:17 joris Exp $ */
+/*
+ * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include "cvs.h"
+#include "log.h"
+#include "diff.h"
+#include "remote.h"
+
+struct cvs_resp cvs_responses[] = {
+ /* this is what our server uses, the client should support it */
+ { "Valid-requests", 1, cvs_client_validreq, RESP_NEEDED },
+ { "ok", 0, cvs_client_ok, RESP_NEEDED},
+ { "error", 0, cvs_client_error, RESP_NEEDED },
+ { "E", 0, cvs_client_e, RESP_NEEDED },
+ { "M", 0, cvs_client_m, RESP_NEEDED },
+ { "Checked-in", 0, cvs_client_checkedin, RESP_NEEDED },
+ { "Updated", 0, cvs_client_updated, RESP_NEEDED },
+ { "Merged", 0, cvs_client_merged, RESP_NEEDED },
+ { "Removed", 0, cvs_client_removed, RESP_NEEDED },
+ { "Remove-entry", 0, cvs_client_remove_entry, RESP_NEEDED },
+
+ /* unsupported responses until told otherwise */
+ { "New-entry", 0, NULL, 0 },
+ { "Created", 0, NULL, 0 },
+ { "Update-existing", 0, NULL, 0 },
+ { "Rcs-diff", 0, NULL, 0 },
+ { "Patched", 0, NULL, 0 },
+ { "Mode", 0, NULL, 0 },
+ { "Mod-time", 0, NULL, 0 },
+ { "Checksum", 0, NULL, 0 },
+ { "Copy-file", 0, NULL, 0 },
+ { "Set-static-directory", 0, NULL, 0 },
+ { "Clear-static-directory", 0, NULL, 0 },
+ { "Set-sticky", 0, NULL, 0 },
+ { "Clear-sticky", 0, NULL, 0 },
+ { "Template", 0, NULL, 0 },
+ { "Set-checkin-prog", 0, NULL, 0 },
+ { "Set-update-prog", 0, NULL, 0 },
+ { "Notified", 0, NULL, 0 },
+ { "Module-expansion", 0, NULL, 0 },
+ { "Wrapper-rcsOption", 0, NULL, 0 },
+ { "Mbinary", 0, NULL, 0 },
+ { "F", 0, NULL, 0 },
+ { "MT", 0, NULL, 0 },
+ { "", -1, NULL, 0 }
+};
+
+int cvs_server(int, char **);
+char *cvs_server_path = NULL;
+
+static char *server_currentdir = NULL;
+static char *server_argv[CVS_CMD_MAXARG];
+static int server_argc = 1;
+
+struct cvs_cmd cvs_cmd_server = {
+ CVS_OP_SERVER, 0, "server", { "", "" },
+ "server mode",
+ NULL,
+ NULL,
+ NULL,
+ cvs_server
+};
+
+
+int
+cvs_server(int argc, char **argv)
+{
+ int l;
+ char *cmd, *data;
+ struct cvs_req *req;
+
+ server_argv[0] = xstrdup("server");
+
+ cvs_server_path = xmalloc(MAXPATHLEN);
+ l = snprintf(cvs_server_path, MAXPATHLEN, "%s/cvs-serv%d",
+ cvs_tmpdir, getpid());
+ if (l == -1 || l >= MAXPATHLEN)
+ fatal("cvs_server: overflow in server path");
+
+ if (mkdir(cvs_server_path, 0700) == -1)
+ fatal("failed to create temporary server directory: %s, %s",
+ cvs_server_path, strerror(errno));
+
+ if (chdir(cvs_server_path) == -1)
+ fatal("failed to change directory to '%s'", cvs_server_path);
+
+ for (;;) {
+ cmd = cvs_remote_input();
+
+ if ((data = strchr(cmd, ' ')) != NULL)
+ (*data++) = '\0';
+
+ req = cvs_remote_get_request_info(cmd);
+ if (req == NULL)
+ fatal("request '%s' is not supported by our server",
+ cmd);
+
+ if (req->hdlr == NULL)
+ fatal("opencvs server does not support '%s'", cmd);
+
+ (*req->hdlr)(data);
+ xfree(cmd);
+ }
+
+ return (0);
+}
+
+void
+cvs_server_send_response(char *fmt, ...)
+{
+ va_list ap;
+ char *data, *s;
+ struct cvs_resp *resp;
+
+ va_start(ap, fmt);
+ vasprintf(&data, fmt, ap);
+ va_end(ap);
+
+ if ((s = strchr(data, ' ')) != NULL)
+ *s = '\0';
+
+ resp = cvs_remote_get_response_info(data);
+ if (resp == NULL)
+ fatal("'%s' is an unknown response", data);
+
+ if (resp->supported != 1)
+ fatal("remote cvs client does not support '%s'", data);
+
+ if (s != NULL)
+ *s = ' ';
+
+ cvs_remote_output(data);
+ xfree(data);
+}
+
+void
+cvs_server_root(char *data)
+{
+ fatal("duplicate Root request from client, violates the protocol");
+}
+
+void
+cvs_server_validresp(char *data)
+{
+ int i;
+ char *sp, *ep;
+ struct cvs_resp *resp;
+
+ sp = data;
+ do {
+ if ((ep = strchr(sp, ' ')) != NULL)
+ *ep = '\0';
+
+ resp = cvs_remote_get_response_info(sp);
+ if (resp != NULL)
+ resp->supported = 1;
+
+ if (ep != NULL)
+ sp = ep + 1;
+ } while (ep != NULL);
+
+ for (i = 0; cvs_responses[i].supported != -1; i++) {
+ resp = &cvs_responses[i];
+ if ((resp->flags & RESP_NEEDED) &&
+ resp->supported != 1) {
+ fatal("client does not support required '%s'",
+ resp->name);
+ }
+ }
+}
+
+void
+cvs_server_validreq(char *data)
+{
+ BUF *bp;
+ char *d;
+ int i, first;
+
+ first = 0;
+ bp = cvs_buf_alloc(512, BUF_AUTOEXT);
+ for (i = 0; cvs_requests[i].supported != -1; i++) {
+ if (cvs_requests[i].hdlr == NULL)
+ continue;
+
+ if (first != 0)
+ cvs_buf_append(bp, " ", 1);
+ else
+ first++;
+
+ cvs_buf_append(bp, cvs_requests[i].name,
+ strlen(cvs_requests[i].name));
+ }
+
+ cvs_buf_putc(bp, '\0');
+ d = cvs_buf_release(bp);
+
+ cvs_server_send_response("Valid-requests %s", d);
+ cvs_server_send_response("ok");
+ xfree(d);
+}
+
+void
+cvs_server_globalopt(char *data)
+{
+ if (!strcmp(data, "-t"))
+ cvs_trace = 1;
+
+ if (!strcmp(data, "-n"))
+ cvs_noexec = 1;
+
+ if (!strcmp(data, "-V"))
+ verbosity = 2;
+
+ cvs_log(LP_TRACE, "cvs_server_globalopt(%s)", data);
+}
+
+void
+cvs_server_directory(char *data)
+{
+ int l;
+ CVSENTRIES *entlist;
+ char *dir, *repo, *parent, *entry, *dirn;
+
+ cvs_log(LP_TRACE, "cvs_server_directory(%s)", data);
+
+ dir = cvs_remote_input();
+ if (strlen(dir) < strlen(current_cvsroot->cr_dir) + 1)
+ fatal("cvs_server_directory: bad Directory request");
+
+ repo = dir + strlen(current_cvsroot->cr_dir) + 1;
+ cvs_mkpath(repo);
+
+ if ((dirn = basename(repo)) == NULL)
+ fatal("cvs_server_directory: %s", strerror(errno));
+
+ if ((parent = dirname(repo)) == NULL)
+ fatal("cvs_server_directory: %s", strerror(errno));
+
+ if (strcmp(parent, ".")) {
+ entlist = cvs_ent_open(parent);
+ entry = xmalloc(CVS_ENT_MAXLINELEN);
+ l = snprintf(entry, CVS_ENT_MAXLINELEN, "D/%s////", dirn);
+ if (l == -1 || l >= CVS_ENT_MAXLINELEN)
+ fatal("cvs_server_directory: overflow");
+
+ cvs_ent_add(entlist, entry);
+ cvs_ent_close(entlist, ENT_SYNC);
+ xfree(entry);
+ }
+
+ if (server_currentdir != NULL)
+ xfree(server_currentdir);
+ server_currentdir = xstrdup(repo);
+
+ xfree(dir);
+}
+
+void
+cvs_server_entry(char *data)
+{
+ CVSENTRIES *entlist;
+
+ cvs_log(LP_TRACE, "cvs_server_entry(%s)", data);
+
+ entlist = cvs_ent_open(server_currentdir);
+ cvs_ent_add(entlist, data);
+ cvs_ent_close(entlist, ENT_SYNC);
+}
+
+void
+cvs_server_modified(char *data)
+{
+ BUF *bp;
+ int fd, l;
+ size_t flen;
+ mode_t fmode;
+ const char *errstr;
+ char *mode, *len, *fpath;
+
+ cvs_log(LP_TRACE, "cvs_server_modified(%s)", data);
+
+ mode = cvs_remote_input();
+ len = cvs_remote_input();
+
+ cvs_strtomode(mode, &fmode);
+ xfree(mode);
+
+ flen = strtonum(len, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ fatal("cvs_server_modified: %s", errstr);
+ xfree(len);
+
+ bp = cvs_remote_receive_file(flen);
+
+ fpath = xmalloc(MAXPATHLEN);
+ l = snprintf(fpath, MAXPATHLEN, "%s/%s", server_currentdir, data);
+ if (l == -1 || l >= MAXPATHLEN)
+ fatal("cvs_server_modified: overflow");
+
+ if ((fd = open(fpath, O_WRONLY | O_CREAT | O_TRUNC)) == -1)
+ fatal("cvs_server_modified: %s: %s", fpath, strerror(errno));
+
+ if (cvs_buf_write_fd(bp, fd) == -1)
+ fatal("cvs_server_modified: failed to write file '%s'", fpath);
+
+ if (fchmod(fd, 0600) == -1)
+ fatal("cvs_server_modified: failed to set file mode");
+
+ xfree(fpath);
+ (void)close(fd);
+ cvs_buf_free(bp);
+}
+
+void
+cvs_server_useunchanged(char *data)
+{
+ cvs_log(LP_TRACE, "cvs_server_useunchanged()");
+}
+
+void
+cvs_server_unchanged(char *data)
+{
+ int l, fd;
+ char *fpath;
+ CVSENTRIES *entlist;
+ struct cvs_ent *ent;
+ struct timeval tv[2];
+
+ cvs_log(LP_TRACE, "cvs_server_unchanged(%s)", data);
+
+ fpath = xmalloc(MAXPATHLEN);
+ l = snprintf(fpath, MAXPATHLEN, "%s/%s", server_currentdir, data);
+ if (l == -1 || l >= MAXPATHLEN)
+ fatal("cvs_server_unchanged: overflow");
+
+ if ((fd = open(fpath, O_RDWR | O_CREAT | O_TRUNC)) == -1)
+ fatal("cvs_server_unchanged: %s: %s", fpath, strerror(errno));
+
+ entlist = cvs_ent_open(server_currentdir);
+ ent = cvs_ent_get(entlist, data);
+ if (ent == NULL)
+ fatal("received Unchanged request for non-existing file");
+ cvs_ent_close(entlist, ENT_NOSYNC);
+
+ tv[0].tv_sec = cvs_hack_time(ent->ce_mtime, 0);
+ tv[0].tv_usec = 0;
+ tv[1] = tv[0];
+ if (futimes(fd, tv) == -1)
+ fatal("cvs_server_unchanged: failed to set modified time");
+
+ if (fchmod(fd, 0600) == -1)
+ fatal("cvs_server_unchanged: failed to set mode");
+
+ cvs_ent_free(ent);
+ xfree(fpath);
+ (void)close(fd);
+}
+
+void
+cvs_server_questionable(char *data)
+{
+ cvs_log(LP_TRACE, "cvs_server_questionable(%s)", data);
+}
+
+void
+cvs_server_argument(char *data)
+{
+ cvs_log(LP_TRACE, "cvs_server_argument(%s)", data);
+
+ if (server_argc > CVS_CMD_MAXARG)
+ fatal("cvs_server_argument: too many arguments sent");
+
+ server_argv[server_argc++] = xstrdup(data);
+}
+
+void
+cvs_server_commit(char *data)
+{
+ cvs_log(LP_TRACE, "cvs_server_commit()");
+
+ if (chdir(server_currentdir) == -1)
+ fatal("cvs_server_commit: %s", strerror(errno));
+
+ cvs_cmdop = CVS_OP_COMMIT;
+ cvs_commit(server_argc, server_argv);
+ cvs_server_send_response("ok");
+}
+
+void
+cvs_server_diff(char *data)
+{
+ cvs_log(LP_TRACE, "cvs_server_diff()");
+
+ if (chdir(server_currentdir) == -1)
+ fatal("cvs_server_diff: %s", strerror(errno));
+
+ cvs_cmdop = CVS_OP_DIFF;
+ cvs_diff(server_argc, server_argv);
+ cvs_server_send_response("ok");
+}
+
+void
+cvs_server_status(char *data)
+{
+ cvs_log(LP_TRACE, "cvs_server_status()");
+
+ if (chdir(server_currentdir) == -1)
+ fatal("cvs_server_status: %s", strerror(errno));
+
+ cvs_cmdop = CVS_OP_STATUS;
+ cvs_status(server_argc, server_argv);
+ cvs_server_send_response("ok");
+}
+
+void
+cvs_server_log(char *data)
+{
+ cvs_log(LP_TRACE, "cvs_server_log()");
+
+ if (chdir(server_currentdir) == -1)
+ fatal("cvs_server_log: %s", strerror(errno));
+
+ cvs_cmdop = CVS_OP_LOG;
+ cvs_getlog(server_argc, server_argv);
+ cvs_server_send_response("ok");
+}
+
+void
+cvs_server_update(char *data)
+{
+ cvs_log(LP_TRACE, "cvs_server_update()");
+
+ if (chdir(server_currentdir) == -1)
+ fatal("cvs_server_update: %s", strerror(errno));
+
+ cvs_cmdop = CVS_OP_UPDATE;
+ cvs_update(server_argc, server_argv);
+ cvs_server_send_response("ok");
+}
diff --git a/usr.bin/cvs/status.c b/usr.bin/cvs/status.c
index d1f3f8cc8d8..7b65e6b432f 100644
--- a/usr.bin/cvs/status.c
+++ b/usr.bin/cvs/status.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: status.c,v 1.67 2006/07/07 13:01:40 joris Exp $ */
+/* $OpenBSD: status.c,v 1.68 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2005, 2006 Xavier Santolaria <xsa@openbsd.org>
@@ -20,8 +20,8 @@
#include "cvs.h"
#include "log.h"
+#include "remote.h"
-int cvs_status(int, char **);
void cvs_status_local(struct cvs_file *);
static int show_sym = 0;
@@ -61,7 +61,7 @@ cvs_status(int argc, char **argv)
char *arg = ".";
struct cvs_recursion cr;
- flags = CR_REPO | CR_RECURSE_DIRS;
+ flags = CR_RECURSE_DIRS;
while ((ch = getopt(argc, argv, cvs_cmd_status.cmd_opts)) != -1) {
switch (ch) {
@@ -83,7 +83,18 @@ cvs_status(int argc, char **argv)
cr.enterdir = NULL;
cr.leavedir = NULL;
- cr.fileproc = cvs_status_local;
+
+ if (current_cvsroot->cr_method == CVS_METHOD_LOCAL) {
+ flags |= CR_REPO;
+ cr.fileproc = cvs_status_local;
+ } else {
+ if (!(flags & CR_RECURSE_DIRS))
+ cvs_client_send_request("Argument -l");
+ if (show_sym)
+ cvs_client_send_request("Argument -v");
+ cr.fileproc = cvs_client_sendfile;
+ }
+
cr.flags = flags;
if (argc > 0)
@@ -91,6 +102,13 @@ cvs_status(int argc, char **argv)
else
cvs_file_run(1, &arg, &cr);
+ if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
+ cvs_client_send_files(argv, argc);
+ cvs_client_senddir(".");
+ cvs_client_send_request("status");
+ cvs_client_get_responses();
+ }
+
return (0);
}
diff --git a/usr.bin/cvs/update.c b/usr.bin/cvs/update.c
index a4156f9758c..c702124b9bc 100644
--- a/usr.bin/cvs/update.c
+++ b/usr.bin/cvs/update.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: update.c,v 1.79 2006/07/03 07:09:35 xsa Exp $ */
+/* $OpenBSD: update.c,v 1.80 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -20,8 +20,8 @@
#include "cvs.h"
#include "log.h"
#include "diff.h"
+#include "remote.h"
-int cvs_update(int, char **);
int prune_dirs = 0;
int print = 0;
int build_dirs = 0;
@@ -49,7 +49,7 @@ cvs_update(int argc, char **argv)
int flags;
struct cvs_recursion cr;
- flags = CR_REPO | CR_RECURSE_DIRS;
+ flags = CR_RECURSE_DIRS;
while ((ch = getopt(argc, argv, cvs_cmd_update.cmd_opts)) != -1) {
switch (ch) {
@@ -97,9 +97,28 @@ cvs_update(int argc, char **argv)
argc -= optind;
argv += optind;
- cr.enterdir = cvs_update_enterdir;
- cr.leavedir = cvs_update_leavedir;
- cr.fileproc = cvs_update_local;
+ if (current_cvsroot->cr_method == CVS_METHOD_LOCAL) {
+ cr.enterdir = cvs_update_enterdir;
+ cr.leavedir = cvs_update_leavedir;
+ cr.fileproc = cvs_update_local;
+ flags |= CR_REPO;
+ } else {
+ if (reset_stickies)
+ cvs_client_send_request("Argument -A");
+ if (build_dirs)
+ cvs_client_send_request("Argument -d");
+ if (!(flags & CR_RECURSE_DIRS))
+ cvs_client_send_request("Argument -l");
+ if (prune_dirs)
+ cvs_client_send_request("Argument -P");
+ if (print)
+ cvs_client_send_request("Argument -p");
+
+ cr.enterdir = NULL;
+ cr.leavedir = NULL;
+ cr.fileproc = cvs_client_sendfile;
+ }
+
cr.flags = flags;
if (argc > 0)
@@ -107,6 +126,13 @@ cvs_update(int argc, char **argv)
else
cvs_file_run(1, &arg, &cr);
+ if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
+ cvs_client_send_files(argv, argc);
+ cvs_client_senddir(".");
+ cvs_client_send_request("update");
+ cvs_client_get_responses();
+ }
+
return (0);
}
diff --git a/usr.bin/cvs/util.c b/usr.bin/cvs/util.c
index afcaee42902..e87ce46dfbe 100644
--- a/usr.bin/cvs/util.c
+++ b/usr.bin/cvs/util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.c,v 1.88 2006/06/14 20:28:53 joris Exp $ */
+/* $OpenBSD: util.c,v 1.89 2006/07/07 17:37:17 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* Copyright (c) 2005, 2006 Joris Vink <joris@openbsd.org>
@@ -99,8 +99,7 @@ cvs_strtomode(const char *str, mode_t *mode)
memset(ms, 0, sizeof ms);
if (sscanf(sp, "%c=%3s", &type, ms) != 2 &&
sscanf(sp, "%c=", &type) != 1) {
- cvs_log(LP_ERR, "failed to scan mode string `%s'", sp);
- continue;
+ fatal("failed to scan mode string `%s'", sp);
}
if (type <= 'a' || type >= 'z' ||
@@ -117,8 +116,7 @@ cvs_strtomode(const char *str, mode_t *mode)
for (sp = ms; *sp != '\0'; sp++) {
if (*sp <= 'a' || *sp >= 'z' ||
cvs_modes[(int)type][*sp - 'a'] == 0) {
- cvs_log(LP_ERR,
- "invalid permission bit `%c'", *sp);
+ fatal("invalid permission bit `%c'", *sp);
} else
m |= cvs_modes[(int)type][*sp - 'a'];
}