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

Annotation of src/usr.bin/rcs/rlog.c, Revision 1.20

1.20    ! xsa         1: /*     $OpenBSD: rlog.c,v 1.19 2006/01/05 10:28:24 xsa Exp $   */
1.1       joris       2: /*
                      3:  * Copyright (c) 2005 Joris Vink <joris@openbsd.org>
1.20    ! xsa         4:  * Copyright (c) 2005, 2006 Xavier Santolaria <xsa@openbsd.org>
1.1       joris       5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  *
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. The name of the author may not be used to endorse or promote products
                     14:  *    derived from this software without specific prior written permission.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                     17:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                     18:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
                     19:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     20:  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     21:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     22:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     23:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     24:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     25:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27:
1.18      xsa        28: #include "includes.h"
1.1       joris      29:
1.19      xsa        30: #include "rcsprog.h"
1.3       niallo     31: #include "diff.h"
1.1       joris      32:
1.20    ! xsa        33: static int       rlog_file(const char *, const char *, RCSFILE *);
        !            34: static void      rlog_rev_print(struct rcs_delta *);
        !            35: static char    **rlog_strsplit(char *, const char *);
1.1       joris      36:
                     37: #define REVSEP         "----------------------------"
                     38: #define REVEND \
1.6       xsa        39:  "============================================================================="
1.1       joris      40:
1.20    ! xsa        41: static int hflag, Lflag, tflag, Nflag, wflag;
        !            42: static char *slist = NULL;
        !            43: static char *wlist = NULL;
1.1       joris      44:
                     45: int
                     46: rlog_main(int argc, char **argv)
                     47: {
                     48:        int Rflag;
                     49:        int i, ch;
                     50:        char fpath[MAXPATHLEN];
                     51:        RCSFILE *file;
                     52:
                     53:        hflag = Rflag = 0;
1.20    ! xsa        54:        while ((ch = rcs_getopt(argc, argv, "hLNqRs:TtVw::x:")) != -1) {
1.1       joris      55:                switch (ch) {
                     56:                case 'h':
                     57:                        hflag = 1;
                     58:                        break;
1.11      xsa        59:                case 'L':
                     60:                        Lflag = 1;
                     61:                        break;
1.1       joris      62:                case 'N':
                     63:                        Nflag = 1;
                     64:                        break;
                     65:                case 'q':
                     66:                        verbose = 0;
                     67:                        break;
                     68:                case 'R':
                     69:                        Rflag = 1;
                     70:                        break;
1.20    ! xsa        71:                case 's':
        !            72:                        slist = rcs_optarg;
        !            73:                        break;
1.8       xsa        74:                case 'T':
                     75:                        /*
                     76:                         * kept for compatibility
                     77:                         */
                     78:                        break;
1.1       joris      79:                case 't':
                     80:                        tflag = 1;
                     81:                        break;
                     82:                case 'V':
                     83:                        printf("%s\n", rcs_version);
                     84:                        exit(0);
1.20    ! xsa        85:                case 'w':
        !            86:                        wflag = 1;
        !            87:                        wlist = rcs_optarg;
        !            88:                        break;
1.14      xsa        89:                case 'x':
                     90:                        rcs_suffixes = rcs_optarg;
                     91:                        break;
1.1       joris      92:                default:
                     93:                        break;
                     94:                }
                     95:        }
                     96:
1.5       joris      97:        argc -= rcs_optind;
                     98:        argv += rcs_optind;
1.1       joris      99:
                    100:        if (argc == 0) {
                    101:                cvs_log(LP_ERR, "no input file");
                    102:                (usage)();
                    103:                exit(1);
                    104:        }
                    105:
1.7       xsa       106:        if ((hflag == 1) && (tflag == 1)) {
1.6       xsa       107:                cvs_log(LP_WARN, "warning: -t overrides -h.");
1.7       xsa       108:                hflag = 0;
                    109:        }
