diff options
Diffstat (limited to 'contrib/cvs/src')
32 files changed, 1623 insertions, 2319 deletions
diff --git a/contrib/cvs/src/NOTES b/contrib/cvs/src/NOTES deleted file mode 100644 index 646ebdf..0000000 --- a/contrib/cvs/src/NOTES +++ /dev/null @@ -1,60 +0,0 @@ -wishlist - Tue Nov 2 15:22:58 PST 1993 - -* bcopy -> memcpy & friends. - ** done 12/18/93 - -* remove static buffers. -* replace list & node cache with recursive obstacks, (xmalloc, - getnode, getlist) -* check all io functions for error return codes. also check all - system calls. -* error check mkdir. - ---- -Old notes... - -* All sizing limits are gone. The rest of these items were incidental - in that effort. - -* login name from history was duplicated. taught existing routine to - cache and use that instead. Also add routines to cache uid, pid, - etc. - -* ign strings were never freed. Now they are. - -* there was a printf("... %s ...", cp) vs *cp bug in history.c. Now - fixed. - -* The environment variables TMPDIR, HOME, and LOGNAME were not - honored. Now they are. - -* extra line inserted by do_editor() is gone. Then obviated. Editor - is now called exactly once per checkin. - -* revised editor behaviour. Never use /dev/tty. If the editor - session fails, we haven't yet done anything. Therefor the user can - safely rerun cvs and we should just fail. Also use the editor for - initial log messages on added files. Also omit the confirmation - when adding directories. Adding directories will require an - explicit "commit" step soon. Make it possible to prevent null login - messages using #define REQUIRE_LOG_MESSAGES - -* prototypes for all callbacks. - -* all callbacks get ref pointers. - -* do_recursion/start_recursion now use recusion_frame's rather than a - list of a lot of pointers and global variables. - -* corrected types on status_dirproc(). - -* CONFIRM_DIRECTORY_ADDS - -* re_comp was innappropriate in a few places. I've eliminated it. - -* FORCE_MESSAGE_ON_ADD - -* So I built a regression test. Let's call it a sanity check to be - less ambitious. It exposed that cvs is difficult to call from - scripts. - diff --git a/contrib/cvs/src/README-rm-add b/contrib/cvs/src/README-rm-add deleted file mode 100644 index 87fd7c6..0000000 --- a/contrib/cvs/src/README-rm-add +++ /dev/null @@ -1,31 +0,0 @@ -WHAT THE "DEATH SUPPORT" FEATURES DO: - -(Some of the death support stuff is documented in the main manual, but -this file is for stuff which noone has gotten around to adding to the -main manual yet). - -CVS with death support can record when a file is active, or alive, and -when it is removed, or dead. With this facility you can record the -history of a file, including the fact that at some point in its life -the file was removed and then later added. - -Files can now be added or removed in a branch and later merged -into the trunk. - - cvs update -A - touch a b c - cvs add a b c ; cvs ci -m "added" a b c - cvs tag -b branchtag - cvs update -r branchtag - touch d ; cvs add d - rm a ; cvs rm a - cvs ci -m "added d, removed a" - cvs update -A - cvs update -jbranchtag - -Added and removed files may also be merged between branches. - -Files removed in the trunk may be merged into branches. - -Files added on the trunk are a special case. They cannot be merged -into a branch. Instead, simply branch the file by hand. diff --git a/contrib/cvs/src/buffer.c b/contrib/cvs/src/buffer.c index 8e66355..d53a5c6 100644 --- a/contrib/cvs/src/buffer.c +++ b/contrib/cvs/src/buffer.c @@ -1,19 +1,7 @@ -/* - * Copyright (C) 1996-2005 The Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - /* Code for the buffer data structure. */ +/* $FreeBSD$ */ + #include <assert.h> #include "cvs.h" #include "buffer.h" @@ -124,13 +112,11 @@ allocate_buffer_datas () /* Allocate buffer_data structures in blocks of 16. */ #define ALLOC_COUNT (16) - alc = xmalloc (ALLOC_COUNT * sizeof (struct buffer_data)); + alc = ((struct buffer_data *) + xmalloc (ALLOC_COUNT * sizeof (struct buffer_data))); space = (char *) valloc (ALLOC_COUNT * BUFFER_DATA_SIZE); - if (!space) - { - free (alc); + if (alc == NULL || space == NULL) return; - } for (i = 0; i < ALLOC_COUNT; i++, alc++, space += BUFFER_DATA_SIZE) { alc->next = free_buffer_data; @@ -1422,16 +1408,10 @@ stdio_buffer_shutdown (buf) { struct stdio_buffer_closure *bc = buf->closure; struct stat s; - int closefp, statted; + int closefp = 1; - /* Must be a pipe or a socket. What could go wrong? - * Well, apparently for disconnected clients under AIX, the - * fstat() will return -1 on the server if the client has gone - * away. - */ - if (fstat(fileno(bc->fp), &s) == -1) statted = 0; - else statted = 1; - closefp = statted; + /* Must be a pipe or a socket. What could go wrong? */ + assert (fstat (fileno (bc->fp), &s) != -1); /* Flush the buffer if we can */ if (buf->flush) @@ -1454,7 +1434,7 @@ stdio_buffer_shutdown (buf) # ifndef NO_SOCKET_TO_FD { /* shutdown() sockets */ - if (statted && S_ISSOCK (s.st_mode)) + if (S_ISSOCK (s.st_mode)) shutdown (fileno (bc->fp), 0); } # endif /* NO_SOCKET_TO_FD */ @@ -1462,7 +1442,7 @@ stdio_buffer_shutdown (buf) /* Can't be set with SHUTDOWN_SERVER defined */ else if (pclose (bc->fp) == EOF) { - error (0, errno, "closing connection to %s", + error (1, errno, "closing connection to %s", current_parsed_root->hostname); closefp = 0; } @@ -1482,7 +1462,7 @@ stdio_buffer_shutdown (buf) # endif # ifndef NO_SOCKET_TO_FD /* shutdown() sockets */ - if (statted && S_ISSOCK (s.st_mode)) + if (S_ISSOCK (s.st_mode)) shutdown (fileno (bc->fp), 1); # else { @@ -1495,19 +1475,19 @@ stdio_buffer_shutdown (buf) buf->output = NULL; } - if (statted && closefp && fclose (bc->fp) == EOF) + if (closefp && fclose (bc->fp) == EOF) { - if (server_active) + if (0 +# ifdef SERVER_SUPPORT + || server_active +# endif /* SERVER_SUPPORT */ + ) { /* Syslog this? */ } # ifdef CLIENT_SUPPORT - /* We are already closing the connection. - * On error, print a warning and try to - * continue to avoid infinte loops. - */ else - error (0, errno, + error (1, errno, "closing down connection to %s", current_parsed_root->hostname); # endif /* CLIENT_SUPPORT */ @@ -1521,13 +1501,8 @@ stdio_buffer_shutdown (buf) do w = waitpid (bc->child_pid, (int *) 0, 0); while (w == -1 && errno == EINTR); - - /* We are already closing the connection. - * On error, print a warning and try to - * continue to avoid infinte loops. - */ if (w == -1) - error (0, errno, "waiting for process %d", bc->child_pid); + error (1, errno, "waiting for process %d", bc->child_pid); } return 0; } @@ -1860,7 +1835,7 @@ packetizing_buffer_output (closure, data, have, wrote) struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; char inbuf[BUFFER_DATA_SIZE + 2]; char stack_outbuf[BUFFER_DATA_SIZE + PACKET_SLOP + 4]; - struct buffer_data *outdata = NULL; + struct buffer_data *outdata; char *outbuf; int size, status, translated; @@ -1915,11 +1890,6 @@ packetizing_buffer_output (closure, data, have, wrote) buf_output (pb->buf, outbuf, translated + 2); else { - /* if ((have + PACKET_SLOP + 4) > BUFFER_DATA_SIZE), then - outdata may be NULL. */ - if (outdata == NULL) - abort (); - outdata->size = translated + 2; buf_append_data (pb->buf, outdata, outdata); } diff --git a/contrib/cvs/src/checkout.c b/contrib/cvs/src/checkout.c index e4d80ea..57933ee 100644 --- a/contrib/cvs/src/checkout.c +++ b/contrib/cvs/src/checkout.c @@ -1,11 +1,6 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. @@ -38,6 +33,10 @@ * edited by the user, if necessary (when the repository is moved, e.g.) */ +/* + * $FreeBSD$ + */ + #include <assert.h> #include "cvs.h" @@ -55,6 +54,7 @@ static const char *const checkout_usage[] = "\t-N\tDon't shorten module paths if -d specified.\n", "\t-P\tPrune empty directories.\n", "\t-R\tProcess directories recursively.\n", + "\t-T\tCreate Template file from local repository for remote commit.\n", "\t-c\t\"cat\" the module database.\n", "\t-f\tForce a head revision match if tag/date not found.\n", "\t-l\tLocal directory only, not recursive\n", @@ -72,13 +72,13 @@ static const char *const checkout_usage[] = static const char *const export_usage[] = { - "Usage: %s %s [-NRfln] [-r tag] [-D date] [-d dir] [-k kopt] module...\n", + "Usage: %s %s [-NRfln] [-r rev] [-D date] [-d dir] [-k kopt] module...\n", "\t-N\tDon't shorten module paths if -d specified.\n", "\t-f\tForce a head revision match if tag/date not found.\n", "\t-l\tLocal directory only, not recursive\n", "\t-R\tProcess directories recursively (default).\n", "\t-n\tDo not run module program (if any).\n", - "\t-r tag\tExport tagged revisions.\n", + "\t-r rev\tExport revision or tag.\n", "\t-D date\tExport revisions as of date.\n", "\t-d dir\tExport into dir instead of module name.\n", "\t-k kopt\tUse RCS kopt -k option on checkout.\n", @@ -97,6 +97,7 @@ static char *date; static char *join_rev1; static char *join_rev2; static int join_tags_validated; +static int pull_template; static char *preload_update_dir; static char *history_name; static enum mtype m_type; @@ -144,7 +145,7 @@ checkout (argc, argv) else { m_type = CHECKOUT; - valid_options = "+ANnk:d:flRpQqcsr:D:j:P"; + valid_options = "+ANnk:d:flRpTQqcsr:D:j:P"; valid_usage = checkout_usage; } @@ -173,11 +174,16 @@ checkout (argc, argv) case 'n': run_module_prog = 0; break; + case 'T': + pull_template = 1; + break; case 'Q': case 'q': +#ifdef SERVER_SUPPORT /* The CVS 1.5 client sends these options (in addition to Global_option requests), so we must ignore them. */ if (!server_active) +#endif error (1, 0, "-q or -Q must be specified before \"%s\"", cvs_cmd_name); @@ -431,8 +437,10 @@ safe_location (where) CLIENT_SERVER_STR, where ? where : "(null)"); +#ifdef CLIENT_SUPPORT /* Don't compare remote CVSROOTs to our destination directory. */ - if (current_parsed_root->isremote) return 1; + if ( current_parsed_root->isremote ) return 1; +#endif /* CLIENT_SUPPORT */ /* set current - even if where is set we'll need to cd back... */ current = xgetwd (); @@ -1054,8 +1062,7 @@ internal error: %s doesn't start with %s in checkout_proc", which = W_REPOS; if (tag != NULL && !tag_validated) { - tag_check_valid (tag, argc - 1, argv + 1, 0, aflag, - repository); + tag_check_valid (tag, argc - 1, argv + 1, 0, aflag, NULL); tag_validated = 1; } } @@ -1098,8 +1105,7 @@ internal error: %s doesn't start with %s in checkout_proc", force_tag_match, 0 /* !local */ , 1 /* update -d */ , aflag, checkout_prune_dirs, pipeout, which, join_rev1, join_rev2, - preload_update_dir, m_type == CHECKOUT, - repository); + preload_update_dir, pull_template, repository); goto out; } @@ -1155,8 +1161,7 @@ internal error: %s doesn't start with %s in checkout_proc", err += do_update (argc - 1, argv + 1, options, tag, date, force_tag_match, local_specified, 1 /* update -d */, aflag, checkout_prune_dirs, pipeout, which, join_rev1, - join_rev2, preload_update_dir, m_type == CHECKOUT, - repository); + join_rev2, preload_update_dir, pull_template, repository); out: free (preload_update_dir); preload_update_dir = oldupdate; diff --git a/contrib/cvs/src/client.c b/contrib/cvs/src/client.c index 22384ed..aae404a 100644 --- a/contrib/cvs/src/client.c +++ b/contrib/cvs/src/client.c @@ -10,6 +10,10 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ +/* + * $FreeBSD$ + */ + #ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ @@ -221,8 +225,7 @@ arg_should_not_be_sent_to_server (arg) /* Try to decide whether we should send arg to the server by checking the contents of the corresponding CVSADM directory. */ { - char *t, *root_string; - cvsroot_t *this_root = NULL; + char *t, *this_root; /* Calculate "dirname arg" */ for (t = arg + strlen (arg) - 1; t >= arg; t--) @@ -252,31 +255,25 @@ arg_should_not_be_sent_to_server (arg) /* Since we didn't find it in the list, check the CVSADM files on disk. */ this_root = Name_Root (arg, (char *) NULL); - root_string = this_root->original; *t = c; } else { /* We're at the beginning of the string. Look at the CVSADM files in cwd. */ - if (CVSroot_cmdline) - root_string = CVSroot_cmdline; - else - { - this_root = Name_Root ((char *) NULL, (char *) NULL); - root_string = this_root->original; - } + this_root = (CVSroot_cmdline ? xstrdup(CVSroot_cmdline) + : Name_Root ((char *) NULL, (char *) NULL)); } /* Now check the value for root. */ - if (root_string && current_parsed_root - && (strcmp (root_string, current_parsed_root->original) != 0)) + if (CVSroot_cmdline == NULL && this_root && current_parsed_root + && (strcmp (this_root, current_parsed_root->original) != 0)) { /* Don't send this, since the CVSROOTs don't match. */ - if (this_root) free_cvsroot_t (this_root); + free (this_root); return 1; } - if (this_root) free_cvsroot_t (this_root); + free (this_root); } /* OK, let's send it. */ @@ -893,6 +890,12 @@ read_line (resultp) #if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT) /* + * Zero if compression isn't supported or requested; non-zero to indicate + * a compression level to request from gzip. + */ +int gzip_level; + +/* * Level of compression to use when running gzip on a single file. */ int file_gzip_level; @@ -1114,8 +1117,6 @@ call_in_directory (pathname, func, data) int reposdirname_absolute; int newdir = 0; - assert (pathname); - reposname = NULL; read_line (&reposname); assert (reposname != NULL); @@ -1197,6 +1198,44 @@ call_in_directory (pathname, func, data) if (CVS_CHDIR (toplevel_wd) < 0) error (1, errno, "could not chdir to %s", toplevel_wd); + /* Create the CVS directory at the top level if needed. The + isdir seems like an unneeded system call, but it *does* + need to be called both if the CVS_CHDIR below succeeds + (e.g. "cvs co .") or if it fails (e.g. basicb-1a in + testsuite). We only need to do this for the "." case, + since the server takes care of forcing this directory to be + created in all other cases. If we don't create CVSADM + here, the call to Entries_Open below will fail. FIXME: + perhaps this means that we should change our algorithm + below that calls Create_Admin instead of having this code + here? */ + if (/* I think the reposdirname_absolute case has to do with + things like "cvs update /foo/bar". In any event, the + code below which tries to put toplevel_repos into + CVS/Repository is almost surely unsuited to + the reposdirname_absolute case. */ + !reposdirname_absolute + && (strcmp (dir_name, ".") == 0) + && ! isdir (CVSADM)) + { + char *repo; + char *r; + + newdir = 1; + + repo = xmalloc (strlen (toplevel_repos) + + 10); + strcpy (repo, toplevel_repos); + r = repo + strlen (repo); + if (r[-1] != '.' || r[-2] != '/') + strcpy (r, "/."); + + Create_Admin (".", ".", repo, (char *) NULL, + (char *) NULL, 0, 1, 1); + + free (repo); + } + if (CVS_CHDIR (dir_name) < 0) { char *dir; @@ -1457,44 +1496,7 @@ handle_copy_file (args, len) { call_in_directory (args, copy_a_file, (char *)NULL); } - - - -/* Attempt to read a file size from a string. Accepts base 8 (0N), base 16 - * (0xN), or base 10. Exits on error. - * - * RETURNS - * The file size, in a size_t. - * - * FATAL ERRORS - * 1. As strtoul(). - * 2. If the number read exceeds SIZE_MAX. - */ -static size_t -strto_file_size (const char *s) -{ - unsigned long tmp; - char *endptr; - - /* Read it. */ - errno = 0; - tmp = strtoul (s, &endptr, 0); - - /* Check for errors. */ - if (errno || endptr == s) - error (1, errno, "Server sent invalid file size `%s'", s); - if (*endptr != '\0') - error (1, 0, - "Server sent trailing characters in file size `%s'", - endptr); - if (tmp > SIZE_MAX) - error (1, 0, "Server sent file size exceeding client max."); - - /* Return it. */ - return (size_t)tmp; -} - - + static void read_counted_file PROTO ((char *, char *)); @@ -1527,7 +1529,9 @@ read_counted_file (filename, fullname) if (size_string[0] == 'z') error (1, 0, "\ protocol error: compressed files not supported for that operation"); - size = strto_file_size (size_string); + /* FIXME: should be doing more error checking, probably. Like using + strtoul and making sure we used up the whole line. */ + size = atoi (size_string); free (size_string); /* A more sophisticated implementation would use only a limited amount @@ -1809,12 +1813,11 @@ update_entries (data_arg, ent_list, short_pathname, filename) { char *size_string; char *mode_string; - size_t size; + int size; char *buf; char *temp_filename; int use_gzip; int patch_failed; - char *s; read_line (&mode_string); @@ -1822,14 +1825,13 @@ update_entries (data_arg, ent_list, short_pathname, filename) if (size_string[0] == 'z') { use_gzip = 1; - s = size_string + 1; + size = atoi (size_string+1); } else { use_gzip = 0; - s = size_string; + size = atoi (size_string); } - size = strto_file_size (s); free (size_string); /* Note that checking this separately from writing the file is @@ -1930,7 +1932,7 @@ update_entries (data_arg, ent_list, short_pathname, filename) #ifdef USE_VMS_FILENAMES /* A VMS rename of "blah.dat" to "foo" to implies a destination of "foo.dat" which is unfortinate for CVS */ - sprintf (temp_filename, "%s_new_", filename); + sprintf (temp_filename, "%s_new_", filename); #else #ifdef _POSIX_NO_TRUNC sprintf (temp_filename, ".new.%.9s", filename); @@ -1983,8 +1985,6 @@ update_entries (data_arg, ent_list, short_pathname, filename) entirely possible that future files will not have the same problem. */ error (0, errno, "cannot write %s", short_pathname); - free (temp_filename); - free (buf); goto discard_file_and_return; } @@ -2841,10 +2841,7 @@ send_a_repository (dir, repository, update_dir_in) const char *repository; const char *update_dir_in; { - char *update_dir; - - assert (update_dir_in); - update_dir = xstrdup (update_dir_in); + char *update_dir = xstrdup (update_dir_in); if (toplevel_repos == NULL && repository != NULL) { @@ -3104,7 +3101,7 @@ handle_mbinary (args, len) /* Get the size. */ read_line (&size_string); - size = strto_file_size (size_string); + size = atoi (size_string); free (size_string); /* OK, now get all the data. The algorithm here is that we read @@ -3253,7 +3250,7 @@ handle_mt (args, len) else if (importmergecmd.seen) { if (strcmp (tag, "conflicts") == 0) - importmergecmd.conflicts = text ? atoi (text) : -1; + importmergecmd.conflicts = atoi (text); else if (strcmp (tag, "mergetag1") == 0) importmergecmd.mergetag1 = xstrdup (text); else if (strcmp (tag, "mergetag2") == 0) @@ -3921,7 +3918,6 @@ auth_server (root, lto_server, lfrom_server, verify_only, do_gssapi, hostinfo) /* Paranoia. */ memset (password, 0, strlen (password)); - free (password); # else /* ! AUTH_CLIENT_SUPPORT */ error (1, 0, "INTERNAL ERROR: This client does not support pserver authentication"); # endif /* AUTH_CLIENT_SUPPORT */ @@ -4036,7 +4032,7 @@ connect_to_forked_server (to_server, from_server) fprintf (stderr, " -> Forking server: %s %s\n", command[0], command[1]); } - child_pid = piped_child (command, &tofd, &fromfd, 0); + child_pid = piped_child (command, &tofd, &fromfd); if (child_pid < 0) error (1, 0, "could not fork server process"); @@ -4240,8 +4236,7 @@ connect_to_gserver (root, sock, hostinfo) if (need > sizeof buf) { - ssize_t got; - size_t total; + int got; /* This usually means that the server sent us an error message. Read it byte by byte and print it out. @@ -4250,19 +4245,13 @@ connect_to_gserver (root, sock, hostinfo) want to do this to work with older servers. */ buf[0] = cbuf[0]; buf[1] = cbuf[1]; - total = 2; - while (got = recv (sock, buf + total, sizeof buf - total, 0)) - { - if (got < 0) - error (1, 0, "recv() from server %s: %s", - root->hostname, SOCK_STRERROR (SOCK_ERRNO)); - total += got; - if (strrchr (buf + total - got, '\n')) - break; - } - buf[total] = '\0'; - if (buf[total - 1] == '\n') - buf[total - 1] = '\0'; + got = recv (sock, buf + 2, sizeof buf - 2, 0); + if (got < 0) + error (1, 0, "recv() from server %s: %s", + root->hostname, SOCK_STRERROR (SOCK_ERRNO)); + buf[got + 2] = '\0'; + if (buf[got + 1] == '\n') + buf[got + 1] = '\0'; error (1, 0, "error from server %s: %s", root->hostname, buf); } @@ -4343,7 +4332,6 @@ start_server () #endif /* HAVE_GSSAPI */ case ext_method: - case extssh_method: #ifdef NO_EXT_METHOD error (0, 0, ":ext: method not supported by this port of CVS"); error (1, 0, "try :server: instead"); @@ -4728,7 +4716,27 @@ start_rsh_server (root, to_server, from_server) char *rsh_argv[10]; if (!cvs_rsh) - cvs_rsh = RSH_DFLT; + /* People sometimes suggest or assume that this should default + to "remsh" on systems like HPUX in which that is the + system-supplied name for the rsh program. However, that + causes various problems (keep in mind that systems such as + HPUX might have non-system-supplied versions of "rsh", like + a Kerberized one, which one might want to use). If we + based the name on what is found in the PATH of the person + who runs configure, that would make it harder to + consistently produce the same result in the face of + different people producing binary distributions. If we + based it on "remsh" always being the default for HPUX + (e.g. based on uname), that might be slightly better but + would require us to keep track of what the defaults are for + each system type, and probably would cope poorly if the + existence of remsh or rsh varies from OS version to OS + version. Therefore, it seems best to have the default + remain "rsh", and tell HPUX users to specify remsh, for + example in CVS_RSH or other such mechanisms to be devised, + if that is what they want (the manual already tells them + that). */ + cvs_rsh = "ssh"; if (!cvs_server) cvs_server = "cvs"; @@ -4789,7 +4797,7 @@ start_rsh_server (root, to_server, from_server) int child_pid; if (!cvs_rsh) - cvs_rsh = "rsh"; + cvs_rsh = "ssh"; if (!cvs_server) cvs_server = "cvs"; @@ -4833,7 +4841,7 @@ start_rsh_server (root, to_server, from_server) fprintf (stderr, "%s ", argv[i]); putc ('\n', stderr); } - child_pid = piped_child (argv, &tofd, &fromfd, 1); + child_pid = piped_child (argv, &tofd, &fromfd); if (child_pid < 0) error (1, errno, "cannot start server via rsh"); @@ -4852,10 +4860,10 @@ start_rsh_server (root, to_server, from_server) /* Send an argument STRING. */ void send_arg (string) - const char *string; + char *string; { char buf[1]; - const char *p = string; + char *p = string; send_to_server ("Argument ", 0); @@ -5147,10 +5155,8 @@ warning: ignoring -k options due to server limitations"); } else if (vers->ts_rcs == NULL || args->force - || strcmp (vers->ts_conflict - && supported_request ("Empty-conflicts") - ? vers->ts_conflict : vers->ts_rcs, vers->ts_user) - || (vers->ts_conflict && !strcmp (cvs_cmd_name, "diff"))) + || strcmp (vers->ts_user, vers->ts_rcs) != 0 + || (vers->vn_user && *vers->vn_user == '0')) { if (args->no_contents && supported_request ("Is-modified")) @@ -5356,15 +5362,36 @@ send_dirleave_proc (callerdat, dir, err, update_dir, entries) } /* - * Send each option in an array to the server, one by one. - * argv might be "--foo=bar", "-C", "5", "-y". + * Send each option in a string to the server, one by one. + * This assumes that the options are separated by spaces, for example + * STRING might be "--foo -C5 -y". */ + void -send_options (int argc, char *const *argv) +send_option_string (string) + char *string; { - int i; - for (i = 0; i < argc; i++) - send_arg (argv[i]); + char *copy; + char *p; + + copy = xstrdup (string); + p = copy; + while (1) + { + char *s; + char l; + + for (s = p; *s != ' ' && *s != '\0'; s++) + ; + l = *s; + *s = '\0'; + if (s != p) + send_arg (p); + if (l == '\0') + break; + p = s + 1; + } + free (copy); } diff --git a/contrib/cvs/src/commit.c b/contrib/cvs/src/commit.c index 7d168c3..1edb95d 100644 --- a/contrib/cvs/src/commit.c +++ b/contrib/cvs/src/commit.c @@ -1,11 +1,6 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. @@ -17,6 +12,7 @@ * * The call is: cvs commit [options] files... * + * $FreeBSD$ */ #include <assert.h> @@ -388,8 +384,12 @@ commit (argc, argv) /* FIXME: Shouldn't this check be much more closely related to the readonly user stuff (CVSROOT/readers, &c). That is, why should root be able to "cvs init", "cvs import", &c, but not "cvs ci"? */ - /* Who we are on the client side doesn't affect logging. */ - if (geteuid () == (uid_t) 0 && !current_parsed_root->isremote) + if (geteuid () == (uid_t) 0 +# ifdef CLIENT_SUPPORT + /* Who we are on the client side doesn't affect logging. */ + && !current_parsed_root->isremote +# endif + ) { struct passwd *pw; @@ -412,7 +412,6 @@ commit (argc, argv) /* Silently ignore -n for compatibility with old * clients. */ - if (!server_active) error(0, 0, "the `-n' option is obsolete"); break; #endif /* SERVER_SUPPORT */ case 'm': @@ -643,8 +642,7 @@ commit (argc, argv) fp = cvs_temp_file (&fname); if (fp == NULL) - error (1, 0, "cannot create temporary file %s", - fname ? fname : "(null)"); + error (1, 0, "cannot create temporary file %s", fname); if (fwrite (saved_message, 1, strlen (saved_message), fp) != strlen (saved_message)) error (1, errno, "cannot write temporary file %s", fname); @@ -715,8 +713,10 @@ commit (argc, argv) Lock_Cleanup (); dellist (&mulist); +#ifdef SERVER_SUPPORT if (server_active) return err; +#endif /* see if we need to sleep before returning to avoid time-stamp races */ if (last_register_time) @@ -871,11 +871,11 @@ check_fileproc (callerdat, finfo) case T_CHECKOUT: case T_PATCH: case T_NEEDS_MERGE: + case T_CONFLICT: case T_REMOVE_ENTRY: error (0, 0, "Up-to-date check failed for `%s'", finfo->fullname); freevers_ts (&vers); return 1; - case T_CONFLICT: case T_MODIFIED: case T_ADDED: case T_REMOVED: @@ -913,30 +913,40 @@ check_fileproc (callerdat, finfo) return 1; } } - if (status == T_CONFLICT && !force_ci) - { - error (0, 0, - "file `%s' had a conflict and has not been modified", - finfo->fullname); - freevers_ts (&vers); - return 1; - } - if (status == T_MODIFIED && !force_ci && file_has_markers (finfo)) + if (status == T_MODIFIED && !force_ci && vers->ts_conflict) { - /* Make this a warning, not an error, because we have - no way of knowing whether the "conflict indicators" - are really from a conflict or whether they are part - of the document itself (cvs.texinfo and sanity.sh in - CVS itself, for example, tend to want to have strings - like ">>>>>>>" at the start of a line). Making people - kludge this the way they need to kludge keyword - expansion seems undesirable. And it is worse than - keyword expansion, because there is no -ko - analogue. */ - error (0, 0, - "\ + /* + * We found a "conflict" marker. + * + * If the timestamp on the file is the same as the + * timestamp stored in the Entries file, we block the commit. + */ + if ( file_has_conflict ( finfo, vers->ts_conflict ) ) + { + error (0, 0, + "file `%s' had a conflict and has not been modified", + finfo->fullname); + freevers_ts (&vers); + return 1; + } + + if (file_has_markers (finfo)) + { + /* Make this a warning, not an error, because we have + no way of knowing whether the "conflict indicators" + are really from a conflict or whether they are part + of the document itself (cvs.texinfo and sanity.sh in + CVS itself, for example, tend to want to have strings + like ">>>>>>>" at the start of a line). Making people + kludge this the way they need to kludge keyword + expansion seems undesirable. And it is worse than + keyword expansion, because there is no -ko + analogue. */ + error (0, 0, + "\ warning: file `%s' seems to still contain conflict indicators", - finfo->fullname); + finfo->fullname); + } } if (status == T_REMOVED) @@ -1275,7 +1285,11 @@ commit_fileproc (callerdat, finfo) if (!got_message) { got_message = 1; - if (!server_active && use_editor) + if ( +#ifdef SERVER_SUPPORT + !server_active && +#endif + use_editor) do_editor (finfo->update_dir, &saved_message, finfo->repository, ulist); do_verify (&saved_message, finfo->repository); @@ -1461,8 +1475,6 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries) Node *p; List *ulist; - assert (repository); - p = findnode (mulist, update_dir); if (p == NULL) return err; @@ -1553,7 +1565,11 @@ commit_direntproc (callerdat, dir, repos, update_dir, entries) /* get commit message */ real_repos = Name_Repository (dir, update_dir); got_message = 1; - if (!server_active && use_editor) + if ( +#ifdef SERVER_SUPPORT + !server_active && +#endif + use_editor) do_editor (update_dir, &saved_message, real_repos, ulist); do_verify (&saved_message, real_repos); free (real_repos); @@ -1737,22 +1753,18 @@ remove_file (finfo, tag, message) if (corev != NULL) free (corev); - retcode = RCS_checkin (finfo->rcs, finfo->file, message, rev, 0, + retcode = RCS_checkin (finfo->rcs, finfo->file, message, rev, RCS_FLAGS_DEAD | RCS_FLAGS_QUIET); if (retcode != 0) { if (!quiet) error (0, retcode == -1 ? errno : 0, "failed to commit dead revision for `%s'", finfo->fullname); - if (prev_rev != NULL) - free (prev_rev); return 1; } /* At this point, the file has been committed as removed. We should probably tell the history file about it */ - corev = rev ? RCS_getbranch (finfo->rcs, rev, 1) : RCS_head (finfo->rcs); - history_write ('R', NULL, corev, finfo->file, finfo->repository); - free (corev); + history_write ('R', NULL, finfo->rcs->head, finfo->file, finfo->repository); if (rev != NULL) free (rev); @@ -2074,8 +2086,7 @@ checkaddfile (file, repository, tag, options, rcsnode) /* and lock it */ if (lock_RCS (file, rcs, rev, repository)) { - error (0, 0, "cannot lock revision %s in `%s'.", - rev ? rev : tag ? tag : "HEAD", rcs->path); + error (0, 0, "cannot lock `%s'.", rcs->path); if (rev != NULL) free (rev); goto out; @@ -2113,14 +2124,13 @@ checkaddfile (file, repository, tag, options, rcsnode) /* commit a dead revision. */ (void) sprintf (tmp, "file %s was initially added on branch %s.", file, tag); - retcode = RCS_checkin (rcs, NULL, tmp, NULL, 0, + retcode = RCS_checkin (rcs, NULL, tmp, NULL, RCS_FLAGS_DEAD | RCS_FLAGS_QUIET); free (tmp); if (retcode != 0) { error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0, "could not create initial dead revision %s", rcs->path); - free (fname); goto out; } @@ -2133,7 +2143,7 @@ checkaddfile (file, repository, tag, options, rcsnode) rcs = RCS_parse (file, repository); if (rcs == NULL) { - error (0, 0, "could not read %s in %s", file, repository); + error (0, 0, "could not read %s", rcs->path); goto out; } *rcsnode = rcs; @@ -2141,8 +2151,7 @@ checkaddfile (file, repository, tag, options, rcsnode) /* and lock it once again. */ if (lock_RCS (file, rcs, NULL, repository)) { - error (0, 0, "cannot lock initial revision in `%s'.", - rcs->path); + error (0, 0, "cannot lock `%s'.", rcs->path); goto out; } } @@ -2155,25 +2164,12 @@ checkaddfile (file, repository, tag, options, rcsnode) char *head; char *magicrev; int retcode; - time_t headtime = -1; - char *revnum, *tmp; - FILE *fp; - time_t t = -1; - struct tm *ct; fixbranch (rcs, sbranch); head = RCS_getversion (rcs, NULL, NULL, 0, (int *) NULL); - if (!head) - error (1, 0, "No head revision in archive file `%s'.", - rcs->path); magicrev = RCS_magicrev (rcs, head); - /* If this is not a new branch, then we will want a dead - version created before this one. */ - if (!newfile) - headtime = RCS_getrevtime (rcs, head, 0, 0); - retcode = RCS_settag (rcs, tag, magicrev); RCS_rewrite (rcs, NULL, NULL); @@ -2186,76 +2182,13 @@ checkaddfile (file, repository, tag, options, rcsnode) "could not stub branch %s for %s", tag, rcs->path); goto out; } - /* We need to add a dead version here to avoid -rtag -Dtime - checkout problems between when the head version was - created and now. */ - if (!newfile && headtime != -1) - { - /* move the new file out of the way. */ - fname = xmalloc (strlen (file) + sizeof (CVSADM) - + sizeof (CVSPREFIX) + 10); - (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file); - rename_file (file, fname); - - /* Create empty FILE. Can't use copy_file with a DEVNULL - argument -- copy_file now ignores device files. */ - fp = fopen (file, "w"); - if (fp == NULL) - error (1, errno, "cannot open %s for writing", file); - if (fclose (fp) < 0) - error (0, errno, "cannot close %s", file); - - /* As we will be hacking the delta date, put the time - this was added into the log message. */ - t = time(NULL); - ct = gmtime(&t); - tmp = xmalloc (strlen (file) + strlen (tag) + 80); - - (void) sprintf (tmp, - "file %s was added on branch %s on %d-%02d-%02d %02d:%02d:%02d +0000", - file, tag, - ct->tm_year + (ct->tm_year < 100 ? 0 : 1900), - ct->tm_mon + 1, ct->tm_mday, - ct->tm_hour, ct->tm_min, ct->tm_sec); - - /* commit a dead revision. */ - revnum = RCS_whatbranch (rcs, tag); - retcode = RCS_checkin (rcs, NULL, tmp, revnum, headtime, - RCS_FLAGS_DEAD | - RCS_FLAGS_QUIET | - RCS_FLAGS_USETIME); - free (revnum); - free (tmp); - - if (retcode != 0) - { - error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0, - "could not created dead stub %s for %s", tag, - rcs->path); - goto out; - } - - /* put the new file back where it was */ - rename_file (fname, file); - free (fname); - - /* double-check that the file was written correctly */ - freercsnode (&rcs); - rcs = RCS_parse (file, repository); - if (rcs == NULL) - { - error (0, 0, "could not read %s", rcs->path); - goto out; - } - *rcsnode = rcs; - } } else { /* lock the branch. (stubbed branches need not be locked.) */ if (lock_RCS (file, rcs, NULL, repository)) { - error (0, 0, "cannot lock head revision in `%s'.", rcs->path); + error (0, 0, "cannot lock `%s'.", rcs->path); goto out; } } diff --git a/contrib/cvs/src/cvs.h b/contrib/cvs/src/cvs.h index 15fd227..c47cdcf 100644 --- a/contrib/cvs/src/cvs.h +++ b/contrib/cvs/src/cvs.h @@ -1,11 +1,6 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS kit. @@ -14,6 +9,7 @@ /* * basic information used in all source files * + * $FreeBSD$ */ @@ -199,6 +195,7 @@ extern int errno; #define CVSROOTADM_WRITERS "writers" #define CVSROOTADM_PASSWD "passwd" #define CVSROOTADM_CONFIG "config" +#define CVSROOTADM_OPTIONS "options" #define CVSNULLREPOS "Emptydir" /* an empty directory */ @@ -212,8 +209,6 @@ extern int errno; #define CVSATTIC "Attic" #define CVSLCK "#cvs.lock" -#define CVSHISTORYLCK "#cvs.history.lock" -#define CVSVALTAGSLCK "#cvs.val-tags.lock" #define CVSRFL "#cvs.rfl" #define CVSWFL "#cvs.wfl" #define CVSRFLPAT "#cvs.rfl.*" /* wildcard expr to match read locks */ @@ -270,6 +265,8 @@ extern int errno; #define CVSREAD_ENV "CVSREAD" /* make files read-only */ #define CVSREAD_DFLT 0 /* writable files by default */ +#define CVSREADONLYFS_ENV "CVSREADONLYFS" /* repository is read-only */ + #define TMPDIR_ENV "TMPDIR" /* Temporary directory */ #define EDITOR1_ENV "CVSEDITOR" /* which editor to use */ @@ -277,10 +274,7 @@ extern int errno; #define EDITOR3_ENV "EDITOR" /* which editor to use */ #define CVSROOT_ENV "CVSROOT" /* source directory root */ -/* Define CVSROOT_DFLT to a fallback value for CVSROOT. - * -#undef CVSROOT_DFL - */ +#define CVSROOT_DFLT NULL /* No dflt; must set for checkout */ #define IGNORE_ENV "CVSIGNORE" /* More files to ignore */ #define WRAPPER_ENV "CVSWRAPPERS" /* name of the wrapper file */ @@ -382,6 +376,7 @@ extern int really_quiet, quiet; extern int use_editor; extern int cvswrite; extern mode_t cvsumask; +extern char *RCS_citag; @@ -400,7 +395,9 @@ extern int safe_location PROTO ((char *)); extern int trace; /* Show all commands */ extern int noexec; /* Don't modify disk anywhere */ +extern int readonlyfs; /* fail on all write locks; succeed all read locks */ extern int logoff; /* Don't write history entry */ +extern int require_real_user; /* skip CVSROOT/passwd, /etc/passwd users only*/ extern int top_level_admin; @@ -429,18 +426,15 @@ int RCS_merge PROTO((RCSNode *, const char *, const char *, const char *, #define RCS_FLAGS_QUIET 4 #define RCS_FLAGS_MODTIME 8 #define RCS_FLAGS_KEEPFILE 16 -#define RCS_FLAGS_USETIME 32 -extern int RCS_exec_rcsdiff PROTO ((RCSNode *rcsfile, int diff_argc, - char *const *diff_argv, - const char *options, +extern int RCS_exec_rcsdiff PROTO ((RCSNode *rcsfile, + const char *opts, const char *options, const char *rev1, const char *rev1_cache, const char *rev2, const char *label1, const char *label2, const char *workfile)); extern int diff_exec PROTO ((const char *file1, const char *file2, const char *label1, const char *label2, - int diff_argc, char *const *diff_argv, - const char *out)); + const char *options, const char *out)); #include "error.h" @@ -464,6 +458,15 @@ char *Name_Repository PROTO((const char *dir, const char *update_dir)); const char *Short_Repository PROTO((const char *repository)); void Sanitize_Repository_Name PROTO((char *repository)); +char *Name_Root PROTO((char *dir, char *update_dir)); +void free_cvsroot_t PROTO((cvsroot_t *root_in)); +cvsroot_t *parse_cvsroot PROTO((const char *root)); +cvsroot_t *local_cvsroot PROTO((const char *dir)); +void Create_Root PROTO((const char *dir, const char *rootdir)); +void root_allow_add PROTO ((char *)); +void root_allow_free PROTO ((void)); +int root_allow_ok PROTO ((char *)); + char *previous_rev PROTO ((RCSNode *rcs, const char *rev)); char *gca PROTO ((const char *rev1, const char *rev2)); extern void check_numeric PROTO ((const char *, int, char **)); @@ -502,6 +505,7 @@ char *get_homedir PROTO ((void)); char *strcat_filename_onto_homedir PROTO ((const char *, const char *)); char *cvs_temp_name PROTO ((void)); FILE *cvs_temp_file PROTO ((char **filename)); +void parseopts PROTO ((const char *root)); int numdots PROTO((const char *s)); char *increment_revnum PROTO ((const char *)); @@ -572,14 +576,6 @@ void lock_tree_for_write PROTO ((int argc, char **argv, int local, int which, /* See lock.c for description. */ extern void lock_dir_for_write PROTO ((char *)); -/* Get a write lock for the history file. */ -int history_lock PROTO ((const char *)); -void clear_history_lock PROTO ((void)); - -/* Get a write lock for the val-tags file. */ -int val_tags_lock PROTO ((const char *)); -void clear_val_tags_lock PROTO ((void)); - /* LockDir setting from CVSROOT/config. */ extern char *lock_dir; @@ -588,6 +584,7 @@ void ParseTag PROTO((char **tagp, char **datep, int *nonbranchp)); void WriteTag PROTO ((const char *dir, const char *tag, const char *date, int nonbranch, const char *update_dir, const char *repository)); +void WriteTemplate PROTO ((const char *dir, const char *update_dir)); void cat_module PROTO((int status)); void check_entries PROTO((char *dir)); void close_module PROTO((DBM * db)); @@ -679,6 +676,8 @@ int SIG_inCrSect PROTO((void)); void read_cvsrc PROTO((int *argc, char ***argv, const char *cmdname)); char *make_message_rcslegal PROTO((const char *message)); +extern int file_has_conflict PROTO ((const struct file_info *, + const char *ts_conflict)); extern int file_has_markers PROTO ((const struct file_info *)); extern void get_file PROTO ((const char *, const char *, const char *, char **, size_t *, size_t *)); @@ -696,8 +695,6 @@ void sleep_past PROTO ((time_t desttime)); #define RUN_SIGIGNORE 0x0010 /* ignore interrupts for command */ #define RUN_TTY (char *)0 /* for the benefit of lint */ -void run_add_arg_p PROTO ((int *, size_t *, char ***, const char *s)); -void run_arg_free_p PROTO ((int, char **)); void run_arg PROTO((const char *s)); void run_print PROTO((FILE * fp)); void run_setup PROTO ((const char *prog)); @@ -706,7 +703,7 @@ int run_exec PROTO((const char *stin, const char *stout, const char *sterr, /* other similar-minded stuff from run.c. */ FILE *run_popen PROTO((const char *, const char *)); -int piped_child PROTO((const char **, int *, int *, int)); +int piped_child PROTO((const char **, int *, int *)); void close_on_exec PROTO((int)); pid_t waitpid PROTO((pid_t, int *, int)); diff --git a/contrib/cvs/src/cvsbug.in b/contrib/cvs/src/cvsbug.in index efc156d..07de151 100755 --- a/contrib/cvs/src/cvsbug.in +++ b/contrib/cvs/src/cvsbug.in @@ -109,14 +109,12 @@ elif [ -f /bin/domainname ]; then /usr/bin/ypcat passwd 2>/dev/null | cat - /etc/passwd | grep "^$LOGNAME:" | cut -f5 -d':' | sed -e 's/,.*//' > $TEMP ORIGINATOR="`cat $TEMP`" - rm -f $TEMP fi fi if [ "$ORIGINATOR" = "" ]; then grep "^$LOGNAME:" /etc/passwd | cut -f5 -d':' | sed -e 's/,.*//' > $TEMP ORIGINATOR="`cat $TEMP`" - rm -f $TEMP fi if [ -n "$ORGANIZATION" ]; then diff --git a/contrib/cvs/src/diff.c b/contrib/cvs/src/diff.c index a5ca2d0..7faaae8 100644 --- a/contrib/cvs/src/diff.c +++ b/contrib/cvs/src/diff.c @@ -1,11 +1,6 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. @@ -17,6 +12,8 @@ * * Without any file arguments, runs diff against all the currently modified * files. + * + * $FreeBSD$ */ #include <assert.h> @@ -57,6 +54,7 @@ static void diff_mark_errors PROTO((int err)); static char *diff_rev1, *diff_rev2; /* Command line dates, from -D option. Malloc'd. */ static char *diff_date1, *diff_date2; +static char *diff_join1, *diff_join2; static char *use_rev1, *use_rev2; static int have_rev1_label, have_rev2_label; @@ -65,9 +63,8 @@ static int have_rev1_label, have_rev2_label; static char *user_file_rev; static char *options; -static char **diff_argv; -static int diff_argc; -static size_t diff_arg_allocated; +static char *opts; +static size_t opts_allocated = 1; static int diff_errors; static int empty_files = 0; @@ -212,54 +209,6 @@ static struct option const longopts[] = {0, 0, 0, 0} }; - - -/* Add one of OPT or LONGOPT, and ARGUMENT, when present, to global DIFF_ARGV. - * - * INPUTS - * opt A character option representation. - * longopt A long option name. - * argument Optional option argument. - * - * GLOBALS - * diff_argc The number of arguments in DIFF_ARGV. - * diff_argv Array of argument strings. - * diff_arg_allocated Allocated length of DIFF_ARGV. - * - * NOTES - * Behavior when both OPT & LONGOPT are provided is undefined. - * - * RETURNS - * Nothing. - */ -static void -add_diff_args (char opt, const char *longopt, const char *argument) -{ - char *tmp; - - /* Add opt or longopt to diff_arv. */ - assert (opt || (longopt && *longopt)); - assert (!(opt && (longopt && *longopt))); - if (opt) - { - tmp = xmalloc (3); - sprintf (tmp, "-%c", opt); - } - else - { - tmp = xmalloc (3 + strlen (longopt)); - sprintf (tmp, "--%s", longopt); - } - run_add_arg_p (&diff_argc, &diff_arg_allocated, &diff_argv, tmp); - free (tmp); - - /* When present, add ARGUMENT to DIFF_ARGV. */ - if (argument) - run_add_arg_p (&diff_argc, &diff_arg_allocated, &diff_argv, argument); -} - - - /* CVS 1.9 and similar versions seemed to have pretty weird handling of -y and -T. In the cases where it called rcsdiff, they would have the meanings mentioned below. In the cases where it @@ -296,6 +245,7 @@ diff (argc, argv) int argc; char **argv; { + char tmp[50]; int c, err = 0; int local = 0; int which; @@ -315,15 +265,18 @@ diff (argc, argv) /* Clean out our global variables (multiroot can call us multiple times and the server can too, if the client sends several diff commands). */ - if (diff_argc) + if (opts == NULL) { - run_arg_free_p (diff_argc, diff_argv); - diff_argc = 0; + opts_allocated = 1; + opts = xmalloc (opts_allocated); } + opts[0] = '\0'; diff_rev1 = NULL; diff_rev2 = NULL; diff_date1 = NULL; diff_date2 = NULL; + diff_join1 = NULL; + diff_join2 = NULL; optind = 0; /* FIXME: This should really be allocating an argv to be passed to diff @@ -334,13 +287,13 @@ diff (argc, argv) * to diff. */ while ((c = getopt_long (argc, argv, - "+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:W:k:r:", + "+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:W:k:r:j:", longopts, &option_index)) != -1) { switch (c) { case 'y': - add_diff_args (0, "side-by-side", NULL); + xrealloc_and_strcat (&opts, &opts_allocated, " --side-by-side"); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'h': case 'i': case 'n': case 'p': case 's': case 't': @@ -348,7 +301,8 @@ diff (argc, argv) case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'B': case 'H': case 'T': - add_diff_args (c, NULL, NULL); + (void) sprintf (tmp, " -%c", (char) c); + xrealloc_and_strcat (&opts, &opts_allocated, tmp); break; case 'L': if (have_rev1_label++) @@ -357,15 +311,33 @@ diff (argc, argv) error (0, 0, "extra -L arguments ignored"); break; } - /* Fall through. */ + + xrealloc_and_strcat (&opts, &opts_allocated, " -L"); + xrealloc_and_strcat (&opts, &opts_allocated, optarg); + break; case 'C': case 'F': case 'I': case 'U': case 'W': - add_diff_args (c, NULL, optarg); + (void) sprintf (tmp, " -%c", (char) c); + xrealloc_and_strcat (&opts, &opts_allocated, tmp); + xrealloc_and_strcat (&opts, &opts_allocated, optarg); + break; + case 131: + /* --ifdef. */ + xrealloc_and_strcat (&opts, &opts_allocated, " --ifdef="); + xrealloc_and_strcat (&opts, &opts_allocated, optarg); break; - case 129: case 130: case 131: case 132: case 133: case 134: + case 129: case 130: case 132: case 133: case 134: case 135: case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: case 145: case 146: - add_diff_args (0, longopts[option_index].name, - longopts[option_index].has_arg ? optarg : NULL); + xrealloc_and_strcat (&opts, &opts_allocated, " --"); + xrealloc_and_strcat (&opts, &opts_allocated, + longopts[option_index].name); + if (longopts[option_index].has_arg == 1 + || (longopts[option_index].has_arg == 2 + && optarg != NULL)) + { + xrealloc_and_strcat (&opts, &opts_allocated, "="); + xrealloc_and_strcat (&opts, &opts_allocated, optarg); + } break; case 'R': local = 0; @@ -378,6 +350,27 @@ diff (argc, argv) free (options); options = RCS_check_kflag (optarg); break; + case 'j': + { + char *ptr; + char *cpy = strdup(optarg); + + if ((ptr = strchr(optarg, ':')) != NULL) + *ptr++ = 0; + if (diff_rev2 != NULL || diff_date2 != NULL) + error (1, 0, + "no more than two revisions/dates can be specified"); + if (diff_rev1 != NULL || diff_date1 != NULL) { + diff_join2 = cpy; + diff_rev2 = optarg; + diff_date2 = ptr ? Make_Date(ptr) : NULL; + } else { + diff_join1 = cpy; + diff_rev1 = optarg; + diff_date1 = ptr ? Make_Date(ptr) : NULL; + } + } + break; case 'r': if (diff_rev2 != NULL || diff_date2 != NULL) error (1, 0, @@ -423,16 +416,21 @@ diff (argc, argv) send_arg("-l"); if (empty_files) send_arg("-N"); - send_options (diff_argc, diff_argv); + send_option_string (opts); if (options[0] != '\0') send_arg (options); - if (diff_rev1) + if (diff_join1) + option_with_arg ("-j", diff_join1); + else if (diff_rev1) option_with_arg ("-r", diff_rev1); - if (diff_date1) + else if (diff_date1) client_senddate (diff_date1); - if (diff_rev2) + + if (diff_join2) + option_with_arg ("-j", diff_join2); + else if (diff_rev2) option_with_arg ("-r", diff_rev2); - if (diff_date2) + else if (diff_date2) client_senddate (diff_date2); send_arg ("--"); @@ -446,28 +444,26 @@ diff (argc, argv) send_to_server ("diff\012", 0); err = get_responses_and_close (); - free (options); - options = NULL; - return (err); - } + } else #endif - - if (diff_rev1 != NULL) - tag_check_valid (diff_rev1, argc, argv, local, 0, ""); - if (diff_rev2 != NULL) - tag_check_valid (diff_rev2, argc, argv, local, 0, ""); - - which = W_LOCAL; - if (diff_rev1 != NULL || diff_date1 != NULL) - which |= W_REPOS | W_ATTIC; - - wrap_setup (); - - /* start the recursion processor */ - err = start_recursion (diff_fileproc, diff_filesdoneproc, diff_dirproc, - diff_dirleaveproc, NULL, argc, argv, local, - which, 0, CVS_LOCK_READ, (char *) NULL, 1, - (char *) NULL); + { + if (diff_rev1 != NULL) + tag_check_valid (diff_rev1, argc, argv, local, 0, ""); + if (diff_rev2 != NULL) + tag_check_valid (diff_rev2, argc, argv, local, 0, ""); + + which = W_LOCAL; + if (diff_rev1 != NULL || diff_date1 != NULL) + which |= W_REPOS | W_ATTIC; + + wrap_setup (); + + /* start the recursion processor */ + err = start_recursion (diff_fileproc, diff_filesdoneproc, diff_dirproc, + diff_dirleaveproc, NULL, argc, argv, local, + which, 0, CVS_LOCK_READ, (char *) NULL, 1, + (char *) NULL); + } /* clean up */ free (options); @@ -477,6 +473,10 @@ diff (argc, argv) free (diff_date1); if (diff_date2 != NULL) free (diff_date2); + if (diff_join1 != NULL) + free (diff_join1); + if (diff_join2 != NULL) + free (diff_join2); return (err); } @@ -522,7 +522,7 @@ diff_fileproc (callerdat, finfo) int exists; exists = 0; - /* special handling for TAG_HEAD */ + /* special handling for TAG_HEAD XXX */ if (diff_rev1 && strcmp (diff_rev1, TAG_HEAD) == 0) { char *head = @@ -733,8 +733,8 @@ RCS file: ", 0); if (empty_file == DIFF_ADDED) { if (use_rev2 == NULL) - status = diff_exec (DEVNULL, finfo->file, label1, label2, - diff_argc, diff_argv, RUN_TTY); + status = diff_exec (DEVNULL, finfo->file, label1, label2, opts, + RUN_TTY); else { int retcode; @@ -750,8 +750,7 @@ RCS file: ", 0); if( retcode != 0 ) goto out; - status = diff_exec (DEVNULL, tmp, label1, label2, - diff_argc, diff_argv, RUN_TTY); + status = diff_exec (DEVNULL, tmp, label1, label2, opts, RUN_TTY); } } else @@ -767,16 +766,16 @@ RCS file: ", 0); if (retcode != 0) goto out; - status = diff_exec (tmp, DEVNULL, label1, label2, - diff_argc, diff_argv, RUN_TTY); + status = diff_exec (tmp, DEVNULL, label1, label2, opts, RUN_TTY); } } else { - status = RCS_exec_rcsdiff (vers->srcfile, diff_argc, diff_argv, - *options ? options : vers->options, - use_rev1, rev1_cache, use_rev2, - label1, label2, finfo->file); + status = RCS_exec_rcsdiff(vers->srcfile, opts, + *options ? options : vers->options, + use_rev1, rev1_cache, use_rev2, + label1, label2, + finfo->file); } @@ -920,7 +919,7 @@ diff_file_nodiff( finfo, vers, empty_file, rev1_cache ) if (diff_rev1 || diff_date1) { - /* special handling for TAG_HEAD */ + /* special handling for TAG_HEAD XXX */ if (diff_rev1 && strcmp (diff_rev1, TAG_HEAD) == 0) { if (vers->vn_rcs != NULL && vers->srcfile != NULL) @@ -936,7 +935,7 @@ diff_file_nodiff( finfo, vers, empty_file, rev1_cache ) } if (diff_rev2 || diff_date2) { - /* special handling for TAG_HEAD */ + /* special handling for TAG_HEAD XXX */ if (diff_rev2 && strcmp (diff_rev2, TAG_HEAD) == 0) { if (vers->vn_rcs != NULL && vers->srcfile != NULL) diff --git a/contrib/cvs/src/entries.c b/contrib/cvs/src/entries.c index c346fb6..1ab7c7e 100644 --- a/contrib/cvs/src/entries.c +++ b/contrib/cvs/src/entries.c @@ -1,11 +1,6 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. @@ -16,6 +11,9 @@ * the Entries file. */ +/* + * $FreeBSD$ + */ #include "cvs.h" #include "getline.h" @@ -542,7 +540,6 @@ Entries_Open (aflag, update_dir) break; default: /* Ignore unrecognized commands. */ - Entnode_Destroy (ent); break; } } @@ -641,6 +638,72 @@ AddEntryNode (list, entdata) return (p); } +static char *root_template; + +static int +get_root_template(const char *repository, const char *path) +{ + if (root_template) { + if (strcmp(path, root_template) == 0) + return(0); + free(root_template); + } + if ((root_template = strdup(path)) == NULL) + return(-1); + return(0); +} + +/* + * Write out/Clear the CVS/Template file. + */ +void +WriteTemplate (dir, update_dir) + const char *dir; + const char *update_dir; +{ + char *tmp = NULL; + struct stat st1; + struct stat st2; + + if (Parse_Info(CVSROOTADM_RCSINFO, "cvs", get_root_template, 1) < 0) + return; + + if (asprintf(&tmp, "%s/%s", dir, CVSADM_TEMPLATE) < 0) + error (1, errno, "out of memory"); + + if (stat(root_template, &st1) == 0) { + if (stat(tmp, &st2) < 0 || st1.st_mtime != st2.st_mtime) { + FILE *fi; + FILE *fo; + + if ((fi = open_file(root_template, "r")) != NULL) { + if ((fo = open_file(tmp, "w")) != NULL) { + int n; + char buf[256]; + + while ((n = fread(buf, 1, sizeof(buf), fi)) > 0) + fwrite(buf, 1, n, fo); + fflush(fo); + if (ferror(fi) || ferror(fo)) { + fclose(fo); + remove(tmp); + error (1, errno, "error copying Template"); + } else { + struct timeval times[2]; + fclose(fo); + times[0].tv_sec = st1.st_mtime; + times[0].tv_usec = 0; + times[1] = times[0]; + utimes(tmp, times); + } + } + fclose(fi); + } + } + } + free(tmp); +} + /* * Write out/Clear the CVS/Tag file. */ diff --git a/contrib/cvs/src/filesubr.c b/contrib/cvs/src/filesubr.c index 14da6292..9353888 100644 --- a/contrib/cvs/src/filesubr.c +++ b/contrib/cvs/src/filesubr.c @@ -17,11 +17,13 @@ definitions under operating systems (like, say, Windows NT) with different file system semantics. */ +/* + * $FreeBSD$ + */ + #include <assert.h> #include "cvs.h" -#include "xsize.h" - static int deep_remove_dir PROTO((const char *path)); /* @@ -107,7 +109,7 @@ copy_file (from, to) error (1, errno, "cannot close %s", to); } - /* preserve last access & modification times */ + /* now, set the times for the copied file to match those of the original */ memset ((char *) &t, 0, sizeof (t)); t.actime = sb.st_atime; t.modtime = sb.st_mtime; @@ -435,10 +437,14 @@ unlink_file_dir (f) { struct stat sb; - /* This is called by the server parent process in contexts where - it is not OK to send output (e.g. after we sent "ok" to the - client). */ - if (trace && !server_active) + if (trace +#ifdef SERVER_SUPPORT + /* This is called by the server parent process in contexts where + it is not OK to send output (e.g. after we sent "ok" to the + client). */ + && !server_active +#endif + ) (void) fprintf (stderr, "-> unlink_file_dir(%s)\n", f); if (noexec) @@ -702,8 +708,7 @@ cvs_temp_name () fp = cvs_temp_file (&fn); if (fp == NULL) - error (1, errno, "Failed to create temporary file %s", - fn ? fn : "(null)"); + error (1, errno, "Failed to create temporary file"); if (fclose (fp) == EOF) error (0, errno, "Failed to close temporary file %s", fn); return fn; @@ -740,8 +745,7 @@ cvs_temp_name () * NFS locking thing, but until I hear of more problems, I'm not going to * bother. */ -FILE * -cvs_temp_file (filename) +FILE *cvs_temp_file (filename) char **filename; { char *fn; @@ -780,11 +784,7 @@ cvs_temp_file (filename) errno = save_errno; } - if (fp == NULL) - { - free (fn); - fn = NULL; - } + if (fp == NULL) free (fn); /* mkstemp is defined to open mode 0600 using glibc 2.0.7+ */ /* FIXME - configure can probably tell us which version of glibc we are * linking to and not chmod for 2.0.7+ @@ -799,11 +799,7 @@ cvs_temp_file (filename) fn = tempnam (Tmpdir, "cvs"); if (fn == NULL) fp = NULL; - else if ((fp = CVS_FOPEN (fn, "w+")) == NULL) - { - free (fn); - fn = NULL; - } + else if ((fp = CVS_FOPEN (fn, "w+")) == NULL) free (fn); else chmod (fn, 0600); /* tempnam returns a pointer to a newly malloc'd string, so there's @@ -853,11 +849,6 @@ cvs_temp_file (filename) #endif *filename = fn; - if (fn == NULL && fp != NULL) - { - fclose (fp); - fp = NULL; - } return fp; } @@ -880,48 +871,32 @@ cvs_temp_file (filename) * This function exits with a fatal error if it fails to read the link for * any reason. */ -#define MAXSIZE (SIZE_MAX < SSIZE_MAX ? SIZE_MAX : SSIZE_MAX) - char * xreadlink (link) const char *link; { char *file = NULL; - size_t buflen = 128; + int buflen = BUFSIZ; + int link_name_len; - /* Get the name of the file to which `from' is linked. */ - while (1) + /* Get the name of the file to which `from' is linked. + FIXME: what portability issues arise here? Are readlink & + ENAMETOOLONG defined on all systems? -twp */ + do { - ssize_t r; - size_t link_name_len; - file = xrealloc (file, buflen); - r = readlink (link, file, buflen); - link_name_len = r; + errno = 0; + link_name_len = readlink (link, file, buflen - 1); + buflen *= 2; + } + while (link_name_len < 0 && errno == ENAMETOOLONG); - if (r < 0 -#ifdef ERANGE - /* AIX 4 and HP-UX report ERANGE if the buffer is too small. */ - && errno != ERANGE -#endif - ) - error (1, errno, "cannot readlink %s", link); + if (link_name_len < 0) + error (1, errno, "cannot readlink %s", link); - /* If there is space for the NUL byte, set it and return. */ - if (r >= 0 && link_name_len < buflen) - { - file[link_name_len] = '\0'; - return file; - } + file[link_name_len] = '\0'; - if (buflen <= MAXSIZE / 2) - buflen *= 2; - else if (buflen < MAXSIZE) - buflen = MAXSIZE; - else - /* Our buffer cannot grow any bigger. */ - error (1, ENAMETOOLONG, "cannot readlink %s", link); - } + return file; } #endif /* HAVE_READLINK */ @@ -974,8 +949,7 @@ last_component (path) const char *path; { const char *last = strrchr (path, '/'); - - assert (path); + if (last && (last != path)) return last + 1; else @@ -1015,7 +989,11 @@ get_homedir () if (home != NULL) return home; - if (!server_active && (env = getenv ("HOME")) != NULL) + if ( +#ifdef SERVER_SUPPORT + !server_active && +#endif + (env = getenv ("HOME")) != NULL) home = env; else if ((pw = (struct passwd *) getpwuid (getuid ())) && pw->pw_dir) @@ -1056,7 +1034,6 @@ expand_wild (argc, argv, pargc, pargv) char ***pargv; { int i; - assert (argv || !argc); if (size_overflow_p (xtimes (argc, sizeof (char *)))) { *pargc = 0; *pargv = NULL; diff --git a/contrib/cvs/src/import.c b/contrib/cvs/src/import.c index ea65677..b962ebc 100644 --- a/contrib/cvs/src/import.c +++ b/contrib/cvs/src/import.c @@ -1,11 +1,6 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. @@ -19,6 +14,8 @@ * VendorReleTag Tag for this particular release * * Additional arguments specify more Vendor Release Tags. + * + * $FreeBSD$ */ #include "cvs.h" @@ -89,14 +86,17 @@ import (argc, argv) { case 'Q': case 'q': +#ifdef SERVER_SUPPORT /* The CVS 1.5 client sends these options (in addition to Global_option requests), so we must ignore them. */ if (!server_active) +#endif error (1, 0, "-q or -Q must be specified before \"%s\"", cvs_cmd_name); break; case 'd': +#ifdef SERVER_SUPPORT if (server_active) { /* CVS 1.10 and older clients will send this, but it @@ -106,6 +106,7 @@ import (argc, argv) "warning: not setting the time of import from the file"); error (0, 0, "due to client limitations"); } +#endif use_file_modtime = 1; break; case 'b': @@ -118,7 +119,6 @@ import (argc, argv) #else use_editor = 0; #endif - if (message) free (message); message = xstrdup(optarg); break; case 'I': @@ -145,6 +145,7 @@ import (argc, argv) if (argc < 3) usage (import_usage); +#ifdef SERVER_SUPPORT /* This is for handling the Checkin-time request. It might seem a bit odd to enable the use_file_modtime code even in the case where Checkin-time was not sent for a particular file. The @@ -156,6 +157,7 @@ import (argc, argv) if (server_active) use_file_modtime = 1; +#endif /* Don't allow "CVS" as any directory in module path. * @@ -212,22 +214,11 @@ import (argc, argv) * support branching to a single level, so the specified vendor branch * must only have two dots in it (like "1.1.1"). */ - { - regex_t pat; - int ret = regcomp (&pat, "^[1-9][0-9]*\\.[1-9][0-9]*\\.[1-9][0-9]*$", - REG_EXTENDED); - assert (!ret); - if (regexec (&pat, vbranch, 0, NULL, 0)) - { - error (1, 0, -"Only numeric branch specifications with two dots are\n" -"supported by import, not `%s'. For example: `1.1.1'.", - vbranch); - } - regfree (&pat); - } - - /* Set vhead to the branch's parent. */ + for (cp = vbranch; *cp != '\0'; cp++) + if (!isdigit ((unsigned char) *cp) && *cp != '.') + error (1, 0, "%s is not a numeric branch", vbranch); + if (numdots (vbranch) != 2) + error (1, 0, "Only branches with two dots are supported: %s", vbranch); vhead = xstrdup (vbranch); cp = strrchr (vhead, '.'); *cp = '\0'; @@ -241,10 +232,17 @@ import (argc, argv) } #endif - if (!server_active && use_editor) + if ( +#ifdef SERVER_SUPPORT + !server_active && +#endif + use_editor) { do_editor ((char *) NULL, &message, - current_parsed_root->isremote ? (char *) NULL : repository, +#ifdef CLIENT_SUPPORT + current_parsed_root->isremote ? (char *) NULL : +#endif + repository, (List *) NULL); } do_verify (&message, repository); @@ -317,8 +315,7 @@ import (argc, argv) /* Create the logfile that will be logged upon completion */ if ((logfp = cvs_temp_file (&tmpfile)) == NULL) - error (1, errno, "cannot create temporary file `%s'", - tmpfile ? tmpfile : "(null)"); + error (1, errno, "cannot create temporary file `%s'", tmpfile); /* On systems where we can unlink an open file, do so, so it will go away no matter how we exit. FIXME-maybe: Should be checking for errors but I'm not sure which error(s) we get if we are on a system @@ -439,9 +436,6 @@ import_descend (message, vtag, targc, targv) ign_add_file (CVSDOTIGNORE, 1); wrap_add_file (CVSDOTWRAPPER, 1); - if (!current_parsed_root->isremote) - lock_dir_for_write (repository); - if ((dirp = CVS_OPENDIR (".")) == NULL) { error (0, errno, "cannot open directory"); @@ -454,13 +448,13 @@ import_descend (message, vtag, targc, targv) { if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0) goto one_more_time_boys; - +#ifdef SERVER_SUPPORT /* CVS directories are created in the temp directory by server.c because it doesn't special-case import. So don't print a message about them, regardless of -I!. */ if (server_active && strcmp (dp->d_name, CVSADM) == 0) goto one_more_time_boys; - +#endif if (ign_name (dp->d_name)) { add_log ('I', dp->d_name); @@ -524,9 +518,6 @@ import_descend (message, vtag, targc, targv) (void) CVS_CLOSEDIR (dirp); } - if (!current_parsed_root->isremote) - Lock_Cleanup (); - if (dirlist != NULL) { Node *head, *p; @@ -759,7 +750,7 @@ add_rev (message, rcs, vfile, vers) tocvsPath = wrap_tocvs_process_file (vfile); status = RCS_checkin (rcs, tocvsPath == NULL ? vfile : tocvsPath, - message, vbranch, 0, + message, vbranch, (RCS_FLAGS_QUIET | RCS_FLAGS_KEEPFILE | (use_file_modtime ? RCS_FLAGS_MODTIME : 0))); ierrno = errno; @@ -1595,7 +1586,11 @@ import_descend_dir (message, dir, vtag, targc, targv) repository = new; } +#ifdef CLIENT_SUPPORT if (!quiet && !current_parsed_root->isremote) +#else + if (!quiet) +#endif error (0, 0, "Importing %s", repository); if ( CVS_CHDIR (dir) < 0) @@ -1606,7 +1601,11 @@ import_descend_dir (message, dir, vtag, targc, targv) err = 1; goto out; } +#ifdef CLIENT_SUPPORT if (!current_parsed_root->isremote && !isdir (repository)) +#else + if (!isdir (repository)) +#endif { rcs = xmalloc (strlen (repository) + sizeof (RCSEXT) + 5); (void) sprintf (rcs, "%s%s", repository, RCSEXT); diff --git a/contrib/cvs/src/lock.c b/contrib/cvs/src/lock.c index 7a5e338..36cbf7d 100644 --- a/contrib/cvs/src/lock.c +++ b/contrib/cvs/src/lock.c @@ -1,11 +1,6 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. @@ -13,6 +8,8 @@ * Set Lock * * Lock file support for CVS. + * + * $FreeBSD$ */ /* The node Concurrency in doc/cvs.texinfo has a brief introduction to @@ -90,17 +87,8 @@ struct lock { case of writelocks, it is just a pointer to the storage allocated for the ->key field. */ char *repository; - - /* The name of the master lock dir. Usually CVSLCK. */ - const char *lockdirname; - - /* The full path to the lock dir, if we are currently holding it. - * - * This will be LOCKDIRNAME catted onto REPOSITORY. We waste a little - * space by storing it, but save a later malloc/free. - */ - char *lockdir; - + /* Do we have a lock named CVSLCK? */ + int have_lckdir; /* Note there is no way of knowing whether the readlock and writelock exist. The code which sets the locks doesn't use SIG_beginCrSect to set a flag like we do for CVSLCK. */ @@ -129,6 +117,7 @@ static char *readlock; static char *writelock; /* Malloc'd array specifying the name of a CVSLCK file (absolute pathname). Will always be non-NULL in the cases where it is used. */ +static char *masterlock; static List *locklist; #define L_OK 0 /* success */ @@ -137,10 +126,7 @@ static List *locklist; /* This is the (single) readlock which is set by Reader_Lock. The repository field is NULL if there is no such lock. */ -static struct lock global_readlock = {NULL, CVSLCK, NULL}; - -static struct lock global_history_lock = {NULL, CVSHISTORYLCK, NULL}; -static struct lock global_val_tags_lock = {NULL, CVSVALTAGSLCK, NULL}; +static struct lock global_readlock; /* List of locks set by lock_tree_for_write. This is redundant with locklist, sort of. */ @@ -156,7 +142,7 @@ static List *locked_list; /* LockDir from CVSROOT/config. */ char *lock_dir; -static char *lock_name PROTO ((const char *repository, const char *name)); +static char *lock_name PROTO ((char *repository, char *name)); /* Return a newly malloc'd string containing the name of the lock for the repository REPOSITORY and the lock file name within that directory @@ -166,13 +152,13 @@ static char *lock_name PROTO ((const char *repository, const char *name)); things simple). */ static char * lock_name (repository, name) - const char *repository; - const char *name; + char *repository; + char *name; { char *retval; - const char *p; + char *p; char *q; - const char *short_repos; + char *short_repos; mode_t save_umask; int saved_umask = 0; @@ -327,10 +313,6 @@ Lock_Cleanup () locked_dir = NULL; locked_list = NULL; } - - if (global_history_lock.repository) clear_history_lock (); - if (global_val_tags_lock.repository) clear_val_tags_lock (); - in_lock_cleanup = 0; } @@ -367,8 +349,6 @@ unlock_proc (p, closure) return (0); } - - /* Remove the lock files. */ static void lock_simple_remove (lock) @@ -383,7 +363,7 @@ lock_simple_remove (lock) if (readlock != NULL) { tmp = lock_name (lock->repository, readlock); - if (CVS_UNLINK (tmp) < 0 && ! existence_error (errno)) + if ( CVS_UNLINK (tmp) < 0 && ! existence_error (errno)) error (0, errno, "failed to remove lock %s", tmp); free (tmp); } @@ -395,12 +375,21 @@ lock_simple_remove (lock) if (writelock != NULL) { tmp = lock_name (lock->repository, writelock); - if (CVS_UNLINK (tmp) < 0 && ! existence_error (errno)) + if ( CVS_UNLINK (tmp) < 0 && ! existence_error (errno)) error (0, errno, "failed to remove lock %s", tmp); free (tmp); } - clear_lock (lock); + if (lock->have_lckdir) + { + tmp = lock_name (lock->repository, CVSLCK); + SIG_beginCrSect (); + if (CVS_RMDIR (tmp) < 0) + error (0, errno, "failed to remove lock dir %s", tmp); + lock->have_lckdir = 0; + SIG_endCrSect (); + free (tmp); + } } @@ -420,7 +409,7 @@ Reader_Lock (xrepository) (void) fprintf (stderr, "%s-> Reader_Lock(%s)\n", CLIENT_SERVER_STR, xrepository); - if (noexec) + if (noexec || readonlyfs) return 0; /* we only do one directory at a time for read locks! */ @@ -497,6 +486,11 @@ Writer_Lock (list) if (noexec) return 0; + if (readonlyfs) { + error (0, 0, "write lock failed - read-only repository"); + return (1); + } + /* We only know how to do one list at a time */ if (locklist != (List *) NULL) { @@ -668,9 +662,6 @@ readers_exist (repository) #endif lockdir = lock_name (repository, ""); - - assert (lockdir != NULL); - lockdir[strlen (lockdir) - 1] = '\0'; /* remove trailing slash */ do { @@ -777,13 +768,13 @@ set_lock (lock, will_wait) long us; struct stat sb; mode_t omask; - char *masterlock; - int status; #ifdef CVS_FUDGELOCKS time_t now; #endif - masterlock = lock_name (lock->repository, lock->lockdirname); + if (masterlock != NULL) + free (masterlock); + masterlock = lock_name (lock->repository, CVSLCK); /* * Note that it is up to the callers of set_lock() to arrange for signal @@ -792,33 +783,33 @@ set_lock (lock, will_wait) */ waited = 0; us = 1; + lock->have_lckdir = 0; for (;;) { - status = -1; + int status = -1; omask = umask (cvsumask); SIG_beginCrSect (); if (CVS_MKDIR (masterlock, 0777) == 0) { - lock->lockdir = masterlock; + lock->have_lckdir = 1; SIG_endCrSect (); status = L_OK; if (waited) lock_obtained (lock->repository); - goto after_sig_unblock; + goto out; } SIG_endCrSect (); - after_sig_unblock: + out: (void) umask (omask); if (status != -1) - goto done; + return status; if (errno != EEXIST) { error (0, errno, "failed to create lock directory for `%s' (%s)", lock->repository, masterlock); - status = L_ERROR; - goto done; + return (L_ERROR); } /* Find out who owns the lock. If the lock directory is @@ -830,8 +821,7 @@ set_lock (lock, will_wait) continue; error (0, errno, "couldn't stat lock directory `%s'", masterlock); - status = L_ERROR; - goto done; + return (L_ERROR); } #ifdef CVS_FUDGELOCKS @@ -853,10 +843,7 @@ set_lock (lock, will_wait) /* if he wasn't willing to wait, return an error */ if (!will_wait) - { - status = L_LOCKED; - goto done; - } + return (L_LOCKED); /* if possible, try a very short sleep without a message */ if (!waited && us < 1000) @@ -887,45 +874,23 @@ set_lock (lock, will_wait) lock_wait (lock->repository); waited = 1; } -done: - if (!lock->lockdir) free (masterlock); - return status; } - - /* - * Clear master lock. - * - * INPUTS - * lock The lock information. - * - * OUTPUTS - * Sets LOCK->lockdir to NULL after removing the directory it names and - * freeing the storage. - * - * ASSUMPTIONS - * If we own the master lock directory, its name is stored in LOCK->lockdir. - * We may free LOCK->lockdir. - * + * Clear master lock. We don't have to recompute the lock name since + * clear_lock is never called except after a successful set_lock(). */ static void clear_lock (lock) struct lock *lock; { SIG_beginCrSect (); - if (lock->lockdir) - { - if (CVS_RMDIR (lock->lockdir) < 0) - error (0, errno, "failed to remove lock dir `%s'", lock->lockdir); - free (lock->lockdir); - lock->lockdir = NULL; - } + if (CVS_RMDIR (masterlock) < 0) + error (0, errno, "failed to remove lock dir `%s'", masterlock); + lock->have_lckdir = 0; SIG_endCrSect (); } - - /* * Print out a message that the lock is still held, then sleep a while. */ @@ -1000,8 +965,7 @@ lock_filesdoneproc (callerdat, err, repository, update_dir, entries) p->key = xstrdup (repository); p->data = xmalloc (sizeof (struct lock)); ((struct lock *)p->data)->repository = p->key; - ((struct lock *)p->data)->lockdirname = CVSLCK; - ((struct lock *)p->data)->lockdir = NULL; + ((struct lock *)p->data)->have_lckdir = 0; /* FIXME-KRP: this error condition should not simply be passed by. */ if (p->key == NULL || addnode (lock_tree_list, p) != 0) @@ -1054,106 +1018,9 @@ lock_dir_for_write (repository) node->key = xstrdup (repository); node->data = xmalloc (sizeof (struct lock)); ((struct lock *)node->data)->repository = node->key; - ((struct lock *)node->data)->lockdirname = CVSLCK; - ((struct lock *)node->data)->lockdir = NULL; + ((struct lock *)node->data)->have_lckdir = 0; (void) addnode (locked_list, node); Writer_Lock (locked_list); } } - - - -/* This is the internal implementation behind history_lock & val_tags_lock. It - * gets a write lock for the history or val-tags file. - * - * RETURNS - * true, on success - * false, on error - */ -static int internal_lock PROTO ((struct lock *lock, const char *xrepository)); -static int -internal_lock (lock, xrepository) - struct lock *lock; - const char *xrepository; -{ - /* remember what we're locking (for Lock_Cleanup) */ - assert (!lock->repository); - lock->repository = xmalloc (strlen (xrepository) + sizeof (CVSROOTADM) + 2); - sprintf (lock->repository, "%s/%s", xrepository, CVSROOTADM); - - /* get the lock dir for our own */ - if (set_lock (lock, 1) != L_OK) - { - if (!really_quiet) - error (0, 0, "failed to obtain history lock in repository `%s'", - xrepository); - - return 0; - } - - return 1; -} - - - -/* This is the internal implementation behind history_lock & val_tags_lock. It - * removes the write lock for the history or val-tags file, when it exists. - */ -static void internal_clear_lock PROTO((struct lock *lock)); -static void -internal_clear_lock (lock) - struct lock *lock; -{ - SIG_beginCrSect (); - if (lock->repository) - { - free (lock->repository); - lock->repository = NULL; - } - SIG_endCrSect (); - - clear_lock (lock); -} - - - -/* Lock the CVSROOT/history file for write. - */ -int -history_lock (xrepository) - const char *xrepository; -{ - return internal_lock (&global_history_lock, xrepository); -} - - - -/* Remove the CVSROOT/history lock, if it exists. - */ -void -clear_history_lock () -{ - internal_clear_lock (&global_history_lock); -} - - - -/* Lock the CVSROOT/val-tags file for write. - */ -int -val_tags_lock (xrepository) - const char *xrepository; -{ - return internal_lock (&global_val_tags_lock, xrepository); -} - - - -/* Remove the CVSROOT/val-tags lock, if it exists. - */ -void -clear_val_tags_lock () -{ - internal_clear_lock (&global_val_tags_lock); -} diff --git a/contrib/cvs/src/log.c b/contrib/cvs/src/log.c index bb1dbde..f8447ba 100644 --- a/contrib/cvs/src/log.c +++ b/contrib/cvs/src/log.c @@ -1,11 +1,6 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. @@ -15,10 +10,11 @@ * Prints the RCS "log" (rlog) information for the specified files. With no * argument, prints the log information for all the files in the directory * (recursive by default). + * + * $FreeBSD$ */ #include "cvs.h" -#include <assert.h> /* This structure holds information parsed from the -r option. */ @@ -129,7 +125,7 @@ static int log_fileproc PROTO ((void *callerdat, struct file_info *finfo)); static struct option_revlist *log_parse_revlist PROTO ((const char *)); static void log_parse_date PROTO ((struct log_data *, const char *)); static void log_parse_list PROTO ((List **, const char *)); -static struct revlist *log_expand_revlist PROTO ((RCSNode *, char *, +static struct revlist *log_expand_revlist PROTO ((RCSNode *, struct option_revlist *, int)); static void log_free_revlist PROTO ((struct revlist *)); @@ -156,14 +152,12 @@ static const char *const log_usage[] = "Usage: %s %s [-lRhtNb] [-r[revisions]] [-d dates] [-s states]\n", " [-w[logins]] [files...]\n", "\t-l\tLocal directory only, no recursion.\n", - "\t-b\tOnly list revisions on the default branch.\n", - "\t-h\tOnly print header.\n", "\t-R\tOnly print name of RCS file.\n", + "\t-h\tOnly print header.\n", "\t-t\tOnly print header and descriptive text.\n", "\t-N\tDo not list tags.\n", - "\t-S\tDo not print name/header if no revisions selected. -d, -r,\n", - "\t\t-s, & -w have little effect in conjunction with -b, -h, -R, and\n", - "\t\t-t without this option.\n", + "\t-S\tDo not print name/header if no revisions selected.\n", + "\t-b\tOnly list revisions on the default branch.\n", "\t-r[revisions]\tA comma-separated list of revisions to print:\n", "\t rev1:rev2 Between rev1 and rev2, including rev1 and rev2.\n", "\t rev1::rev2 Between rev1 and rev2, excluding rev1.\n", @@ -242,7 +236,7 @@ cvslog (argc, argv) prl = &log_data.revlist; optind = 0; - while ((c = getopt (argc, argv, "+bd:hlNSRr::s:tw::")) != -1) + while ((c = getopt (argc, argv, "+bd:hlNnSRr::s:tw::")) != -1) { switch (c) { @@ -261,6 +255,9 @@ cvslog (argc, argv) case 'N': log_data.notags = 1; break; + case 'n': + log_data.notags = 0; + break; case 'S': log_data.sup_header = 1; break; @@ -316,7 +313,6 @@ cvslog (argc, argv) { p = log_data.datelist; log_data.datelist = p->next; - assert (p->start != NULL && p->end != NULL); send_to_server ("Argument -d\012", 0); send_to_server ("Argument ", 0); date_to_internet (datetmp, p->start); @@ -328,21 +324,23 @@ cvslog (argc, argv) date_to_internet (datetmp, p->end); send_to_server (datetmp, 0); send_to_server ("\012", 0); - free (p->start); - free (p->end); + if (p->start) + free (p->start); + if (p->end) + free (p->end); free (p); } while (log_data.singledatelist != NULL) { p = log_data.singledatelist; log_data.singledatelist = p->next; - assert (p->end != NULL); send_to_server ("Argument -d\012", 0); send_to_server ("Argument ", 0); date_to_internet (datetmp, p->end); send_to_server (datetmp, 0); send_to_server ("\012", 0); - free (p->end); + if (p->end) + free (p->end); free (p); } @@ -815,30 +813,21 @@ log_fileproc (callerdat, finfo) { struct log_data *log_data = (struct log_data *) callerdat; Node *p; - char *baserev; int selrev = -1; RCSNode *rcsfile; char buf[50]; struct revlist *revlist = NULL; struct log_data_and_rcs log_data_and_rcs; - rcsfile = finfo->rcs; - p = findnode (finfo->entries, finfo->file); - if (p != NULL) - { - Entnode *e = p->data; - baserev = e->version; - if (baserev[0] == '-') ++baserev; - } - else - baserev = NULL; - - if (rcsfile == NULL) + if ((rcsfile = finfo->rcs) == NULL) { /* no rcs file. What *do* we know about this file? */ - if (baserev != NULL) + p = findnode (finfo->entries, finfo->file); + if (p != NULL) { - if (baserev[0] == '0' && baserev[1] == '\0') + Entnode *e = p->data; + + if (e->version[0] == '0' && e->version[1] == '\0') { if (!really_quiet) error (0, 0, "%s has been added, but not committed", @@ -861,7 +850,7 @@ log_fileproc (callerdat, finfo) /* Turn any symbolic revisions in the revision list into numeric revisions. */ - revlist = log_expand_revlist (rcsfile, baserev, log_data->revlist, + revlist = log_expand_revlist (rcsfile, log_data->revlist, log_data->default_branch); if (log_data->sup_header || (!log_data->header && !log_data->long_header)) @@ -1051,9 +1040,8 @@ log_fileproc (callerdat, finfo) * Expand any symbolic revisions. */ static struct revlist * -log_expand_revlist (rcs, baserev, revlist, default_branch) +log_expand_revlist (rcs, revlist, default_branch) RCSNode *rcs; - char *baserev; struct option_revlist *revlist; int default_branch; { @@ -1074,26 +1062,13 @@ log_expand_revlist (rcs, baserev, revlist, default_branch) /* If both first and last are NULL, it means that we want just the head of the default branch, which is RCS_head. */ nr->first = RCS_head (rcs); - if (!nr->first) - { - if (!really_quiet) - error (0, 0, "No head revision in archive `%s'.", - rcs->path); - nr->last = NULL; - nr->fields = 0; - } - else - { - nr->last = xstrdup (nr->first); - nr->fields = numdots (nr->first) + 1; - } + nr->last = xstrdup (nr->first); + nr->fields = numdots (nr->first) + 1; } else if (r->branchhead) { char *branch; - assert (r->first != NULL); - /* Print just the head of the branch. */ if (isdigit ((unsigned char) r->first[0])) nr->first = RCS_getbranch (rcs, r->first, 1); @@ -1108,11 +1083,10 @@ log_expand_revlist (rcs, baserev, revlist, default_branch) free (branch); } } - if (!nr->first) + if (nr->first == NULL && !really_quiet) { - if (!really_quiet) - error (0, 0, "warning: no branch `%s' in `%s'", - r->first, rcs->path); + error (0, 0, "warning: no branch `%s' in `%s'", + r->first, rcs->path); nr->last = NULL; nr->fields = 0; } @@ -1128,9 +1102,7 @@ log_expand_revlist (rcs, baserev, revlist, default_branch) nr->first = xstrdup (r->first); else { - if (baserev && strcmp (r->first, TAG_BASE) == 0) - nr->first = xstrdup (baserev); - else if (RCS_nodeisbranch (rcs, r->first)) + if (RCS_nodeisbranch (rcs, r->first)) nr->first = RCS_whatbranch (rcs, r->first); else nr->first = RCS_gettag (rcs, r->first, 1, (int *) NULL); @@ -1148,9 +1120,7 @@ log_expand_revlist (rcs, baserev, revlist, default_branch) nr->last = xstrdup (r->last); else { - if (baserev && strcmp (r->last, TAG_BASE) == 0) - nr->last = xstrdup (baserev); - else if (RCS_nodeisbranch (rcs, r->last)) + if (RCS_nodeisbranch (rcs, r->last)) nr->last = RCS_whatbranch (rcs, r->last); else nr->last = RCS_gettag (rcs, r->last, 1, (int *) NULL); @@ -1176,7 +1146,6 @@ log_expand_revlist (rcs, baserev, revlist, default_branch) nr->first = xstrdup (nr->last); cp = strrchr (nr->first, '.'); - assert (cp); strcpy (cp + 1, "0"); } } @@ -1191,7 +1160,6 @@ log_expand_revlist (rcs, baserev, revlist, default_branch) char *cp; cp = strrchr (nr->last, '.'); - assert (cp); *cp = '\0'; } } @@ -1291,9 +1259,7 @@ log_expand_revlist (rcs, baserev, revlist, default_branch) char *cp; nr->first = xstrdup (rcs->head); - assert (nr->first); cp = strrchr (nr->first, '.'); - assert (cp); *cp = '\0'; } nr->last = xstrdup (nr->first); @@ -1644,8 +1610,8 @@ log_version (log_data, revlist, rcs, ver, trunk) &sec); if (year < 1900) year += 1900; - sprintf (buf, "%04d/%02d/%02d %02d:%02d:%02d", year, mon, mday, - hour, min, sec); + sprintf (buf, "%04d%c%02d%c%02d %02d:%02d:%02d", + year, datesep, mon, datesep, mday, hour, min, sec); cvs_output (buf, 0); cvs_output ("; author: ", 0); @@ -1681,7 +1647,6 @@ log_version (log_data, revlist, rcs, ver, trunk) if (padd != NULL) { - assert (pdel); cvs_output (" lines: +", 0); cvs_output (padd->data, 0); cvs_output (" -", 2); diff --git a/contrib/cvs/src/login.c b/contrib/cvs/src/login.c index fe95544..86705ea 100644 --- a/contrib/cvs/src/login.c +++ b/contrib/cvs/src/login.c @@ -1,15 +1,12 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (c) 1995, Cyclic Software, Bloomington, IN, USA + * Copyright (c) 1995, Cyclic Software, Bloomington, IN, USA * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with CVS. * * Allow user to log in for an authenticating server. + * + * $FreeBSD$ */ #include "cvs.h" @@ -387,8 +384,7 @@ process: /* create and open a temp file */ if ((tmp_fp = cvs_temp_file (&tmp_name)) == NULL) - error (1, errno, "unable to open temp file %s", - tmp_name ? tmp_name : "(null)"); + error (1, errno, "unable to open temp file %s", tmp_name); line = 0; while ((line_length = getline (&linebuf, &linebuf_len, fp)) >= 0) @@ -461,7 +457,7 @@ process: if (fprintf (fp, "/1 %s %s\n", cvsroot_canonical, newpassword) == EOF) error (1, errno, "cannot write %s", passfile); if (fclose (fp) < 0) - error (1, errno, "cannot close %s", passfile); + error (0, errno, "cannot close %s", passfile); } /* Utter, total, raving paranoia, I know. */ diff --git a/contrib/cvs/src/logmsg.c b/contrib/cvs/src/logmsg.c index 5ac4b0e..fbbcc3c 100644 --- a/contrib/cvs/src/logmsg.c +++ b/contrib/cvs/src/logmsg.c @@ -1,14 +1,11 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. + * + * $FreeBSD$ */ #include <assert.h> @@ -201,7 +198,11 @@ do_editor (dir, messagep, repository, changes) struct stat pre_stbuf, post_stbuf; int retcode = 0; +#ifdef CLIENT_SUPPORT assert (!current_parsed_root->isremote != !repository); +#else + assert (repository); +#endif if (noexec || reuse_log_message) return; @@ -227,6 +228,8 @@ do_editor (dir, messagep, repository, changes) (*messagep)[strlen (*messagep) - 1] != '\n') (void) fprintf (fp, "\n"); } + else + (void) fprintf (fp, "\n"); if (repository != NULL) /* tack templates on if necessary */ @@ -291,7 +294,12 @@ do_editor (dir, messagep, repository, changes) if (editinfo_editor) free (editinfo_editor); editinfo_editor = (char *) NULL; - if (!current_parsed_root->isremote && repository != NULL) +#ifdef CLIENT_SUPPORT + if (current_parsed_root->isremote) + ; /* nothing, leave editinfo_editor NULL */ + else +#endif + if (repository != NULL) (void) Parse_Info (CVSROOTADM_EDITINFO, repository, editinfo_proc, 0); /* run the editor */ @@ -418,9 +426,11 @@ do_verify (messagep, repository) struct stat pre_stbuf, post_stbuf; +#ifdef CLIENT_SUPPORT if (current_parsed_root->isremote) /* The verification will happen on the server. */ return; +#endif /* FIXME? Do we really want to skip this on noexec? What do we do for the other administrative files? */ @@ -439,8 +449,7 @@ do_verify (messagep, repository) temp file, and close the file. */ if ((fp = cvs_temp_file (&fname)) == NULL) - error (1, errno, "cannot create temporary file %s", - fname ? fname : "(null)"); + error (1, errno, "cannot create temporary file %s", fname); if (*messagep != NULL) fputs (*messagep, fp); @@ -546,7 +555,7 @@ do_verify (messagep, repository) if (unlink_file (fname) < 0) error (0, errno, "cannot remove %s", fname); free (fname); - free (verifymsg_script); + free( verifymsg_script ); verifymsg_script = NULL; } @@ -742,8 +751,6 @@ logfile_write (repository, filter, message, logfp, changes) char *fmt_percent; /* the location of the percent sign that starts the format string. */ - assert (repository); - /* The user may specify a format string as part of the filter. Originally, `%s' was the only valid string. The string that was substituted for it was: diff --git a/contrib/cvs/src/main.c b/contrib/cvs/src/main.c index c5911c3..932dbd2 100644 --- a/contrib/cvs/src/main.c +++ b/contrib/cvs/src/main.c @@ -1,24 +1,21 @@ /* - * Copyright (C) 1986-2006 The Free Software Foundation, Inc. + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * - * Portions Copyright (C) 1998-2006 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner - * - * You may distribute under the terms of the GNU General Public License - * as specified in the README file that comes with the CVS source distribution. + * You may distribute under the terms of the GNU General Public License + * as specified in the README file that comes with the CVS source distribution. * * This is the main C driver for the CVS system. * * Credit to Dick Grune, Vrije Universiteit, Amsterdam, for writing * the shell-script CVS system that this is based on. * + * $FreeBSD$ */ #include <assert.h> #include "cvs.h" +#include "prepend_args.h" #ifdef HAVE_WINSOCK_H #include <winsock.h> @@ -46,14 +43,10 @@ int really_quiet = 0; int quiet = 0; int trace = 0; int noexec = 0; +int readonlyfs = 0; +int require_real_user = 0; int logoff = 0; -/* - * Zero if compression isn't supported or requested; non-zero to indicate - * a compression level to request from gzip. - */ -int gzip_level; - /* Set if we should be writing CVSADM directories at top level. At least for now we'll make the default be off (the CVS 1.9, not CVS 1.9.2, behavior). */ @@ -74,6 +67,15 @@ char *Editor = EDITOR_DFLT; values in CVS/Root files, we maintain a list of them. */ List *root_directories = NULL; +/* We step through the above values. This variable is set to reflect + * the currently active value. + * + * Now static. FIXME - this variable should be removable (well, localizable) + * with a little more work. + */ +static char *current_root = NULL; + + static const struct cmd { char *fullname; /* Full name of the function (e.g. "commit") */ @@ -108,7 +110,7 @@ static const struct cmd { { "add", "ad", "new", add, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, { "admin", "adm", "rcs", admin, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, - { "annotate", "ann", NULL, annotate, CVS_CMD_USES_WORK_DIR }, + { "annotate", "ann", "blame", annotate, CVS_CMD_USES_WORK_DIR }, { "checkout", "co", "get", checkout, 0 }, { "commit", "ci", "com", commit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, { "diff", "di", "dif", diff, CVS_CMD_USES_WORK_DIR }, @@ -189,7 +191,8 @@ static const char *const usg[] = version control means. */ "For CVS updates and additional information, see\n", - " the CVS home page at http://cvs.nongnu.org/\n", + " the CVS home page at http://www.cvshome.org/ or\n", + " Pascal Molli's CVS site at http://www.loria.fr/~molli/cvs-index.html\n", NULL, }; @@ -248,8 +251,10 @@ static const char *const opt_usage[] = " -q Cause CVS to be somewhat quiet.\n", " -r Make checked-out files read-only.\n", " -w Make checked-out files read-write (default).\n", + " -g Force group-write perms on checked-out files.\n", " -n Do not execute anything that will change the disk.\n", " -t Show trace of program execution -- try with -n.\n", + " -R Assume repository is read-only, such as CDROM\n", " -v CVS version and copyright.\n", " -T tmpdir Use 'tmpdir' for temporary files.\n", " -e editor Use 'editor' for editing log information.\n", @@ -273,9 +278,9 @@ set_root_directory (p, ignored) Node *p; void *ignored; { - if (current_parsed_root == NULL && p->data != NULL) + if (current_root == NULL && p->data == NULL) { - current_parsed_root = p->data; + current_root = p->key; return 1; } return 0; @@ -395,19 +400,19 @@ main (argc, argv) int argc; char **argv; { - cvsroot_t *CVSroot_parsed = NULL; - int cvsroot_update_env = 1; + char *CVSroot = CVSROOT_DFLT; char *cp, *end; const struct cmd *cm; int c, err = 0; - int tmpdir_update_env; + int tmpdir_update_env, cvs_update_env; + int free_CVSroot = 0; int free_Editor = 0; int free_Tmpdir = 0; int help = 0; /* Has the user asked for help? This lets us support the `cvs -H cmd' convention to give help for cmd. */ - static const char short_options[] = "+Qqrwtnvb:T:e:d:Hfz:s:xa"; + static const char short_options[] = "+QqgrwtnRvb:T:e:d:Hfz:s:xaU"; static struct option long_options[] = { {"help", 0, NULL, 'H'}, @@ -450,6 +455,7 @@ main (argc, argv) * Query the environment variables up-front, so that * they can be overridden by command line arguments */ + cvs_update_env = 0; tmpdir_update_env = *Tmpdir; /* TMPDIR_DFLT must be set */ if ((cp = getenv (TMPDIR_ENV)) != NULL) { @@ -462,8 +468,19 @@ main (argc, argv) Editor = cp; else if ((cp = getenv (EDITOR3_ENV)) != NULL) Editor = cp; + if ((cp = getenv (CVSROOT_ENV)) != NULL) + { + CVSroot = cp; + cvs_update_env = 0; /* it's already there */ + } if (getenv (CVSREAD_ENV) != NULL) cvswrite = 0; + if (getenv (CVSREADONLYFS_ENV) != NULL) { + readonlyfs = 1; + logoff = 1; + } + + prepend_default_options (getenv ("CVS_OPTIONS"), &argc, &argv); /* Set this to 0 to force getopt initialization. getopt() sets this to 1 internally. */ @@ -526,9 +543,20 @@ main (argc, argv) case 'w': cvswrite = 1; break; + case 'g': + /* + * force full group write perms (used for shared checked-out + * source trees, see manual page) + */ + umask(umask(077) & 007); + break; case 't': trace = 1; break; + case 'R': + readonlyfs = 1; + logoff = 1; + break; case 'n': noexec = 1; logoff = 1; @@ -538,12 +566,8 @@ main (argc, argv) version (0, (char **) NULL); (void) fputs ("\n", stdout); (void) fputs ("\ -Copyright (C) 2006 Free Software Foundation, Inc.\n\ -\n\ -Senior active maintainers include Larry Jones, Derek R. Price,\n\ -and Mark D. Baushke. Please see the AUTHORS and README files from the CVS\n\ -distribution kit for a complete list of contributors and copyrights.\n", - stdout); +Copyright (c) 1989-2004 Brian Berliner, david d `zoo' zuhn, \n\ + Jeff Polk, and other authors\n", stdout); (void) fputs ("\n", stdout); (void) fputs ("CVS may be copied only under the terms of the GNU General Public License,\n", stdout); (void) fputs ("a copy of which can be found with the CVS distribution kit.\n", stdout); @@ -551,12 +575,6 @@ distribution kit for a complete list of contributors and copyrights.\n", (void) fputs ("Specify the --help option for further information about CVS\n", stdout); -#ifdef SYSTEM_CLEANUP - /* Hook for OS-specific behavior, for example socket subsystems - * on NT and OS2 or dealing with windows and arguments on Mac. - */ - SYSTEM_CLEANUP (); -#endif exit (0); break; case 'b': @@ -567,13 +585,11 @@ distribution kit for a complete list of contributors and copyrights.\n", either new or old CVS. */ break; case 'T': - if (free_Tmpdir) free (Tmpdir); Tmpdir = xstrdup (optarg); free_Tmpdir = 1; tmpdir_update_env = 1; /* need to update environment */ break; case 'e': - if (free_Editor) free (Editor); Editor = xstrdup (optarg); free_Editor = 1; break; @@ -581,6 +597,11 @@ distribution kit for a complete list of contributors and copyrights.\n", if (CVSroot_cmdline != NULL) free (CVSroot_cmdline); CVSroot_cmdline = xstrdup (optarg); + if (free_CVSroot) + free (CVSroot); + CVSroot = xstrdup (optarg); + free_CVSroot = 1; + cvs_update_env = 1; /* need to update environment */ break; case 'H': help = 1; @@ -589,10 +610,12 @@ distribution kit for a complete list of contributors and copyrights.\n", use_cvsrc = 0; /* unnecessary, since we've done it above */ break; case 'z': +#ifdef CLIENT_SUPPORT gzip_level = strtol (optarg, &end, 10); if (*end != '\0' || gzip_level < 0 || gzip_level > 9) error (1, 0, "gzip compression level must be between 0 and 9"); +#endif /* CLIENT_SUPPORT */ /* If no CLIENT_SUPPORT, we just silently ignore the gzip * level, so that users can have it in their .cvsrc and not * cause any trouble. @@ -623,6 +646,11 @@ distribution kit for a complete list of contributors and copyrights.\n", We will issue an error later if stream authentication is not supported. */ break; + case 'U': +#ifdef SERVER_SUPPORT + require_real_user = 1; +#endif + break; case '?': default: usage (usg); @@ -716,18 +744,21 @@ distribution kit for a complete list of contributors and copyrights.\n", cvs_cmd_name = "server"; } # endif /* AUTH_SERVER_SUPPORT || HAVE_GSSAPI */ -#endif /* SERVER_SUPPORT */ server_active = strcmp (cvs_cmd_name, "server") == 0; +#endif /* SERVER_SUPPORT */ + /* This is only used for writing into the history file. For remote connections, it might be nice to have hostname and/or remote path, on the other hand I'm not sure whether it is worth the trouble. */ +#ifdef SERVER_SUPPORT if (server_active) CurDir = xstrdup ("<remote>"); else +#endif { CurDir = xgetwd (); if (CurDir == NULL) @@ -735,10 +766,7 @@ distribution kit for a complete list of contributors and copyrights.\n", } if (Tmpdir == NULL || Tmpdir[0] == '\0') - { - if (free_Tmpdir) free (Tmpdir); Tmpdir = "/tmp"; - } #ifdef HAVE_PUTENV if (tmpdir_update_env) @@ -749,6 +777,12 @@ distribution kit for a complete list of contributors and copyrights.\n", (void) putenv (env); /* do not free env, as putenv has control of it */ } + { + char *env; + env = xmalloc (sizeof "CVS_PID=" + 32); /* XXX pid < 10^32 */ + (void) sprintf (env, "CVS_PID=%ld", (long) getpid ()); + (void) putenv (env); + } #endif #ifndef DONT_USE_SIGNALS @@ -786,66 +820,68 @@ distribution kit for a complete list of contributors and copyrights.\n", if (use_cvsrc) read_cvsrc (&argc, &argv, cvs_cmd_name); +#ifdef SERVER_SUPPORT /* Fiddling with CVSROOT doesn't make sense if we're running - * in server mode, since the client will send the repository - * directory after the connection is made. - */ + in server mode, since the client will send the repository + directory after the connection is made. */ + if (!server_active) +#endif { - /* First check if a root was set via the command line. */ - if (CVSroot_cmdline) - { - if (!(CVSroot_parsed = parse_cvsroot (CVSroot_cmdline))) - error (1, 0, "Bad CVSROOT: `%s'.", CVSroot_cmdline); - } - + char *CVSADM_Root; + /* See if we are able to find a 'better' value for CVSroot - * in the CVSADM_ROOT directory. - * - * "cvs import" shouldn't check CVS/Root; in general it - * ignores CVS directories and CVS/Root is likely to - * specify a different repository than the one we are - * importing to, but if this is not import and no root was - * specified on the command line, set the root from the - * CVS/Root file. - */ - if (!CVSroot_parsed - && !(cm->attr & CVS_CMD_IGNORE_ADMROOT) - ) - CVSroot_parsed = Name_Root (NULL, NULL); + in the CVSADM_ROOT directory. */ - /* Now, if there is no root on the command line and we didn't find - * one in a file, set it via the $CVSROOT env var. - */ - if (!CVSroot_parsed) + CVSADM_Root = NULL; + + /* "cvs import" shouldn't check CVS/Root; in general it + ignores CVS directories and CVS/Root is likely to + specify a different repository than the one we are + importing to. */ + + if (!(cm->attr & CVS_CMD_IGNORE_ADMROOT) + + /* -d overrides CVS/Root, so don't give an error if the + latter points to a nonexistent repository. */ + && CVSroot_cmdline == NULL) { - char *tmp = getenv (CVSROOT_ENV); - if (tmp) - { - if (!(CVSroot_parsed = parse_cvsroot (tmp))) - error (1, 0, "Bad CVSROOT: `%s'.", tmp); - cvsroot_update_env = 0; - } + CVSADM_Root = Name_Root((char *) NULL, (char *) NULL); } -#ifdef CVSROOT_DFLT - if (!CVSroot_parsed) + if (CVSADM_Root != NULL) { - if (!(CVSroot_parsed = parse_cvsroot (CVSROOT_DFLT))) - error (1, 0, "Bad CVSROOT: `%s'.", CVSROOT_DFLT); + if (CVSroot == NULL || !cvs_update_env) + { + CVSroot = CVSADM_Root; + cvs_update_env = 1; /* need to update environment */ + } } -#endif /* CVSROOT_DFLT */ /* Now we've reconciled CVSROOT from the command line, the CVS/Root file, and the environment variable. Do the last sanity checks on the variable. */ - if (!CVSroot_parsed) + + if (! CVSroot) { error (0, 0, "No CVSROOT specified! Please use the `-d' option"); error (1, 0, "or set the %s environment variable.", CVSROOT_ENV); } + + if (! *CVSroot) + { + error (0, 0, + "CVSROOT is set but empty! Make sure that the"); + error (0, 0, + "specification of CVSROOT is valid, either via the"); + error (0, 0, + "`-d' option, the %s environment variable, or the", + CVSROOT_ENV); + error (1, 0, + "CVS/Root file (if any)."); + } } /* Here begins the big loop over unique cvsroot values. We @@ -857,19 +893,19 @@ distribution kit for a complete list of contributors and copyrights.\n", root_directories = getlist (); /* Prime it. */ - if (CVSroot_parsed) + if (CVSroot != NULL) { Node *n; n = getnode (); n->type = NT_UNKNOWN; - n->key = xstrdup (CVSroot_parsed->original); - n->data = CVSroot_parsed; + n->key = xstrdup (CVSroot); + n->data = NULL; if (addnode (root_directories, n)) error (1, 0, "cannot add initial CVSROOT %s", n->key); } - assert (current_parsed_root == NULL); + assert (current_root == NULL); /* If we're running the server, we want to execute this main loop once and only once (we won't be serving multiple roots @@ -877,58 +913,70 @@ distribution kit for a complete list of contributors and copyrights.\n", once). To get out of the loop, we perform a "break" at the end of things. */ - while (server_active || - walklist (root_directories, set_root_directory, NULL)) + while ( +#ifdef SERVER_SUPPORT + server_active || +#endif + walklist (root_directories, set_root_directory, NULL) + ) { +#ifdef SERVER_SUPPORT /* Fiddling with CVSROOT doesn't make sense if we're running in server mode, since the client will send the repository directory after the connection is made. */ if (!server_active) +#endif { /* Now we're 100% sure that we have a valid CVSROOT variable. Parse it to see if we're supposed to do remote accesses or use a special access method. */ + if (current_parsed_root != NULL) + free_cvsroot_t (current_parsed_root); + if ((current_parsed_root = parse_cvsroot (current_root)) == NULL) + error (1, 0, "Bad CVSROOT: `%s'.", current_root); + if (trace) fprintf (stderr, "%s-> main loop with CVSROOT=%s\n", - CLIENT_SERVER_STR, current_parsed_root->original); + CLIENT_SERVER_STR, current_root); /* * Check to see if the repository exists. */ +#ifdef CLIENT_SUPPORT if (!current_parsed_root->isremote) +#endif /* CLIENT_SUPPORT */ { char *path; int save_errno; path = xmalloc (strlen (current_parsed_root->directory) - + strlen (CVSROOTADM) + 2); - sprintf (path, "%s/%s", current_parsed_root->directory, - CVSROOTADM); + + sizeof (CVSROOTADM) + + 2); + (void) sprintf (path, "%s/%s", current_parsed_root->directory, CVSROOTADM); if (!isaccessible (path, R_OK | X_OK)) { save_errno = errno; - /* If this is "cvs init", the root need not exist yet. - */ - if (strcmp (cvs_cmd_name, "init")) + /* If this is "cvs init", the root need not exist yet. */ + if (strcmp (cvs_cmd_name, "init") != 0) + { error (1, save_errno, "%s", path); } + } free (path); } #ifdef HAVE_PUTENV - /* Update the CVSROOT environment variable. */ - if (cvsroot_update_env) + /* Update the CVSROOT environment variable if necessary. */ + /* FIXME (njc): should we always set this with the CVSROOT from the command line? */ + if (cvs_update_env) { static char *prev; char *env; - - env = xmalloc (strlen (CVSROOT_ENV) - + strlen (current_parsed_root->original) - + 2); - sprintf (env, "%s=%s", CVSROOT_ENV, - current_parsed_root->original); + env = xmalloc (strlen (CVSROOT_ENV) + strlen (CVSroot) + + 1 + 1); + (void) sprintf (env, "%s=%s", CVSROOT_ENV, CVSroot); (void) putenv (env); /* do not free env yet, as putenv has control of it */ /* but do free the previous value, if any */ @@ -946,13 +994,23 @@ distribution kit for a complete list of contributors and copyrights.\n", predetermine whether CVSROOT/config overrides things from read_cvsrc and other such places or vice versa. That sort of thing probably needs more thought. */ - if (!server_active && !current_parsed_root->isremote) + if (1 +#ifdef SERVER_SUPPORT + && !server_active +#endif +#ifdef CLIENT_SUPPORT + && !current_parsed_root->isremote +#endif + ) { /* If there was an error parsing the config file, parse_config already printed an error. We keep going. Why? Because if we didn't, then there would be no way to check in a new CVSROOT/config file to fix the broken one! */ parse_config (current_parsed_root->directory); + + /* Now is a convenient time to read CVSROOT/options */ + parseopts(current_parsed_root->directory); } #ifdef CLIENT_SUPPORT @@ -973,28 +1031,31 @@ distribution kit for a complete list of contributors and copyrights.\n", err = (*(cm->func)) (argc, argv); /* Mark this root directory as done. When the server is - active, our list will be empty -- don't try and + active, current_root will be NULL -- don't try and remove it from the list. */ - if (!server_active) + if (current_root != NULL) { - Node *n = findnode (root_directories, - current_parsed_root->original); + Node *n = findnode (root_directories, current_root); assert (n != NULL); - assert (n->data != NULL); - free_cvsroot_t (n->data); - n->data = NULL; - current_parsed_root = NULL; + n->data = (void *) 1; + current_root = NULL; } + +#if 0 + /* This will not work yet, since it tries to free (void *) 1. */ + dellist (&root_directories); +#endif +#ifdef SERVER_SUPPORT if (server_active) { server_active = 0; break; } +#endif } /* end of loop for cvsroot values */ - dellist (&root_directories); } /* end of stuff that gets done if the user DOESN'T ask for help */ Lock_Cleanup (); @@ -1006,6 +1067,8 @@ distribution kit for a complete list of contributors and copyrights.\n", free ((char *)program_path); if (CVSroot_cmdline != NULL) free (CVSroot_cmdline); + if (free_CVSroot) + free (CVSroot); if (free_Editor) free (Editor); if (free_Tmpdir) @@ -1140,3 +1203,64 @@ usage (cpp) (void) fprintf (stderr, *cpp); error_exit (); } + +void +parseopts(root) + const char *root; +{ + char path[PATH_MAX]; + int save_errno; + char buf[1024]; + const char *p; + char *q; + FILE *fp; + + if (root == NULL) { + printf("no CVSROOT in parseopts\n"); + return; + } + p = strchr (root, ':'); + if (p) + p++; + else + p = root; + if (p == NULL) { + printf("mangled CVSROOT in parseopts\n"); + return; + } + (void) sprintf (path, "%s/%s/%s", p, CVSROOTADM, CVSROOTADM_OPTIONS); + if ((fp = fopen(path, "r")) != NULL) { + while (fgets(buf, sizeof buf, fp) != NULL) { + if (buf[0] == '#') + continue; + q = strrchr(buf, '\n'); + if (q) + *q = '\0'; + + if (!strcmp(buf, "iso8601")) { + datesep = '-'; + } + if (!strncmp(buf, "tag=", 4)) { + char *what; + char *rcs_localid; + + rcs_localid = buf + 4; + RCS_setlocalid(rcs_localid); + } + if (!strncmp(buf, "tagexpand=", 10)) { + char *what; + char *rcs_incexc; + + rcs_incexc = buf + 10; + RCS_setincexc(rcs_incexc); + } + /* + * OpenBSD has a "umask=" and "dlimit=" command, we silently + * ignore them here since they are not much use to us. cvsumask + * defaults to 002 already, and the dlimit (data size limit) + * should really be handled elsewhere (eg: login.conf). + */ + } + fclose(fp); + } +} diff --git a/contrib/cvs/src/mkmodules.c b/contrib/cvs/src/mkmodules.c index 3ac06b3..0c91387 100644 --- a/contrib/cvs/src/mkmodules.c +++ b/contrib/cvs/src/mkmodules.c @@ -1,14 +1,12 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as - * specified in the README file that comes with the CVS kit. */ + * specified in the README file that comes with the CVS kit. + * + * $FreeBSD$ + */ #include "cvs.h" #include "getline.h" @@ -286,7 +284,7 @@ static const char *const modules_contents[] = { static const char *const config_contents[] = { "# Set this to \"no\" if pserver shouldn't check system users/passwords\n", - "#SystemAuth=yes\n", + "#SystemAuth=no\n", "\n", "# Put CVS lock files in this directory rather than directly in the repository.\n", "#LockDir=/var/lock/cvs\n", @@ -307,7 +305,7 @@ static const char *const config_contents[] = { "#LogHistory=" ALL_HISTORY_REC_TYPES "\n", "\n", "# Set `RereadLogAfterVerify' to `always' (the default) to allow the verifymsg\n", - "# script to change the log message. Set it to `stat' to force CVS to verify\n", + "# script to change the log message. Set it to `stat' to force CVS to verify", "# that the file has changed before reading it (this can take up to an extra\n", "# second per directory being committed, so it is not recommended for large\n", "# repositories. Set it to `never' (the previous CVS behavior) to prevent\n", @@ -581,17 +579,7 @@ checkout_file (file, temp) free (rcs); return (1); } - rcsnode = RCS_parsercsfile (rcs); - if (!rcsnode) - { - /* Probably not necessary (?); RCS_parsercsfile already printed a - message. */ - error (0, 0, "Failed to parse `%s'.", rcs); - free (rcs); - return 1; - } - retcode = RCS_checkout (rcsnode, NULL, NULL, NULL, NULL, temp, (RCSCHECKOUTPROC) NULL, (void *) NULL); if (retcode != 0) diff --git a/contrib/cvs/src/options.h.in b/contrib/cvs/src/options.h.in deleted file mode 100644 index a3ee047..0000000 --- a/contrib/cvs/src/options.h.in +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) 1992, Brian Berliner and Jeff Polk - * Copyright (c) 1989-1992, Brian Berliner - * - * You may distribute under the terms of the GNU General Public License as - * specified in the README file that comes with the CVS source distribution. - * - * This file holds (most of) the configuration tweaks that can be made to - * customize CVS for your site. CVS comes configured for a typical SunOS 4.x - * environment. The comments for each configurable item are intended to be - * self-explanatory. All #defines are tested first to see if an over-riding - * option was specified on the "make" command line. - * - * If special libraries are needed, you will have to edit the Makefile.in file - * or the configure script directly. Sorry. - */ - -/* By default, CVS stores its modules and other such items in flat - text files (MY_NDBM enables this). Turning off MY_NDBM causes CVS - to look for a system-supplied ndbm database library and use it - instead. That may speed things up, but the default setting - generally works fine too. */ - -#ifndef MY_NDBM -#define MY_NDBM -#endif - -/* - * The "patch" program to run when using the CVS server and accepting - * patches across the network. Specify a full pathname if your site - * wants to use a particular patch. - */ -#ifndef PATCH_PROGRAM -#define PATCH_PROGRAM "patch" -#endif - -/* Directory used for storing temporary files, if not overridden by - environment variables or the -T global option. There should be little - need to change this (-T is a better mechanism if you need to use a - different directory for temporary files). */ -#ifndef TMPDIR_DFLT -#define TMPDIR_DFLT "/tmp" -#endif - -/* - * The default editor to use, if one does not specify the "-e" option - * to cvs, or does not have an EDITOR environment variable. I set - * this to just "vi", and use the shell to find where "vi" actually - * is. This allows sites with /usr/bin/vi or /usr/ucb/vi to work - * equally well (assuming that your PATH is reasonable). - */ -#ifndef EDITOR_DFLT -#define EDITOR_DFLT "vi" -#endif - -/* - * The default umask to use when creating or otherwise setting file or - * directory permissions in the repository. Must be a value in the - * range of 0 through 0777. For example, a value of 002 allows group - * rwx access and world rx access; a value of 007 allows group rwx - * access but no world access. This value is overridden by the value - * of the CVSUMASK environment variable, which is interpreted as an - * octal number. - */ -#ifndef UMASK_DFLT -#define UMASK_DFLT 002 -#endif - -/* - * The cvs admin command is restricted to the members of the group - * CVS_ADMIN_GROUP. If this group does not exist, all users are - * allowed to run cvs admin. To disable the cvs admin for all users, - * create an empty group CVS_ADMIN_GROUP. To disable access control - * for cvs admin, comment out the define below. - */ -#ifndef CVS_ADMIN_GROUP -#define CVS_ADMIN_GROUP "cvsadmin" -#endif - -/* - * The Repository file holds the path to the directory within the - * source repository that contains the RCS ,v files for each CVS - * working directory. This path is either a full-path or a path - * relative to CVSROOT. - * - * The big advantage that I can see to having a relative path is that - * one can change the physical location of the master source - * repository, change the contents of CVS/Root files in your - * checked-out code, and CVS will work without problems. - * - * Therefore, RELATIVE_REPOS is now the default. In the future, this - * is likely to disappear entirely as a compile-time (or other) option, - * so if you have other software which relies on absolute pathnames, - * update them. - */ -#define RELATIVE_REPOS 1 - -/* - * When committing or importing files, you must enter a log message. - * Normally, you can do this either via the -m flag on the command - * line or an editor will be started for you. If you like to use - * logging templates (the rcsinfo file within the $CVSROOT/CVSROOT - * directory), you might want to force people to use the editor even - * if they specify a message with -m. Enabling FORCE_USE_EDITOR will - * cause the -m message to be appended to the temp file when the - * editor is started. - */ -#ifndef FORCE_USE_EDITOR -/* #define FORCE_USE_EDITOR */ -#endif - -/* - * When locking the repository, some sites like to remove locks and - * assume the program that created them went away if the lock has - * existed for a long time. This used to be the default for previous - * versions of CVS. CVS now attempts to be much more robust, so lock - * files should not be left around by mistake. The new behaviour will - * never remove old locks (they must now be removed by hand). - * Enabling CVS_FUDGELOCKS will cause CVS to remove locks that are - * older than CVSLCKAGE seconds. - * - * Use of this option is NOT recommended. - */ -#ifndef CVS_FUDGELOCKS -/* #define CVS_FUDGELOCKS */ -#endif - -/* - * When committing a permanent change, CVS and RCS make a log entry of - * who committed the change. If you are committing the change logged - * in as "root" (not under "su" or other root-priv giving program), - * CVS/RCS cannot determine who is actually making the change. - * - * As such, by default, CVS disallows changes to be committed by users - * logged in as "root". You can disable this option by commenting out - * the lines below. - */ -#ifndef CVS_BADROOT -#define CVS_BADROOT -#endif - -/* Define this to enable the SETXID support. The way to use this is - to create a group with no users in it (except perhaps cvs - administrators), set the cvs executable to setgid that group, chown - all the repository files to that group, and change all directory - permissions in the repository to 770. The last person to modify a - file will own it, but as long as directory permissions are set - right that won't matter. You'll need a system which inherits file - groups from the parent directory (WARNING: using the wrong kind of - system (I think Solaris 2.4 is the wrong kind, for example) will - create a security hole! You will receive no warning other than the - fact that files in the working directory are owned by the group - which cvs is setgid to). - - One security hole which has been reported is that setgid is not - turned off when the editor is invoked--most editors provide a way - to execute a shell, or the user can specify an editor (this one is - large enough to drive a truck through). Don't assume that the - holes described here are the only ones; I don't know how carefully - SETXID has been inspected for security holes. */ -#ifndef SETXID_SUPPORT -/* #define SETXID_SUPPORT */ -#endif - -/* - * Should we build the password-authenticating client? Whether to - * include the password-authenticating _server_, on the other hand, is - * set in config.h. - */ -#ifdef CLIENT_SUPPORT -#define AUTH_CLIENT_SUPPORT 1 -#endif - -/* - * If you are working with a large remote repository and a 'cvs - * checkout' is swamping your network and memory, define these to - * enable flow control. You will end up with even less probability of - * a consistent checkout (see Concurrency in cvs.texinfo), but CVS - * doesn't try to guarantee that anyway. The master server process - * will monitor how far it is getting behind, if it reaches the high - * water mark, it will signal the child process to stop generating - * data when convenient (ie: no locks are held, currently at the - * beginning of a new directory). Once the buffer has drained - * sufficiently to reach the low water mark, it will be signalled to - * start again. You may override the default hi/low watermarks here - * too. - */ -#define SERVER_FLOWCONTROL -#define SERVER_HI_WATER (2 * 1024 * 1024) -#define SERVER_LO_WATER (1 * 1024 * 1024) - -/* End of CVS configuration section */ - -/* - * Externs that are included in libc, but are used frequently enough - * to warrant defining here. - */ -#ifndef STDC_HEADERS -extern void exit (); -#endif diff --git a/contrib/cvs/src/parseinfo.c b/contrib/cvs/src/parseinfo.c index 0fe9c33..5e34add 100644 --- a/contrib/cvs/src/parseinfo.c +++ b/contrib/cvs/src/parseinfo.c @@ -1,20 +1,16 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. + * + * $FreeBSD$ */ #include "cvs.h" #include "getline.h" #include <assert.h> -#include "history.h" extern char *logHistory; @@ -46,8 +42,6 @@ Parse_Info (infofile, repository, callproc, all) const char *srepos; const char *regex_err; - assert (repository); - if (current_parsed_root == NULL) { /* XXX - should be error maybe? */ @@ -278,7 +272,8 @@ parse_config (cvsroot) value, currently at least. */ error (0, errno, "cannot open %s", infopath); } - goto set_defaults_and_return; + free (infopath); + return 0; } while (getline (&line, &line_allocated, fp_info) >= 0) @@ -357,6 +352,25 @@ parse_config (cvsroot) goto error_return; } } + else if (strcmp (line, "tag") == 0) { + RCS_setlocalid(p); + } + else if (strcmp (line, "umask") == 0) { + cvsumask = (mode_t)(strtol(p, NULL, 8) & 0777); + } + else if (strcmp (line, "dlimit") == 0) { +#ifdef BSD +#include <sys/resource.h> + struct rlimit rl; + + if (getrlimit(RLIMIT_DATA, &rl) != -1) { + rl.rlim_cur = atoi(p); + rl.rlim_cur *= 1024; + + (void) setrlimit(RLIMIT_DATA, &rl); + } +#endif /* BSD */ + } else if (strcmp (line, "PreservePermissions") == 0) { if (strcmp (p, "no") == 0) @@ -402,8 +416,8 @@ warning: this CVS does not support PreservePermissions"); { if (strcmp (p, "all") != 0) { - if (logHistory) free (logHistory); - logHistory = xstrdup (p); + logHistory=xmalloc(strlen (p) + 1); + strcpy (logHistory, p); } } else if (strcmp (line, "RereadLogAfterVerify") == 0) @@ -415,6 +429,16 @@ warning: this CVS does not support PreservePermissions"); else if (strcmp (p, "stat") == 0) RereadLogAfterVerify = LOGMSG_REREAD_STAT; } + else if (strcmp(line, "LocalKeyword") == 0) + { + /* Recognize cvs-1.12-style keyword control rather than erroring out. */ + RCS_setlocalid(p); + } + else if (strcmp(line, "KeywordExpand") == 0) + { + /* Recognize cvs-1.12-style keyword control rather than erroring out. */ + RCS_setincexc(p); + } else { /* We may be dealing with a keyword which was added in a @@ -443,17 +467,12 @@ warning: this CVS does not support PreservePermissions"); error (0, errno, "cannot close %s", infopath); goto error_return; } -set_defaults_and_return: - if (!logHistory) - logHistory = xstrdup (ALL_HISTORY_REC_TYPES); free (infopath); if (line != NULL) free (line); return 0; error_return: - if (!logHistory) - logHistory = xstrdup (ALL_HISTORY_REC_TYPES); if (infopath != NULL) free (infopath); if (line != NULL) diff --git a/contrib/cvs/src/patch.c b/contrib/cvs/src/patch.c index 9af10a6..7d99f29 100644 --- a/contrib/cvs/src/patch.c +++ b/contrib/cvs/src/patch.c @@ -1,11 +1,6 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. @@ -15,6 +10,8 @@ * Create a Larry Wall format "patch" file between a previous release and the * current head of a module, or between two releases. Can specify the * release as either a date or a revision number. + * + * $FreeBSD$ */ #include <assert.h> @@ -47,7 +44,7 @@ static int unidiff = 0; static const char *const patch_usage[] = { - "Usage: %s %s [-flR] [-c|-u] [-s|-t] [-V %%d] [-k kopt]\n", + "Usage: %s %s [-flR] [-c|-u] [-s|-t] [-V %%d]\n", " -r rev|-D date [-r rev2 | -D date2] modules...\n", "\t-f\tForce a head revision match if tag/date not found.\n", "\t-l\tLocal directory only, not recursive\n", @@ -56,10 +53,9 @@ static const char *const patch_usage[] = "\t-u\tUnidiff format.\n", "\t-s\tShort patch - one liner per file.\n", "\t-t\tTop two diffs - last change made to the file.\n", - "\t-V vers\tUse RCS Version \"vers\" for keyword expansion.\n", - "\t-k kopt\tSpecify keyword expansion mode.\n", "\t-D date\tDate.\n", "\t-r rev\tRevision - symbolic or numeric.\n", + "\t-V vers\tUse RCS Version \"vers\" for keyword expansion.\n", "(Specify the --help global option for a list of other help options)\n", NULL }; @@ -87,9 +83,11 @@ patch (argc, argv) { case 'Q': case 'q': +#ifdef SERVER_SUPPORT /* The CVS 1.5 client sends these options (in addition to Global_option requests), so we must ignore them. */ if (!server_active) +#endif error (1, 0, "-q or -Q must be specified before \"%s\"", cvs_cmd_name); @@ -342,7 +340,6 @@ patch_proc (argc, argv, xwhere, mwhere, mfile, shorten, local_specified, { error (0, errno, "cannot chdir to %s", repository); free (repository); - free (where); return 1; } @@ -405,9 +402,6 @@ patch_fileproc (callerdat, finfo) char *cp1, *cp2; FILE *fp; int line_length; - int dargc = 0; - size_t darg_allocated = 0; - char **dargv = NULL; line1 = NULL; line1_chars_allocated = 0; @@ -518,8 +512,7 @@ patch_fileproc (callerdat, finfo) */ if ((fp1 = cvs_temp_file (&tmpfile1)) == NULL) { - error (0, errno, "cannot create temporary file %s", - tmpfile1 ? tmpfile1 : "(null)"); + error (0, errno, "cannot create temporary file %s", tmpfile1); ret = 1; goto out; } @@ -528,8 +521,7 @@ patch_fileproc (callerdat, finfo) error (0, errno, "warning: cannot close %s", tmpfile1); if ((fp2 = cvs_temp_file (&tmpfile2)) == NULL) { - error (0, errno, "cannot create temporary file %s", - tmpfile2 ? tmpfile2 : "(null)"); + error (0, errno, "cannot create temporary file %s", tmpfile2); ret = 1; goto out; } @@ -538,8 +530,7 @@ patch_fileproc (callerdat, finfo) error (0, errno, "warning: cannot close %s", tmpfile2); if ((fp3 = cvs_temp_file (&tmpfile3)) == NULL) { - error (0, errno, "cannot create temporary file %s", - tmpfile3 ? tmpfile3 : "(null)"); + error (0, errno, "cannot create temporary file %s", tmpfile3); ret = 1; goto out; } @@ -590,10 +581,8 @@ patch_fileproc (callerdat, finfo) (void)utime (tmpfile2, &t); } - if (unidiff) run_add_arg_p (&dargc, &darg_allocated, &dargv, "-u"); - else run_add_arg_p (&dargc, &darg_allocated, &dargv, "-c"); - switch (diff_exec (tmpfile1, tmpfile2, NULL, NULL, dargc, dargv, - tmpfile3)) + switch (diff_exec (tmpfile1, tmpfile2, NULL, NULL, unidiff ? "-u" : "-c", + tmpfile3)) { case -1: /* fork/wait failure */ error (1, errno, "fork for diff failed on %s", rcs); @@ -755,33 +744,16 @@ failed to read diff file header %s for %s: end of file", tmpfile3, rcs); free (line1); if (line2) free (line2); - if (tmpfile1 != NULL) - { - if (CVS_UNLINK (tmpfile1) < 0) - error (0, errno, "cannot unlink %s", tmpfile1); - free (tmpfile1); - tmpfile1 = NULL; - } - if (tmpfile2 != NULL) - { - if (CVS_UNLINK (tmpfile2) < 0) - error (0, errno, "cannot unlink %s", tmpfile2); - free (tmpfile2); - tmpfile2 = NULL; - } - if (tmpfile3 != NULL) - { - if (CVS_UNLINK (tmpfile3) < 0) - error (0, errno, "cannot unlink %s", tmpfile3); - free (tmpfile3); - tmpfile3 = NULL; - } - - if (dargc) - { - run_arg_free_p (dargc, dargv); - free (dargv); - } + if (CVS_UNLINK (tmpfile1) < 0) + error (0, errno, "cannot unlink %s", tmpfile1); + if (CVS_UNLINK (tmpfile2) < 0) + error (0, errno, "cannot unlink %s", tmpfile2); + if (CVS_UNLINK (tmpfile3) < 0) + error (0, errno, "cannot unlink %s", tmpfile3); + free (tmpfile1); + free (tmpfile2); + free (tmpfile3); + tmpfile1 = tmpfile2 = tmpfile3 = NULL; out2: if (vers_tag != NULL) diff --git a/contrib/cvs/src/rcs.c b/contrib/cvs/src/rcs.c index e1d62ed..1d3c1fd 100644 --- a/contrib/cvs/src/rcs.c +++ b/contrib/cvs/src/rcs.c @@ -1,17 +1,13 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. * * The routines contained in this file do all the rcs file parsing and * manipulation + * + * $FreeBSD$ */ #include <assert.h> @@ -30,6 +26,7 @@ # endif #endif +int datesep = '/'; int preserve_perms = 0; /* The RCS -k options, and a set of enums that must match the array. @@ -140,6 +137,8 @@ static char *rcs_lockfilename PROTO ((const char *)); evaluates its arguments multiple times. */ #define STREQ(a, b) (*(char *)(a) == *(char *)(b) && strcmp ((a), (b)) == 0) +static char * getfullCVSname PROTO ((char *, char **)); + /* * We don't want to use isspace() from the C library because: * @@ -304,8 +303,8 @@ RCS_parse (file, repos) } else if (! existence_error (errno)) { + free ( rcsfile ); error (0, errno, "cannot open %s", rcsfile); - free (rcsfile); } return retval; @@ -501,13 +500,8 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp) RCS_addaccess expects nothing but spaces. FIXME: It would be easy and more efficient to change RCS_addaccess. */ - if (rdata->access) - { - error (0, 0, - "Duplicate `access' keyword found in RCS file."); - free (rdata->access); - } - rdata->access = rcsbuf_valcopy (&rcsbuf, value, 1, NULL); + rdata->access = rcsbuf_valcopy (&rcsbuf, value, 1, + (size_t *) NULL); } continue; } @@ -517,15 +511,8 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp) if (STREQ (key, "locks")) { if (value != NULL) - { - if (rdata->locks_data) - { - error (0, 0, - "Duplicate `locks' keyword found in RCS file."); - free (rdata->locks_data); - } - rdata->locks_data = rcsbuf_valcopy (&rcsbuf, value, 0, NULL); - } + rdata->locks_data = rcsbuf_valcopy (&rcsbuf, value, 0, + (size_t *) NULL); if (! rcsbuf_getkey (&rcsbuf, &key, &value)) { error (1, 0, "premature end of file reading %s", rcsfile); @@ -542,16 +529,8 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp) if (STREQ (RCSSYMBOLS, key)) { if (value != NULL) - { - if (rdata->symbols_data) - { - error (0, 0, - "Duplicate `%s' keyword found in RCS file.", - RCSSYMBOLS); - free (rdata->symbols_data); - } - rdata->symbols_data = rcsbuf_valcopy (&rcsbuf, value, 0, NULL); - } + rdata->symbols_data = rcsbuf_valcopy (&rcsbuf, value, 0, + (size_t *) NULL); continue; } @@ -575,14 +554,8 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp) if (STREQ (key, "comment")) { - if (rdata->comment) - { - error (0, 0, - "warning: duplicate key `%s' in RCS file `%s'", - key, rcsfile); - free (rdata->comment); - } - rdata->comment = rcsbuf_valcopy (&rcsbuf, value, 0, NULL); + rdata->comment = rcsbuf_valcopy (&rcsbuf, value, 0, + (size_t *) NULL); continue; } if (rdata->other == NULL) @@ -616,9 +589,14 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp) q->key = vnode->version; /* add the nodes to the list */ - if (addnode (rdata->versions, q)) - error (1, 0, "Multiple %s revision deltas found in `%s'", - q->key, rcsfile); + if (addnode (rdata->versions, q) != 0) + { +#if 0 + purify_printf("WARNING: Adding duplicate version: %s (%s)\n", + q->key, rcsfile); + freenode (q); +#endif + } } /* Here KEY and VALUE are whatever caused getdelta to return NULL. */ @@ -772,10 +750,10 @@ RCS_fully_parse (rcs) break; vers = findnode (rcs->versions, key); - if (!vers) + if (vers == NULL) error (1, 0, - "Delta text %s without revision information in `%s'.", - key, rcs->path); + "mismatch in rcs file %s between deltas and deltatexts (%s)", + rcs->path, key); vnode = vers->data; @@ -2099,8 +2077,6 @@ do_symbols (list, val) char *cp = val; char *tag, *rev; - assert (cp); - for (;;) { /* skip leading whitespace */ @@ -2143,8 +2119,6 @@ do_locks (list, val) char *cp = val; char *user, *rev; - assert (cp); - for (;;) { /* skip leading whitespace */ @@ -2329,12 +2303,6 @@ RCS_tag2rev (rcs, tag) * the 0 in some other position -- <dan@gasboy.com> */ pa = strrchr (rev, '.'); - if (!pa) - /* This might happen, for instance, if an RCS file only contained - * revisions 2.x and higher, and REV == "1". - */ - error (1, 0, "revision `%s' does not exist", tag); - pb = xmalloc (strlen (rev) + 3); *pa++ = 0; (void) sprintf (pb, "%s.%d.%s", rev, RCS_MAGIC_BRANCH, pa); @@ -2539,13 +2507,25 @@ RCS_magicrev (rcs, rev) char *rev; { int rev_num; - char *xrev, *test_branch; + char *xrev, *test_branch, *local_branch_num; xrev = xmalloc (strlen (rev) + 14); /* enough for .0.number */ check_rev = xrev; + local_branch_num = getenv("CVS_LOCAL_BRANCH_NUM"); + if (local_branch_num) + { + rev_num = atoi(local_branch_num); + if (rev_num < 2) + rev_num = 2; + else + rev_num &= ~1; + } + else + rev_num = 2; + /* only look at even numbered branches */ - for (rev_num = 2; ; rev_num += 2) + for ( ; ; rev_num += 2) { /* see if the physical branch exists */ (void) sprintf (xrev, "%s.%d", rev, rev_num); @@ -2909,9 +2889,8 @@ RCS_getbranchpoint (rcs, target) vp = findnode (rcs->versions, branch); if (vp == NULL) - { + { error (0, 0, "%s: can't find branch point %s", rcs->path, target); - free (branch); return NULL; } rev = vp->data; @@ -3045,8 +3024,6 @@ RCS_getdate (rcs, date, force_tag_match) { char *date_1_1 = vers->date; - assert (p->data != NULL); - vers = p->data; if (RCS_datecmp (vers->date, date_1_1) != 0) return xstrdup ("1.1"); @@ -3315,7 +3292,7 @@ translate_symtag (rcs, tag) if (rcs->symbols_data != NULL) { size_t len; - char *cp, *last; + char *cp; /* Look through the RCS symbols information. This is like do_symbols, but we don't add the information to a list. In @@ -3324,16 +3301,8 @@ translate_symtag (rcs, tag) len = strlen (tag); cp = rcs->symbols_data; - /* Keeping track of LAST below isn't strictly necessary, now that tags - * should be parsed for validity before they are accepted, but tags - * with spaces used to cause the code below to loop indefintely, so - * I have corrected for that. Now, in the event that I missed - * something, the server cannot be hung. -DRP - */ - last = NULL; while ((cp = strchr (cp, tag[0])) != NULL) { - if (cp == last) break; if ((cp == rcs->symbols_data || whitespace (cp[-1])) && strncmp (cp, tag, len) == 0 && cp[len] == ':') @@ -3356,7 +3325,6 @@ translate_symtag (rcs, tag) ++cp; if (*cp == '\0') break; - last = cp; } } @@ -3484,8 +3452,6 @@ RCS_isdead (rcs, tag) Node *p; RCSVers *version; - assert (rcs != NULL); - if (rcs->flags & PARTIAL) RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL); @@ -3531,27 +3497,31 @@ struct rcs_keyword { const char *string; size_t len; + int expandit; }; #define KEYWORD_INIT(s) (s), sizeof (s) - 1 -static const struct rcs_keyword keywords[] = +static struct rcs_keyword keywords[] = { - { KEYWORD_INIT ("Author") }, - { KEYWORD_INIT ("Date") }, - { KEYWORD_INIT ("Header") }, - { KEYWORD_INIT ("Id") }, - { KEYWORD_INIT ("Locker") }, - { KEYWORD_INIT ("Log") }, - { KEYWORD_INIT ("Name") }, - { KEYWORD_INIT ("RCSfile") }, - { KEYWORD_INIT ("Revision") }, - { KEYWORD_INIT ("Source") }, - { KEYWORD_INIT ("State") }, - { NULL, 0 } + { KEYWORD_INIT ("Author"), 1 }, + { KEYWORD_INIT ("Date"), 1 }, + { KEYWORD_INIT ("CVSHeader"), 1 }, + { KEYWORD_INIT ("Header"), 1 }, + { KEYWORD_INIT ("Id"), 1 }, + { KEYWORD_INIT ("Locker"), 1 }, + { KEYWORD_INIT ("Log"), 1 }, + { KEYWORD_INIT ("Name"), 1 }, + { KEYWORD_INIT ("RCSfile"), 1 }, + { KEYWORD_INIT ("Revision"), 1 }, + { KEYWORD_INIT ("Source"), 1 }, + { KEYWORD_INIT ("State"), 1 }, + { NULL, 0, 0 }, + { NULL, 0, 0 } }; enum keyword { KEYWORD_AUTHOR = 0, KEYWORD_DATE, + KEYWORD_CVSHEADER, KEYWORD_HEADER, KEYWORD_ID, KEYWORD_LOCKER, @@ -3560,8 +3530,10 @@ enum keyword KEYWORD_RCSFILE, KEYWORD_REVISION, KEYWORD_SOURCE, - KEYWORD_STATE + KEYWORD_STATE, + KEYWORD_LOCALID }; +enum keyword keyword_local = KEYWORD_ID; /* Convert an RCS date string into a readable string. This is like the RCS date2str function. */ @@ -3577,8 +3549,8 @@ printable_date (rcs_date) &sec); if (year < 1900) year += 1900; - sprintf (buf, "%04d/%02d/%02d %02d:%02d:%02d", year, mon, mday, - hour, min, sec); + sprintf (buf, "%04d%c%02d%c%02d %02d:%02d:%02d", + year, datesep, mon, datesep, mday, hour, min, sec); return xstrdup (buf); } @@ -3739,7 +3711,8 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen) slen = s - srch; for (keyword = keywords; keyword->string != NULL; keyword++) { - if (keyword->len == slen + if (keyword->expandit + && keyword->len == slen && strncmp (keyword->string, srch, slen) == 0) { break; @@ -3786,15 +3759,25 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen) free_value = 1; break; + case KEYWORD_CVSHEADER: case KEYWORD_HEADER: case KEYWORD_ID: + case KEYWORD_LOCALID: { const char *path; int free_path; char *date; + char *old_path; - if (kw == KEYWORD_HEADER) + old_path = NULL; + if (kw == KEYWORD_HEADER || + (kw == KEYWORD_LOCALID && + keyword_local == KEYWORD_HEADER)) path = rcs->path; + else if (kw == KEYWORD_CVSHEADER || + (kw == KEYWORD_LOCALID && + keyword_local == KEYWORD_CVSHEADER)) + path = getfullCVSname(rcs->path, &old_path); else path = last_component (rcs->path); path = escape_keyword_value (path, &free_path); @@ -3817,6 +3800,8 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen) * and we can discard the const. */ free ((char *)path); + if (old_path) + free (old_path); free (date); free_value = 1; } @@ -3946,13 +3931,6 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen) if (*snl == '\n') ++cnl; - /* If the log message did not end in a newline, increment - * the newline count so we have space for the extra leader. - * Failure to do so results in a buffer overrun. - */ - if (loglen && snl[-1] != '\n') - ++cnl; - date = printable_date (ver->date); sub = xrealloc (sub, (sublen @@ -3961,10 +3939,6 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen) + strlen (date) + strlen (ver->author) + loglen - /* Use CNL + 2 below: One leader for each log - * line, plus the Revision/Author/Date line, - * plus a trailing blank line. - */ + (cnl + 2) * leader_len + 20)); if (expand != KFLAG_V) @@ -4004,14 +3978,6 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen) ++slnl; memcpy (sub + sublen, sl, slnl - sl); sublen += slnl - sl; - if (slnl == logend && slnl[-1] != '\n') - { - /* There was no EOL at the end of the log message. Add - * one. - */ - sub[sublen] = '\n'; - ++sublen; - } sl = slnl; } } @@ -4130,8 +4096,7 @@ expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen) Otherwise, if WORKFILE is NULL, check out the revision to SOUT. If SOUT is RUN_TTY, then write the contents of the revision to standard output. When using SOUT, the output is generally a - temporary file; don't bother to get the file modes correct. When - NOEXEC is set, WORKFILEs are not written but SOUTs are. + temporary file; don't bother to get the file modes correct. REV is the numeric revision to check out. It may be NULL, which means to check out the head of the default branch. @@ -4206,7 +4171,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat) assert (rev == NULL || isdigit ((unsigned char) *rev)); - if (noexec && !server_active && workfile != NULL) + if (noexec && workfile != NULL) return 0; assert (sout == RUN_TTY || workfile == NULL); @@ -4236,23 +4201,10 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat) gothead = 0; if (! rcsbuf_getrevnum (&rcsbuf, &key)) error (1, 0, "unexpected EOF reading %s", rcs->path); - - if (!STREQ (rcs->head, key)) - error (1, 0, "Expected head revision %s, found %s.", - rcs->head, key); - while (rcsbuf_getkey (&rcsbuf, &key, &value)) { if (STREQ (key, "log")) - { - if (log) - { - error (0, 0, -"Duplicate log keyword found for head revision in RCS file."); - free (log); - } log = rcsbuf_valcopy (&rcsbuf, value, 0, &loglen); - } else if (STREQ (key, "text")) { gothead = 1; @@ -4752,7 +4704,6 @@ RCS_findlock_or_tip (rcs) char *user = getcaller(); Node *lock, *p; List *locklist; - char *defaultrev = NULL; /* Find unique delta locked by caller. This code is very similar to the code in RCS_unlock -- perhaps it could be abstracted @@ -4798,17 +4749,7 @@ RCS_findlock_or_tip (rcs) those error checks are to make users lock before a checkin, and we do that in other ways if at all anyway (e.g. rcslock.pl). */ - defaultrev = RCS_getbranch (rcs, rcs->branch, 0); - p = findnode (rcs->versions, defaultrev); - if (defaultrev != NULL) - free (defaultrev); - if (!p) - { - error (0, 0, "RCS file `%s' does not contain its default revision.", - rcs->path); - return NULL; - } - + p = findnode (rcs->versions, RCS_getbranch (rcs, rcs->branch, 0)); return p->data; } @@ -4922,8 +4863,6 @@ RCS_addbranch (rcs, branch) Node *marker; RCSVers *branchnode; - assert (branch); - /* Append to end by default. */ marker = NULL; @@ -5042,21 +4981,18 @@ RCS_addbranch (rcs, branch) or zero for success. */ int -RCS_checkin (rcs, workfile_in, message, rev, citime, flags) +RCS_checkin (rcs, workfile_in, message, rev, flags) RCSNode *rcs; const char *workfile_in; const char *message; const char *rev; - time_t citime; int flags; { RCSVers *delta, *commitpt; Deltatext *dtext; Node *nodep; char *tmpfile, *changefile; - int dargc = 0; - size_t darg_allocated = 0; - char **dargv = NULL; + char *diffopts; size_t bufsize; int status, checkin_quiet; struct tm *ftm; @@ -5078,7 +5014,6 @@ RCS_checkin (rcs, workfile_in, message, rev, citime, flags) { char *p; int extlen = strlen (RCSEXT); - assert (rcs->path); workfile = xstrdup (last_component (rcs->path)); p = workfile + (strlen (workfile) - extlen); assert (strncmp (p, RCSEXT, extlen) == 0); @@ -5113,8 +5048,6 @@ RCS_checkin (rcs, workfile_in, message, rev, citime, flags) } modtime = ws.st_mtime; } - else if (flags & RCS_FLAGS_USETIME) - modtime = citime; else (void) time (&modtime); ftm = gmtime (&modtime); @@ -5356,7 +5289,6 @@ workfile); if (dots == 0) { tip = xstrdup (rcs->head); - assert (tip != NULL); if (atoi (tip) != atoi (branch)) { newrev = (char *) xrealloc (newrev, strlen (newrev) + 3); @@ -5486,10 +5418,9 @@ workfile); /* Diff options should include --binary if the RCS file has -kb set in its `expand' field. */ - run_add_arg_p (&dargc, &darg_allocated, &dargv, "-a"); - run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n"); - if (rcs->expand && STREQ (rcs->expand, "b")) - run_add_arg_p (&dargc, &darg_allocated, &dargv, "--binary"); + diffopts = (rcs->expand != NULL && STREQ (rcs->expand, "b") + ? "-a -n --binary" + : "-a -n"); if (STREQ (commitpt->version, rcs->head) && numdots (delta->version) == 1) @@ -5512,8 +5443,7 @@ workfile); memset (commitpt->text, 0, sizeof (Deltatext)); bufsize = 0; - switch (diff_exec (workfile, tmpfile, NULL, NULL, - dargc, dargv, changefile)) + switch (diff_exec (workfile, tmpfile, NULL, NULL, diffopts, changefile)) { case 0: case 1: @@ -5561,8 +5491,7 @@ workfile); /* This file is not being inserted at the head, but on a side branch somewhere. Make a diff from the previous revision to the working file. */ - switch (diff_exec (tmpfile, workfile, NULL, NULL, - dargc, dargv, changefile)) + switch (diff_exec (tmpfile, workfile, NULL, NULL, diffopts, changefile)) { case 0: case 1: @@ -5589,9 +5518,6 @@ workfile); } } - run_arg_free_p (dargc, dargv); - free (dargv); - /* Update DELTA linkage. It is important not to do this before the very end of RCS_checkin; if an error arises that forces us to abort checking in, we must not have malformed deltas @@ -5664,13 +5590,7 @@ workfile); freedeltatext (dtext); if (status != 0) - { - /* If delta has not been added to a List, then freeing the Node key - * won't free delta->version. - */ - if (delta->version) free (delta->version); free_rcsvers_contents (delta); - } return status; } @@ -6372,12 +6292,7 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive) /* A range consisting of a branch number means the latest revision on that branch. */ if (RCS_isbranch (rcs, rev1) && STREQ (rev1, rev2)) - { - char *tmp = RCS_getbranch (rcs, rev1, 0); - free (rev1); - free (rev2); - rev1 = rev2 = tmp; - } + rev1 = rev2 = RCS_getbranch (rcs, rev1, 0); else { /* Make sure REV1 and REV2 are ordered correctly (in the @@ -6665,10 +6580,6 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive) } else { - int dargc = 0; - size_t darg_allocated = 0; - char **dargv = NULL; - beforefile = cvs_temp_name(); status = RCS_checkout (rcs, NULL, before, NULL, "-ko", beforefile, (RCSCHECKOUTPROC)0, NULL); @@ -6676,12 +6587,7 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive) goto delrev_done; outfile = cvs_temp_name(); - run_add_arg_p (&dargc, &darg_allocated, &dargv, "-a"); - run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n"); - status = diff_exec (beforefile, afterfile, NULL, NULL, - dargc, dargv, outfile); - run_arg_free_p (dargc, dargv); - free (dargv); + status = diff_exec (beforefile, afterfile, NULL, NULL, "-an", outfile); if (status == 2) { @@ -6779,7 +6685,7 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive) delrev_done: if (rev1 != NULL) free (rev1); - if (rev2 && rev2 != rev1) + if (rev2 != NULL) free (rev2); if (branchpoint != NULL) free (branchpoint); @@ -7140,7 +7046,6 @@ apply_rcs_changes (lines, diffbuf, difflen, name, addvers, delvers) }; struct deltafrag *dfhead; struct deltafrag *df; - int err; dfhead = NULL; for (p = diffbuf; p != NULL && p < diffbuf + difflen; ) @@ -7206,39 +7111,33 @@ apply_rcs_changes (lines, diffbuf, difflen, name, addvers, delvers) } } - err = 0; for (df = dfhead; df != NULL;) { unsigned int ln; - /* Once an error is encountered, just free the rest of the list and - * return. - */ - if (!err) - switch (df->type) - { - case FRAG_ADD: - if (! linevector_add (lines, df->new_lines, df->len, addvers, - df->pos)) - err = 1; - break; - case FRAG_DELETE: - if (df->pos > lines->nlines - || df->pos + df->nlines > lines->nlines) - return 0; - if (delvers != NULL) - for (ln = df->pos; ln < df->pos + df->nlines; ++ln) - lines->vector[ln]->vers = delvers; - linevector_delete (lines, df->pos, df->nlines); - break; - } - + switch (df->type) + { + case FRAG_ADD: + if (! linevector_add (lines, df->new_lines, df->len, addvers, + df->pos)) + return 0; + break; + case FRAG_DELETE: + if (df->pos > lines->nlines + || df->pos + df->nlines > lines->nlines) + return 0; + if (delvers != NULL) + for (ln = df->pos; ln < df->pos + df->nlines; ++ln) + lines->vector[ln]->vers = delvers; + linevector_delete (lines, df->pos, df->nlines); + break; + } df = df->next; free (dfhead); dfhead = df; } - return !err; + return 1; } /* Apply an RCS change text to a buffer. The function name starts @@ -7356,18 +7255,12 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen) struct linevector trunklines; int foundhead; - assert (version); - if (fp == NULL) { rcsbuf_cache_open (rcs, rcs->delta_pos, &fp, &rcsbuf_local); rcsbuf = &rcsbuf_local; } - assert (rcsbuf); - - if (log) *log = NULL; - ishead = 1; vers = NULL; prev_vers = NULL; @@ -7395,13 +7288,6 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen) if (! rcsbuf_getrevnum (rcsbuf, &key)) error (1, 0, "unexpected EOF reading RCS file %s", rcs->path); - /* look up the revision */ - node = findnode (rcs->versions, key); - if (!node) - error (1, 0, - "Delta text %s without revision information in `%s'.", - key, rcs->path); - if (next != NULL && ! STREQ (next, key)) { /* This is not the next version we need. It is a branch @@ -7413,6 +7299,13 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen) { isnext = 1; + /* look up the revision */ + node = findnode (rcs->versions, key); + if (node == NULL) + error (1, 0, + "mismatch in rcs file %s between deltas and deltatexts (%s)", + rcs->path, key); + /* Stash the previous version. */ prev_vers = vers; @@ -7438,12 +7331,6 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen) && STREQ (key, "log") && STREQ (branchversion, version)) { - if (*log != NULL) - { - error (0, 0, "Duplicate `log' keyword in RCS file (`%s').", - rcs->path); - free (*log); - } *log = rcsbuf_valcopy (rcsbuf, value, 0, loglen); } @@ -7525,9 +7412,6 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen) if (vers->branches == NULL) error (1, 0, "missing expected branches in %s", rcs->path); - if (!cpversion) - error (1, 0, "Invalid revision number in `%s'.", - rcs->path); *cpversion = '.'; ++cpversion; cpversion = strchr (cpversion, '.'); @@ -7913,10 +7797,9 @@ RCS_getdeltatext (rcs, fp, rcsbuf) } p = findnode (rcs->versions, num); - if (!p) - error (1, 0, - "Delta text %s without revision information in `%s'.", - num, rcs->path); + if (p == NULL) + error (1, 0, "mismatch in rcs file %s between deltas and deltatexts (%s)", + rcs->path, num); d = (Deltatext *) xmalloc (sizeof (Deltatext)); d->version = xstrdup (num); @@ -8181,65 +8064,31 @@ RCS_putdtree (rcs, rev, fp) RCSVers *versp; Node *p, *branch; - /* Previously, this function used a recursive implementation, but - if the trunk has a huge number of revisions and the program - stack is not big, a stack overflow could occur, so this - nonrecursive version was developed to be more safe. */ - Node *branchlist, *onebranch; - List *branches; - List *onebranchlist; - if (rev == NULL) return; - branches = getlist(); - - for (; rev != NULL;) + /* Find the delta node for this revision. */ + p = findnode (rcs->versions, rev); + if (p == NULL) { - /* Find the delta node for this revision. */ - p = findnode (rcs->versions, rev); - if (p == NULL) - { - error (1, 0, - "error parsing repository file %s, file may be corrupt.", - rcs->path); - } - - versp = p->data; - - /* Print the delta node and go for its `next' node. This - prints the trunk. If there are any branches printed on this - revision, mark we have some. */ - putdelta (versp, fp); - /* Store branch information into branch list so to write its - trunk afterwards */ - if (versp->branches != NULL) - { - branch = getnode(); - branch->data = versp->branches; - - addnode(branches, branch); - } - - rev = versp->next; + error (1, 0, + "error parsing repository file %s, file may be corrupt.", + rcs->path); } + + versp = p->data; - /* If there are any branches printed on this revision, + /* Print the delta node and recurse on its `next' node. This prints + the trunk. If there are any branches printed on this revision, print those trunks as well. */ - branchlist = branches->list; - for (branch = branchlist->next; - branch != branchlist; - branch = branch->next) - { - onebranchlist = (List *)(branch->data); - onebranch = onebranchlist->list; - for (p = onebranch->next; p != onebranch; p = p->next) + putdelta (versp, fp); + RCS_putdtree (rcs, versp->next, fp); + if (versp->branches != NULL) + { + branch = versp->branches->list; + for (p = branch->next; p != branch; p = p->next) RCS_putdtree (rcs, p->key, fp); - - branch->data = NULL; /* so to prevent its freeing on dellist */ } - - dellist(&branches); } static void @@ -8344,11 +8193,6 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt) } np = findnode (rcs->versions, dtext->version); - if (!np) - error (1, 0, - "Delta text %s without revision information in `%s'.", - dtext->version, rcs->path); - dadmin = np->data; /* If this revision has been outdated, just skip it. */ @@ -8636,28 +8480,6 @@ rcs_internal_unlockfile (fp, rcsfile) real solution is to check each call to fprintf rather than waiting until the end like this. */ error (1, errno, "error writing to lock file %s", rcs_lockfile); - - /* Flush and sync the file, or the user may be told the commit completed, - * while a server crash/power failure could still cause the data to be - * lost. - * - * Invoking rename(",<file>," , "<file>,v") on Linux and almost all UNIXs - * only flushes the inode for the target file to disk, it does not - * guarantee flush of the kernel buffers allocated for the ,<file>,. - * Depending upon the load on the machine, the Linux kernel's flush daemon - * process may not flush for a while. In the meantime the CVS transaction - * could have been declared committed to the end CVS user (CVS process has - * returned the final "OK"). If the machine crashes prior to syncing the - * changes to disk, the committed transaction can be lost. - */ - if (fflush (fp) != 0) - error (1, errno, "error flushing file `%s' to kernel buffers", - rcs_lockfile); -#ifdef HAVE_FSYNC - if (fsync (rcs_lockfd) < 0) - error (1, errno, "error fsyncing file `%s'", rcs_lockfile); -#endif - if (fclose (fp) == EOF) error (1, errno, "error closing lock file %s", rcs_lockfile); rcs_lockfd = -1; @@ -8712,8 +8534,6 @@ RCS_rewrite (rcs, newdtext, insertpt) FILE *fin, *fout; struct rcsbuffer rcsbufin; - assert (rcs); - if (noexec) return; @@ -8837,3 +8657,105 @@ make_file_label (path, rev, rcs) } return label; } + +void +RCS_setlocalid (arg) + const char *arg; +{ + char *copy, *next, *key; + + copy = xstrdup(arg); + next = copy; + key = strtok(next, "="); + + keywords[KEYWORD_LOCALID].string = xstrdup(key); + keywords[KEYWORD_LOCALID].len = strlen(key); + keywords[KEYWORD_LOCALID].expandit = 1; + + /* options? */ + while (key = strtok(NULL, ",")) { + if (!strcmp(key, keywords[KEYWORD_ID].string)) + keyword_local = KEYWORD_ID; + else if (!strcmp(key, keywords[KEYWORD_HEADER].string)) + keyword_local = KEYWORD_HEADER; + else if (!strcmp(key, keywords[KEYWORD_CVSHEADER].string)) + keyword_local = KEYWORD_CVSHEADER; + else + error(1, 0, "Unknown LocalId mode: %s", key); + } + free(copy); +} + +void +RCS_setincexc (arg) + const char *arg; +{ + char *key; + char *copy, *next; + int include = 0; + struct rcs_keyword *keyword; + + copy = xstrdup(arg); + next = copy; + switch (*next++) { + case 'e': + include = 0; + break; + case 'i': + include = 1; + break; + default: + free(copy); + return; + } + + if (include) + for (keyword = keywords; keyword->string != NULL; keyword++) + { + keyword->expandit = 0; + } + + key = strtok(next, ","); + while (key) { + for (keyword = keywords; keyword->string != NULL; keyword++) { + if (strcmp (keyword->string, key) == 0) + keyword->expandit = include; + } + key = strtok(NULL, ","); + } + free(copy); + return; +} + +#define ATTIC "/" CVSATTIC +static char * +getfullCVSname(CVSname, pathstore) + char *CVSname, **pathstore; +{ + if (current_parsed_root->directory) { + int rootlen; + char *c = NULL; + int alen = sizeof(ATTIC) - 1; + + *pathstore = xstrdup(CVSname); + if ((c = strrchr(*pathstore, '/')) != NULL) { + if (c - *pathstore >= alen) { + if (!strncmp(c - alen, ATTIC, alen)) { + while (*c != '\0') { + *(c - alen) = *c; + c++; + } + *(c - alen) = '\0'; + } + } + } + + rootlen = strlen(current_parsed_root->directory); + if (!strncmp(*pathstore, current_parsed_root->directory, rootlen) && + (*pathstore)[rootlen] == '/') + CVSname = (*pathstore + rootlen + 1); + else + CVSname = (*pathstore); + } + return CVSname; +} diff --git a/contrib/cvs/src/rcs.h b/contrib/cvs/src/rcs.h index 3a66640..d40d178 100644 --- a/contrib/cvs/src/rcs.h +++ b/contrib/cvs/src/rcs.h @@ -1,16 +1,13 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. * * RCS source control definitions needed by rcs.c and friends + * + * $FreeBSD$ */ /* Strings which indicate a conflict if they occur at the start of a line. */ @@ -229,8 +226,7 @@ void RCS_setexpand PROTO ((RCSNode *, const char *)); int RCS_checkout PROTO ((RCSNode *, const char *, const char *, const char *, const char *, const char *, RCSCHECKOUTPROC, void *)); int RCS_checkin PROTO ((RCSNode *rcs, const char *workfile, - const char *message, const char *rev, time_t citime, - int flags)); + const char *message, const char *rev, int flags)); int RCS_cmp_file PROTO((RCSNode *, const char *, char **, const char *, const char *, const char *)); int RCS_settag PROTO ((RCSNode *, const char *, const char *)); @@ -250,8 +246,11 @@ int rcs_change_text PROTO ((const char *, char *, size_t, const char *, void RCS_deltas PROTO ((RCSNode *, FILE *, struct rcsbuffer *, const char *, enum rcs_delta_op, char **, size_t *, char **, size_t *)); +void RCS_setincexc PROTO ((const char *arg)); +void RCS_setlocalid PROTO ((const char *arg)); char *make_file_label PROTO ((const char *, const char *, RCSNode *)); +extern int datesep; extern int preserve_perms; /* From import.c. */ diff --git a/contrib/cvs/src/rcscmds.c b/contrib/cvs/src/rcscmds.c index a9e576a..df91ff8 100644 --- a/contrib/cvs/src/rcscmds.c +++ b/contrib/cvs/src/rcscmds.c @@ -1,17 +1,14 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. * * The functions in this file provide an interface for performing * operations directly on RCS files. + * + * $FreeBSD$ */ #include "cvs.h" @@ -56,8 +53,8 @@ On a related note, see the comments at diff_exec, later in this file, for more on the diff library. */ -static void RCS_output_diff_options PROTO ((int, char *const *, const char *, - const char *, const char *)); +static void RCS_output_diff_options PROTO ((const char *, const char *, + const char *, const char *)); /* Stuff to deal with passing arguments the way libdiff.a wants to deal @@ -69,18 +66,17 @@ static void RCS_output_diff_options PROTO ((int, char *const *, const char *, argument will be parsed into whitespace separated words and added to the global call_diff_argv list. - Then, optionally, call call_diff_add_arg for each additional argument + Then, optionally, call call_diff_arg for each additional argument that you'd like to pass to the diff library. Finally, call call_diff or call_diff3 to produce the diffs. */ static char **call_diff_argv; static int call_diff_argc; -static size_t call_diff_argc_allocated; +static int call_diff_argc_allocated; static void call_diff_add_arg PROTO ((const char *)); -static void call_diff_setup PROTO ((const char *prog, - int argc, char * const *argv)); +static void call_diff_setup PROTO ((const char *prog)); static int call_diff PROTO ((const char *out)); static int call_diff3 PROTO ((char *out)); @@ -89,37 +85,62 @@ static void call_diff_flush_output PROTO((void)); static void call_diff_write_stdout PROTO((const char *)); static void call_diff_error PROTO((const char *, const char *, const char *)); - - -static void -call_diff_add_arg (s) - const char *s; -{ - run_add_arg_p (&call_diff_argc, &call_diff_argc_allocated, &call_diff_argv, - s); -} - - - /* VARARGS */ static void -call_diff_setup (prog, argc, argv) +call_diff_setup (prog) const char *prog; - int argc; - char * const *argv; { + char *cp; int i; + char *call_diff_prog; /* clean out any malloc'ed values from call_diff_argv */ - run_arg_free_p (call_diff_argc, call_diff_argv); + for (i = 0; i < call_diff_argc; i++) + { + if (call_diff_argv[i]) + { + free (call_diff_argv[i]); + call_diff_argv[i] = (char *) 0; + } + } call_diff_argc = 0; + call_diff_prog = xstrdup (prog); + /* put each word into call_diff_argv, allocating it as we go */ - call_diff_add_arg (prog); - for (i = 0; i < argc; i++) - call_diff_add_arg (argv[i]); + for (cp = strtok (call_diff_prog, " \t"); + cp != NULL; + cp = strtok ((char *) NULL, " \t")) + call_diff_add_arg (cp); + free (call_diff_prog); } +static void +call_diff_arg (s) + const char *s; +{ + call_diff_add_arg (s); +} + +static void +call_diff_add_arg (s) + const char *s; +{ + /* allocate more argv entries if we've run out */ + if (call_diff_argc >= call_diff_argc_allocated) + { + call_diff_argc_allocated += 50; + call_diff_argv = (char **) + xrealloc ((char *) call_diff_argv, + call_diff_argc_allocated * sizeof (char **)); + } + + if (s) + call_diff_argv[call_diff_argc++] = xstrdup (s); + else + /* Not post-incremented on purpose! */ + call_diff_argv[call_diff_argc] = (char *) 0; +} /* Callback function for the diff library to write data to the output file. This is used when we are producing output to stdout. */ @@ -192,8 +213,6 @@ static int call_diff (out) const char *out; { - call_diff_add_arg (NULL); - if (out == RUN_TTY) return diff_run (call_diff_argc, call_diff_argv, NULL, &call_diff_stdout_callbacks); @@ -245,7 +264,6 @@ RCS_merge(rcs, path, workfile, options, rev1, rev2) symbolic). */ xrev1 = RCS_gettag (rcs, rev1, 0, NULL); xrev2 = RCS_gettag (rcs, rev2, 0, NULL); - assert (xrev1 && xrev2); /* Check out chosen revisions. The error message when RCS_checkout fails is not very informative -- it is taken verbatim from RCS 5.7, @@ -286,21 +304,21 @@ RCS_merge(rcs, path, workfile, options, rev1, rev2) /* Remember that the first word in the `call_diff_setup' string is used now only for diagnostic messages -- CVS no longer forks to run diff3. */ diffout = cvs_temp_name(); - call_diff_setup ("diff3", 0, NULL); - call_diff_add_arg ("-E"); - call_diff_add_arg ("-am"); - - call_diff_add_arg ("-L"); - call_diff_add_arg (workfile); - call_diff_add_arg ("-L"); - call_diff_add_arg (xrev1); - call_diff_add_arg ("-L"); - call_diff_add_arg (xrev2); - - call_diff_add_arg ("--"); - call_diff_add_arg (workfile); - call_diff_add_arg (tmp1); - call_diff_add_arg (tmp2); + call_diff_setup ("diff3"); + call_diff_arg ("-E"); + call_diff_arg ("-am"); + + call_diff_arg ("-L"); + call_diff_arg (workfile); + call_diff_arg ("-L"); + call_diff_arg (xrev1); + call_diff_arg ("-L"); + call_diff_arg (xrev2); + + call_diff_arg ("--"); + call_diff_arg (workfile); + call_diff_arg (tmp1); + call_diff_arg (tmp2); retval = call_diff3 (diffout); @@ -366,11 +384,10 @@ RCS_merge(rcs, path, workfile, options, rev1, rev2) about this--any such features are undocumented in the context of CVS, and I'm not sure how important to users. */ int -RCS_exec_rcsdiff (rcsfile, diff_argc, diff_argv, options, rev1, rev1_cache, - rev2, label1, label2, workfile) +RCS_exec_rcsdiff(rcsfile, opts, options, rev1, rev1_cache, rev2, + label1, label2, workfile ) RCSNode *rcsfile; - int diff_argc; - char * const *diff_argv; + const char *opts; const char *options; const char *rev1; const char *rev1_cache; @@ -450,9 +467,8 @@ RCS file: ", 0); use_file2 = tmpfile2; } - RCS_output_diff_options (diff_argc, diff_argv, rev1, rev2, workfile); - status = diff_exec (use_file1, use_file2, label1, label2, - diff_argc, diff_argv, RUN_TTY); + RCS_output_diff_options (opts, rev1, rev2, workfile); + status = diff_exec( use_file1, use_file2, label1, label2, opts, RUN_TTY ); if (status >= 0) { retval = status; @@ -531,15 +547,16 @@ RCS file: ", 0); message on stderr. */ int -diff_exec (file1, file2, label1, label2, dargc, dargv, out) +diff_exec (file1, file2, label1, label2, options, out) const char *file1; const char *file2; const char *label1; const char *label2; - int dargc; - char * const *dargv; + const char *options; const char *out; { + char *args; + #ifdef PRESERVE_PERMISSIONS_SUPPORT /* If either file1 or file2 are special files, pretend they are /dev/null. Reason: suppose a file that represents a block @@ -573,15 +590,18 @@ diff_exec (file1, file2, label1, label2, dargc, dargv, out) } #endif - /* The first arg to call_diff_setup is used only for error reporting. */ - call_diff_setup ("diff", dargc, dargv); + args = xmalloc (strlen (options) + 10); + /* The first word in this string is used only for error reporting. */ + sprintf (args, "diff %s", options); + call_diff_setup (args); if (label1) - call_diff_add_arg (label1); + call_diff_arg (label1); if (label2) - call_diff_add_arg (label2); - call_diff_add_arg ("--"); - call_diff_add_arg (file1); - call_diff_add_arg (file2); + call_diff_arg (label2); + call_diff_arg ("--"); + call_diff_arg (file1); + call_diff_arg (file2); + free (args); return call_diff (out); } @@ -593,23 +613,19 @@ diff_exec (file1, file2, label1, label2, dargc, dargv, out) that I have seen. */ static void -RCS_output_diff_options (diff_argc, diff_argv, rev1, rev2, workfile) - int diff_argc; - char * const *diff_argv; +RCS_output_diff_options (opts, rev1, rev2, workfile) + const char *opts; const char *rev1; const char *rev2; const char *workfile; { - int i; - - cvs_output ("diff", 0); - for (i = 0; i < diff_argc; i++) - { - cvs_output (" ", 1); - cvs_output (diff_argv[i], 0); - } - cvs_output (" -r", 3); - cvs_output (rev1, 0); + char *tmp; + + tmp = (char *) xmalloc (strlen (opts) + strlen (rev1) + 10); + + sprintf (tmp, "diff%s -r%s", opts, rev1); + cvs_output (tmp, 0); + free (tmp); if (rev2) { diff --git a/contrib/cvs/src/recurse.c b/contrib/cvs/src/recurse.c index 2416861..20a0f9b 100644 --- a/contrib/cvs/src/recurse.c +++ b/contrib/cvs/src/recurse.c @@ -1,17 +1,12 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. * * General recursion handler * + * $FreeBSD$ */ #include "cvs.h" @@ -140,25 +135,6 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat, frame.aflag = aflag; frame.locktype = locktype; frame.dosrcs = dosrcs; - - /* If our repository_in has a trailing "/.", remove it before storing it - * for do_recursion(). - * - * FIXME: This is somewhat of a hack in the sense that many of our callers - * painstakingly compute and add the trailing '.' we now remove. - */ - while (repository_in && strlen (repository_in) >= 2 - && repository_in[strlen (repository_in) - 2] == '/' - && repository_in[strlen (repository_in) - 1] == '.') - { - /* Beware the case where the string is exactly "/." or "//.". - * Paths with a leading "//" are special on some early UNIXes. - */ - if (strlen (repository_in) == 2 || strlen (repository_in) == 3) - repository_in[strlen (repository_in) - 1] = '\0'; - else - repository_in[strlen (repository_in) - 2] = '\0'; - } frame.repository = repository_in; expand_wild (argc, argv, &argc, &argv); @@ -196,24 +172,21 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat, && CVSroot_cmdline == NULL && current_parsed_root->isremote) { - cvsroot_t *root = Name_Root (NULL, update_dir); - if (root) - { - if (strcmp (root->original, current_parsed_root->original)) - /* We're skipping this directory because it is for - * a different root. Therefore, we just want to - * do the subdirectories only. Processing files would - * cause a working directory from one repository to be - * processed against a different repository, which could - * cause all kinds of spurious conflicts and such. - * - * Question: what about the case of "cvs update foo" - * where we process foo/bar and not foo itself? That - * seems to be handled somewhere (else) but why should - * it be a separate case? Needs investigation... */ - just_subdirs = 1; - free_cvsroot_t (root); - } + char *root = Name_Root (NULL, update_dir); + if (root && strcmp (root, current_parsed_root->original) != 0) + /* We're skipping this directory because it is for + a different root. Therefore, we just want to + do the subdirectories only. Processing files would + cause a working directory from one repository to be + processed against a different repository, which could + cause all kinds of spurious conflicts and such. + + Question: what about the case of "cvs update foo" + where we process foo/bar and not foo itself? That + seems to be handled somewhere (else) but why should + it be a separate case? Needs investigation... */ + just_subdirs = 1; + free (root); } #endif @@ -334,8 +307,11 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat, addfile (&files_by_dir, dir, comp); else if (isdir (dir)) { - if ((which & W_LOCAL) && isdir (CVSADM) && - !current_parsed_root->isremote) + if ((which & W_LOCAL) && isdir (CVSADM) +#ifdef CLIENT_SUPPORT + && !current_parsed_root->isremote +#endif + ) { /* otherwise, look for it in the repository. */ char *tmp_update_dir; @@ -591,7 +567,7 @@ do_recursion (frame) * generating data, to give the buffers a chance to drain to the * remote client. We should not have locks active at this point, * but if there are writelocks around, we cannot pause here. */ - if (server_active && locktype != CVS_LOCK_WRITE) + if (server_active && locktype != CVS_LOCK_NONE) server_pause_check(); #endif @@ -607,41 +583,43 @@ do_recursion (frame) directories, since we're guaranteed to have only one CVSROOT -- our own. */ - /* If -d was specified, it should override CVS/Root. + if ( + /* If -d was specified, it should override CVS/Root. + + In the single-repository case, it is long-standing CVS behavior + and makes sense - the user might want another access method, + another server (which mounts the same repository), &c. - In the single-repository case, it is long-standing CVS behavior - and makes sense - the user might want another access method, - another server (which mounts the same repository), &c. + In the multiple-repository case, -d overrides all CVS/Root + files. That is the only plausible generalization I can + think of. */ + CVSroot_cmdline == NULL - In the multiple-repository case, -d overrides all CVS/Root - files. That is the only plausible generalization I can - think of. */ - if (CVSroot_cmdline == NULL && !server_active) +#ifdef SERVER_SUPPORT + && ! server_active +#endif + ) { - cvsroot_t *this_root = Name_Root ((char *) NULL, update_dir); + char *this_root = Name_Root ((char *) NULL, update_dir); if (this_root != NULL) { - if (findnode (root_directories, this_root->original)) - { - process_this_directory = !strcmp (current_parsed_root->original, - this_root->original); - free_cvsroot_t (this_root); - } - else + if (findnode (root_directories, this_root) == NULL) { /* Add it to our list. */ Node *n = getnode (); n->type = NT_UNKNOWN; - n->key = xstrdup (this_root->original); - n->data = this_root; + n->key = xstrdup (this_root); if (addnode (root_directories, n)) - error (1, 0, "cannot add new CVSROOT %s", - this_root->original); - - process_this_directory = 0; + error (1, 0, "cannot add new CVSROOT %s", this_root); + } + + process_this_directory = + (strcmp (current_parsed_root->original, this_root) == 0); + + free (this_root); } } @@ -704,8 +682,7 @@ do_recursion (frame) if (repository == NULL) { Name_Repository ((char *) NULL, update_dir); - assert (!"Not reached. Please report this problem to <" - PACKAGE_BUGREPORT ">"); + assert (!"Not reached. Please report this problem to <bug-cvs@gnu.org>"); } /* find the files and fill in entries if appropriate */ @@ -1054,41 +1031,42 @@ but CVS uses %s for its own purposes; skipping %s directory", /* Only process this directory if the root matches. This nearly duplicates code in do_recursion. */ - /* If -d was specified, it should override CVS/Root. + if ( + /* If -d was specified, it should override CVS/Root. + + In the single-repository case, it is long-standing CVS behavior + and makes sense - the user might want another access method, + another server (which mounts the same repository), &c. - In the single-repository case, it is long-standing CVS behavior - and makes sense - the user might want another access method, - another server (which mounts the same repository), &c. + In the multiple-repository case, -d overrides all CVS/Root + files. That is the only plausible generalization I can + think of. */ + CVSroot_cmdline == NULL - In the multiple-repository case, -d overrides all CVS/Root - files. That is the only plausible generalization I can - think of. */ - if (CVSroot_cmdline == NULL && !server_active) +#ifdef SERVER_SUPPORT + && ! server_active +#endif + ) { - cvsroot_t *this_root = Name_Root (dir, update_dir); + char *this_root = Name_Root (dir, update_dir); if (this_root != NULL) { - if (findnode (root_directories, this_root->original)) - { - process_this_directory = !strcmp (current_parsed_root->original, - this_root->original); - free_cvsroot_t (this_root); - } - else + if (findnode (root_directories, this_root) == NULL) { /* Add it to our list. */ Node *n = getnode (); n->type = NT_UNKNOWN; - n->key = xstrdup (this_root->original); - n->data = this_root; + n->key = xstrdup (this_root); if (addnode (root_directories, n)) - error (1, 0, "cannot add new CVSROOT %s", - this_root->original); + error (1, 0, "cannot add new CVSROOT %s", this_root); - process_this_directory = 0; } + + process_this_directory = (strcmp (current_parsed_root->original, this_root) == 0); + + free (this_root); } } diff --git a/contrib/cvs/src/server.c b/contrib/cvs/src/server.c index 29aab00..e186c34 100644 --- a/contrib/cvs/src/server.c +++ b/contrib/cvs/src/server.c @@ -8,6 +8,10 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ +/* + * $FreeBSD$ + */ + #include <assert.h> #include "cvs.h" #include "watch.h" @@ -16,8 +20,6 @@ #include "getline.h" #include "buffer.h" -int server_active = 0; - #if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT) # ifdef HAVE_GSSAPI /* This stuff isn't included solely with SERVER_SUPPORT since some of these @@ -358,20 +360,13 @@ create_adm_p (base_dir, dir) dir_where_cvsadm_lives = xmalloc (strlen (base_dir) + strlen (dir) + 100); if (dir_where_cvsadm_lives == NULL) - { - free (p); return ENOMEM; - } /* Allocate some space for the temporary string in which we will construct filenames. */ tmp = xmalloc (strlen (base_dir) + strlen (dir) + 100); if (tmp == NULL) - { - free (p); - free (dir_where_cvsadm_lives); return ENOMEM; - } /* We make several passes through this loop. On the first pass, @@ -782,6 +777,9 @@ E Protocol error: Root says \"%s\" but pserver says \"%s\"", nothing. But for rsh, we need to do it now. */ parse_config (current_parsed_root->directory); + /* Now is a good time to read CVSROOT/options too. */ + parseopts(current_parsed_root->directory); + path = xmalloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM) + 2); @@ -1236,7 +1234,6 @@ serve_sticky (arg) if (alloc_pending (80 + strlen (CVSADM_TAG))) sprintf (pending_error_text, "E cannot write to %s", CVSADM_TAG); pending_error = save_errno; - (void) fclose (f); return; } if (fclose (f) == EOF) @@ -1685,9 +1682,7 @@ serve_unchanged (arg) * is allowed, but broken versions of WinCVS & TortoiseCVS rely on * this behavior. */ - if (*timefield != '+') - /* Skip this for entries with conflict markers. */ - *timefield = '='; + *timefield = '='; break; } } @@ -1758,10 +1753,7 @@ serve_is_modified (arg) * is allowed, but broken versions of WinCVS & TortoiseCVS rely on * this behavior. */ - if (*timefield != '+') - /* Skip this for entries with conflict markers. */ - *timefield = 'M'; - + *timefield = 'M'; if (kopt != NULL) { if (alloc_pending (strlen (name) + 80)) @@ -1848,7 +1840,6 @@ serve_entry (arg) cp = xmalloc (strlen (arg) + 2); if (cp == NULL) { - free (p); pending_error = ENOMEM; return; } @@ -2712,25 +2703,6 @@ set_nonblock_fd (fd) -/* - * Set buffer FD to blocking I/O. Returns 0 for success or errno code. - */ -int -set_block_fd (fd) - int fd; -{ - int flags; - - flags = fcntl (fd, F_GETFL, 0); - if (flags < 0) - return errno; - if (fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) < 0) - return errno; - return 0; -} - - - static void do_cvs_command (cmd_name, command) char *cmd_name; @@ -2954,31 +2926,22 @@ error \n"); { char junk; ssize_t status; - set_block_fd (flowcontrol_pipe[0]); - while ((status = read (flowcontrol_pipe[0], &junk, 1)) > 0); + while ((status = read (flowcontrol_pipe[0], &junk, 1)) > 0 + || (status == -1 && errno == EAGAIN)); } /* FIXME: No point in printing an error message with error(), * as STDERR is already closed, but perhaps this could be syslogged? */ #endif - rcs_cleanup (); - Lock_Cleanup (); - /* Don't call server_cleanup - the parent will handle that. */ -#ifdef SYSTEM_CLEANUP - /* Hook for OS-specific behavior, for example socket subsystems on - NT and OS2 or dealing with windows and arguments on Mac. */ - SYSTEM_CLEANUP (); -#endif exit (exitstatus); } /* OK, sit around getting all the input from the child. */ { - struct buffer *stdoutbuf = NULL; - struct buffer *stderrbuf = NULL; - struct buffer *protocol_inbuf = NULL; - int err_exit = 0; + struct buffer *stdoutbuf; + struct buffer *stderrbuf; + struct buffer *protocol_inbuf; /* Number of file descriptors to check in select (). */ int num_to_check; int count_needed = 1; @@ -3031,8 +2994,7 @@ error \n"); { buf_output0 (buf_to_net, "E close failed\n"); print_error (errno); - err_exit = 1; - goto child_finish; + goto error_exit; } stdout_pipe[1] = -1; @@ -3040,8 +3002,7 @@ error \n"); { buf_output0 (buf_to_net, "E close failed\n"); print_error (errno); - err_exit = 1; - goto child_finish; + goto error_exit; } stderr_pipe[1] = -1; @@ -3049,8 +3010,7 @@ error \n"); { buf_output0 (buf_to_net, "E close failed\n"); print_error (errno); - err_exit = 1; - goto child_finish; + goto error_exit; } protocol_pipe[1] = -1; @@ -3059,8 +3019,7 @@ error \n"); { buf_output0 (buf_to_net, "E close failed\n"); print_error (errno); - err_exit = 1; - goto child_finish; + goto error_exit; } flowcontrol_pipe[0] = -1; #endif /* SERVER_FLOWCONTROL */ @@ -3069,9 +3028,7 @@ error \n"); { buf_output0 (buf_to_net, "E close failed\n"); print_error (errno); - dev_null_fd = -1; /* Do not try to close it again. */ - err_exit = 1; - goto child_finish; + goto error_exit; } dev_null_fd = -1; @@ -3158,8 +3115,7 @@ error \n"); { buf_output0 (buf_to_net, "E select failed\n"); print_error (errno); - err_exit = 1; - goto child_finish; + goto error_exit; } } while (numfds < 0); @@ -3192,8 +3148,7 @@ error \n"); { buf_output0 (buf_to_net, "E buf_input_data failed\n"); print_error (status); - err_exit = 1; - goto child_finish; + goto error_exit; } /* @@ -3267,8 +3222,7 @@ error \n"); { buf_output0 (buf_to_net, "E buf_input_data failed\n"); print_error (status); - err_exit = 1; - goto child_finish; + goto error_exit; } /* What should we do with errors? syslog() them? */ @@ -3293,8 +3247,7 @@ error \n"); { buf_output0 (buf_to_net, "E buf_input_data failed\n"); print_error (status); - err_exit = 1; - goto child_finish; + goto error_exit; } /* What should we do with errors? syslog() them? */ @@ -3374,33 +3327,21 @@ E CVS locks may need cleaning up.\n"); command_pid = -1; } - child_finish: /* * OK, we've waited for the child. By now all CVS locks are free * and it's OK to block on the network. */ set_block (buf_to_net); buf_flush (buf_to_net, 1); - if (protocol_inbuf) - { - buf_shutdown (protocol_inbuf); - buf_free (protocol_inbuf); - protocol_inbuf = NULL; - } - if (stderrbuf) - { - buf_shutdown (stderrbuf); - buf_free (stderrbuf); - stderrbuf = NULL; - } - if (stdoutbuf) - { - buf_shutdown (stdoutbuf); - buf_free (stdoutbuf); - stdoutbuf = NULL; - } - if (err_exit) - goto error_exit; + buf_shutdown (protocol_inbuf); + buf_free (protocol_inbuf); + protocol_inbuf = NULL; + buf_shutdown (stderrbuf); + buf_free (stderrbuf); + stderrbuf = NULL; + buf_shutdown (stdoutbuf); + buf_free (stdoutbuf); + stdoutbuf = NULL; } if (errs) @@ -3424,8 +3365,7 @@ E CVS locks may need cleaning up.\n"); command_pid = -1; } - if (dev_null_fd >= 0) - close (dev_null_fd); + close (dev_null_fd); close (protocol_pipe[0]); close (protocol_pipe[1]); close (stderr_pipe[0]); @@ -3753,10 +3693,6 @@ server_checked_in (file, update_dir, repository) const char *update_dir; const char *repository; { - assert (file); - assert (update_dir); - assert (repository); - if (noexec) return; if (scratched_file != NULL && entries_line == NULL) @@ -4190,7 +4126,6 @@ server_updated (finfo, vers, updated, mode, checksum, filebuf) free (scratched_file); scratched_file = NULL; } - buf_send_counted (protocol); return; } @@ -4269,6 +4204,7 @@ CVS server internal error: no mode in server_updated"); if (updated == SERVER_UPDATED) { Node *node; + Entnode *entnode; if (!(supported_response ("Created") && supported_response ("Update-existing"))) @@ -4286,13 +4222,9 @@ CVS server internal error: no mode in server_updated"); in case we end up processing it again (e.g. modules3-6 in the testsuite). */ node = findnode_fn (finfo->entries, finfo->file); - assert (node != NULL); - if (node != NULL) - { - Entnode *entnode = node->data; - free (entnode->timestamp); - entnode->timestamp = xstrdup ("="); - } + entnode = node->data; + free (entnode->timestamp); + entnode->timestamp = xstrdup ("="); } else if (updated == SERVER_MERGED) buf_output0 (protocol, "Merged "); @@ -4580,12 +4512,9 @@ struct template_proc_data static struct template_proc_data *tpd; static int -template_proc PROTO((const char *repository, const char *template)); - -static int template_proc (repository, template) - const char *repository; - const char *template; + char *repository; + char *template; { FILE *fp; char buf[1024]; @@ -4863,7 +4792,6 @@ struct request requests[] = REQ_LINE("Checkin-time", serve_checkin_time, 0), REQ_LINE("Modified", serve_modified, RQ_ESSENTIAL), REQ_LINE("Is-modified", serve_is_modified, 0), - REQ_LINE("Empty-conflicts", serve_noop, 0), /* The client must send this request to interoperate with CVS 1.5 through 1.9 servers. The server must support it (although it can @@ -5118,6 +5046,8 @@ server_cleanup (sig) } } +int server_active = 0; + int server (argc, argv) int argc; @@ -5549,7 +5479,6 @@ check_repository_password (username, password, repository, host_user_ptr) { if (!existence_error (errno)) error (0, errno, "cannot open %s", filename); - free (filename); return 0; } @@ -5680,7 +5609,10 @@ check_password (username, password, repository) password file. If so, that's enough to authenticate with. If not, we'll check /etc/passwd. */ - rc = check_repository_password (username, password, repository, + if (require_real_user) + rc = 0; /* "not found" */ + else + rc = check_repository_password (username, password, repository, &host_user); if (rc == 2) @@ -5980,8 +5912,6 @@ pserver_authenticate_connection () printf ("I LOVE YOU\n"); fflush (stdout); - /* It's okay to skip rcs_cleanup() and Lock_Cleanup() here. */ - #ifdef SYSTEM_CLEANUP /* Hook for OS-specific behavior, for example socket subsystems on NT and OS2 or dealing with windows and arguments on Mac. */ @@ -6495,10 +6425,12 @@ cvs_output (str, len) size_t to_write = len; const char *p = str; - /* Local users that do 'cvs status 2>&1' on a local repository - may see the informational messages out-of-order with the - status messages unless we use the fflush (stderr) here. */ - fflush (stderr); + /* For symmetry with cvs_outerr we would call fflush (stderr) + here. I guess the assumption is that stderr will be + unbuffered, so we don't need to. That sounds like a sound + assumption from the manpage I looked at, but if there was + something fishy about it, my guess is that calling fflush + would not produce a significant performance problem. */ while (to_write > 0) { @@ -6555,16 +6487,16 @@ this client does not support writing binary files to stdout"); size_t written; size_t to_write = len; const char *p = str; + + /* For symmetry with cvs_outerr we would call fflush (stderr) + here. I guess the assumption is that stderr will be + unbuffered, so we don't need to. That sounds like a sound + assumption from the manpage I looked at, but if there was + something fishy about it, my guess is that calling fflush + would not produce a significant performance problem. */ #ifdef USE_SETMODE_STDOUT int oldmode; -#endif - - /* Local users that do 'cvs status 2>&1' on a local repository - may see the informational messages out-of-order with the - status messages unless we use the fflush (stderr) here. */ - fflush (stderr); -#ifdef USE_SETMODE_STDOUT /* It is possible that this should be the same ifdef as USE_SETMODE_BINARY but at least for the moment we keep them separate. Mostly this is just laziness and/or a question diff --git a/contrib/cvs/src/stamp-h2.in b/contrib/cvs/src/stamp-h2.in deleted file mode 100644 index 9788f70..0000000 --- a/contrib/cvs/src/stamp-h2.in +++ /dev/null @@ -1 +0,0 @@ -timestamp diff --git a/contrib/cvs/src/tag.c b/contrib/cvs/src/tag.c index 6525eb2..903f357 100644 --- a/contrib/cvs/src/tag.c +++ b/contrib/cvs/src/tag.c @@ -1,11 +1,6 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. @@ -15,6 +10,8 @@ * Add or delete a symbolic name to an RCS file, or a collection of RCS files. * Tag uses the checked out revision in the current directory, rtag uses * the modules database, if necessary. + * + * $FreeBSD$ */ #include "cvs.h" @@ -155,9 +152,11 @@ cvstag (argc, argv) break; case 'Q': case 'q': +#ifdef SERVER_SUPPORT /* The CVS 1.5 client sends these options (in addition to Global_option requests), so we must ignore them. */ if (!server_active) +#endif error (1, 0, "-q or -Q must be specified before \"%s\"", cvs_cmd_name); @@ -355,12 +354,11 @@ rtag_proc (argc, argv, xwhere, mwhere, mfile, shorten, local_specified, { error (0, errno, "cannot chdir to %s", repository); free (repository); - free (where); return (1); } /* End section which is identical to patch_proc. */ - if (delete_flag || force_tag_move || attic_too || numtag) + if (delete_flag || attic_too || (force_tag_match && numtag)) which = W_REPOS | W_ATTIC; else which = W_REPOS; @@ -1136,170 +1134,6 @@ val_fileproc (callerdat, finfo) -/* This routine determines whether a tag appears in CVSROOT/val-tags. - * - * The val-tags file will be open read-only when IDB is NULL. Since writes to - * val-tags always append to it, the lack of locking is okay. The worst case - * race condition might misinterpret a partially written "foobar" matched, for - * instance, a request for "f", "foo", of "foob". Such a mismatch would be - * caught harmlessly later. - * - * Before CVS adds a tag to val-tags, it will lock val-tags for write and - * verify that the tag is still not present to avoid adding it twice. - * - * NOTES - * This function expects its parent to handle any necessary locking of the - * val-tags file. - * - * INPUTS - * idb When this value is NULL, the val-tags file is opened in - * in read-only mode. When present, the val-tags file is opened - * in read-write mode and the DBM handle is stored in *IDB. - * name The tag to search for. - * - * OUTPUTS - * *idb The val-tags file opened for read/write, or NULL if it couldn't - * be opened. - * - * ERRORS - * Exits with an error message if the val-tags file cannot be opened for - * read (failure to open val-tags read/write is harmless - see below). - * - * RETURNS - * true 1. If NAME exists in val-tags. - * 2. If IDB is non-NULL and val-tags cannot be opened for write. - * This allows callers to ignore the harmless inability to - * update the val-tags cache. - * false If the file could be opened and the tag is not present. - */ -static int is_in_val_tags PROTO((DBM **idb, const char *name)); -static int -is_in_val_tags (idb, name) - DBM **idb; - const char *name; -{ - DBM *db = NULL; - char *valtags_filename; - datum mytag; - int status; - - /* Casting out const should be safe here - input datums are not - * written to by the myndbm functions. - */ - mytag.dptr = (char *)name; - mytag.dsize = strlen (name); - - valtags_filename = xmalloc (strlen (current_parsed_root->directory) - + sizeof CVSROOTADM - + sizeof CVSROOTADM_VALTAGS + 3); - sprintf (valtags_filename, "%s/%s/%s", current_parsed_root->directory, - CVSROOTADM, CVSROOTADM_VALTAGS); - - if (idb) - { - db = dbm_open (valtags_filename, O_RDWR, 0666); - if (!db) - { - mode_t omask; - - if (!existence_error (errno)) - { - error (0, errno, "warning: cannot open %s read/write", - valtags_filename); - *idb = NULL; - return 1; - } - - omask = umask (cvsumask); - db = dbm_open (valtags_filename, O_RDWR | O_CREAT | O_TRUNC, 0666); - umask (omask); - if (!db) - { - error (0, errno, "warning: cannot create %s", - valtags_filename); - *idb = NULL; - return 1; - } - - *idb = db; - return 0; - } - - *idb = db; - } - else - { - db = dbm_open (valtags_filename, O_RDONLY, 0444); - if (!db && !existence_error (errno)) - error (1, errno, "cannot read %s", valtags_filename); - } - - /* If the file merely fails to exist, we just keep going and create - it later if need be. */ - - status = 0; - if (db) - { - datum val; - - val = dbm_fetch (db, mytag); - if (val.dptr != NULL) - /* Found. The tag is valid. */ - status = 1; - - /* FIXME: should check errors somehow (add dbm_error to myndbm.c?). */ - - if (!idb) dbm_close (db); - } - - free (valtags_filename); - return status; -} - - - -/* Add a tag to the CVSROOT/val-tags cache. Establishes a write lock and - * reverifies that the tag does not exist before adding it. - */ -static void add_to_val_tags PROTO((const char *name)); -static void -add_to_val_tags (name) - const char *name; -{ - DBM *db; - datum mytag; - datum value; - - if (noexec) return; - - val_tags_lock (current_parsed_root->directory); - - /* Check for presence again since we have a lock now. */ - if (is_in_val_tags (&db, name)) - { - clear_val_tags_lock (); - if (db) - dbm_close (db); - return; - } - - /* Casting out const should be safe here - input datums are not - * written to by the myndbm functions. - */ - mytag.dptr = (char *)name; - mytag.dsize = strlen (name); - value.dptr = "y"; - value.dsize = 1; - - if (dbm_store (db, mytag, value, DBM_REPLACE) < 0) - error (0, errno, "failed to store %s into val-tags", name); - dbm_close (db); - - clear_val_tags_lock (); -} - - - static Dtype val_direntproc PROTO ((void *, const char *, const char *, const char *, List *)); @@ -1341,6 +1175,10 @@ tag_check_valid (name, argc, argv, local, aflag, repository) int aflag; char *repository; { + DBM *db; + char *valtags_filename; + int nowrite = 0; + datum mytag; struct val_args the_val_args; struct saved_cwd cwd; int which; @@ -1363,12 +1201,52 @@ Numeric tag %s contains characters other than digits and '.'", name); || strcmp (name, TAG_HEAD) == 0) return; - /* Verify that the tag is valid syntactically. Some later code once made - * assumptions about this. - */ - RCS_check_tag (name); + if (readonlyfs) + return; + + /* FIXME: This routine doesn't seem to do any locking whatsoever + (and it is called from places which don't have locks in place). + If two processes try to write val-tags at the same time, it would + seem like we are in trouble. */ - if (is_in_val_tags (NULL, name)) return; + mytag.dptr = name; + mytag.dsize = strlen (name); + + valtags_filename = xmalloc (strlen (current_parsed_root->directory) + + sizeof CVSROOTADM + + sizeof CVSROOTADM_VALTAGS + 3); + sprintf (valtags_filename, "%s/%s/%s", current_parsed_root->directory, + CVSROOTADM, CVSROOTADM_VALTAGS); + db = dbm_open (valtags_filename, O_RDWR, 0666); + if (db == NULL) + { + if (!existence_error (errno)) + { + error (0, errno, "warning: cannot open %s read/write", + valtags_filename); + db = dbm_open (valtags_filename, O_RDONLY, 0666); + if (db != NULL) + nowrite = 1; + else if (!existence_error (errno)) + error (1, errno, "cannot read %s", valtags_filename); + } + /* If the file merely fails to exist, we just keep going and create + it later if need be. */ + } + if (db != NULL) + { + datum val; + + val = dbm_fetch (db, mytag); + if (val.dptr != NULL) + { + /* Found. The tag is valid. */ + dbm_close (db); + free (valtags_filename); + return; + } + /* FIXME: should check errors somehow (add dbm_error to myndbm.c?). */ + } /* We didn't find the tag in val-tags, so look through all the RCS files to see whether it exists there. Yes, this is expensive, but there @@ -1413,11 +1291,41 @@ Numeric tag %s contains characters other than digits and '.'", name); if (!the_val_args.found) error (1, 0, "no such tag %s", name); else + { /* The tags is valid but not mentioned in val-tags. Add it. */ - add_to_val_tags (name); -} + datum value; + if (noexec || nowrite) + { + if (db != NULL) + dbm_close (db); + free (valtags_filename); + return; + } + if (db == NULL) + { + mode_t omask; + omask = umask (cvsumask); + db = dbm_open (valtags_filename, O_RDWR | O_CREAT | O_TRUNC, 0666); + (void)umask (omask); + + if (db == NULL) + { + error (0, errno, "warning: cannot create %s", valtags_filename); + free (valtags_filename); + return; + } + } + value.dptr = "y"; + value.dsize = 1; + if (dbm_store (db, mytag, value, DBM_REPLACE) < 0) + error (0, errno, "cannot store %s into %s", name, + valtags_filename); + dbm_close (db); + } + free (valtags_filename); +} /* * Check whether a join tag is valid. This is just like diff --git a/contrib/cvs/src/update.c b/contrib/cvs/src/update.c index 6f1c937..0ddf3bc 100644 --- a/contrib/cvs/src/update.c +++ b/contrib/cvs/src/update.c @@ -1,11 +1,6 @@ /* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner + * Copyright (c) 1992, Brian Berliner and Jeff Polk + * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS source distribution. @@ -36,10 +31,11 @@ * versions, these are updated too. If the -d option was specified, new * directories added to the repository are automatically created and updated * as well. + * + * $FreeBSD$ */ #include "cvs.h" -#include <assert.h> #include "savecwd.h" #ifdef SERVER_SUPPORT # include "md5.h" @@ -101,10 +97,10 @@ static char *join_rev2, *date_rev2; static int aflag = 0; static int toss_local_changes = 0; static int force_tag_match = 1; +static int pull_template = 0; static int update_build_dirs = 0; static int update_prune_dirs = 0; static int pipeout = 0; -static int dotemplate = 0; #ifdef SERVER_SUPPORT static int patches = 0; static int rcs_diff_patches = 0; @@ -129,6 +125,7 @@ static const char *const update_usage[] = "\t-j rev\tMerge in changes made between current revision and rev.\n", "\t-I ign\tMore files to ignore (! to reset).\n", "\t-W spec\tWrappers specification line.\n", + "\t-T\tCreate CVS/Template.\n", "(Specify the --help global option for a list of other help options)\n", NULL }; @@ -144,6 +141,7 @@ update (argc, argv) int c, err; int local = 0; /* recursive by default */ int which; /* where to look for files and dirs */ + int xpull_template = 0; if (argc == -1) usage (update_usage); @@ -153,7 +151,7 @@ update (argc, argv) /* parse the args */ optind = 0; - while ((c = getopt (argc, argv, "+ApCPflRQqduk:r:D:j:I:W:")) != -1) + while ((c = getopt (argc, argv, "+ApCPflRQTqduk:r:D:j:I:W:")) != -1) { switch (c) { @@ -182,13 +180,18 @@ update (argc, argv) break; case 'Q': case 'q': +#ifdef SERVER_SUPPORT /* The CVS 1.5 client sends these options (in addition to Global_option requests), so we must ignore them. */ if (!server_active) +#endif error (1, 0, "-q or -Q must be specified before \"%s\"", cvs_cmd_name); break; + case 'T': + xpull_template = 1; + break; case 'd': update_build_dirs = 1; break; @@ -199,7 +202,6 @@ update (argc, argv) tag = optarg; break; case 'D': - if (date) free (date); date = Make_Date (optarg); break; case 'P': @@ -418,8 +420,8 @@ update (argc, argv) /* call the command line interface */ err = do_update (argc, argv, options, tag, date, force_tag_match, local, update_build_dirs, aflag, update_prune_dirs, - pipeout, which, join_rev1, join_rev2, (char *) NULL, 1, - (char *) NULL); + pipeout, which, join_rev1, join_rev2, (char *) NULL, + xpull_template, (char *) NULL); /* free the space Make_Date allocated if necessary */ if (date != NULL) @@ -436,7 +438,7 @@ update (argc, argv) int do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag, xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir, - xdotemplate, repository) + xpull_template, repository) int argc; char **argv; char *xoptions; @@ -452,7 +454,7 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag, char *xjoin_rev1; char *xjoin_rev2; char *preload_update_dir; - int xdotemplate; + int xpull_template; char *repository; { int err = 0; @@ -467,7 +469,7 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag, aflag = xaflag; update_prune_dirs = xprune; pipeout = xpipeout; - dotemplate = xdotemplate; + pull_template = xpull_template; /* setup the join support */ join_rev1 = xjoin_rev1; @@ -519,8 +521,13 @@ do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag, argc, argv, local, which, aflag, CVS_LOCK_READ, preload_update_dir, 1, repository); +#ifdef SERVER_SUPPORT + if (server_active) + return err; +#endif + /* see if we need to sleep before returning to avoid time-stamp races */ - if (!server_active && last_register_time) + if (last_register_time) { sleep_past (last_register_time); } @@ -604,7 +611,7 @@ update_fileproc (callerdat, finfo) && tag != NULL && finfo->rcs != NULL) { - char *rev = RCS_getversion (finfo->rcs, tag, NULL, 1, NULL); + char *rev = RCS_getversion (finfo->rcs, tag, date, 1, NULL); if (rev != NULL && !RCS_nodeisbranch (finfo->rcs, tag)) nonbranch = 1; @@ -676,7 +683,11 @@ update_fileproc (callerdat, finfo) bakname = backup_file (finfo->file, vers->vn_user); /* This behavior is sufficiently unexpected to justify overinformativeness, I think. */ - if (!really_quiet && !server_active) +#ifdef SERVER_SUPPORT + if ((! really_quiet) && (! server_active)) +#else /* ! SERVER_SUPPORT */ + if (! really_quiet) +#endif /* SERVER_SUPPORT */ (void) printf ("(Locally modified %s moved to %s)\n", finfo->file, bakname); free (bakname); @@ -691,7 +702,8 @@ update_fileproc (callerdat, finfo) { if (vers->ts_conflict) { - if (file_has_markers (finfo)) + if (file_has_conflict (finfo, vers->ts_conflict) + || file_has_markers (finfo)) { write_letter (finfo, 'C'); retval = 1; @@ -842,7 +854,11 @@ update_filesdone_proc (callerdat, err, repository, update_dir, entries) if (unlink_file_dir (CVSADM) < 0 && !existence_error (errno)) error (0, errno, "cannot remove %s directory", CVSADM); } +#ifdef SERVER_SUPPORT else if (!server_active && !pipeout) +#else + else if (!pipeout) +#endif /* SERVER_SUPPORT */ { /* If there is no CVS/Root file, add one */ if (!isfile (CVSADM_ROOT)) @@ -895,11 +911,15 @@ update_dirent_proc (callerdat, dir, repository, update_dir, entries) is when update -d is specified, and the working directory is gone but the subdirectory is still mentioned in CVS/Entries). */ - /* In the remote case, the client should refrain from - sending us the directory in the first place. So we - want to continue to give an error, so clients make - sure to do this. */ - if (!server_active && !isdir (repository)) + if (1 +#ifdef SERVER_SUPPORT + /* In the remote case, the client should refrain from + sending us the directory in the first place. So we + want to continue to give an error, so clients make + sure to do this. */ + && !server_active +#endif + && !isdir (repository)) return R_SKIP_ALL; if (noexec) @@ -937,7 +957,7 @@ update_dirent_proc (callerdat, dir, repository, update_dir, entries) via WriteTag. */ 0, 0, - dotemplate); + pull_template); rewrite_tag = 1; nonbranch = 0; Subdir_Register (entries, (char *) NULL, dir); @@ -996,6 +1016,12 @@ update_dirent_proc (callerdat, dir, repository, update_dir, entries) nonbranch = 0; } + /* keep the CVS/Template file current */ + if (pull_template) + { + WriteTemplate (dir, update_dir); + } + /* initialize the ignore list for this directory */ ignlist = getlist (); } @@ -1187,10 +1213,13 @@ scratch_file (finfo, vers) #endif if (unlink_file (finfo->file) < 0 && ! existence_error (errno)) error (0, errno, "unable to remove %s", finfo->fullname); - else if (!server_active) - { + else +#ifdef SERVER_SUPPORT /* skip this step when the server is running since * server_updated should have handled it */ + if (!server_active) +#endif + { /* keep the vers structure up to date in case we do a join * - if there isn't a file, it can't very well have a version number, can it? */ @@ -1232,7 +1261,11 @@ checkout_file (finfo, vers_ts, adding, merging, update_server) /* Don't screw with backup files if we're going to stdout, or if we are the server. */ - if (!pipeout && !server_active) + if (!pipeout +#ifdef SERVER_SUPPORT + && ! server_active +#endif + ) { backup = xmalloc (strlen (finfo->file) + sizeof (CVSADM) @@ -1324,9 +1357,7 @@ VERS: ", 0); for us to stat. */ if (stat (vers_ts->srcfile->path, &sb) < 0) { -#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) buf_free (revbuf); -#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */ error (1, errno, "cannot stat %s", vers_ts->srcfile->path); } @@ -1493,10 +1524,8 @@ VERS: ", 0); free (backup); } -#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) if (revbuf != NULL) buf_free (revbuf); -#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */ return retval; } @@ -1697,9 +1726,7 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum) retcode = 0; if (! fail) { - int dargc = 0; - size_t darg_allocated = 0; - char **dargv = NULL; + char *diff_options; /* If the client does not support the Rcs-diff command, we send a context diff, and the client must invoke patch. @@ -1707,13 +1734,16 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum) new approach only requires running diff in the server; the client can handle everything without invoking an external program. */ - if (!rcs_diff_patches) + if (! rcs_diff_patches) + { /* We use -c, not -u, because that is what CVS has traditionally used. Kind of a moot point, now that Rcs-diff is preferred, so there is no point in making the compatibility issues worse. */ - run_add_arg_p (&dargc, &darg_allocated, &dargv, "-c"); + diff_options = "-c"; + } else + { /* Now that diff is librarified, we could be passing -a if we wanted to. However, it is unclear to me whether we would want to. Does diff -a, in any significant @@ -1723,11 +1753,10 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum) 'binary'. Conversely, do they tend to be much larger in the bad cases? This needs some more thought/investigation, I suspect. */ - run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n"); - retcode = diff_exec (file1, file2, NULL, NULL, dargc, dargv, - finfo->file); - run_arg_free_p (dargc, dargv); - free (dargv); + + diff_options = "-n"; + } + retcode = diff_exec (file1, file2, NULL, NULL, diff_options, finfo->file); /* A retcode of 0 means no differences. 1 means some differences. */ if (retcode != 0 @@ -1918,47 +1947,6 @@ write_letter (finfo, letter) -/* Reregister a file after a merge. */ -static void -RegisterMerge PROTO((struct file_info *finfo, Vers_TS *vers, - const char *backup, int has_conflicts)); -static void -RegisterMerge (finfo, vers, backup, has_conflicts) - struct file_info *finfo; - Vers_TS *vers; - const char *backup; - int has_conflicts; -{ - /* This file is the result of a merge, which means that it has - been modified. We use a special timestamp string which will - not compare equal to any actual timestamp. */ - char *cp = NULL; - - if (has_conflicts) - { - time (&last_register_time); - cp = time_stamp (finfo->file); - } - Register (finfo->entries, finfo->file, vers->vn_rcs ? vers->vn_rcs : "0", - "Result of merge", vers->options, vers->tag, vers->date, cp); - if (cp) - free (cp); - -#ifdef SERVER_SUPPORT - /* Send the new contents of the file before the message. If we - wanted to be totally correct, we would have the client write - the message only after the file has safely been written. */ - if (server_active) - { - server_copy_file (finfo->file, finfo->update_dir, finfo->repository, - backup); - server_updated (finfo, vers, SERVER_MERGED, (mode_t) -1, NULL, NULL); - } -#endif -} - - - /* * Do all the magic associated with a file which needs to be merged */ @@ -1972,8 +1960,6 @@ merge_file (finfo, vers) int retcode = 0; int retval; - assert (vers->vn_user); - /* * The users currently modified file is moved to a backup file name * ".#filename.version", so that it will stay around for a few days @@ -2011,21 +1997,13 @@ merge_file (finfo, vers) thought needs to go into this, and in the meantime it is safe to treat any such mismatch as an automatic conflict. -twp */ - retcode = RCS_checkout (finfo->rcs, finfo->file, - vers->vn_rcs, vers->tag, - vers->options, NULL, NULL, NULL); - if (retcode) - { - error (0, 0, "failed to check out `%s' file", finfo->fullname); - error (0, 0, "restoring `%s' from backup file `%s'", - finfo->fullname, backup); - rename_file (backup, finfo->file); - retval = 1; - goto out; - } - xchmod (finfo->file, 1); +#ifdef SERVER_SUPPORT + if (server_active) + server_copy_file (finfo->file, finfo->update_dir, + finfo->repository, backup); +#endif - RegisterMerge (finfo, vers, backup, 1); + status = checkout_file (finfo, vers, 0, 1, 1); /* Is there a better term than "nonmergeable file"? What we really mean is, not something that CVS cannot or does not @@ -2059,6 +2037,24 @@ merge_file (finfo, vers) if (strcmp (vers->options, "-V4") == 0) vers->options[0] = '\0'; + /* This file is the result of a merge, which means that it has + been modified. We use a special timestamp string which will + not compare equal to any actual timestamp. */ + { + char *cp = 0; + + if (status) + { + (void) time (&last_register_time); + cp = time_stamp (finfo->file); + } + Register (finfo->entries, finfo->file, vers->vn_rcs, + "Result of merge", vers->options, vers->tag, + vers->date, cp); + if (cp) + free (cp); + } + /* fix up the vers structure, in case it is used by join */ if (join_rev1) { @@ -2069,7 +2065,19 @@ merge_file (finfo, vers) vers->vn_user = xstrdup (vers->vn_rcs); } - RegisterMerge (finfo, vers, backup, status); +#ifdef SERVER_SUPPORT + /* Send the new contents of the file before the message. If we + wanted to be totally correct, we would have the client write + the message only after the file has safely been written. */ + if (server_active) + { + server_copy_file (finfo->file, finfo->update_dir, finfo->repository, + backup); + server_updated (finfo, vers, SERVER_MERGED, + (mode_t) -1, (unsigned char *) NULL, + (struct buffer *) NULL); + } +#endif /* FIXME: the noexec case is broken. RCS_merge could be doing the xcmp on the temporary files without much hassle, I think. */ @@ -2663,7 +2671,31 @@ join_file (finfo, vers) RCS_checkout above, and we aren't running as the server. However, that is not the normal case, and calling Register again won't cost much in that case. */ - RegisterMerge (finfo, vers, backup, status); + { + char *cp = 0; + + if (status) + { + (void) time (&last_register_time); + cp = time_stamp (finfo->file); + } + Register (finfo->entries, finfo->file, + vers->vn_rcs ? vers->vn_rcs : "0", "Result of merge", + vers->options, vers->tag, vers->date, cp); + if (cp) + free(cp); + } + +#ifdef SERVER_SUPPORT + if (server_active) + { + server_copy_file (finfo->file, finfo->update_dir, finfo->repository, + backup); + server_updated (finfo, vers, SERVER_MERGED, + (mode_t) -1, (unsigned char *) NULL, + (struct buffer *) NULL); + } +#endif out: free (rev1); diff --git a/contrib/cvs/src/update.h b/contrib/cvs/src/update.h index 8d581b1..c886b4c 100644 --- a/contrib/cvs/src/update.h +++ b/contrib/cvs/src/update.h @@ -10,10 +10,14 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ +/* + * $FreeBSD$ + */ + int do_update PROTO((int argc, char *argv[], char *xoptions, char *xtag, char *xdate, int xforce, int local, int xbuild, int xaflag, int xprune, int xpipeout, int which, char *xjoin_rev1, char *xjoin_rev2, char *preload_update_dir, - int xdotemplate, char *repository)); + int xpull_template, char *repository)); int joining PROTO((void)); extern int isemptydir PROTO ((const char *dir, int might_not_exist)); diff --git a/contrib/cvs/src/version.c.in b/contrib/cvs/src/version.c.in deleted file mode 100644 index aa2f97f..0000000 --- a/contrib/cvs/src/version.c.in +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 1994 david d `zoo' zuhn - * Copyright (c) 1994 Free Software Foundation, Inc. - * Copyright (c) 1992, Brian Berliner and Jeff Polk - * Copyright (c) 1989-1992, Brian Berliner - * - * You may distribute under the terms of the GNU General Public License as - * specified in the README file that comes with this CVS source distribution. - * - * version.c - the CVS version number - */ - -#include "cvs.h" - -char *version_string = "Concurrent Versions System (CVS) @VERSION@"; - -#ifdef CLIENT_SUPPORT -#ifdef SERVER_SUPPORT -char *config_string = " (client/server)\n"; -#else -char *config_string = " (client)\n"; -#endif -#else -#ifdef SERVER_SUPPORT -char *config_string = " (server)\n"; -#else -char *config_string = "\n"; -#endif -#endif - - - -static const char *const version_usage[] = -{ - "Usage: %s %s\n", - NULL -}; - - - -/* - * Output a version string for the client and server. - * - * This function will output the simple version number (for the '--version' - * option) or the version numbers of the client and server (using the 'version' - * command). - */ -int -version (argc, argv) - int argc; - char **argv; -{ - int err = 0; - - if (argc == -1) - usage (version_usage); - -#ifdef CLIENT_SUPPORT - if (current_parsed_root && current_parsed_root->isremote) - (void) fputs ("Client: ", stdout); -#endif - - /* Having the year here is a good idea, so people have - some idea of how long ago their version of CVS was - released. */ - (void) fputs (version_string, stdout); - (void) fputs (config_string, stdout); - -#ifdef CLIENT_SUPPORT - if (current_parsed_root && current_parsed_root->isremote) - { - (void) fputs ("Server: ", stdout); - start_server (); - if (supported_request ("version")) - send_to_server ("version\012", 0); - else - { - send_to_server ("noop\012", 0); - fputs ("(unknown)\n", stdout); - } - err = get_responses_and_close (); - } -#endif - return err; -} - diff --git a/contrib/cvs/src/version.h.in b/contrib/cvs/src/version.h.in deleted file mode 100644 index 48580cb..0000000 --- a/contrib/cvs/src/version.h.in +++ /dev/null @@ -1,15 +0,0 @@ -/* -*- c -*- - * - * Copyright (c) 1992, Brian Berliner and Jeff Polk - * Copyright (c) 1989-1992, Brian Berliner - * - * You may distribute under the terms of the GNU General Public License as - * specified in the README file that comes with the CVS kit. - */ - -#ifndef VERSION_H -#define VERSION_H 1 - -#define version_string "Concurrent Versions System (CVS) @VERSION@" - -#endif /* VERSION_H */ |