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