Annotation of src/usr.bin/cvs/logmsg.c, Revision 1.30
1.30 ! joris 1: /* $OpenBSD$ */
1.1 jfb 2: /*
1.30 ! joris 3: * Copyright (c) 2007 Joris Vink <joris@openbsd.org>
1.1 jfb 4: *
1.30 ! joris 5: * Permission to use, copy, modify, and distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 jfb 16: */
17:
1.27 xsa 18: #include "includes.h"
1.1 jfb 19:
20: #include "cvs.h"
1.30 ! joris 21: #include "file.h"
1.1 jfb 22: #include "log.h"
1.30 ! joris 23: #include "worklist.h"
1.1 jfb 24:
1.30 ! joris 25: #define CVS_LOGMSG_PREFIX "CVS:"
! 26: #define CVS_LOGMSG_LINE \
1.1 jfb 27: "----------------------------------------------------------------------"
28:
1.17 xsa 29: char *
1.30 ! joris 30: cvs_logmsg_read(const char *path)
1.1 jfb 31: {
1.30 ! joris 32: int fd;
! 33: BUF *bp;
! 34: FILE *fp;
1.1 jfb 35: size_t len;
36: struct stat st;
1.30 ! joris 37: char *buf, *lbuf;
! 38:
! 39: if ((fd = open(path, O_RDONLY)) == -1)
! 40: fatal("cvs_logmsg_read: open %s", strerror(errno));
1.1 jfb 41:
1.30 ! joris 42: if (fstat(fd, &st) == -1)
! 43: fatal("cvs_logmsg_read: fstat %s", strerror(errno));
1.1 jfb 44:
1.24 xsa 45: if (!S_ISREG(st.st_mode))
1.30 ! joris 46: fatal("cvs_logmsg_read: file is not a regular file");
1.1 jfb 47:
1.30 ! joris 48: if ((fp = fdopen(fd, "r")) == NULL)
! 49: fatal("cvs_logmsg_read: fdopen %s", strerror(errno));
1.1 jfb 50:
1.30 ! joris 51: lbuf = NULL;
! 52: bp = cvs_buf_alloc(st.st_size, BUF_AUTOEXT);
! 53: while ((buf = fgetln(fp, &len))) {
! 54: if (buf[len - 1] == '\n') {
! 55: buf[len - 1] = '\0';
! 56: } else {
! 57: lbuf = xmalloc(len + 1);
! 58: strlcpy(lbuf, buf, len);
! 59: buf = lbuf;
! 60: }
1.1 jfb 61:
1.30 ! joris 62: len = strlen(buf);
1.1 jfb 63: if (len == 0)
64: continue;
1.30 ! joris 65:
! 66: if (!strncmp(buf, CVS_LOGMSG_PREFIX,
! 67: strlen(CVS_LOGMSG_PREFIX)))
1.1 jfb 68: continue;
69:
1.30 ! joris 70: cvs_buf_append(bp, buf, len);
! 71: cvs_buf_putc(bp, '\n');
! 72: }
! 73:
! 74: if (lbuf != NULL)
! 75: xfree(lbuf);
1.1 jfb 76:
1.11 jfb 77: (void)fclose(fp);
1.30 ! joris 78: (void)close(fd);
1.11 jfb 79:
1.23 xsa 80: cvs_buf_putc(bp, '\0');
1.30 ! joris 81: return (cvs_buf_release(bp));
1.1 jfb 82: }
83:
1.17 xsa 84: char *
1.30 ! joris 85: cvs_logmsg_create(struct cvs_flisthead *added, struct cvs_flisthead *removed,
! 86: struct cvs_flisthead *modified)
1.1 jfb 87: {
88: FILE *fp;
1.30 ! joris 89: size_t len;
! 90: int c, fd, argc;
! 91: struct cvs_filelist *cf;
1.1 jfb 92: struct stat st1, st2;
1.30 ! joris 93: char *fpath, *logmsg, *argv[4];
1.8 jfb 94:
1.30 ! joris 95: fpath = xmalloc(MAXPATHLEN);
! 96: len = strlcpy(fpath, cvs_tmpdir, MAXPATHLEN);
! 97: if (len >= MAXPATHLEN)
! 98: fatal("cvs_logmsg_create: truncation");
! 99:
! 100: len = strlcat(fpath, "/cvsXXXXXXXXXX", MAXPATHLEN);
! 101: if (len >= MAXPATHLEN)
! 102: fatal("cvs_logmsg_create: truncation");
1.1 jfb 103:
1.30 ! joris 104: if ((fd = mkstemp(fpath)) == NULL)
! 105: fatal("cvs_logmsg_create: mkstemp %s", strerror(errno));
1.1 jfb 106:
1.24 xsa 107: if ((fp = fdopen(fd, "w")) == NULL) {
1.30 ! joris 108: (void)unlink(fpath);
! 109: fatal("cvs_logmsg_create: fdopen %s", strerror(errno));
1.8 jfb 110: }
1.1 jfb 111:
1.8 jfb 112: fprintf(fp, "\n%s %s\n%s Enter Log. Lines beginning with `%s' are "
113: "removed automatically\n%s\n", CVS_LOGMSG_PREFIX, CVS_LOGMSG_LINE,
114: CVS_LOGMSG_PREFIX, CVS_LOGMSG_PREFIX, CVS_LOGMSG_PREFIX);
115:
1.30 ! joris 116: if (!TAILQ_EMPTY(added)) {
! 117: fprintf(fp, "%s Added Files:", CVS_LOGMSG_PREFIX);
! 118: TAILQ_FOREACH(cf, added, flist)
! 119: fprintf(fp, "\n%s\t%s",
! 120: CVS_LOGMSG_PREFIX, cf->file_path);
! 121: fputs("\n", fp);
! 122: }
! 123:
! 124: if (!TAILQ_EMPTY(removed)) {
! 125: fprintf(fp, "%s Removed Files:", CVS_LOGMSG_PREFIX);
! 126: TAILQ_FOREACH(cf, removed, flist)
! 127: fprintf(fp, "\n%s\t%s",
! 128: CVS_LOGMSG_PREFIX, cf->file_path);
! 129: fputs("\n", fp);
! 130: }
! 131:
! 132: if (!TAILQ_EMPTY(modified)) {
! 133: fprintf(fp, "%s Modified Files:", CVS_LOGMSG_PREFIX);
! 134: TAILQ_FOREACH(cf, modified, flist)
! 135: fprintf(fp, "\n%s\t%s",
! 136: CVS_LOGMSG_PREFIX, cf->file_path);
! 137: fputs("\n", fp);
! 138: }
1.1 jfb 139:
1.9 jfb 140: fprintf(fp, "%s %s\n", CVS_LOGMSG_PREFIX, CVS_LOGMSG_LINE);
1.1 jfb 141: (void)fflush(fp);
142:
143: if (fstat(fd, &st1) == -1) {
1.30 ! joris 144: (void)unlink(fpath);
! 145: fatal("cvs_logmsg_create: fstat %s", strerror(errno));
1.1 jfb 146: }
147:
1.30 ! joris 148: argc = 0;
! 149: argv[argc++] = cvs_editor;
! 150: argv[argc++] = fpath;
! 151: argv[argc] = NULL;
! 152:
! 153: logmsg = NULL;
! 154:
1.1 jfb 155: for (;;) {
1.30 ! joris 156: if (cvs_exec(argc, argv) < 0)
1.1 jfb 157: break;
1.8 jfb 158:
1.1 jfb 159: if (fstat(fd, &st2) == -1) {
1.30 ! joris 160: (void)unlink(fpath);
! 161: fatal("cvs_logmsg_create: fstat %s", strerror(errno));
1.1 jfb 162: }
163:
1.30 ! joris 164: if (st1.st_mtime != st2.st_mtime) {
! 165: logmsg = cvs_logmsg_read(fpath);
1.1 jfb 166: break;
167: }
168:
1.30 ! joris 169: printf("\nLog message unchanged or not specified\n"
! 170: "a)bort, c)ontinue, e(dit)\nAction: (continue) ");
! 171: (void)fflush(stdout);
! 172:
! 173: c = getc(stdin);
! 174: if (c == 'a') {
! 175: fatal("Aborted by user");
! 176: } else if (c == '\n' || c == 'c') {
! 177: logmsg = xstrdup("");
1.1 jfb 178: break;
1.30 ! joris 179: } else if (c == 'e') {
1.1 jfb 180: continue;
1.30 ! joris 181: } else {
! 182: cvs_log(LP_ERR, "invalid input");
1.1 jfb 183: continue;
184: }
185: }
186:
187: (void)fclose(fp);
188: (void)close(fd);
1.30 ! joris 189: (void)unlink(fpath);
! 190: xfree(fpath);
1.1 jfb 191:
1.30 ! joris 192: return (logmsg);
1.1 jfb 193: }