diff options
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/cvs/Makefile | 11 | ||||
-rw-r--r-- | usr.bin/cvs/checkout.c | 100 | ||||
-rw-r--r-- | usr.bin/cvs/client.c | 585 | ||||
-rw-r--r-- | usr.bin/cvs/cmd.c | 4 | ||||
-rw-r--r-- | usr.bin/cvs/commit.c | 24 | ||||
-rw-r--r-- | usr.bin/cvs/cvs.c | 36 | ||||
-rw-r--r-- | usr.bin/cvs/cvs.h | 11 | ||||
-rw-r--r-- | usr.bin/cvs/diff.c | 47 | ||||
-rw-r--r-- | usr.bin/cvs/diff_internals.c | 6 | ||||
-rw-r--r-- | usr.bin/cvs/fatal.c | 6 | ||||
-rw-r--r-- | usr.bin/cvs/file.c | 4 | ||||
-rw-r--r-- | usr.bin/cvs/getlog.c | 69 | ||||
-rw-r--r-- | usr.bin/cvs/log.c | 11 | ||||
-rw-r--r-- | usr.bin/cvs/remote.c | 209 | ||||
-rw-r--r-- | usr.bin/cvs/remote.h | 92 | ||||
-rw-r--r-- | usr.bin/cvs/server.c | 455 | ||||
-rw-r--r-- | usr.bin/cvs/status.c | 26 | ||||
-rw-r--r-- | usr.bin/cvs/update.c | 38 | ||||
-rw-r--r-- | usr.bin/cvs/util.c | 8 |
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']; } |