Annotation of src/usr.bin/cvs/logmsg.c, Revision 1.37
1.37 ! xsa 1: /* $OpenBSD: logmsg.c,v 1.36 2007/01/25 08:21:08 otto Exp $ */
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);
1.36 otto 58: memcpy(lbuf, buf, len);
59: lbuf[len] = '\0';
1.30 joris 60: buf = lbuf;
61: }
1.1 jfb 62:
1.30 joris 63: len = strlen(buf);
1.1 jfb 64: if (len == 0)
65: continue;
1.30 joris 66:
67: if (!strncmp(buf, CVS_LOGMSG_PREFIX,
68: strlen(CVS_LOGMSG_PREFIX)))
1.1 jfb 69: continue;
70:
1.30 joris 71: cvs_buf_append(bp, buf, len);
72: cvs_buf_putc(bp, '\n');
73: }
74:
75: if (lbuf != NULL)
76: xfree(lbuf);
1.1 jfb 77:
1.11 jfb 78: (void)fclose(fp);
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.34 xsa 89: int c, fd, argc, saved_errno;
1.30 joris 90: struct cvs_filelist *cf;
1.1 jfb 91: struct stat st1, st2;
1.30 joris 92: char *fpath, *logmsg, *argv[4];
1.8 jfb 93:
1.35 xsa 94: (void)xasprintf(&fpath, "%s/cvsXXXXXXXXXX", cvs_tmpdir);
1.1 jfb 95:
1.30 joris 96: if ((fd = mkstemp(fpath)) == NULL)
97: fatal("cvs_logmsg_create: mkstemp %s", strerror(errno));
1.33 joris 98:
99: cvs_worklist_add(fpath, &temp_files);
1.1 jfb 100:
1.24 xsa 101: if ((fp = fdopen(fd, "w")) == NULL) {
1.34 xsa 102: saved_errno = errno;
1.30 joris 103: (void)unlink(fpath);
1.34 xsa 104: fatal("cvs_logmsg_create: fdopen %s", strerror(saved_errno));
1.8 jfb 105: }
1.1 jfb 106:
1.8 jfb 107: fprintf(fp, "\n%s %s\n%s Enter Log. Lines beginning with `%s' are "
108: "removed automatically\n%s\n", CVS_LOGMSG_PREFIX, CVS_LOGMSG_LINE,
109: CVS_LOGMSG_PREFIX, CVS_LOGMSG_PREFIX, CVS_LOGMSG_PREFIX);
110:
1.31 joris 111: if (added != NULL && !TAILQ_EMPTY(added)) {
1.30 joris 112: fprintf(fp, "%s Added Files:", CVS_LOGMSG_PREFIX);
113: TAILQ_FOREACH(cf, added, flist)
114: fprintf(fp, "\n%s\t%s",
115: CVS_LOGMSG_PREFIX, cf->file_path);
116: fputs("\n", fp);
117: }
118:
1.31 joris 119: if (removed != NULL && !TAILQ_EMPTY(removed)) {
1.30 joris 120: fprintf(fp, "%s Removed Files:", CVS_LOGMSG_PREFIX);
121: TAILQ_FOREACH(cf, removed, flist)
122: fprintf(fp, "\n%s\t%s",
123: CVS_LOGMSG_PREFIX, cf->file_path);
124: fputs("\n", fp);
125: }
126:
1.31 joris 127: if (modified != NULL && !TAILQ_EMPTY(modified)) {
1.30 joris 128: fprintf(fp, "%s Modified Files:", CVS_LOGMSG_PREFIX);
129: TAILQ_FOREACH(cf, modified, flist)
130: fprintf(fp, "\n%s\t%s",
131: CVS_LOGMSG_PREFIX, cf->file_path);
132: fputs("\n", fp);
133: }
1.1 jfb 134:
1.9 jfb 135: fprintf(fp, "%s %s\n", CVS_LOGMSG_PREFIX, CVS_LOGMSG_LINE);
1.1 jfb 136: (void)fflush(fp);
137:
138: if (fstat(fd, &st1) == -1) {
1.34 xsa 139: saved_errno = errno;
1.30 joris 140: (void)unlink(fpath);
1.34 xsa 141: fatal("cvs_logmsg_create: fstat %s", strerror(saved_errno));
1.1 jfb 142: }
143:
1.30 joris 144: argc = 0;
145: argv[argc++] = cvs_editor;
146: argv[argc++] = fpath;
147: argv[argc] = NULL;
148:
149: logmsg = NULL;
150:
1.1 jfb 151: for (;;) {
1.30 joris 152: if (cvs_exec(argc, argv) < 0)
1.1 jfb 153: break;
1.8 jfb 154:
1.1 jfb 155: if (fstat(fd, &st2) == -1) {
1.34 xsa 156: saved_errno = errno;
1.30 joris 157: (void)unlink(fpath);
1.34 xsa 158: fatal("cvs_logmsg_create: fstat %s",
159: strerror(saved_errno));
1.1 jfb 160: }
161:
1.30 joris 162: if (st1.st_mtime != st2.st_mtime) {
163: logmsg = cvs_logmsg_read(fpath);
1.1 jfb 164: break;
165: }
166:
1.30 joris 167: printf("\nLog message unchanged or not specified\n"
1.32 jasper 168: "a)bort, c)ontinue, e)dit\nAction: (continue) ");
1.30 joris 169: (void)fflush(stdout);
170:
171: c = getc(stdin);
172: if (c == 'a') {
173: fatal("Aborted by user");
174: } else if (c == '\n' || c == 'c') {
175: logmsg = xstrdup("");
1.1 jfb 176: break;
1.30 joris 177: } else if (c == 'e') {
1.1 jfb 178: continue;
1.30 joris 179: } else {
180: cvs_log(LP_ERR, "invalid input");
1.1 jfb 181: continue;
182: }
183: }
184:
185: (void)fclose(fp);
1.30 joris 186: (void)unlink(fpath);
187: xfree(fpath);
1.1 jfb 188:
1.30 joris 189: return (logmsg);
1.1 jfb 190: }