1 /* $OpenBSD: history.c,v 1.3 2004/07/30 01:49:23 jfb Exp $ */ 2 /* 3 * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. The name of the author may not be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 16 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 17 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 18 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/param.h> 28 #include <sys/stat.h> 29 30 #include <errno.h> 31 #include <stdio.h> 32 #include <fcntl.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <string.h> 36 #include <sysexits.h> 37 38 #include "cvs.h" 39 #include "rcs.h" 40 #include "log.h" 41 #include "proto.h" 42 43 #define CVS_HISTORY_MAXMOD 16 44 45 /* history flags */ 46 #define CVS_HF_A 0x01 47 #define CVS_HF_C 0x02 48 #define CVS_HF_E 0x04 49 #define CVS_HF_L 0x08 50 #define CVS_HF_M 0x10 51 #define CVS_HF_O 0x20 52 #define CVS_HF_T 0x40 53 #define CVS_HF_W 0x80 54 55 #define CVS_HF_EXCL (CVS_HF_C|CVS_HF_E|CVS_HF_M|CVS_HF_O|CVS_HF_T|CVS_HF_X) 56 57 static void cvs_history_print (struct cvs_hent *); 58 59 60 extern char *__progname; 61 62 63 /* 64 * cvs_history() 65 * 66 * Handle the `cvs history' command. 67 */ 68 69 int 70 cvs_history(int argc, char **argv) 71 { 72 int ch, flags; 73 u_int nbmod, rep; 74 char *user, *zone, *tag, *cp; 75 char *modules[CVS_HISTORY_MAXMOD], histpath[MAXPATHLEN]; 76 struct cvsroot *root; 77 struct cvs_hent *hent; 78 CVSHIST *hp; 79 80 tag = NULL; 81 user = NULL; 82 zone = "+0000"; 83 nbmod = 0; 84 flags = 0; 85 rep = 0; 86 87 while ((ch = getopt(argc, argv, "acelm:oTt:u:wx:z:")) != -1) { 88 switch (ch) { 89 case 'a': 90 flags |= CVS_HF_A; 91 break; 92 case 'c': 93 rep++; 94 flags |= CVS_HF_C; 95 break; 96 case 'e': 97 rep++; 98 flags |= CVS_HF_E; 99 break; 100 case 'l': 101 flags |= CVS_HF_L; 102 break; 103 case 'm': 104 rep++; 105 flags |= CVS_HF_M; 106 if (nbmod == CVS_HISTORY_MAXMOD) { 107 cvs_log(LP_ERR, "too many `-m' options"); 108 return (EX_USAGE); 109 } 110 modules[nbmod++] = optarg; 111 break; 112 case 'o': 113 rep++; 114 flags |= CVS_HF_O; 115 break; 116 case 'T': 117 rep++; 118 flags |= CVS_HF_T; 119 break; 120 case 't': 121 tag = optarg; 122 break; 123 case 'u': 124 user = optarg; 125 break; 126 case 'w': 127 flags |= CVS_HF_W; 128 break; 129 case 'x': 130 rep++; 131 for (cp = optarg; *cp != '\0'; cp++) { 132 } 133 break; 134 case 'z': 135 zone = optarg; 136 break; 137 default: 138 return (EX_USAGE); 139 } 140 } 141 142 if (rep > 1) { 143 cvs_log(LP_ERR, 144 "Only one report type allowed from: \"-Tcomxe\""); 145 return (EX_USAGE); 146 } 147 else if (rep == 0) 148 flags |= CVS_HF_O; /* use -o as default */ 149 150 root = cvsroot_get("."); 151 if (root->cr_method == CVS_METHOD_LOCAL) { 152 snprintf(histpath, sizeof(histpath), "%s/%s", root->cr_dir, 153 CVS_PATH_HISTORY); 154 hp = cvs_hist_open(histpath); 155 if (hp == NULL) { 156 return (EX_UNAVAILABLE); 157 } 158 159 while ((hent = cvs_hist_getnext(hp)) != NULL) { 160 cvs_history_print(hent); 161 } 162 cvs_hist_close(hp); 163 } 164 else { 165 if (flags & CVS_HF_C) 166 cvs_sendarg(root, "-c", 0); 167 168 if (flags & CVS_HF_O) 169 cvs_sendarg(root, "-o", 0); 170 171 if (tag != NULL) { 172 cvs_sendarg(root, "-t", 0); 173 cvs_sendarg(root, tag, 0); 174 } 175 if (user != NULL) { 176 cvs_sendarg(root, "-u", 0); 177 cvs_sendarg(root, user, 0); 178 } 179 180 cvs_sendarg(root, "-z", 0); 181 cvs_sendarg(root, zone, 0); 182 183 cvs_sendreq(root, CVS_REQ_HISTORY, NULL); 184 } 185 186 return (0); 187 } 188 189 190 static void 191 cvs_history_print(struct cvs_hent *hent) 192 { 193 struct tm etime; 194 195 if (localtime_r(&(hent->ch_date), &etime) == NULL) { 196 cvs_log(LP_ERROR, "failed to convert timestamp to structure"); 197 return; 198 } 199 200 printf("%c %4d-%02d-%02d %02d:%02d +%04d %-16s %-16s\n", 201 hent->ch_event, etime.tm_year + 1900, etime.tm_mon + 1, 202 etime.tm_mday, etime.tm_hour, etime.tm_min, 203 0, hent->ch_user, hent->ch_repo); 204 } 205