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
cvs_log(u_int level,const char * fmt,...)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
cvs_vlog(u_int level,const char * fmt,va_list vap)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
cvs_printf(const char * fmt,...)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