1.6       xsa       110:
1.1       joris     111:        for (i = 0; i < argc; i++) {
                    112:                if (rcs_statfile(argv[i], fpath, sizeof(fpath)) < 0)
                    113:                        continue;
                    114:
1.17      niallo    115:                if ((file = rcs_open(fpath, RCS_READ|RCS_PARSE_FULLY)) == NULL)
1.11      xsa       116:                        continue;
                    117:
                    118:                if ((Lflag == 1) && (TAILQ_EMPTY(&(file->rf_locks)))) {
                    119:                        rcs_close(file);
                    120:                        continue;
                    121:                }
                    122:
1.9       xsa       123:                if (Rflag == 1) {
                    124:                        printf("%s\n", fpath);
1.11      xsa       125:                        rcs_close(file);
1.9       xsa       126:                        continue;
                    127:                }
                    128:
                    129:                rlog_file(argv[i], fpath, file);
                    130:
1.1       joris     131:                rcs_close(file);
                    132:        }
                    133:
                    134:        return (0);
                    135: }
                    136:
                    137: void
                    138: rlog_usage(void)
                    139: {
1.4       deraadt   140:        fprintf(stderr,
1.20    ! xsa       141:            "usage: rlog [-hLNqRTtV] [-sstates] [-w[logins]] "
        !           142:            "[-xsuffixes] file ...\n");
1.1       joris     143: }
                    144:
                    145: static int
                    146: rlog_file(const char *fname, const char *fpath, RCSFILE *file)
                    147: {
                    148:        char numb[64];
                    149:        struct rcs_sym *sym;
                    150:        struct rcs_access *acp;
1.20    ! xsa       151:        struct rcs_delta *rdp;
1.10      xsa       152:        struct rcs_lock *lkp;
1.1       joris     153:
1.12      xsa       154:        printf("\nRCS file: %s", fpath);
1.6       xsa       155:        printf("\nWorking file: %s", fname);
1.1       joris     156:        printf("\nhead:");
                    157:        if (file->rf_head != NULL)
                    158:                printf(" %s", rcsnum_tostr(file->rf_head, numb, sizeof(numb)));
                    159:
                    160:        printf("\nbranch:");
                    161:        if (rcs_branch_get(file) != NULL) {
                    162:                printf(" %s", rcsnum_tostr(rcs_branch_get(file),
                    163:                    numb, sizeof(numb)));
                    164:        }
                    165:
                    166:        printf("\nlocks: %s", (file->rf_flags & RCS_SLOCK) ? "strict" : "");
1.10      xsa       167:        TAILQ_FOREACH(lkp, &(file->rf_locks), rl_list)
                    168:                printf("\n\t%s: %s", lkp->rl_name,
                    169:                    rcsnum_tostr(lkp->rl_num, numb, sizeof(numb)));
1.1       joris     170:        printf("\naccess list:\n");
                    171:        TAILQ_FOREACH(acp, &(file->rf_access), ra_list)
                    172:                printf("\t%s\n", acp->ra_name);
                    173:
                    174:        if (Nflag == 0) {
                    175:                printf("symbolic names:\n");
                    176:                TAILQ_FOREACH(sym, &(file->rf_symbols), rs_list) {
                    177:                        printf("\t%s: %s\n", sym->rs_name,
                    178:                            rcsnum_tostr(sym->rs_num, numb, sizeof(numb)));
                    179:                }
                    180:        }
                    181:
                    182:        printf("keyword substitution: %s\n",
                    183:            file->rf_expand == NULL ? "kv" : file->rf_expand);
                    184:
1.20    ! xsa       185:        printf("total revisions: %u", file->rf_ndelta);
        !           186:
        !           187:        if ((hflag == 0) && (tflag == 0))
        !           188:                printf(";\tselected revisions:"); /* XXX */
        !           189:
        !           190:        printf("\n");
        !           191:
1.1       joris     192:
                    193:        if ((hflag == 0) || (tflag == 1))
1.13      xsa       194:                printf("description:\n%s", file->rf_desc);
1.1       joris     195:
1.20    ! xsa       196:        if ((hflag == 0) && (tflag == 0)) {
        !           197:                TAILQ_FOREACH(rdp, &(file->rf_delta), rd_list)
        !           198:                        rlog_rev_print(rdp);
        !           199:        }
1.1       joris     200:
                    201:        printf("%s\n", REVEND);
                    202:        return (0);
1.16      xsa       203: }
                    204:
                    205: static void
