diff options
-rw-r--r-- | gnu/usr.bin/cvs/src/cvs.h | 2 | ||||
-rw-r--r-- | gnu/usr.bin/cvs/src/main.c | 44 | ||||
-rw-r--r-- | gnu/usr.bin/cvs/src/rcscmds.c | 114 |
3 files changed, 148 insertions, 12 deletions
diff --git a/gnu/usr.bin/cvs/src/cvs.h b/gnu/usr.bin/cvs/src/cvs.h index 38fb5fb3c66..ac053441ec6 100644 --- a/gnu/usr.bin/cvs/src/cvs.h +++ b/gnu/usr.bin/cvs/src/cvs.h @@ -184,6 +184,7 @@ extern int errno; #define CVSROOTADM_WRAPPER "cvswrappers" #define CVSROOTADM_NOTIFY "notify" #define CVSROOTADM_USERS "users" +#define CVSROOTADM_OPTIONS "options" #define CVSNULLREPOS "Emptydir" /* an empty directory */ @@ -415,6 +416,7 @@ 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 char *RCS_citag; /* special -Z tag for RCS */ extern char hostname[]; diff --git a/gnu/usr.bin/cvs/src/main.c b/gnu/usr.bin/cvs/src/main.c index dafe689f85d..cac95441644 100644 --- a/gnu/usr.bin/cvs/src/main.c +++ b/gnu/usr.bin/cvs/src/main.c @@ -678,6 +678,7 @@ error 0 %s: no such user\n", user); "Sorry, you don't have read/write access to the history file"); error (1, save_errno, "%s", path); } + parseopts(); } } @@ -837,3 +838,46 @@ usage (cpp) (void) fprintf (stderr, *cpp); exit (EXIT_FAILURE); } + +parseopts() +{ + char path[PATH_MAX]; + int save_errno; + char buf[1024]; + char *p; + FILE *fp; + + (void) sprintf (path, "%s/%s/%s", CVSroot, CVSROOTADM, CVSROOTADM_OPTIONS); + if ((fp = fopen(path, "r")) != NULL) { + while (fgets(buf, sizeof buf, fp) != NULL) { + if (buf[0] == '#') + continue; + p = strrchr(buf, '\n'); + if (p) + *p = '\0'; + + if (!strncmp(buf, "tag=", 4)) { + RCS_citag = strdup(buf+4); + } else if (!strncmp(buf, "umask=", 6)) { + int mode; + + mode = strtol(buf+6, NULL, 8); + umask((mode_t)mode); + } + else if (!strncmp(buf, "dlimit=", 7)) { +#ifdef __OpenBSD__ +#include <sys/resource.h> + struct rlimit rl; + + if (getrlimit(RLIMIT_DATA, &rl) != -1) { + rl.rlim_cur = atoi(buf+7); + rl.rlim_cur *= 1024; + + (void) setrlimit(RLIMIT_DATA, &rl); + } +#endif /* __OpenBSD__ */ + } + } + fclose(fp); + } +} diff --git a/gnu/usr.bin/cvs/src/rcscmds.c b/gnu/usr.bin/cvs/src/rcscmds.c index 593cf5c0bba..eabd1aec310 100644 --- a/gnu/usr.bin/cvs/src/rcscmds.c +++ b/gnu/usr.bin/cvs/src/rcscmds.c @@ -10,6 +10,14 @@ */ #include "cvs.h" +#include <assert.h> + +/* For RCS file PATH, make symbolic tag TAG point to revision REV. + This validates that TAG is OK for a user to use. Return value is + -1 for error (and errno is set to indicate the error), positive for + error (and an error message has been printed), or zero for success. */ + +char *RCS_citag; int RCS_settag(path, tag, rev) @@ -17,7 +25,18 @@ RCS_settag(path, tag, rev) const char *tag; const char *rev; { - run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, tag, rev); + if (strcmp (tag, TAG_BASE) == 0 + || strcmp (tag, TAG_HEAD) == 0) + { + /* Print the name of the tag might be considered redundant + with the caller, which also prints it. Perhaps this helps + clarify why the tag name is considered reserved, I don't + know. */ + error (0, 0, "Attempt to add reserved tag name %s", tag); + return 1; + } + + run_setup ("%s%s -x,v/ -q -N%s:%s", Rcsbin, RCS, tag, rev); run_arg (path); return run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); } @@ -28,8 +47,9 @@ int RCS_deltag(path, tag, noerr) const char *path; const char *tag; + int noerr; { - run_setup ("%s%s -q -N%s", Rcsbin, RCS, tag); + run_setup ("%s%s -x,v/ -q -N%s", Rcsbin, RCS, tag); run_arg (path); return run_exec (RUN_TTY, RUN_TTY, noerr ? DEVNULL : RUN_TTY, RUN_NORMAL); } @@ -40,7 +60,7 @@ RCS_setbranch(path, rev) const char *path; const char *rev; { - run_setup ("%s%s -q -b%s", Rcsbin, RCS, rev ? rev : ""); + run_setup ("%s%s -x,v/ -q -b%s", Rcsbin, RCS, rev ? rev : ""); run_arg (path); return run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); } @@ -53,7 +73,7 @@ RCS_lock(path, rev, noerr) const char *rev; int noerr; { - run_setup ("%s%s -q -l%s", Rcsbin, RCS, rev ? rev : ""); + run_setup ("%s%s -x,v/ -q -l%s", Rcsbin, RCS, rev ? rev : ""); run_arg (path); return run_exec (RUN_TTY, RUN_TTY, noerr ? DEVNULL : RUN_TTY, RUN_NORMAL); } @@ -64,8 +84,9 @@ int RCS_unlock(path, rev, noerr) const char *path; const char *rev; + int noerr; { - run_setup ("%s%s -q -u%s", Rcsbin, RCS, rev ? rev : ""); + run_setup ("%s%s -x,v/ -q -u%s", Rcsbin, RCS, rev ? rev : ""); run_arg (path); return run_exec (RUN_TTY, RUN_TTY, noerr ? DEVNULL : RUN_TTY, RUN_NORMAL); } @@ -80,25 +101,94 @@ RCS_merge(path, options, rev1, rev2) { int status; - /* We pass -E to rcsmerge so that it will not indicate a conflict if - both things we are merging are modified the same way. - - Well, okay, but my rcsmerge doesn't take a -E option. --JimB */ /* XXX - Do merge by hand instead of using rcsmerge, due to -k handling */ - run_setup ("%s%s %s -r%s -r%s %s", Rcsbin, RCS_RCSMERGE, + run_setup ("%s%s -x,v/ %s -r%s -r%s %s", Rcsbin, RCS_RCSMERGE, options, rev1, rev2, path); status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); #ifndef HAVE_RCS5 if (status == 0) { /* Run GREP to see if there appear to be conflicts in the file */ - run_setup ("%s -s", GREP); + run_setup ("%s", GREP); run_arg (RCS_MERGE_PAT); run_arg (path); - status = (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) == 0); + status = (run_exec (RUN_TTY, DEVNULL, RUN_TTY, RUN_NORMAL) == 0); } #endif return status; } + +/* Check out a revision from RCSFILE into WORKFILE, or to standard output + if WORKFILE is NULL. If WORKFILE is "", let RCS pick the working file + name. TAG is the tag to check out, or NULL if one should check out + the head of the default branch. OPTIONS is a string such as + -kb or -kkv, for keyword expansion options, or NULL if there are none. + If WORKFILE is NULL, run regardless of noexec; if non-NULL, noexec + inhibits execution. SOUT is what to do with standard output + (typically RUN_TTY). If FLAGS & RCS_FLAGS_LOCK, lock it. If + FLAGS & RCS_FLAGS_FORCE, check out even on top of an existing file. + If NOERR is nonzero, suppress errors. */ +int +RCS_checkout (rcsfile, workfile, tag, options, sout, flags, noerr) + char *rcsfile; + char *workfile; + char *tag; + char *options; + char *sout; + int flags; + int noerr; +{ + run_setup ("%s%s -x,v/ -q %s%s", Rcsbin, RCS_CO, + tag ? "-r" : "", tag ? tag : ""); + if (options != NULL && options[0] != '\0') + run_arg (options); + if (workfile == NULL) + run_arg ("-p"); + if (flags & RCS_FLAGS_LOCK) + run_arg ("-l"); + if (flags & RCS_FLAGS_FORCE) + run_arg ("-f"); + if (RCS_citag) + run_arg (RCS_citag); + run_arg (rcsfile); + if (workfile != NULL && workfile[0] != '\0') + run_arg (workfile); + return run_exec (RUN_TTY, sout, noerr ? DEVNULL : RUN_TTY, + workfile == NULL ? (RUN_NORMAL | RUN_REALLY) : RUN_NORMAL); +} + +/* Check in to RCSFILE with revision REV (which must be greater than the + largest revision) and message MESSAGE (which is checked for legality). + If FLAGS & RCS_FLAGS_DEAD, check in a dead revision. If NOERR, do not + report errors. If FLAGS & RCS_FLAGS_QUIET suppress errors somewhat more + selectively. If FLAGS & RCS_FLAGS_MODTIME, use the working file's + modification time for the checkin time. WORKFILE is the working file + to check in from, or NULL to use the usual RCS rules for deriving it + from the RCSFILE. */ +int +RCS_checkin (rcsfile, workfile, message, rev, flags, noerr) + char *rcsfile; + char *workfile; + char *message; + char *rev; + int flags; + int noerr; +{ + run_setup ("%s%s -x,v/ -f %s%s", Rcsbin, RCS_CI, + rev ? "-r" : "", rev ? rev : ""); + if (flags & RCS_FLAGS_DEAD) + run_arg ("-sdead"); + if (flags & RCS_FLAGS_QUIET) + run_arg ("-q"); + if (flags & RCS_FLAGS_MODTIME) + run_arg ("-d"); + if (RCS_citag) + run_arg (RCS_citag); + run_args ("-m%s", make_message_rcslegal (message)); + if (workfile != NULL) + run_arg (workfile); + run_arg (rcsfile); + return run_exec (RUN_TTY, RUN_TTY, noerr ? DEVNULL : RUN_TTY, RUN_NORMAL); +} |