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