1.20    ! xsa       206: rlog_rev_print(struct rcs_delta *rdp)
1.16      xsa       207: {
1.20    ! xsa       208:        int i, found;
        !           209:        char *author, numb[64];
        !           210:        char **sargv, **wargv;
        !           211:
        !           212:        i = found = 0;
        !           213:        author = NULL;
        !           214:
        !           215:        /* -sstates */
        !           216:        if (slist != NULL) {
        !           217:                sargv = rlog_strsplit(slist, ",");
        !           218:                for (i = 0; sargv[i] != NULL; i++) {
        !           219:                        if (strcmp(rdp->rd_state, sargv[i]) == 0) {
        !           220:                                found++;
        !           221:                                break;
        !           222:                        }
        !           223:                        found = 0;
        !           224:                }
        !           225:        }
        !           226:        /* -w[logins] */
        !           227:        if (wflag == 1) {
        !           228:                if (wlist != NULL) {
        !           229:                        wargv = rlog_strsplit(wlist, ",");
        !           230:                        for (i = 0; wargv[i] != NULL; i++) {
        !           231:                                if (strcmp(rdp->rd_author, wargv[i]) == 0) {
        !           232:                                        found++;
        !           233:                                        break;
        !           234:                                }
        !           235:                                found = 0;
        !           236:                        }
        !           237:                } else {
        !           238:                        if ((author = getlogin()) == NULL)
        !           239:                                fatal("getlogin failed");
1.16      xsa       240:
1.20    ! xsa       241:                        if (strcmp(rdp->rd_author, author) == 0)
        !           242:                                found++;
        !           243:                }
        !           244:        }
1.16      xsa       245:
1.20    ! xsa       246:        /* XXX dirty... */
        !           247:        if ((((slist != NULL) && (wflag == 1)) && (found < 2)) ||
        !           248:            (((slist != NULL) || (wflag == 1)) && (found == 0)))
        !           249:                return;
        !           250:
        !           251:        printf("%s\n", REVSEP);
        !           252:
        !           253:        rcsnum_tostr(rdp->rd_num, numb, sizeof(numb));
        !           254:
        !           255:        printf("revision %s\n", numb);
        !           256:        printf("date: %d/%02d/%02d %02d:%02d:%02d;"
        !           257:            "  author: %s;  state: %s;\n",
        !           258:            rdp->rd_date.tm_year + 1900,
        !           259:            rdp->rd_date.tm_mon + 1,
        !           260:            rdp->rd_date.tm_mday, rdp->rd_date.tm_hour,
        !           261:            rdp->rd_date.tm_min, rdp->rd_date.tm_sec,
        !           262:            rdp->rd_author, rdp->rd_state);
        !           263:        printf("%s", rdp->rd_log);
        !           264: }
1.16      xsa       265:
1.20    ! xsa       266: /*
        !           267:  * rlog_strsplit()
        !           268:  *
        !           269:  * Split a string <str> of <sep>-separated values and allocate
        !           270:  * an argument vector for the values found.
        !           271:  */
        !           272: static char **
        !           273: rlog_strsplit(char *str, const char *sep)
        !           274: {
        !           275:        char **argv, **nargv;
        !           276:        char *cp, *p;
        !           277:        int i = 0;
        !           278:
        !           279:        cp = xstrdup(str);
        !           280:        argv = (char **)xmalloc((i+1) * sizeof(char *));
        !           281:
        !           282:        while ((p = strsep(&cp, sep)) != NULL) {
        !           283:                argv[i++] = p;
        !           284:                nargv = (char **)xrealloc((void *)argv, (i+1) * sizeof(char *));
        !           285:                argv = nargv;
1.16      xsa       286:        }
1.20    ! xsa       287:        argv[i] = NULL;
        !           288:
        !           289:        return (argv);
1.1       joris     290: }