1 /* $OpenBSD: log.c,v 1.36 2006/07/07 17:37:17 joris Exp $ */ 2 /* 3 * Copyright (c) 2006 Joris Vink <joris@openbsd.org> 4 * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> 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 28 #include "includes.h" 29 30 #include "cvs.h" 31 #include "log.h" 32 33 extern char *__progname; 34 static int send_m = 1; 35 36 /* 37 * cvs_log() 38 * 39 * Log the format-string message 40 * The <fmt> argument should not have a terminating newline, as this is taken 41 * care of by the logging facility. 42 */ 43 void 44 cvs_log(u_int level, const char *fmt, ...) 45 { 46 va_list vap; 47 48 va_start(vap, fmt); 49 cvs_vlog(level, fmt, vap); 50 va_end(vap); 51 } 52 53 /* 54 * cvs_vlog() 55 * 56 * The <fmt> argument should not have a terminating newline, as this is taken 57 * care of by the logging facility. 58 */ 59 void 60 cvs_vlog(u_int level, const char *fmt, va_list vap) 61 { 62 int ecp; 63 char prefix[64], buf[1024], ebuf[255]; 64 FILE *out; 65 char *cmdname; 66 struct cvs_cmd *cmdp; 67 68 if (cvs_trace != 1 && level == LP_TRACE) 69 return; 70 71 if (level == LP_ERRNO) 72 ecp = errno; 73 else 74 ecp = 0; 75 76 /* always use the command name in error messages, not aliases */ 77 if (cvs_command == NULL) 78 cmdname = " "; 79 else { 80 cmdp = cvs_findcmd(cvs_command); 81 cmdname = cmdp->cmd_name; 82 } 83 84 /* The cvs program appends the command name to the program name */ 85 if (level == LP_TRACE) { 86 strlcpy(prefix, " -> ", sizeof(prefix)); 87 if (cvs_server_active) 88 prefix[0] = 'S'; 89 else 90 prefix[0] = 'C'; 91 } else if (cvs_command != NULL) { 92 if (level == LP_ABORT) 93 snprintf(prefix, sizeof(prefix), "%s [%s aborted]", 94 __progname, cmdname); 95 else 96 snprintf(prefix, sizeof(prefix), "%s %s", __progname, 97 cmdname); 98 } else /* just use the standard strlcpy */ 99 strlcpy(prefix, __progname, sizeof(prefix)); 100 101 vsnprintf(buf, sizeof(buf), fmt, vap); 102 if (level == LP_ERRNO) { 103 snprintf(ebuf, sizeof(ebuf), ": %s", strerror(errno)); 104 strlcat(buf, ebuf, sizeof(buf)); 105 } 106 107 if (level == LP_NOTICE) 108 out = stdout; 109 else 110 out = stderr; 111 112 if (cvs_server_active) { 113 if (out == stdout) 114 putc('M', out); 115 else { 116 out = stdout; 117 putc('E', out); 118 } 119 120 putc(' ', out); 121 } 122 123 fputs(prefix, out); 124 if (level != LP_TRACE) 125 fputs(": ", out); 126 fputs(buf, out); 127 fputc('\n', out); 128 129 /* preserve it just in case we changed it? */ 130 if (level == LP_ERRNO) 131 errno = ecp; 132 } 133 134 /* 135 * cvs_printf() 136 * 137 * Wrapper function around printf() that prepends a 'M' command when 138 * the program is acting as server. 139 */ 140 int 141 cvs_printf(const char *fmt, ...) 142 { 143 int ret; 144 char *nstr, *dp, *sp; 145 va_list vap; 146 147 va_start(vap, fmt); 148 149 if (cvs_server_active) { 150 ret = vasprintf(&nstr, fmt, vap); 151 if (ret == -1) 152 fatal("cvs_printf: %s", strerror(errno)); 153 for (dp = nstr; *dp != '\0';) { 154 sp = strchr(dp, '\n'); 155 if (sp == NULL) 156 for (sp = dp; *sp != '\0'; sp++) 157 ; 158 159 if (send_m) { 160 send_m = 0; 161 putc('M', stdout); 162 putc(' ', stdout); 163 } 164 165 fwrite(dp, sizeof(char), (size_t)(sp - dp), stdout); 166 167 if (*sp != '\n') 168 break; 169 170 putc('\n', stdout); 171 send_m = 1; 172 dp = sp + 1; 173 } 174 xfree(nstr); 175 } else 176 ret = vprintf(fmt, vap); 177 178 va_end(vap); 179 return (ret); 180 } 181