• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #include <stdarg.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <syslog.h>
10 
11 #include "dumper.h"
12 
dumpf(struct dumper * dumper,const char * format,...)13 void dumpf(struct dumper *dumper, const char *format, ...)
14 {
15 	va_list ap;
16 	va_start(ap, format);
17 	dumper->vprintf(dumper, format, ap);
18 	va_end(ap);
19 }
20 
21 /* dumper which outputs to syslog */
22 
23 struct syslog_data {
24 	int priority;
25 	struct dumper *mem_dumper;
26 };
27 
syslog_vprintf(struct dumper * dumper,const char * fmt,va_list ap)28 static void syslog_vprintf(struct dumper *dumper, const char *fmt, va_list ap)
29 {
30 	char *buf;
31 	int size, i;
32 	struct syslog_data *data = (struct syslog_data *)dumper->data;
33 	struct dumper *mem_dumper = data->mem_dumper;
34 
35 	/* We cannot use syslog() directly each time we are called,
36 	 * because syslog() will always append a newline to the
37 	 * output, so the user will not be able to construct a line
38 	 * incrementally using multiple calls. What we do here is to
39 	 * collect the output in a buffer until a newline is given by
40 	 * the user. */
41 
42 	mem_dumper->vprintf(mem_dumper, fmt, ap);
43 again:
44 	mem_dumper_get(mem_dumper, &buf, &size);
45 	for (i = 0; i < size; i++) {
46 		if (buf[i] == '\n') {
47 			syslog(data->priority, "%.*s", i + 1, buf);
48 			mem_dumper_consume(mem_dumper, i + 1);
49 			goto again;
50 		}
51 	}
52 }
53 
syslog_dumper_create(int priority)54 struct dumper *syslog_dumper_create(int priority)
55 {
56 	struct dumper *dumper = calloc(1, sizeof(struct dumper));
57 	struct syslog_data *data = calloc(1, sizeof(struct syslog_data));
58 	data->priority = priority;
59 	data->mem_dumper = mem_dumper_create();
60 	dumper->data = data;
61 	dumper->vprintf = &syslog_vprintf;
62 	return dumper;
63 }
64 
syslog_dumper_free(struct dumper * dumper)65 void syslog_dumper_free(struct dumper *dumper)
66 {
67 	mem_dumper_free(((struct syslog_data *)dumper->data)->mem_dumper);
68 	free(dumper->data);
69 	free(dumper);
70 }
71 
72 /* dumper which outputs to a memory buffer */
73 
74 struct mem_data {
75 	char *buf;
76 	int size;
77 	int capacity;
78 };
79 
mem_vprintf(struct dumper * dumper,const char * format,va_list ap)80 static void mem_vprintf(struct dumper *dumper, const char *format, va_list ap)
81 {
82 	int n;
83 	char *tmp;
84 	struct mem_data *data = (struct mem_data *)dumper->data;
85 
86 	while (1) {
87 		/* try to use the remaining space */
88 		int remaining = data->capacity - data->size;
89 		n = vsnprintf(data->buf + data->size, remaining, format, ap);
90 
91 		/* enough space? */
92 		if (n > -1 && n < remaining) {
93 			data->size += n;
94 			return;
95 		}
96 
97 		/* allocate more space and try again */
98 		tmp = realloc(data->buf, data->capacity * 2);
99 		if (tmp == NULL)
100 			return;
101 		data->buf = tmp;
102 		data->capacity *= 2;
103 	}
104 }
105 
mem_dumper_create()106 struct dumper *mem_dumper_create()
107 {
108 	struct dumper *dumper = calloc(1, sizeof(struct dumper));
109 	struct mem_data *data = calloc(1, sizeof(struct mem_data));
110 	if (!dumper || !data)
111 		return NULL;
112 	data->size = 0;
113 	data->capacity = 80;
114 	data->buf = malloc(data->capacity);
115 	if (!data->buf) {
116 		free(data);
117 		return NULL;
118 	}
119 	data->buf[0] = '\0';
120 	dumper->data = data;
121 	dumper->vprintf = &mem_vprintf;
122 	return dumper;
123 }
124 
mem_dumper_free(struct dumper * dumper)125 void mem_dumper_free(struct dumper *dumper)
126 {
127 	struct mem_data *data = (struct mem_data *)dumper->data;
128 	free(data->buf);
129 	free(data);
130 	free(dumper);
131 }
132 
mem_dumper_clear(struct dumper * dumper)133 void mem_dumper_clear(struct dumper *dumper)
134 {
135 	struct mem_data *data = (struct mem_data *)dumper->data;
136 	data->buf[0] = '\0';
137 	data->size = 0;
138 }
139 
mem_dumper_consume(struct dumper * dumper,int n)140 void mem_dumper_consume(struct dumper *dumper, int n)
141 {
142 	struct mem_data *data = (struct mem_data *)dumper->data;
143 	if (n > data->size)
144 		n = data->size;
145 	memmove(data->buf, data->buf + n, data->size - n + 1);
146 	data->size -= n;
147 }
148 
mem_dumper_get(struct dumper * dumper,char ** buf,int * size)149 void mem_dumper_get(struct dumper *dumper, char **buf, int *size)
150 {
151 	struct mem_data *data = (struct mem_data *)dumper->data;
152 	*buf = data->buf;
153 	*size = data->size;
154 }
155