1 /* $OpenBSD: log.c,v 1.47 2015/11/05 09:48:21 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 <stdlib.h> 30 #include <string.h> 31 32 #include "cvs.h" 33 34 extern char *__progname; 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 FILE *out; 64 char *cmdname; 65 66 if (cvs_trace != 1 && level == LP_TRACE) 67 return; 68 69 if (level == LP_ERRNO) 70 ecp = errno; 71 else 72 ecp = 0; 73 74 if (level == LP_NOTICE) 75 out = stdout; 76 else 77 out = stderr; 78 79 if (cvs_server_active) { 80 if (out == stdout) 81 putc('M', out); 82 else { 83 out = stdout; 84 putc('E', out); 85 } 86 87 putc(' ', out); 88 } 89 90 cmdname = (cmdp != NULL) ? cmdp->cmd_name : __progname; 91 92 /* The cvs program appends the command name to the program name */ 93 if (level == LP_TRACE) { 94 if (cvs_server_active) 95 putc('S', out); 96 else 97 putc('C', out); 98 (void)fputs("-> ", out); 99 } else if (level != LP_RCS) { 100 (void)fputs(__progname, out); 101 putc(' ', out); 102 if (level == LP_ABORT) 103 (void)fprintf(out, 104 "[%s aborted]", cmdname); 105 else 106 (void)fputs(cmdname, out); 107 (void)fputs(": ", out); 108 } 109 110 (void)vfprintf(out, fmt, vap); 111 if (level == LP_ERRNO) { 112 (void)fprintf(out, ": %s\n", strerror(ecp)); 113 114 /* preserve it just in case we changed it? */ 115 errno = ecp; 116 } else 117 fputc('\n', out); 118 } 119 120 /* 121 * cvs_printf() 122 * 123 * Wrapper function around printf() that prepends a 'M' command when 124 * the program is acting as server. 125 */ 126 int 127 cvs_printf(const char *fmt, ...) 128 { 129 static int send_m = 1; 130 int ret; 131 char *nstr, *dp, *sp; 132 va_list vap; 133 134 va_start(vap, fmt); 135 136 ret = vasprintf(&nstr, fmt, vap); 137 if (ret == -1) 138 fatal("cvs_printf: could not allocate memory"); 139 140 for (dp = nstr; *dp != '\0';) { 141 sp = strchr(dp, '\n'); 142 if (sp == NULL) 143 for (sp = dp; *sp != '\0'; sp++) 144 ; 145 146 if (cvs_server_active && send_m) { 147 send_m = 0; 148 putc('M', stdout); 149 putc(' ', stdout); 150 } 151 152 if (dp != nstr && dp != sp && 153 !strncmp(dp, LOG_REVSEP, sp - dp)) 154 putc('>', stdout); 155 156 fwrite(dp, sizeof(char), (size_t)(sp - dp), stdout); 157 158 if (*sp != '\n') 159 break; 160 161 putc('\n', stdout); 162 send_m = 1; 163 dp = sp + 1; 164 } 165 166 free(nstr); 167 va_end(vap); 168 169 return (ret); 170 } 171