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