summaryrefslogtreecommitdiff
path: root/usr.bin/rcs/rcsprog.c
diff options
context:
space:
mode:
authorJoris Vink <joris@cvs.openbsd.org>2005-12-24 03:48:10 +0000
committerJoris Vink <joris@cvs.openbsd.org>2005-12-24 03:48:10 +0000
commit15359496dd724a8f559b24cfbb0c190712179aea (patch)
treef46323e250283a5a5695949a5961c785416dcbaf /usr.bin/rcs/rcsprog.c
parentdf8e51b47fdf7c21a916cf8bc682acdaddb86444 (diff)
- support for -n -N and -t;
- check for path truncation; - do not pollute flags being passed to rcs_open() with local flags; - fix rcs initialization stuff;
Diffstat (limited to 'usr.bin/rcs/rcsprog.c')
-rw-r--r--usr.bin/rcs/rcsprog.c140
1 files changed, 129 insertions, 11 deletions
diff --git a/usr.bin/rcs/rcsprog.c b/usr.bin/rcs/rcsprog.c
index 5e4cef2f51f..29a0ff5facd 100644
--- a/usr.bin/rcs/rcsprog.c
+++ b/usr.bin/rcs/rcsprog.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rcsprog.c,v 1.55 2005/12/21 16:10:50 xsa Exp $ */
+/* $OpenBSD: rcsprog.c,v 1.56 2005/12/24 03:48:09 joris Exp $ */
/*
* Copyright (c) 2005 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -43,12 +43,20 @@
#define RCS_CMD_MAXARG 128
#define RCS_DEFAULT_SUFFIX ",v/"
-#define RCSPROG_OPTSTRING "A:a:b::c:e::hik:Lm:MqTUVx:z:"
+#define RCSPROG_OPTSTRING "A:a:b::c:e::hik:Lm:Mn:N:qt::TUVx:z:"
+
+#define DESC_PROMPT "enter description, terminated with single '.' " \
+ "or end of file:\nNOTE: This is NOT the log message!" \
+ "\n>> "
const char rcs_version[] = "OpenCVS RCS version 3.6";
int verbose = 1;
int pipeout = 0;
+#define RCS_NFLAG 1
+#define RCS_TFLAG 2
+static int rcsflags = 0;
+
int rcs_optind;
char *rcs_optarg;
char *rcs_suffixes;
@@ -69,6 +77,9 @@ struct rcs_prog {
{ "ident", ident_main, ident_usage },
};
+static void rcs_set_description(RCSFILE *, const char *);
+static void rcs_attach_symbol(RCSFILE *, const char *);
+
void
rcs_set_rev(const char *str, RCSNUM **rev)
{
@@ -223,6 +234,7 @@ rcs_getopt(int argc, char **argv, const char *optstr)
int
rcs_statfile(char *fname, char *out, size_t len)
{
+ size_t len1;
int l, found, strdir;
char defaultsuffix[] = RCS_DEFAULT_SUFFIX;
char filev[MAXPATHLEN], fpath[MAXPATHLEN];
@@ -270,10 +282,12 @@ rcs_statfile(char *fname, char *out, size_t len)
if (l == -1 || l >= (int)sizeof(fpath))
fatal("rcs_statfile: path truncation");
} else {
- strlcpy(fpath, filev, sizeof(fpath));
+ len1 = strlcpy(fpath, filev, sizeof(fpath));
+ if (len1 >= sizeof(fpath))
+ fatal("path truncation in rcs_statfile");
}
- if (stat(fpath, &st) != -1) {
+ if ((stat(fpath, &st) != -1) || (rcsflags & RCS_CREATE)) {
found++;
break;
}
@@ -292,7 +306,9 @@ rcs_statfile(char *fname, char *out, size_t len)
return (-1);
}
- strlcpy(out, fpath, len);
+ len1 = strlcpy(out, fpath, len);
+ if (len1 >= len)
+ fatal("path truncation in rcs_statfile");
return (0);
}
@@ -357,7 +373,7 @@ rcs_main(int argc, char **argv)
{
int i, ch, flags, kflag, lkmode;
char fpath[MAXPATHLEN], ofpath[MAXPATHLEN];
- char *logstr, *logmsg;
+ char *logstr, *logmsg, *nflag, *descfile;
char *alist, *comment, *elist, *unp, *sp;
mode_t fmode;
RCSFILE *file, *oldfile;
@@ -368,6 +384,7 @@ rcs_main(int argc, char **argv)
kflag = lkmode = -1;
fmode = 0;
flags = RCS_RDWR;
+ descfile = nflag = NULL;
logstr = alist = comment = elist = NULL;
while ((ch = rcs_getopt(argc, argv, RCSPROG_OPTSTRING)) != -1) {
@@ -375,7 +392,7 @@ rcs_main(int argc, char **argv)
case 'A':
if (rcs_statfile(rcs_optarg, ofpath, sizeof(ofpath)) < 0)
exit(1);
- flags |= CO_ACLAPPEND;
+ rcsflags |= CO_ACLAPPEND;
break;
case 'a':
alist = rcs_optarg;
@@ -391,6 +408,7 @@ rcs_main(int argc, char **argv)
exit(0);
case 'i':
flags |= RCS_CREATE;
+ rcsflags |= RCS_CREATE;
break;
case 'k':
kflag = rcs_kflag_get(rcs_optarg);
@@ -412,11 +430,22 @@ rcs_main(int argc, char **argv)
case 'M':
/* ignore for the moment */
break;
+ case 'n':
+ nflag = xstrdup(rcs_optarg);
+ break;
+ case 'N':
+ nflag = xstrdup(rcs_optarg);
+ rcsflags |= RCS_NFLAG;
+ break;
case 'q':
verbose = 0;
break;
+ case 't':
+ descfile = rcs_optarg;
+ rcsflags |= RCS_TFLAG;
+ break;
case 'T':
- flags |= PRESERVETIME;
+ rcsflags |= PRESERVETIME;
break;
case 'U':
if (lkmode == RCS_LOCK_STRICT)
@@ -459,9 +488,18 @@ rcs_main(int argc, char **argv)
if ((file = rcs_open(fpath, flags, fmode)) == NULL)
continue;
- if (flags & PRESERVETIME)
+ if (rcsflags & RCS_CREATE)
+ rcs_set_description(file, NULL);
+
+ if (rcsflags & RCS_TFLAG)
+ rcs_set_description(file, descfile);
+
+ if (rcsflags & PRESERVETIME)
rcs_mtime = rcs_get_mtime(file->rf_path);
+ if (nflag != NULL)
+ rcs_attach_symbol(file, nflag);
+
if (logstr != NULL) {
if ((logmsg = strchr(logstr, ':')) == NULL) {
cvs_log(LP_ERR, "missing log message");
@@ -490,7 +528,7 @@ rcs_main(int argc, char **argv)
}
/* entries to add from <oldfile> */
- if (flags & CO_ACLAPPEND) {
+ if (rcsflags & CO_ACLAPPEND) {
/* XXX */
if ((oldfile = rcs_open(ofpath, RCS_READ)) == NULL)
exit(1);
@@ -526,7 +564,7 @@ rcs_main(int argc, char **argv)
rcs_close(file);
- if (flags & PRESERVETIME)
+ if (rcsflags & PRESERVETIME)
rcs_set_mtime(fpath, rcs_mtime);
if (verbose == 1)
@@ -536,5 +574,85 @@ rcs_main(int argc, char **argv)
if (logstr != NULL)
xfree(logstr);
+ if (nflag != NULL)
+ xfree(nflag);
+
return (0);
}
+
+static void
+rcs_attach_symbol(RCSFILE *file, const char *symname)
+{
+ char *rnum;
+ RCSNUM *rev;
+ char rbuf[16];
+ int rm;
+
+ rm = 0;
+ rev = NULL;
+ if ((rnum = strrchr(symname, ':')) != NULL) {
+ if (rnum[1] == '\0')
+ rev = file->rf_head;
+ *(rnum++) = '\0';
+ } else {
+ rm = 1;
+ }
+
+ if (rev == NULL && rm != 1) {
+ if ((rev = rcsnum_parse(rnum)) == NULL)
+ fatal("bad revision %s", rnum);
+ }
+
+ if (rcsflags & RCS_NFLAG)
+ rm = 1;
+
+ if (rm == 1) {
+ if (rcs_sym_remove(file, symname) < 0) {
+ if ((rcs_errno == RCS_ERR_NOENT) &&
+ !(rcsflags & RCS_NFLAG))
+ cvs_log(LP_WARN,
+ "can't delete nonexisting symbol %s", symname);
+ } else {
+ if (rcsflags & RCS_NFLAG)
+ rm = 0;
+ }
+ }
+
+ if (rm == 0) {
+ if ((rcs_sym_add(file, symname, rev) < 0) &&
+ (rcs_errno == RCS_ERR_DUPENT)) {
+ rcsnum_tostr(rcs_sym_getrev(file, symname),
+ rbuf, sizeof(rbuf));
+ fatal("symbolic name %s already bound to %s",
+ symname, rbuf);
+ }
+ }
+}
+
+static void
+rcs_set_description(RCSFILE *file, const char *in)
+{
+ BUF *bp;
+ char *content, buf[128];
+
+ content = NULL;
+ if (in != NULL) {
+ bp = cvs_buf_load(in, BUF_AUTOEXT);
+ } else {
+ bp = cvs_buf_alloc(64, BUF_AUTOEXT);
+
+ printf(DESC_PROMPT);
+ for (;;) {
+ fgets(buf, sizeof(buf), stdin);
+ if (feof(stdin) || ferror(stdin) || buf[0] == '.')
+ break;
+ cvs_buf_append(bp, buf, strlen(buf));
+ printf(">> ");
+ }
+ }
+
+ cvs_buf_putc(bp, '\0');
+ content = cvs_buf_release(bp);
+
+ rcs_desc_set(file, content);
+}