[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.38

1.38    ! otto        1: /*     $OpenBSD: logmsg.c,v 1.37 2007/01/25 22:49:39 xsa 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.38    ! otto       18: #include <sys/stat.h>
        !            19:
        !            20: #include <errno.h>
        !            21: #include <fcntl.h>
        !            22: #include <string.h>
        !            23: #include <unistd.h>
1.1       jfb        24:
                     25: #include "cvs.h"
                     26:
1.30      joris      27: #define CVS_LOGMSG_PREFIX              "CVS:"
                     28: #define CVS_LOGMSG_LINE                \
1.1       jfb        29: "----------------------------------------------------------------------"
                     30:
1.17      xsa        31: char *
1.30      joris      32: cvs_logmsg_read(const char *path)
1.1       jfb        33: {
1.30      joris      34:        int fd;
                     35:        BUF *bp;
                     36:        FILE *fp;
1.1       jfb        37:        size_t len;
                     38:        struct stat st;
1.30      joris      39:        char *buf, *lbuf;
                     40:
                     41:        if ((fd = open(path, O_RDONLY)) == -1)
                     42:                fatal("cvs_logmsg_read: open %s", strerror(errno));
1.1       jfb        43:
1.30      joris      44:        if (fstat(fd, &st) == -1)
                     45:                fatal("cvs_logmsg_read: fstat %s", strerror(errno));
1.1       jfb        46:
1.24      xsa        47:        if (!S_ISREG(st.st_mode))
1.30      joris      48:                fatal("cvs_logmsg_read: file is not a regular file");
1.1       jfb        49:
1.30      joris      50:        if ((fp = fdopen(fd, "r")) == NULL)
                     51:                fatal("cvs_logmsg_read: fdopen %s", strerror(errno));
1.1       jfb        52:
1.30      joris      53:        lbuf = NULL;
                     54:        bp = cvs_buf_alloc(st.st_size, BUF_AUTOEXT);
                     55:        while ((buf = fgetln(fp, &len))) {
                     56:                if (buf[len - 1] == '\n') {
                     57:                        buf[len - 1] = '\0';
                     58:                } else {
                     59:                        lbuf = xmalloc(len + 1);
1.36      otto       60:                        memcpy(lbuf, buf, len);
                     61:                        lbuf[len] = '\0';
1.30      joris      62:                        buf = lbuf;
                     63:                }
1.1       jfb        64:
1.30      joris      65:                len = strlen(buf);
1.1       jfb        66:                if (len == 0)
                     67:                        continue;
1.30      joris      68:
                     69:                if (!strncmp(buf, CVS_LOGMSG_PREFIX,
                     70:                    strlen(CVS_LOGMSG_PREFIX)))
1.1       jfb        71:                        continue;
                     72:
1.30      joris      73:                cvs_buf_append(bp, buf, len);
                     74:                cvs_buf_putc(bp, '\n');
                     75:        }
                     76:
                     77:        if (lbuf != NULL)
                     78:                xfree(lbuf);
1.1       jfb        79:
1.11      jfb        80:        (void)fclose(fp);
                     81:
1.23      xsa        82:        cvs_buf_putc(bp, '\0');
1.30      joris      83:        return (cvs_buf_release(bp));
1.1       jfb        84: }
                     85:
1.17      xsa        86: char *
1.30      joris      87: cvs_logmsg_create(struct cvs_flisthead *added, struct cvs_flisthead *removed,
                     88:        struct cvs_flisthead *modified)
1.1       jfb        89: {
                     90:        FILE *fp;
1.34      xsa        91:        int c, fd, argc, saved_errno;
1.30      joris      92:        struct cvs_filelist *cf;
1.1       jfb        93:        struct stat st1, st2;
1.30      joris      94:        char *fpath, *logmsg, *argv[4];
1.8       jfb        95:
1.35      xsa        96:        (void)xasprintf(&fpath, "%s/cvsXXXXXXXXXX", cvs_tmpdir);
1.1       jfb        97:
1.30      joris      98:        if ((fd = mkstemp(fpath)) == NULL)
                     99:                fatal("cvs_logmsg_create: mkstemp %s", strerror(errno));
1.33      joris     100:
                    101:        cvs_worklist_add(fpath, &temp_files);
1.1       jfb       102:
1.24      xsa       103:        if ((fp = fdopen(fd, "w")) == NULL) {
1.34      xsa       104:                saved_errno = errno;
1.30      joris     105:                (void)unlink(fpath);
1.34      xsa       106:                fatal("cvs_logmsg_create: fdopen %s", strerror(saved_errno));
1.8       jfb       107:        }
1.1       jfb       108:
1.8       jfb       109:        fprintf(fp, "\n%s %s\n%s Enter Log.  Lines beginning with `%s' are "
                    110:            "removed automatically\n%s\n", CVS_LOGMSG_PREFIX, CVS_LOGMSG_LINE,
                    111:            CVS_LOGMSG_PREFIX, CVS_LOGMSG_PREFIX, CVS_LOGMSG_PREFIX);
                    112:
1.31      joris     113:        if (added != NULL && !TAILQ_EMPTY(added)) {
1.30      joris     114:                fprintf(fp, "%s Added Files:", CVS_LOGMSG_PREFIX);
                    115:                TAILQ_FOREACH(cf, added, flist)
                    116:                        fprintf(fp, "\n%s\t%s",
                    117:                            CVS_LOGMSG_PREFIX, cf->file_path);
                    118:                fputs("\n", fp);
                    119:        }
                    120:
1.31      joris     121:        if (removed != NULL && !TAILQ_EMPTY(removed)) {
1.30      joris     122:                fprintf(fp, "%s Removed Files:", CVS_LOGMSG_PREFIX);
                    123:                TAILQ_FOREACH(cf, removed, flist)
                    124:                        fprintf(fp, "\n%s\t%s",
                    125:                            CVS_LOGMSG_PREFIX, cf->file_path);
                    126:                fputs("\n", fp);
                    127:        }
                    128:
1.31      joris     129:        if (modified != NULL && !TAILQ_EMPTY(modified)) {
1.30      joris     130:                fprintf(fp, "%s Modified Files:", CVS_LOGMSG_PREFIX);
                    131:                TAILQ_FOREACH(cf, modified, flist)
                    132:                        fprintf(fp, "\n%s\t%s",
                    133:                            CVS_LOGMSG_PREFIX, cf->file_path);
                    134:                fputs("\n", fp);
                    135:        }
1.1       jfb       136:
1.9       jfb       137:        fprintf(fp, "%s %s\n", CVS_LOGMSG_PREFIX, CVS_LOGMSG_LINE);
1.1       jfb       138:        (void)fflush(fp);
                    139:
                    140:        if (fstat(fd, &st1) == -1) {
1.34      xsa       141:                saved_errno = errno;
1.30      joris     142:                (void)unlink(fpath);
1.34      xsa       143:                fatal("cvs_logmsg_create: fstat %s", strerror(saved_errno));
1.1       jfb       144:        }
                    145:
1.30      joris     146:        argc = 0;
                    147:        argv[argc++] = cvs_editor;
                    148:        argv[argc++] = fpath;
                    149:        argv[argc] = NULL;
                    150:
                    151:        logmsg = NULL;
                    152:
1.1       jfb       153:        for (;;) {
1.30      joris     154:                if (cvs_exec(argc, argv) < 0)
1.1       jfb       155:                        break;
1.8       jfb       156:
1.1       jfb       157:                if (fstat(fd, &st2) == -1) {
1.34      xsa       158:                        saved_errno = errno;
1.30      joris     159:                        (void)unlink(fpath);
1.34      xsa       160:                        fatal("cvs_logmsg_create: fstat %s",
                    161:                            strerror(saved_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"
1.32      jasper    170:                    "a)bort, c)ontinue, e)dit\nAction: (continue) ");
1.30      joris     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);
1.30      joris     188:        (void)unlink(fpath);
                    189:        xfree(fpath);
1.1       jfb       190:
1.30      joris     191:        return (logmsg);
1.1       jfb       192: }