xref: /openbsd-src/usr.bin/cvs/log.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
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