[BACK]Return to logmsg.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

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: }