diff options
Diffstat (limited to 'contrib/cvs/src')
32 files changed, 820 insertions, 991 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..db2bea0 100644 --- a/contrib/cvs/src/buffer.c +++ b/contrib/cvs/src/buffer.c @@ -14,6 +14,8 @@ /* Code for the buffer data structure. */ +/* $FreeBSD$ */ + #include <assert.h> #include "cvs.h" #include "buffer.h" diff --git a/contrib/cvs/src/checkout.c b/contrib/cvs/src/checkout.c index e4d80ea..a1cd6cc 100644 --- a/contrib/cvs/src/checkout.c +++ b/contrib/cvs/src/checkout.c @@ -38,6 +38,10 @@ * edited by the user, if necessary (when the repository is moved, e.g.) */ +/* + * $FreeBSD$ + */ + #include <assert.h> #include "cvs.h" @@ -55,6 +59,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", @@ -97,6 +102,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 +150,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,6 +179,9 @@ checkout (argc, argv) case 'n': run_module_prog = 0; break; + case 'T': + pull_template = 1; + break; case 'Q': case 'q': /* The CVS 1.5 client sends these options (in addition to @@ -1098,8 +1107,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 +1163,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 78fc989..318db4a 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 */ @@ -160,22 +164,17 @@ is_arg_a_parent_or_listed_dir (n, d) void *d; { char *directory = n->key; /* name of the dir sent to server */ - char *this_argv_elem = xstrdup (d); /* this argv element */ - int retval; + char *this_argv_elem = (char *) d; /* this argv element */ /* Say we should send this argument if the argument matches the beginning of a directory name sent to the server. This way, the server will know to start at the top of that directory hierarchy and descend. */ - strip_trailing_slashes (this_argv_elem); if (strncmp (directory, this_argv_elem, strlen (this_argv_elem)) == 0) - retval = 1; - else - retval = 0; + return 1; - free (this_argv_elem); - return retval; + return 0; } static int arg_should_not_be_sent_to_server PROTO((char *)); @@ -274,7 +273,8 @@ arg_should_not_be_sent_to_server (arg) } /* Now check the value for root. */ - if (root_string && current_parsed_root + if (CVSroot_cmdline == NULL && + root_string && current_parsed_root && (strcmp (root_string, current_parsed_root->original) != 0)) { /* Don't send this, since the CVSROOTs don't match. */ @@ -2783,8 +2783,7 @@ send_repository (dir, repos, update_dir) send_to_server (repos, 0); send_to_server ("\012", 1); - if (strcmp (cvs_cmd_name, "import") - && supported_request ("Static-directory")) + if (supported_request ("Static-directory")) { adm_name[0] = '\0'; if (dir[0] != '\0') @@ -2798,8 +2797,7 @@ send_repository (dir, repos, update_dir) send_to_server ("Static-directory\012", 0); } } - if (strcmp (cvs_cmd_name, "import") - && supported_request ("Sticky")) + if (supported_request ("Sticky")) { FILE *f; if (dir[0] == '\0') @@ -3842,7 +3840,7 @@ auth_server (root, lto_server, lfrom_server, verify_only, do_gssapi, hostinfo) int do_gssapi; struct hostent *hostinfo; { - char *username = ""; /* the username we use to connect */ + char *username; /* the username we use to connect */ char no_passwd = 0; /* gets set if no password found */ /* FIXME!!!!!!!!!!!!!!!!!! @@ -3926,8 +3924,9 @@ auth_server (root, lto_server, lfrom_server, verify_only, do_gssapi, hostinfo) send_to_server(end, 0); send_to_server("\012", 1); - free_cvs_password (password); - password = NULL; + /* 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 */ @@ -4726,20 +4725,15 @@ start_rsh_server (root, to_server, from_server) /* If you're working through firewalls, you can set the CVS_RSH environment variable to a script which uses rsh to invoke another rsh on a proxy machine. */ - char *env_cvs_rsh = getenv ("CVS_RSH"); - char *env_cvs_ssh = getenv ("CVS_SSH"); - char *cvs_rsh; + char *cvs_rsh = getenv ("CVS_RSH"); char *cvs_server = getenv ("CVS_SERVER"); int i = 0; /* This needs to fit "rsh", "-b", "-l", "USER", "host", "cmd (w/ args)", and NULL. We leave some room to grow. */ char *rsh_argv[10]; - if (root->method == extssh_method) - cvs_rsh = env_cvs_ssh ? env_cvs_ssh : SSH_DFLT; - else - cvs_rsh = env_cvs_rsh ? env_cvs_rsh : RSH_DFLT; - + if (!cvs_rsh) + cvs_rsh = RSH_DFLT; if (!cvs_server) cvs_server = "cvs"; @@ -4793,19 +4787,14 @@ start_rsh_server (root, to_server, from_server) /* If you're working through firewalls, you can set the CVS_RSH environment variable to a script which uses rsh to invoke another rsh on a proxy machine. */ - char *env_cvs_rsh = getenv ("CVS_RSH"); - char *env_cvs_ssh = getenv ("CVS_SSH"); - char *cvs_rsh; + char *cvs_rsh = getenv ("CVS_RSH"); char *cvs_server = getenv ("CVS_SERVER"); char *command; int tofd, fromfd; int child_pid; - if (root->method == extssh_method) - cvs_rsh = env_cvs_ssh ? env_cvs_ssh : SSH_DFLT; - else - cvs_rsh = env_cvs_rsh ? env_cvs_rsh : RSH_DFLT; - + if (!cvs_rsh) + cvs_rsh = RSH_DFLT; if (!cvs_server) cvs_server = "cvs"; @@ -5166,7 +5155,8 @@ warning: ignoring -k options due to server limitations"); || 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"))) + || (vers->ts_conflict && !strcmp (cvs_cmd_name, "diff")) + || (vers->vn_user && *vers->vn_user == '0')) { if (args->no_contents && supported_request ("Is-modified")) diff --git a/contrib/cvs/src/commit.c b/contrib/cvs/src/commit.c index 7d168c3..b3ba47b 100644 --- a/contrib/cvs/src/commit.c +++ b/contrib/cvs/src/commit.c @@ -17,6 +17,7 @@ * * The call is: cvs commit [options] files... * + * $FreeBSD$ */ #include <assert.h> diff --git a/contrib/cvs/src/cvs.h b/contrib/cvs/src/cvs.h index 187a354..f412aa0 100644 --- a/contrib/cvs/src/cvs.h +++ b/contrib/cvs/src/cvs.h @@ -14,6 +14,7 @@ /* * basic information used in all source files * + * $FreeBSD$ */ @@ -199,6 +200,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 */ @@ -270,6 +272,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 */ @@ -300,6 +304,9 @@ extern int errno; command line, the client, etc. */ #define MAXDATELEN 50 +/* FreeBSD.org default is to use ssh. */ +#define RSH_DFLT "ssh" + /* The type of an entnode. */ enum ent_type { @@ -382,6 +389,7 @@ extern int really_quiet, quiet; extern int use_editor; extern int cvswrite; extern mode_t cvsumask; +extern char *RCS_citag; @@ -400,7 +408,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; @@ -502,6 +512,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 *)); @@ -588,6 +599,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)); @@ -916,7 +928,6 @@ char *descramble PROTO ((char *str)); #ifdef AUTH_CLIENT_SUPPORT char *get_cvs_password PROTO((void)); -void free_cvs_password PROTO((char *str)); int get_cvs_port_number PROTO((const cvsroot_t *root)); char *normalize_cvsroot PROTO((const cvsroot_t *root)); #endif /* AUTH_CLIENT_SUPPORT */ 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..8a61f9a 100644 --- a/contrib/cvs/src/diff.c +++ b/contrib/cvs/src/diff.c @@ -17,6 +17,8 @@ * * Without any file arguments, runs diff against all the currently modified * files. + * + * $FreeBSD$ */ #include <assert.h> @@ -57,6 +59,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; @@ -324,6 +327,8 @@ diff (argc, argv) 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,7 +339,7 @@ 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) @@ -378,6 +383,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, @@ -426,13 +452,18 @@ diff (argc, argv) send_options (diff_argc, diff_argv); 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,12 +477,9 @@ diff (argc, argv) send_to_server ("diff\012", 0); err = get_responses_and_close (); - free (options); - options = NULL; - return (err); - } + } else #endif - + { /* FreeBSD addition - warning idention not changed til matching-} */ if (diff_rev1 != NULL) tag_check_valid (diff_rev1, argc, argv, local, 0, ""); if (diff_rev2 != NULL) @@ -468,6 +496,7 @@ diff (argc, argv) diff_dirleaveproc, NULL, argc, argv, local, which, 0, CVS_LOCK_READ, (char *) NULL, 1, (char *) NULL); + } /* FreeBSD addition */ /* clean up */ free (options); @@ -477,6 +506,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); } diff --git a/contrib/cvs/src/entries.c b/contrib/cvs/src/entries.c index c346fb6..9592c3c 100644 --- a/contrib/cvs/src/entries.c +++ b/contrib/cvs/src/entries.c @@ -16,6 +16,9 @@ * the Entries file. */ +/* + * $FreeBSD$ + */ #include "cvs.h" #include "getline.h" @@ -641,6 +644,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 1e1f901..186f0c6 100644 --- a/contrib/cvs/src/filesubr.c +++ b/contrib/cvs/src/filesubr.c @@ -17,6 +17,10 @@ definitions under operating systems (like, say, Windows NT) with different file system semantics. */ +/* + * $FreeBSD$ + */ + #include <assert.h> #include "cvs.h" diff --git a/contrib/cvs/src/import.c b/contrib/cvs/src/import.c index bc918e0..d4e2f24 100644 --- a/contrib/cvs/src/import.c +++ b/contrib/cvs/src/import.c @@ -19,6 +19,8 @@ * VendorReleTag Tag for this particular release * * Additional arguments specify more Vendor Release Tags. + * + * $FreeBSD$ */ #include "cvs.h" @@ -162,21 +164,14 @@ import (argc, argv) * Could abstract this to valid_module_path, but I don't think we'll need * to call it from anywhere else. */ - /* for each "CVS" in path... */ - cp = argv[0]; - while ((cp = strstr(cp, "CVS")) != NULL) + if ((cp = strstr(argv[0], "CVS")) && /* path contains "CVS" AND ... */ + ((cp == argv[0]) || ISDIRSEP(*(cp-1))) && /* /^CVS/ OR m#/CVS# AND ... */ + ((*(cp+3) == '\0') || ISDIRSEP(*(cp+3))) /* /CVS$/ OR m#CVS/# */ + ) { - if ( /* /^CVS/ OR m#/CVS#... */ - (cp == argv[0] || ISDIRSEP(*(cp-1))) - /* ...AND /CVS$/ OR m#CVS/# */ - && (*(cp+3) == '\0' || ISDIRSEP(*(cp+3))) - ) - { - error (0, 0, - "The word `CVS' is reserved by CVS and may not be used"); - error (1, 0, "as a directory in a path or as a file name."); - } - cp += 3; + error (0, 0, + "The word `CVS' is reserved by CVS and may not be used"); + error (1, 0, "as a directory in a path or as a file name."); } for (i = 1; i < argc; i++) /* check the tags for validity */ @@ -1608,8 +1603,8 @@ import_descend_dir (message, dir, vtag, targc, targv) if ( CVS_CHDIR (dir) < 0) { ierrno = errno; - fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", dir); - error (0, ierrno, "ERROR: cannot chdir to %s", dir); + fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository); + error (0, ierrno, "ERROR: cannot chdir to %s", repository); err = 1; goto out; } diff --git a/contrib/cvs/src/lock.c b/contrib/cvs/src/lock.c index 6f818da..a407dac 100644 --- a/contrib/cvs/src/lock.c +++ b/contrib/cvs/src/lock.c @@ -13,6 +13,8 @@ * Set Lock * * Lock file support for CVS. + * + * $FreeBSD$ */ /* The node Concurrency in doc/cvs.texinfo has a brief introduction to @@ -173,7 +175,7 @@ lock_name (repository, name) const char *p; char *q; const char *short_repos; - mode_t save_umask = 0; + mode_t save_umask; int saved_umask = 0; if (lock_dir == NULL) @@ -420,7 +422,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 +499,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) { diff --git a/contrib/cvs/src/log.c b/contrib/cvs/src/log.c index 1730874..a952283 100644 --- a/contrib/cvs/src/log.c +++ b/contrib/cvs/src/log.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1986-2008 The Free Software Foundation, Inc. + * Copyright (C) 1986-2005 The Free Software Foundation, Inc. * * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, * and others. @@ -15,6 +15,8 @@ * 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" @@ -87,7 +89,7 @@ struct log_data /* Nonzero if the -N option was seen, meaning that tag information should not be printed. */ int notags; - /* Nonzero if the -b option was seen, meaning that revisions + /* Nonzero if the -b option was seen, meaning that only revisions on the default branch should be printed. */ int default_branch; /* Nonzero if the -S option was seen, meaning that the header/name @@ -156,12 +158,11 @@ 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\tList revisions on the default branch.\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-t\tOnly print header and descriptive text.\n", "\t-N\tDo not list tags.\n", - "\t-n\tList tags (default).\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", @@ -1648,8 +1649,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); diff --git a/contrib/cvs/src/login.c b/contrib/cvs/src/login.c index 1d20c97..3222228 100644 --- a/contrib/cvs/src/login.c +++ b/contrib/cvs/src/login.c @@ -10,6 +10,8 @@ * specified in the README file that comes with CVS. * * Allow user to log in for an authenticating server. + * + * $FreeBSD$ */ #include "cvs.h" @@ -115,20 +117,20 @@ password_entry_parseline (cvsroot_canonical, warn, linenumber, linebuf) { /* Yes: slurp '^/\d+\D' and parse the rest of the line according to version number */ char *q; - unsigned long int entry_version = 0; + unsigned long int entry_version; if (isspace(*(linebuf + 1))) - { /* special case since strtoul ignores leading white space */ q = linebuf + 1; - } else - { entry_version = strtoul (linebuf + 1, &q, 10); - if (q != linebuf + 1) - /* assume a delimiting seperator */ - q++; - } + + if (q == linebuf + 1) + /* no valid digits found by strtoul */ + entry_version = 0; + else + /* assume a delimiting seperator */ + q++; switch (entry_version) { @@ -566,40 +568,21 @@ login (argc, argv) password_entry_operation (password_entry_add, current_parsed_root, typed_password); - free_cvs_password (typed_password); + memset (typed_password, 0, strlen (typed_password)); + free (typed_password); + + free (cvs_password); free (cvsroot_canonical); + cvs_password = NULL; return 0; } -/* Free the password returned by get_cvs_password() and also free the - * saved cvs_password if they are different pointers. Be paranoid - * about the in-memory copy of the password and overwrite it with zero - * bytes before doing the free(). - */ -void -free_cvs_password (char *password) -{ - if (password && password != cvs_password) - { - memset (password, 0, strlen (password)); - free (password); - } - - if (cvs_password) - { - memset (cvs_password, 0, strlen (cvs_password)); - free (cvs_password); - cvs_password = NULL; - } -} - -/* Returns the _scrambled_ password in freshly allocated memory. The server - * must descramble before hashing and comparing. If password file not found, - * or password not found in the file, just return NULL. - */ +/* Returns the _scrambled_ password. The server must descramble + before hashing and comparing. If password file not found, or + password not found in the file, just return NULL. */ char * get_cvs_password () { @@ -610,7 +593,7 @@ get_cvs_password () context, then assume they have supplied the correct, scrambled password. */ if (cvs_password) - return xstrdup (cvs_password); + return cvs_password; if (getenv ("CVS_PASSWORD") != NULL) { diff --git a/contrib/cvs/src/logmsg.c b/contrib/cvs/src/logmsg.c index 5ac4b0e..6878aaf 100644 --- a/contrib/cvs/src/logmsg.c +++ b/contrib/cvs/src/logmsg.c @@ -9,6 +9,8 @@ * * 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> @@ -227,6 +229,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 */ diff --git a/contrib/cvs/src/main.c b/contrib/cvs/src/main.c index 3dace64..1365321 100644 --- a/contrib/cvs/src/main.c +++ b/contrib/cvs/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1986-2008 The Free Software Foundation, Inc. + * Copyright (C) 1986-2006 The Free Software Foundation, Inc. * * Portions Copyright (C) 1998-2006 Derek Price, Ximbiot <http://ximbiot.com>, * and others. @@ -15,10 +15,12 @@ * 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,6 +48,8 @@ int really_quiet = 0; int quiet = 0; int trace = 0; int noexec = 0; +int readonlyfs = 0; +int require_real_user = 0; int logoff = 0; /* @@ -248,8 +252,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", @@ -407,7 +413,7 @@ main (argc, argv) 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'}, @@ -464,6 +470,12 @@ main (argc, argv) Editor = cp; 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 +538,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; @@ -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); @@ -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 @@ -953,6 +987,9 @@ distribution kit for a complete list of contributors and copyrights.\n", 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 @@ -1140,3 +1177,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 751d4c7..cdd766e 100644 --- a/contrib/cvs/src/mkmodules.c +++ b/contrib/cvs/src/mkmodules.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1986-2008 The Free Software Foundation, Inc. + * Copyright (C) 1986-2005 The Free Software Foundation, Inc. * * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, * and others. @@ -8,9 +8,11 @@ * 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 kit. */ + * specified in the README file that comes with the CVS kit. + * + * $FreeBSD$ + */ -#include <assert.h> #include "cvs.h" #include "getline.h" #include "history.h" @@ -262,6 +264,7 @@ static const char *const modules_contents[] = { "# key [options] directory files...\n", "#\n", "# Where \"options\" are composed of:\n", + "# -i prog Run \"prog\" on \"cvs commit\" from top-level of module.\n", "# -o prog Run \"prog\" on \"cvs checkout\" of module.\n", "# -e prog Run \"prog\" on \"cvs export\" of module.\n", "# -t prog Run \"prog\" on \"cvs rtag\" of module.\n", @@ -288,13 +291,6 @@ static const char *const config_contents[] = { "# Set this to \"no\" if pserver shouldn't check system users/passwords\n", "#SystemAuth=yes\n", "\n", - "# Set `IgnoreUnknownConfigKeys' to `yes' to ignore unknown config\n", - "# keys which are supported in a future version of CVS.\n", - "# This option is intended to be useful as a transition for read-only\n", - "# mirror sites when sites may need to be updated later than the\n", - "# primary CVS repository.\n", - "#IgnoreUnknownConfigKeys=no\n", - "\n", "# Put CVS lock files in this directory rather than directly in the repository.\n", "#LockDir=/var/lock/cvs\n", "\n", @@ -853,41 +849,6 @@ rename_rcsfile (temp, real) free (bak); } - -/* - * Walk PATH backwards to the root directory looking for the root of a - * repository. - */ -static char * -in_repository (const char *path) -{ - char *cp = xstrdup (path); - - for (;;) - { - if (isdir (cp)) - { - int foundit; - char *adm = xmalloc (strlen(cp) + strlen(CVSROOTADM) + 2); - sprintf (adm, "%s/%s", cp, CVSROOTADM); - foundit = isdir (adm); - free (adm); - if (foundit) return cp; - } - - /* If last_component() returns the empty string, then cp either - * points at the system root or is the empty string itself. - */ - if (!*last_component (cp) || !strcmp (cp, ".") - || last_component(cp) == cp) - break; - - cp[strlen(cp) - strlen(last_component(cp)) - 1] = '\0'; - } - - return NULL; -} - const char *const init_usage[] = { "Usage: %s %s\n", @@ -909,11 +870,8 @@ init (argc, argv) /* Exit status. */ int err = 0; - char *root_dir; const struct admin_file *fileptr; - assert (!server_active); - umask (cvsumask); if (argc == -1 || argc > 1) @@ -930,14 +888,6 @@ init (argc, argv) } #endif /* CLIENT_SUPPORT */ - root_dir = in_repository (current_parsed_root->directory); - - if (root_dir && strcmp (root_dir, current_parsed_root->directory)) - error (1, 0, - "Cannot initialize repository under existing CVSROOT: `%s'", - root_dir); - free (root_dir); - /* Note: we do *not* create parent directories as needed like the old cvsinit.sh script did. Few utilities do that, and a non-existent parent directory is as likely to be a typo as something 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 feccc71..c206fb7 100644 --- a/contrib/cvs/src/parseinfo.c +++ b/contrib/cvs/src/parseinfo.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1986-2008 The Free Software Foundation, Inc. + * Copyright (C) 1986-2005 The Free Software Foundation, Inc. * * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, * and others. @@ -9,6 +9,8 @@ * * 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" @@ -245,7 +247,6 @@ parse_config (cvsroot) /* FIXME-reentrancy: If we do a multi-threaded server, this would need to go to the per-connection data structures. */ static int parsed = 0; - int ignore_unknown_config_keys = 0; /* Authentication code and serve_root might both want to call us. Let this happen smoothly. */ @@ -358,6 +359,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) @@ -416,23 +436,16 @@ warning: this CVS does not support PreservePermissions"); else if (strcmp (p, "stat") == 0) RereadLogAfterVerify = LOGMSG_REREAD_STAT; } - else if (strcmp (line, "IgnoreUnknownConfigKeys") == 0) + else if (strcmp(line, "LocalKeyword") == 0) { - if (strcmp (p, "no") == 0 || strcmp (p, "false") == 0 - || strcmp (p, "off") == 0 || strcmp (p, "0") == 0) - ignore_unknown_config_keys = 0; - else if (strcmp (p, "yes") == 0 || strcmp (p, "true") == 0 - || strcmp (p, "on") == 0 || strcmp (p, "1") == 0) - ignore_unknown_config_keys = 1; - else - { - error (0, 0, "%s: unrecognized value '%s' for '%s'", - infopath, p, line); - goto error_return; - } + /* 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 if (ignore_unknown_config_keys) - ; else { /* We may be dealing with a keyword which was added in a diff --git a/contrib/cvs/src/patch.c b/contrib/cvs/src/patch.c index 9af10a6..65f5051 100644 --- a/contrib/cvs/src/patch.c +++ b/contrib/cvs/src/patch.c @@ -15,6 +15,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> diff --git a/contrib/cvs/src/rcs.c b/contrib/cvs/src/rcs.c index 73ce8ea..fe51dd0 100644 --- a/contrib/cvs/src/rcs.c +++ b/contrib/cvs/src/rcs.c @@ -12,6 +12,8 @@ * * The routines contained in this file do all the rcs file parsing and * manipulation + * + * $FreeBSD$ */ #include <assert.h> @@ -30,15 +32,7 @@ # endif #endif -#ifdef MMAP_FALLBACK_TEST -void *my_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) -{ - if (rand() & 1) return mmap(addr, len, prot, flags, fd, offset); - return NULL; -} -#define mmap my_mmap -#endif - +int datesep = '/'; int preserve_perms = 0; /* The RCS -k options, and a set of enums that must match the array. @@ -74,8 +68,6 @@ struct rcsbuffer this is non-zero, we must search the string for pairs of '@' and convert them to a single '@'. */ int embedded_at; - /* Whether the buffer has been mmap'ed or not. */ - int mmapped; }; static RCSNode *RCS_parsercsfile_i PROTO((FILE * fp, const char *rcsfile)); @@ -87,8 +79,10 @@ static void rcsbuf_close PROTO ((struct rcsbuffer *)); static int rcsbuf_getkey PROTO ((struct rcsbuffer *, char **keyp, char **valp)); static int rcsbuf_getrevnum PROTO ((struct rcsbuffer *, char **revp)); +#ifndef HAVE_MMAP static char *rcsbuf_fill PROTO ((struct rcsbuffer *, char *ptr, char **keyp, char **valp)); +#endif static int rcsbuf_valcmp PROTO ((struct rcsbuffer *)); static char *rcsbuf_valcopy PROTO ((struct rcsbuffer *, char *val, int polish, size_t *lenp)); @@ -149,6 +143,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: * @@ -838,8 +834,8 @@ warning: duplicate key `%s' in version `%s' of RCS file `%s'", op = *cp++; if (op != 'a' && op != 'd') error (1, 0, "\ -unrecognized operation '\\x%x' in %s revision %s", - op, rcs->path, vnode->version); +unrecognized operation '\\x%x' in %s", + op, rcs->path); (void) strtoul (cp, (char **) &cp, 10); if (*cp++ != ' ') error (1, 0, "space expected in %s revision %s", @@ -1038,58 +1034,46 @@ rcsbuf_open (rcsbuf, fp, filename, pos) const char *filename; unsigned long pos; { -#ifdef HAVE_MMAP - void *p; - struct stat fs; - size_t mmap_off = 0; -#endif - if (rcsbuf_inuse) error (1, 0, "rcsbuf_open: internal error"); rcsbuf_inuse = 1; #ifdef HAVE_MMAP - /* When we have mmap, it is much more efficient to let the system do the - * buffering and caching for us - */ + { + /* When we have mmap, it is much more efficient to let the system do the + * buffering and caching for us + */ + struct stat fs; + size_t mmap_off = 0; - if ( fstat (fileno(fp), &fs) < 0 ) - error ( 1, errno, "Could not stat RCS archive %s for mapping", filename ); + if ( fstat (fileno(fp), &fs) < 0 ) + error ( 1, errno, "Could not stat RCS archive %s for mapping", filename ); - if (pos) - { - size_t ps = getpagesize (); - mmap_off = ( pos / ps ) * ps; - } + if (pos) + { + size_t ps = getpagesize (); + mmap_off = ( pos / ps ) * ps; + } + + /* Map private here since this particular buffer is read only */ + rcsbuf_buffer = mmap ( NULL, fs.st_size - mmap_off, + PROT_READ | PROT_WRITE, + MAP_PRIVATE, fileno(fp), mmap_off ); + if ( rcsbuf_buffer == NULL || rcsbuf_buffer == MAP_FAILED ) + error ( 1, errno, "Could not map memory to RCS archive %s", filename ); - /* Map private here since this particular buffer is read only */ - p = mmap ( NULL, fs.st_size - mmap_off, PROT_READ | PROT_WRITE, - MAP_PRIVATE, fileno(fp), mmap_off ); - if (p != NULL && p != MAP_FAILED) - { - if (rcsbuf_buffer) free (rcsbuf_buffer); - rcsbuf_buffer = p; rcsbuf_buffer_size = fs.st_size - mmap_off; - rcsbuf->mmapped = 1; rcsbuf->ptr = rcsbuf_buffer + pos - mmap_off; rcsbuf->ptrend = rcsbuf_buffer + fs.st_size - mmap_off; rcsbuf->pos = mmap_off; } - else - { -#ifndef MMAP_FALLBACK_TEST - error (0, errno, "Could not map memory to RCS archive %s", filename); -#endif -#endif /* HAVE_MMAP */ - if (rcsbuf_buffer_size < RCSBUF_BUFSIZE) +#else /* HAVE_MMAP */ + if (rcsbuf_buffer_size < RCSBUF_BUFSIZE) expand_string (&rcsbuf_buffer, &rcsbuf_buffer_size, RCSBUF_BUFSIZE); - rcsbuf->mmapped = 0; - rcsbuf->ptr = rcsbuf_buffer; - rcsbuf->ptrend = rcsbuf_buffer; - rcsbuf->pos = pos; -#ifdef HAVE_MMAP - } + rcsbuf->ptr = rcsbuf_buffer; + rcsbuf->ptrend = rcsbuf_buffer; + rcsbuf->pos = pos; #endif /* HAVE_MMAP */ rcsbuf->fp = fp; rcsbuf->filename = filename; @@ -1107,12 +1091,7 @@ rcsbuf_close (rcsbuf) if (! rcsbuf_inuse) error (1, 0, "rcsbuf_close: internal error"); #ifdef HAVE_MMAP - if (rcsbuf->mmapped) - { - munmap ( rcsbuf_buffer, rcsbuf_buffer_size ); - rcsbuf_buffer = NULL; - rcsbuf_buffer_size = 0; - } + munmap ( rcsbuf_buffer, rcsbuf_buffer_size ); #endif rcsbuf_inuse = 0; } @@ -1157,10 +1136,11 @@ rcsbuf_getkey (rcsbuf, keyp, valp) assert (ptr >= rcsbuf_buffer && ptr <= rcsbuf_buffer + rcsbuf_buffer_size); assert (ptrend >= rcsbuf_buffer && ptrend <= rcsbuf_buffer + rcsbuf_buffer_size); +#ifndef HAVE_MMAP /* If the pointer is more than RCSBUF_BUFSIZE bytes into the buffer, move back to the start of the buffer. This keeps the buffer from growing indefinitely. */ - if (!rcsbuf->mmapped && ptr - rcsbuf_buffer >= RCSBUF_BUFSIZE) + if (ptr - rcsbuf_buffer >= RCSBUF_BUFSIZE) { int len; @@ -1179,18 +1159,23 @@ rcsbuf_getkey (rcsbuf, keyp, valp) ptrend = ptr + len; rcsbuf->ptrend = ptrend; } +#endif /* ndef HAVE_MMAP */ /* Skip leading whitespace. */ while (1) { if (ptr >= ptrend) +#ifndef HAVE_MMAP { ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL); if (ptr == NULL) +#endif return 0; +#ifndef HAVE_MMAP ptrend = rcsbuf->ptrend; } +#endif c = *ptr; if (! my_whitespace (c)) @@ -1209,13 +1194,17 @@ rcsbuf_getkey (rcsbuf, keyp, valp) { ++ptr; if (ptr >= ptrend) +#ifndef HAVE_MMAP { ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL); if (ptr == NULL) +#endif error (1, 0, "EOF in key in RCS file %s", rcsbuf->filename); +#ifndef HAVE_MMAP ptrend = rcsbuf->ptrend; } +#endif c = *ptr; if (c == ';' || my_whitespace (c)) break; @@ -1244,13 +1233,17 @@ rcsbuf_getkey (rcsbuf, keyp, valp) while (1) { if (ptr >= ptrend) +#ifndef HAVE_MMAP { ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL); if (ptr == NULL) +#endif error (1, 0, "EOF while looking for value in RCS file %s", rcsbuf->filename); +#ifndef HAVE_MMAP ptrend = rcsbuf->ptrend; } +#endif c = *ptr; if (c == ';') { @@ -1285,6 +1278,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp) while (1) { while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL) +#ifndef HAVE_MMAP { /* Note that we pass PTREND as the PTR value to rcsbuf_fill, so that we will wind up setting PTR to @@ -1292,25 +1286,31 @@ rcsbuf_getkey (rcsbuf, keyp, valp) that we don't search the same bytes again. */ ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp); if (ptr == NULL) +#endif error (1, 0, "EOF while looking for end of string in RCS file %s", rcsbuf->filename); +#ifndef HAVE_MMAP ptrend = rcsbuf->ptrend; } +#endif /* Handle the special case of an '@' right at the end of the known bytes. */ if (pat + 1 >= ptrend) +#ifndef HAVE_MMAP { /* Note that we pass PAT, not PTR, here. */ pat = rcsbuf_fill (rcsbuf, pat, keyp, valp); if (pat == NULL) { +#endif /* EOF here is OK; it just means that the last character of the file was an '@' terminating a value for a key type which does not require a trailing ';'. */ pat = rcsbuf->ptrend - 1; +#ifndef HAVE_MMAP } ptrend = rcsbuf->ptrend; @@ -1318,6 +1318,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp) /* Note that the value of PTR is bogus here. This is OK, because we don't use it. */ } +#endif if (pat + 1 >= ptrend || pat[1] != '@') break; @@ -1367,13 +1368,17 @@ rcsbuf_getkey (rcsbuf, keyp, valp) char n; if (ptr >= ptrend) +#ifndef HAVE_MMAP { ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp); if (ptr == NULL) +#endif error (1, 0, "EOF in value in RCS file %s", rcsbuf->filename); +#ifndef HAVE_MMAP ptrend = rcsbuf->ptrend; } +#endif n = *ptr; if (n == ';') { @@ -1408,6 +1413,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp) /* Find the ';' which must end the value. */ start = ptr; while ((psemi = memchr (ptr, ';', ptrend - ptr)) == NULL) +#ifndef HAVE_MMAP { int slen; @@ -1418,10 +1424,13 @@ rcsbuf_getkey (rcsbuf, keyp, valp) slen = start - *valp; ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp); if (ptr == NULL) +#endif error (1, 0, "EOF in value in RCS file %s", rcsbuf->filename); +#ifndef HAVE_MMAP start = *valp + slen; ptrend = rcsbuf->ptrend; } +#endif /* See if there are any '@' strings in the value. */ pat = memchr (start, '@', psemi - start); @@ -1465,6 +1474,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp) while (1) { while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL) +#ifndef HAVE_MMAP { /* Note that we pass PTREND as the PTR value to rcsbuff_fill, so that we will wind up setting PTR @@ -1472,22 +1482,29 @@ rcsbuf_getkey (rcsbuf, keyp, valp) that we don't search the same bytes again. */ ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp); if (ptr == NULL) +#endif error (1, 0, "EOF while looking for end of string in RCS file %s", rcsbuf->filename); +#ifndef HAVE_MMAP ptrend = rcsbuf->ptrend; } +#endif /* Handle the special case of an '@' right at the end of the known bytes. */ if (pat + 1 >= ptrend) +#ifndef HAVE_MMAP { ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp); if (ptr == NULL) +#endif error (1, 0, "EOF in value in RCS file %s", rcsbuf->filename); +#ifndef HAVE_MMAP ptrend = rcsbuf->ptrend; } +#endif if (pat[1] != '@') break; @@ -1530,12 +1547,16 @@ rcsbuf_getrevnum (rcsbuf, revp) while (1) { if (ptr >= ptrend) +#ifndef HAVE_MMAP { ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL); if (ptr == NULL) +#endif return 0; +#ifndef HAVE_MMAP ptrend = rcsbuf->ptrend; } +#endif c = *ptr; if (! whitespace (c)) @@ -1556,14 +1577,18 @@ unexpected '\\x%x' reading revision number in RCS file %s", { ++ptr; if (ptr >= ptrend) +#ifndef HAVE_MMAP { ptr = rcsbuf_fill (rcsbuf, ptr, revp, (char **) NULL); if (ptr == NULL) +#endif error (1, 0, "unexpected EOF reading revision number in RCS file %s", rcsbuf->filename); +#ifndef HAVE_MMAP ptrend = rcsbuf->ptrend; } +#endif c = *ptr; } @@ -1581,6 +1606,7 @@ unexpected '\\x%x' reading revision number in RCS file %s", return 1; } +#ifndef HAVE_MMAP /* Fill RCSBUF_BUFFER with bytes from the file associated with RCSBUF, updating PTR and the PTREND field. If KEYP and *KEYP are not NULL, then *KEYP points into the buffer, and must be adjusted if the @@ -1596,9 +1622,6 @@ rcsbuf_fill (rcsbuf, ptr, keyp, valp) { int got; - if (rcsbuf->mmapped) - return NULL; - if (rcsbuf->ptrend - rcsbuf_buffer + RCSBUF_BUFSIZE > rcsbuf_buffer_size) { int poff, peoff, koff, voff; @@ -1631,6 +1654,7 @@ rcsbuf_fill (rcsbuf, ptr, keyp, valp) return ptr; } +#endif /* HAVE_MMAP */ /* Test whether the last value returned by rcsbuf_getkey is a composite value or not. */ @@ -1942,7 +1966,7 @@ static unsigned long rcsbuf_ftell (rcsbuf) struct rcsbuffer *rcsbuf; { - return rcsbuf->pos + (rcsbuf->ptr - rcsbuf_buffer); + return rcsbuf->pos + rcsbuf->ptr - rcsbuf_buffer; } /* Return a pointer to any data buffered for RCSBUF, along with the @@ -2008,7 +2032,8 @@ rcsbuf_cache_open (rcs, pos, pfp, prcsbuf) FILE **pfp; struct rcsbuffer *prcsbuf; { - if (cached_rcs == rcs && !cached_rcsbuf.mmapped) +#ifndef HAVE_MMAP + if (cached_rcs == rcs) { if (rcsbuf_ftell (&cached_rcsbuf) != pos) { @@ -2038,6 +2063,7 @@ rcsbuf_cache_open (rcs, pos, pfp, prcsbuf) } else { +#endif /* ifndef HAVE_MMAP */ /* FIXME: If these routines can be rewritten to not write to the * rcs file buffer, there would be a considerably larger memory savings * from using mmap since the shared file would never need be copied to @@ -2052,13 +2078,17 @@ rcsbuf_cache_open (rcs, pos, pfp, prcsbuf) *pfp = CVS_FOPEN (rcs->path, FOPEN_BINARY_READ); if (*pfp == NULL) error (1, 0, "unable to reopen `%s'", rcs->path); +#ifndef HAVE_MMAP if (pos != 0) { if (fseek (*pfp, pos, SEEK_SET) != 0) error (1, 0, "cannot fseek RCS file %s", rcs->path); } +#endif /* ifndef HAVE_MMAP */ rcsbuf_open (prcsbuf, *pfp, rcs->path, pos); +#ifndef HAVE_MMAP } +#endif /* ifndef HAVE_MMAP */ } @@ -2514,13 +2544,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); @@ -3506,27 +3548,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, @@ -3535,8 +3581,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. */ @@ -3552,8 +3600,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); } @@ -3714,7 +3762,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; @@ -3761,15 +3810,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); @@ -3792,6 +3851,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; } @@ -4140,8 +4201,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat) { int free_rev = 0; enum kflag expand; - FILE *fp; - FILE *ofp = NULL; + FILE *fp, *ofp; struct stat sb; struct rcsbuffer rcsbuf; char *key; @@ -6260,25 +6320,6 @@ findtag (node, arg) return 0; } -static int findmagictag PROTO ((Node *, void *)); - -/* Return a nonzero value if a magic tag rooted at ARG is found. */ - -static int -findmagictag (node, arg) - Node *node; - void *arg; -{ - char *rev = (char *)arg; - size_t len = strlen (rev); - - if (strncmp (node->data, rev, len) == 0 && - strncmp ((char *)node->data + len, ".0.", 3) == 0) - return 1; - else - return 0; -} - /* Delete revisions between REV1 and REV2. The changes between the two revisions must be collapsed, and the result stored in the revision immediately preceding the lower one. Return 0 for successful completion, @@ -6538,9 +6579,8 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive) /* Doing this only for the :: syntax is for compatibility. See cvs.texinfo for somewhat more discussion. */ - if (!inclusive && - (walklist (RCS_symbols (rcs), findtag, revp->version) || - walklist (RCS_symbols (rcs), findmagictag, revp->version))) + if (!inclusive + && walklist (RCS_symbols (rcs), findtag, revp->version)) { /* We don't print which file this happens to on the theory that the caller will print the name of the file in a @@ -6997,6 +7037,31 @@ linevector_add (vec, text, len, vers, pos) return 1; } +static void linevector_delete PROTO ((struct linevector *, unsigned int, + unsigned int)); + +/* Remove NLINES lines from VEC at position POS (where line 0 is the + first line). */ +static void +linevector_delete (vec, pos, nlines) + struct linevector *vec; + unsigned int pos; + unsigned int nlines; +{ + unsigned int i; + unsigned int last; + + last = vec->nlines - nlines; + for (i = pos; i < pos + nlines; ++i) + { + if (--vec->vector[i]->refcount == 0) + free (vec->vector[i]); + } + for (i = pos; i < last; ++i) + vec->vector[i] = vec->vector[i + nlines]; + vec->nlines -= nlines; +} + static void linevector_copy PROTO ((struct linevector *, struct linevector *)); /* Copy FROM to TO, copying the vectors but not the lines pointed to. */ @@ -7040,7 +7105,7 @@ linevector_free (vec) if (vec->vector != NULL) { for (ln = 0; ln < vec->nlines; ++ln) - if (vec->vector[ln] && --vec->vector[ln]->refcount == 0) + if (--vec->vector[ln]->refcount == 0) free (vec->vector[ln]); free (vec->vector); @@ -7075,27 +7140,20 @@ apply_rcs_changes PROTO ((struct linevector *, const char *, size_t, const char *, RCSVers *, RCSVers *)); /* Apply changes to the line vector LINES. DIFFBUF is a buffer of - * length DIFFLEN holding the change text from an RCS file (the output - * of diff -n). NAME is used in error messages. The VERS field of - * any line added is set to ADDVERS. The VERS field of any line - * deleted is set to DELVERS, unless DELVERS is NULL, in which case - * the VERS field of deleted lines is unchanged. - * - * RETURNS - * Non-zero if the change text is applied successfully to ORIG_LINES. - * - * If the change text does not appear to apply to ORIG_LINES (e.g., a - * line number is invalid), this function will return zero and ORIG_LINES - * will remain unmolested. - * - * ERRORS - * If the change text is improperly formatted (e.g., it is not the output - * of diff -n), the function calls error with a status of 1, causing the - * program to exit. - */ + length DIFFLEN holding the change text from an RCS file (the output + of diff -n). NAME is used in error messages. The VERS field of + any line added is set to ADDVERS. The VERS field of any line + deleted is set to DELVERS, unless DELVERS is NULL, in which case + the VERS field of deleted lines is unchanged. The function returns + non-zero if the change text is applied successfully. It returns + zero if the change text does not appear to apply to LINES (e.g., a + line number is invalid). If the change text is improperly + formatted (e.g., it is not the output of diff -n), the function + calls error with a status of 1, causing the program to exit. */ + static int -apply_rcs_changes (orig_lines, diffbuf, difflen, name, addvers, delvers) - struct linevector *orig_lines; +apply_rcs_changes (lines, diffbuf, difflen, name, addvers, delvers) + struct linevector *lines; const char *diffbuf; size_t difflen; const char *name; @@ -7117,15 +7175,10 @@ apply_rcs_changes (orig_lines, diffbuf, difflen, name, addvers, delvers) struct deltafrag *next; }; struct deltafrag *dfhead; - struct deltafrag **dftail; struct deltafrag *df; - unsigned long numlines, lastmodline, offset; - struct linevector lines; int err; dfhead = NULL; - dftail = &dfhead; - numlines = orig_lines->nlines; /* start with init # of lines */ for (p = diffbuf; p != NULL && p < diffbuf + difflen; ) { op = *p++; @@ -7134,9 +7187,9 @@ apply_rcs_changes (orig_lines, diffbuf, difflen, name, addvers, delvers) of op determines the syntax. */ error (1, 0, "unrecognized operation '\\x%x' in %s", op, name); - *dftail = df = xmalloc (sizeof *df); - *(dftail = &df->next) = NULL; - + df = (struct deltafrag *) xmalloc (sizeof (struct deltafrag)); + df->next = dfhead; + dfhead = df; df->pos = strtoul (p, (char **) &q, 10); if (p == q) @@ -7177,7 +7230,6 @@ apply_rcs_changes (orig_lines, diffbuf, difflen, name, addvers, delvers) df->len = q - p; p = q; - numlines += df->nlines; } else { @@ -7187,155 +7239,41 @@ apply_rcs_changes (orig_lines, diffbuf, difflen, name, addvers, delvers) assert (op == 'd'); df->type = FRAG_DELETE; - numlines -= df->nlines; } } - /* New temp data structure to hold new org before - copy back into original structure. */ - lines.nlines = lines.lines_alloced = numlines; - lines.vector = xmalloc (numlines * sizeof *lines.vector); - - /* We changed the list order to first to last -- so the - list never gets larger than the size numlines. */ - lastmodline = 0; - - /* offset created when adding/removing lines - between new and original structure */ - offset = 0; err = 0; - for (df = dfhead; df != NULL; ) + for (df = dfhead; df != NULL;) { unsigned int ln; - unsigned long deltaend; - - if (df->pos > orig_lines->nlines) - err = 1; - /* On error, just free the rest of the list. */ + /* Once an error is encountered, just free the rest of the list and + * return. + */ if (!err) - { - /* Here we need to get to the line where the next insert will - begin, which is DF->pos in ORIG_LINES. We will fill up to - DF->pos - OFFSET in LINES with original items. */ - for (deltaend = df->pos - offset; - lastmodline < deltaend; - lastmodline++) - { - /* we need to copy from the orig structure into new one */ - lines.vector[lastmodline] = - orig_lines->vector[lastmodline + offset]; - lines.vector[lastmodline]->refcount++; - } - switch (df->type) { - case FRAG_ADD: - { - const char *textend, *p; - const char *nextline_text; - struct line *q; - int nextline_newline; - size_t nextline_len; - - textend = df->new_lines + df->len; - nextline_newline = 0; - nextline_text = df->new_lines; - for (p = df->new_lines; p < textend; ++p) - { - if (*p == '\n') - { - nextline_newline = 1; - if (p + 1 == textend) - { - /* If there are no characters beyond the - last newline, we don't consider it - another line. */ - break; - } - - nextline_len = p - nextline_text; - q = xmalloc (sizeof *q + nextline_len); - q->vers = addvers; - q->text = (char *)(q + 1); - q->len = nextline_len; - q->has_newline = nextline_newline; - q->refcount = 1; - memcpy (q->text, nextline_text, nextline_len); - lines.vector[lastmodline++] = q; - offset--; - - nextline_text = (char *)p + 1; - nextline_newline = 0; - } - } - nextline_len = p - nextline_text; - q = xmalloc (sizeof *q + nextline_len); - q->vers = addvers; - q->text = (char *)(q + 1); - q->len = nextline_len; - q->has_newline = nextline_newline; - q->refcount = 1; - memcpy (q->text, nextline_text, nextline_len); - lines.vector[lastmodline++] = q; - - /* For each line we add the offset between the #'s - decreases. */ - offset--; - break; - } - - case FRAG_DELETE: - /* we are removing this many lines from the source. */ - offset += df->nlines; - - if (df->pos + df->nlines > orig_lines->nlines) - err = 1; - else if (delvers) - for (ln = df->pos; ln < df->pos + df->nlines; ++ln) - if (orig_lines->vector[ln]->refcount > 1) - /* Annotate needs this but, since the original - * vector is disposed of before returning from - * this function, we only need keep track if - * there are multiple references. - */ - orig_lines->vector[ln]->vers = delvers; - break; + 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; } - } df = df->next; free (dfhead); dfhead = df; } - if (err) - { - /* No reason to try and move a half-mutated and known invalid - * text into the output buffer. - */ - linevector_free (&lines); - } - else - { - /* add the rest of the remaining lines to the data vector */ - for (; lastmodline < numlines; lastmodline++) - { - /* we need to copy from the orig structure into new one */ - lines.vector[lastmodline] = orig_lines->vector[lastmodline - + offset]; - lines.vector[lastmodline]->refcount++; - } - - /* Move the lines vector to the original structure for output, - * first deleting the old. - */ - linevector_free (orig_lines); - orig_lines->vector = lines.vector; - orig_lines->lines_alloced = numlines; - orig_lines->nlines = lines.nlines; - } - return !err; } @@ -8408,8 +8346,10 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt) char *bufrest; int nls; size_t buflen; +#ifndef HAVE_MMAP char buf[8192]; int got; +#endif /* Count the number of versions for which we have to do some special operation. */ @@ -8523,30 +8463,29 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt) fwrite (bufrest, 1, buflen, fout); } - if (!rcsbufin->mmapped) +#ifndef HAVE_MMAP + /* This bit isn't necessary when using mmap since the entire file + * will already be available via the RCS buffer. Besides, the + * mmap code doesn't always keep the file pointer up to date, so + * this adds some data twice. + */ + while ((got = fread (buf, 1, sizeof buf, fin)) != 0) { - /* This bit isn't necessary when using mmap since the entire file - * will already be available via the RCS buffer. Besides, the - * mmap code doesn't always keep the file pointer up to date, so - * this adds some data twice. - */ - while ((got = fread (buf, 1, sizeof buf, fin)) != 0) + if (nls > 0 + && got >= nls + && buf[0] == '\n' + && strncmp (buf, "\n\n\n", nls) == 0) { - if (nls > 0 - && got >= nls - && buf[0] == '\n' - && strncmp (buf, "\n\n\n", nls) == 0) - { - fwrite (buf + 1, 1, got - 1, fout); - } - else - { - fwrite (buf, 1, got, fout); - } + fwrite (buf + 1, 1, got - 1, fout); + } + else + { + fwrite (buf, 1, got, fout); + } nls = 0; - } } +#endif /* HAVE_MMAP */ } /* A helper procedure for RCS_copydeltas. This is called via walklist @@ -8934,3 +8873,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..08b8a5f 100644 --- a/contrib/cvs/src/rcs.h +++ b/contrib/cvs/src/rcs.h @@ -11,6 +11,8 @@ * 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. */ @@ -250,8 +252,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..18182ff 100644 --- a/contrib/cvs/src/rcscmds.c +++ b/contrib/cvs/src/rcscmds.c @@ -12,6 +12,8 @@ * * The functions in this file provide an interface for performing * operations directly on RCS files. + * + * $FreeBSD$ */ #include "cvs.h" diff --git a/contrib/cvs/src/recurse.c b/contrib/cvs/src/recurse.c index fb865a9..1fb33c1 100644 --- a/contrib/cvs/src/recurse.c +++ b/contrib/cvs/src/recurse.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1986-2008 The Free Software Foundation, Inc. + * Copyright (C) 1986-2005 The Free Software Foundation, Inc. * * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, * and others. @@ -12,6 +12,7 @@ * * General recursion handler * + * $FreeBSD$ */ #include "cvs.h" @@ -662,6 +663,7 @@ do_recursion (frame) { repository = frame->repository; assert (repository != NULL); + assert (strstr (repository, "/./") == NULL); } fileattr_startdir (repository); @@ -764,7 +766,7 @@ do_recursion (frame) have writelocks in place, and there is no way to get writelocks here. */ if (current_parsed_root->isremote) - cvs_notify_check (repository, update_dir); + notify_check (repository, update_dir); #endif /* CLIENT_SUPPORT */ finfo_struct.repository = repository; diff --git a/contrib/cvs/src/server.c b/contrib/cvs/src/server.c index 374c7d3..3262bba 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" @@ -759,19 +763,6 @@ serve_root (arg) return; } - /* We need to check :ext: server here, :pserver: checks happen below. */ - if (root_allow_used() && !root_allow_ok (arg) -# ifdef AUTH_SERVER_SUPPORT - && Pserver_Repos == NULL -# endif - ) - { - if (alloc_pending (80 + strlen (arg))) - sprintf (pending_error_text, - "E Bad root %s", arg); - return; - } - #ifdef AUTH_SERVER_SUPPORT if (Pserver_Repos != NULL) { @@ -795,6 +786,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); @@ -2767,7 +2761,7 @@ do_cvs_command (cmd_name, command) int dev_null_fd = -1; - int errs = 0; + int errs; command_pid = -1; stdout_pipe[0] = -1; @@ -2966,8 +2960,9 @@ error \n"); #ifdef SERVER_FLOWCONTROL { char junk; + ssize_t status; set_block_fd (flowcontrol_pipe[0]); - while (read (flowcontrol_pipe[0], &junk, 1) > 0); + while ((status = read (flowcontrol_pipe[0], &junk, 1)) > 0); } /* FIXME: No point in printing an error message with error(), * as STDERR is already closed, but perhaps this could be syslogged? @@ -3999,11 +3994,38 @@ static void serve_init (arg) char *arg; { - if (alloc_pending (80 + strlen (arg))) - sprintf (pending_error_text, "E init may not be run remotely"); + cvsroot_t *saved_parsed_root; + + if (!isabsolute (arg)) + { + if (alloc_pending (80 + strlen (arg))) + sprintf (pending_error_text, + "E init %s must be an absolute pathname", arg); + } +#ifdef AUTH_SERVER_SUPPORT + else if (Pserver_Repos != NULL) + { + if (strcmp (Pserver_Repos, arg) != 0) + { + if (alloc_pending (80 + strlen (Pserver_Repos) + strlen (arg))) + /* The explicitness is to aid people who are writing clients. + I don't see how this information could help an + attacker. */ + sprintf (pending_error_text, "\ +E Protocol error: init says \"%s\" but pserver says \"%s\"", + arg, Pserver_Repos); + } + } +#endif if (print_pending_error ()) return; + + saved_parsed_root = current_parsed_root; + current_parsed_root = local_cvsroot (arg); + do_cvs_command ("init", init); + free_cvsroot_t (current_parsed_root); + current_parsed_root = saved_parsed_root; } static void serve_annotate PROTO ((char *)); @@ -5665,7 +5687,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) 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..43451ce 100644 --- a/contrib/cvs/src/tag.c +++ b/contrib/cvs/src/tag.c @@ -15,6 +15,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" @@ -1363,6 +1365,9 @@ Numeric tag %s contains characters other than digits and '.'", name); || strcmp (name, TAG_HEAD) == 0) return; + if (readonlyfs) + return; + /* Verify that the tag is valid syntactically. Some later code once made * assumptions about this. */ diff --git a/contrib/cvs/src/update.c b/contrib/cvs/src/update.c index 117561a..3d82ee4 100644 --- a/contrib/cvs/src/update.c +++ b/contrib/cvs/src/update.c @@ -36,6 +36,8 @@ * 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" @@ -101,10 +103,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 +131,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 +147,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 +157,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) { @@ -189,6 +193,9 @@ update (argc, argv) "-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; @@ -418,8 +425,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 +443,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 +459,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 +474,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; @@ -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; @@ -937,7 +944,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 +1003,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 (); } @@ -1435,10 +1448,8 @@ VERS: ", 0); /* fix up the vers structure, in case it is used by join */ if (join_rev1) { - /* FIXME: It seems like we should be preserving ts_user - * & ts_rcs here, but setting them causes problems in - * join_file(). - */ + /* FIXME: Throwing away the original revision info is almost + certainly wrong -- what if join_rev1 is "BASE"? */ if (vers_ts->vn_user != NULL) free (vers_ts->vn_user); if (vers_ts->vn_rcs != NULL) @@ -1647,11 +1658,21 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum) data.final_nl = 0; data.compute_checksum = 0; - /* Duplicating the client working file, so use the original sticky options. + /* FIXME - Passing vers_ts->tag here is wrong in the least number + * of cases. Since we don't know whether vn_user was checked out + * using a tag, we pass vers_ts->tag, which, assuming the user did + * not specify a new TAG to -r, will be the branch we are on. + * + * The only thing it is used for is to substitute in for the Name + * RCS keyword, so in the error case, the patch fails to apply on + * the client end and we end up resending the whole file. + * + * At least, if we are keeping track of the tag vn_user came from, + * I don't know where yet. -DRP */ retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL, - vers_ts->vn_user, vers_ts->entdata->tag, - vers_ts->entdata->options, RUN_TTY, + vers_ts->vn_user, vers_ts->tag, + vers_ts->options, RUN_TTY, patch_file_write, (void *) &data); if (fclose (e) < 0) @@ -2209,7 +2230,6 @@ join_file (finfo, vers) if (rev2 == NULL || RCS_isdead (vers->srcfile, rev2)) { char *mrev; - short conflict = 0; if (rev2 != NULL) free (rev2); @@ -2260,7 +2280,8 @@ join_file (finfo, vers) || vers->vn_user[0] == '-' || RCS_isdead (vers->srcfile, vers->vn_user)) { - free (rev1); + if (rev1 != NULL) + free (rev1); return; } @@ -2269,107 +2290,56 @@ join_file (finfo, vers) resolve. No_Difference will already have been called in this case, so comparing the timestamps is sufficient to determine whether the file is locally modified. */ - if (/* may have changed on destination branch */ - /* file added locally */ - !strcmp (vers->vn_user, "0") - || /* destination branch modified in repository */ - strcmp (rev1, vers->vn_user) - || /* locally modified */ - vers->ts_user && strcmp (vers->ts_user, vers->ts_rcs)) + if (strcmp (vers->vn_user, "0") == 0 + || (vers->ts_user != NULL + && strcmp (vers->ts_user, vers->ts_rcs) != 0)) { - /* The removal should happen if either the file has never changed - * on the destination or the file has changed to be identical to - * the first join revision. - * - * ------R-----------D - * | - * \----J1---J2-----S - * - * So: - * - * J2 is dead. - * D is destination. - * R is source branch root/GCA. - * if J1 == D removal should happen - * if D == R removal should happen - * otherwise, fail. - * - * (In the source, J2 = REV2, D = user file (potentially VN_USER), - * R = GCA computed below) - */ - char *gca_rev1 = gca (rev1, vers->vn_user); -#ifdef SERVER_SUPPORT - if (server_active && !isreadable (finfo->file)) - { - int retcode; - /* The file is up to date. Need to check out the current - * contents. - */ - /* FIXME - see the FIXME comment above the call to RCS_checkout - * in the patch_file function. - */ - retcode = RCS_checkout (vers->srcfile, finfo->file, - vers->vn_user, vers->tag, - NULL, RUN_TTY, NULL, NULL); - if (retcode) - error (1, 0, - "failed to check out %s file", finfo->fullname); - } -#endif - if (/* genuinely changed on destination branch */ - RCS_cmp_file (vers->srcfile, gca_rev1, NULL, - NULL, vers->options, finfo->file) - && /* genuinely different from REV1 */ - RCS_cmp_file (vers->srcfile, rev1, NULL, - NULL, vers->options, finfo->file)) - conflict = 1; - } - - free (rev1); - - if (conflict) - { - char *cp; - - if (jdate2) + if (jdate2 != NULL) error (0, 0, - "file %s has been removed in revision %s as of %s, but the destination is incompatibly modified", + "file %s is locally modified, but has been removed in revision %s as of %s", finfo->fullname, jrev2, jdate2); else error (0, 0, - "file %s has been removed in revision %s, but the destination is incompatibly modified", + "file %s is locally modified, but has been removed in revision %s", finfo->fullname, jrev2); - /* Register the conflict with the client. */ + /* FIXME: Should we arrange to return a non-zero exit + status? */ - /* FIXME: vers->ts_user should always be set here but sometimes - * isn't, namely when checkout_file() has just created the file, - * but simply setting it in checkout_file() appears to cause other - * problems. - */ - if (isfile (finfo->file)) - cp = time_stamp (finfo->file); + if (rev1 != NULL) + free (rev1); + + return; + } + + /* If only one join tag was specified, and the user file has + been changed since the greatest common ancestor (rev1), + then there is a conflict we can not resolve. See above for + the rationale. */ + if (join_rev2 == NULL + && strcmp (rev1, vers->vn_user) != 0) + { + if (jdate2 != NULL) + error (0, 0, + "file %s has been modified, but has been removed in revision %s as of %s", + finfo->fullname, jrev2, jdate2); else - cp = xstrdup (vers->ts_user); + error (0, 0, + "file %s has been modified, but has been removed in revision %s", + finfo->fullname, jrev2); - Register (finfo->entries, finfo->file, vers->vn_user, - "Result of merge", vers->options, vers->tag, vers->date, - cp); - write_letter (finfo, 'C'); - free (cp); + /* FIXME: Should we arrange to return a non-zero exit + status? */ -#ifdef SERVER_SUPPORT - /* Abuse server_checked_in() to send the updated entry without - * needing to update the file. - */ - if (server_active) - server_checked_in (finfo->file, finfo->update_dir, - finfo->repository); -#endif + if (rev1 != NULL) + free (rev1); return; } + if (rev1 != NULL) + free (rev1); + /* The user file exists and has not been modified. Mark it for removal. FIXME: If we are doing a checkout, this has the effect of first checking out the file, and then 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 */ |