1 /* $OpenBSD: history.c,v 1.5 2004/12/07 17:10:56 tedu 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 int 69 cvs_history(int argc, char **argv) 70 { 71 int ch, flags; 72 u_int nbmod, rep; 73 char *user, *zone, *tag, *cp; 74 char *modules[CVS_HISTORY_MAXMOD], histpath[MAXPATHLEN]; 75 struct cvsroot *root; 76 struct cvs_hent *hent; 77 CVSHIST *hp; 78 79 tag = NULL; 80 user = NULL; 81 zone = "+0000"; 82 nbmod = 0; 83 flags = 0; 84 rep = 0; 85 86 while ((ch = getopt(argc, argv, "acelm:oTt:u:wx:z:")) != -1) { 87 switch (ch) { 88 case 'a': 89 flags |= CVS_HF_A; 90 break; 91 case 'c': 92 rep++; 93 flags |= CVS_HF_C; 94 break; 95 case 'e': 96 rep++; 97 flags |= CVS_HF_E; 98 break; 99 case 'l': 100 flags |= CVS_HF_L; 101 break; 102 case 'm': 103 rep++; 104 flags |= CVS_HF_M; 105 if (nbmod == CVS_HISTORY_MAXMOD) { 106 cvs_log(LP_ERR, "too many `-m' options"); 107 return (EX_USAGE); 108 } 109 modules[nbmod++] = optarg; 110 break; 111 case 'o': 112 rep++; 113 flags |= CVS_HF_O; 114 break; 115 case 'T': 116 rep++; 117 flags |= CVS_HF_T; 118 break; 119 case 't': 120 tag = optarg; 121 break; 122 case 'u': 123 user = optarg; 124 break; 125 case 'w': 126 flags |= CVS_HF_W; 127 break; 128 case 'x': 129 rep++; 130 for (cp = optarg; *cp != '\0'; cp++) { 131 } 132 break; 133 case 'z': 134 zone = optarg; 135 break; 136 default: 137 return (EX_USAGE); 138 } 139 } 140 141 if (rep > 1) { 142 cvs_log(LP_ERR, 143 "Only one report type allowed from: \"-Tcomxe\""); 144 return (EX_USAGE); 145 } else if (rep == 0) 146 flags |= CVS_HF_O; /* use -o as default */ 147 148 root = cvsroot_get("."); 149 if (root->cr_method == CVS_METHOD_LOCAL) { 150 snprintf(histpath, sizeof(histpath), "%s/%s", root->cr_dir, 151 CVS_PATH_HISTORY); 152 hp = cvs_hist_open(histpath); 153 if (hp == NULL) { 154 return (EX_UNAVAILABLE); 155 } 156 157 while ((hent = cvs_hist_getnext(hp)) != NULL) { 158 cvs_history_print(hent); 159 } 160 cvs_hist_close(hp); 161 } else { 162 if (flags & CVS_HF_C) 163 cvs_sendarg(root, "-c", 0); 164 165 if (flags & CVS_HF_O) 166 cvs_sendarg(root, "-o", 0); 167 168 if (tag != NULL) { 169 cvs_sendarg(root, "-t", 0); 170 cvs_sendarg(root, tag, 0); 171 } 172 if (user != NULL) { 173 cvs_sendarg(root, "-u", 0); 174 cvs_sendarg(root, user, 0); 175 } 176 177 cvs_sendarg(root, "-z", 0); 178 cvs_sendarg(root, zone, 0); 179 180 cvs_sendreq(root, CVS_REQ_HISTORY, NULL); 181 } 182 183 return (0); 184 } 185 186 187 static void 188 cvs_history_print(struct cvs_hent *hent) 189 { 190 struct tm etime; 191 192 if (localtime_r(&(hent->ch_date), &etime) == NULL) { 193 cvs_log(LP_ERROR, "failed to convert timestamp to structure"); 194 return; 195 } 196 197 printf("%c %4d-%02d-%02d %02d:%02d +%04d %-16s %-16s\n", 198 hent->ch_event, etime.tm_year + 1900, etime.tm_mon + 1, 199 etime.tm_mday, etime.tm_hour, etime.tm_min, 200 0, hent->ch_user, hent->ch_repo); 201 } 202