Index: lib/md5.h =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/lib/md5.h,v retrieving revision 1.1.1.3 retrieving revision 1.2 diff -u -p -r1.1.1.3 -r1.2 --- lib/md5.h 11 Dec 1999 12:22:56 -0000 1.1.1.3 +++ lib/md5.h 11 Dec 1999 15:10:02 -0000 1.2 @@ -1,8 +1,21 @@ /* See md5.c for explanation and copyright information. */ +/* + * $FreeBSD$ + */ + #ifndef MD5_H #define MD5_H +#ifdef __FreeBSD__ +#define cvs_MD5Context MD5Context +#define cvs_MD5Init MD5Init +#define cvs_MD5Update MD5Update +#define cvs_MD5Final MD5Final +#define cvs_MD5Transform MD5Transform +#include +#else + /* Unlike previous versions of this code, uint32 need not be exactly 32 bits, merely 32 bits or more. Choosing a data type which is 32 bits instead of 64 is not important; speed is considerably more @@ -23,4 +36,6 @@ void cvs_MD5Final PROTO ((unsigned char struct cvs_MD5Context *context)); void cvs_MD5Transform PROTO ((cvs_uint32 buf[4], const unsigned char in[64])); +#endif + #endif /* !MD5_H */ Index: src/checkout.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/checkout.c,v retrieving revision 1.1.1.14 retrieving revision 1.6 diff -u -p -r1.1.1.14 -r1.6 --- src/checkout.c 26 Dec 2007 03:55:02 -0000 1.1.1.14 +++ src/checkout.c 26 Dec 2007 04:09:41 -0000 1.6 @@ -38,6 +38,10 @@ * edited by the user, if necessary (when the repository is moved, e.g.) */ +/* + * $FreeBSD$ + */ + #include #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 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 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; Index: src/client.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/client.c,v retrieving revision 1.1.1.17 retrieving revision 1.13 diff -u -p -r1.1.1.17 -r1.13 --- src/client.c 26 Dec 2007 03:55:02 -0000 1.1.1.17 +++ src/client.c 26 Dec 2007 05:08:14 -0000 1.13 @@ -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 */ @@ -269,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. */ @@ -4789,7 +4794,7 @@ start_rsh_server (root, to_server, from_ int child_pid; if (!cvs_rsh) - cvs_rsh = "rsh"; + cvs_rsh = RSH_DFLT; if (!cvs_server) cvs_server = "cvs"; @@ -5150,7 +5155,8 @@ warning: ignoring -k options due to serv || 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")) Index: src/cvs.h =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/cvs.h,v retrieving revision 1.1.1.16 diff -u -p -r1.1.1.16 cvs.h --- src/cvs.h 26 Dec 2007 03:55:03 -0000 1.1.1.16 +++ src/cvs.h 7 Jan 2008 04:40:44 -0000 @@ -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 * 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)); Index: src/cvsbug.in =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/cvsbug.in,v retrieving revision 1.1.1.3 retrieving revision 1.2 diff -u -p -r1.1.1.3 -r1.2 --- src/cvsbug.in 15 Apr 2004 01:01:55 -0000 1.1.1.3 +++ src/cvsbug.in 7 Sep 2005 13:39:44 -0000 1.2 @@ -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 Index: src/diff.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/diff.c,v retrieving revision 1.1.1.13 retrieving revision 1.22 diff -u -p -r1.1.1.13 -r1.22 --- src/diff.c 26 Dec 2007 03:55:02 -0000 1.1.1.13 +++ src/diff.c 31 Dec 2007 03:27:32 -0000 1.22 @@ -17,6 +17,8 @@ * * Without any file arguments, runs diff against all the currently modified * files. + * + * $FreeBSD$ */ #include @@ -57,6 +59,7 @@ static void diff_mark_errors PROTO((int 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); } Index: src/entries.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/entries.c,v retrieving revision 1.1.1.9 retrieving revision 1.5 diff -u -p -r1.1.1.9 -r1.5 --- src/entries.c 26 Dec 2007 03:55:02 -0000 1.1.1.9 +++ src/entries.c 2 Jan 2008 08:57:42 -0000 1.5 @@ -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. */ Index: src/filesubr.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/filesubr.c,v retrieving revision 1.1.1.13 retrieving revision 1.14 diff -u -p -r1.1.1.13 -r1.14 --- src/filesubr.c 26 Dec 2007 03:55:03 -0000 1.1.1.13 +++ src/filesubr.c 31 Dec 2007 03:59:16 -0000 1.14 @@ -17,6 +17,10 @@ definitions under operating systems (like, say, Windows NT) with different file system semantics. */ +/* + * $FreeBSD$ + */ + #include #include "cvs.h" @@ -887,7 +891,7 @@ xreadlink (link) const char *link; { char *file = NULL; - size_t buflen = 128; + size_t buflen = BUFSIZ; /* Get the name of the file to which `from' is linked. */ while (1) Index: src/lock.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/lock.c,v retrieving revision 1.1.1.13 retrieving revision 1.14 diff -u -p -r1.1.1.13 -r1.14 --- src/lock.c 26 Dec 2007 03:55:03 -0000 1.1.1.13 +++ src/lock.c 2 Jan 2008 09:05:04 -0000 1.14 @@ -13,6 +13,8 @@ * Set Lock * * Lock file support for CVS. + * + * $FreeBSD$ */ /* The node Concurrency in doc/cvs.texinfo has a brief introduction to @@ -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) { Index: src/log.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/log.c,v retrieving revision 1.1.1.13 retrieving revision 1.4 diff -u -p -r1.1.1.13 -r1.4 --- src/log.c 26 Dec 2007 03:55:03 -0000 1.1.1.13 +++ src/log.c 2 Jan 2008 09:13:03 -0000 1.4 @@ -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" @@ -242,7 +244,7 @@ cvslog (argc, argv) prl = &log_data.revlist; optind = 0; - while ((c = getopt (argc, argv, "+bd:hlNSRr::s:tw::")) != -1) + while ((c = getopt (argc, argv, "+bd:hlNnSRr::s:tw::")) != -1) { switch (c) { @@ -261,6 +263,9 @@ cvslog (argc, argv) case 'N': log_data.notags = 1; break; + case 'n': + log_data.notags = 0; + break; case 'S': log_data.sup_header = 1; break; @@ -1644,8 +1649,8 @@ log_version (log_data, revlist, rcs, ver &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); Index: src/logmsg.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/logmsg.c,v retrieving revision 1.1.1.11 retrieving revision 1.13 diff -u -p -r1.1.1.11 -r1.13 --- src/logmsg.c 26 Dec 2007 03:55:03 -0000 1.1.1.11 +++ src/logmsg.c 2 Jan 2008 09:36:37 -0000 1.13 @@ -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 @@ -227,6 +229,8 @@ do_editor (dir, messagep, repository, ch (*messagep)[strlen (*messagep) - 1] != '\n') (void) fprintf (fp, "\n"); } + else + (void) fprintf (fp, "\n"); if (repository != NULL) /* tack templates on if necessary */ Index: src/main.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/main.c,v retrieving revision 1.1.1.14 retrieving revision 1.26 diff -u -p -r1.1.1.14 -r1.26 --- src/main.c 26 Dec 2007 03:55:03 -0000 1.1.1.14 +++ src/main.c 2 Jan 2008 10:17:27 -0000 1.26 @@ -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 #include "cvs.h" +#include "prepend_args.h" #ifdef HAVE_WINSOCK_H #include @@ -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; /* @@ -108,7 +112,7 @@ static const struct cmd { { "add", "ad", "new", add, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, { "admin", "adm", "rcs", admin, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, - { "annotate", "ann", NULL, annotate, CVS_CMD_USES_WORK_DIR }, + { "annotate", "ann", "blame", annotate, CVS_CMD_USES_WORK_DIR }, { "checkout", "co", "get", checkout, 0 }, { "commit", "ci", "com", commit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, { "diff", "di", "dif", diff, CVS_CMD_USES_WORK_DIR }, @@ -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 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 (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 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); + } +} Index: src/parseinfo.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/parseinfo.c,v retrieving revision 1.1.1.13 retrieving revision 1.4 diff -u -p -r1.1.1.13 -r1.4 --- src/parseinfo.c 26 Dec 2007 03:55:03 -0000 1.1.1.13 +++ src/parseinfo.c 2 Jan 2008 10:18:49 -0000 1.4 @@ -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" @@ -357,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 + 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) Index: src/rcs.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/rcs.c,v retrieving revision 1.1.1.15 retrieving revision 1.29 diff -u -p -r1.1.1.15 -r1.29 --- src/rcs.c 26 Dec 2007 03:55:03 -0000 1.1.1.15 +++ src/rcs.c 7 Jan 2008 02:03:50 -0000 1.29 @@ -12,6 +12,8 @@ * * The routines contained in this file do all the rcs file parsing and * manipulation + * + * $FreeBSD$ */ #include @@ -30,6 +32,7 @@ # endif #endif +int datesep = '/'; int preserve_perms = 0; /* The RCS -k options, and a set of enums that must match the array. @@ -140,6 +143,8 @@ static char *rcs_lockfilename PROTO ((co 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: * @@ -2539,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); @@ -3531,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, @@ -3560,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. */ @@ -3577,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); } @@ -3739,7 +3762,8 @@ expand_keywords (rcs, ver, name, log, lo slen = s - srch; for (keyword = keywords; keyword->string != NULL; keyword++) { - if (keyword->len == slen + if (keyword->expandit + && keyword->len == slen && strncmp (keyword->string, srch, slen) == 0) { break; @@ -3786,15 +3810,25 @@ expand_keywords (rcs, ver, name, log, lo free_value = 1; break; + case KEYWORD_CVSHEADER: case KEYWORD_HEADER: case KEYWORD_ID: + case KEYWORD_LOCALID: { const char *path; int free_path; char *date; + char *old_path; - if (kw == KEYWORD_HEADER) + old_path = NULL; + if (kw == KEYWORD_HEADER || + (kw == KEYWORD_LOCALID && + keyword_local == KEYWORD_HEADER)) path = rcs->path; + else if (kw == KEYWORD_CVSHEADER || + (kw == KEYWORD_LOCALID && + keyword_local == KEYWORD_CVSHEADER)) + path = getfullCVSname(rcs->path, &old_path); else path = last_component (rcs->path); path = escape_keyword_value (path, &free_path); @@ -3817,6 +3851,8 @@ expand_keywords (rcs, ver, name, log, lo * and we can discard the const. */ free ((char *)path); + if (old_path) + free (old_path); free (date); free_value = 1; } @@ -8837,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; +} Index: src/rcs.h =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/rcs.h,v retrieving revision 1.1.1.11 retrieving revision 1.12 diff -u -p -r1.1.1.11 -r1.12 --- src/rcs.h 26 Dec 2007 03:55:03 -0000 1.1.1.11 +++ src/rcs.h 2 Jan 2008 10:20:57 -0000 1.12 @@ -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 * 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. */ Index: src/server.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/server.c,v retrieving revision 1.1.1.19 retrieving revision 1.25 diff -u -p -r1.1.1.19 -r1.25 --- src/server.c 26 Dec 2007 03:55:03 -0000 1.1.1.19 +++ src/server.c 7 Jan 2008 02:44:32 -0000 1.25 @@ -8,6 +8,10 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ +/* + * $FreeBSD$ + */ + #include #include "cvs.h" #include "watch.h" @@ -782,6 +786,9 @@ E Protocol error: Root says \"%s\" but p 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); @@ -5680,7 +5687,10 @@ check_password (username, password, repo 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) Index: src/tag.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/tag.c,v retrieving revision 1.1.1.13 retrieving revision 1.3 diff -u -p -r1.1.1.13 -r1.3 --- src/tag.c 26 Dec 2007 03:55:03 -0000 1.1.1.13 +++ src/tag.c 2 Jan 2008 08:54:42 -0000 1.3 @@ -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 || strcmp (name, TAG_HEAD) == 0) return; + if (readonlyfs) + return; + /* Verify that the tag is valid syntactically. Some later code once made * assumptions about this. */ Index: src/update.c =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/update.c,v retrieving revision 1.1.1.16 retrieving revision 1.15 diff -u -p -r1.1.1.16 -r1.15 --- src/update.c 26 Dec 2007 03:55:03 -0000 1.1.1.16 +++ src/update.c 7 Jan 2008 02:49:44 -0000 1.15 @@ -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, x 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, x 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, repo 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, repo nonbranch = 0; } + /* keep the CVS/Template file current */ + if (pull_template) + { + WriteTemplate (dir, update_dir); + } + /* initialize the ignore list for this directory */ ignlist = getlist (); } Index: src/update.h =================================================================== RCS file: /home/obrien/Cvs/cvs/contrib/cvs/src/update.h,v retrieving revision 1.1.1.4 retrieving revision 1.3 diff -u -p -r1.1.1.4 -r1.3 --- src/update.h 15 Apr 2004 01:01:55 -0000 1.1.1.4 +++ src/update.h 15 Apr 2004 01:17:28 -0000 1.3 @@ -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));