File: io.c

package info (click to toggle)
systemtap 2.6-0.2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 21,220 kB
  • ctags: 10,944
  • sloc: cpp: 53,239; ansic: 50,615; exp: 33,694; sh: 9,906; xml: 7,665; perl: 2,089; python: 1,534; tcl: 1,236; makefile: 797; java: 148; lisp: 104; awk: 94; asm: 91; sed: 16
file content (168 lines) | stat: -rw-r--r-- 4,541 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/* -*- linux-c -*- 
 * I/O for printing warnings, errors and debug messages
 * Copyright (C) 2012 Red Hat Inc.
 *
 * This file is part of systemtap, and is free software.  You can
 * redistribute it and/or modify it under the terms of the GNU General
 * Public License (GPL); either version 2, or (at your option) any
 * later version.
 */

#ifndef _STAPDYN_IO_C_
#define _STAPDYN_IO_C_

#include <sys/param.h>
#include "transport.h"
#include "vsprintf.h"
#include "print.h"

#define WARN_STRING "WARNING: "
#define ERR_STRING "ERROR: "

enum code { INFO=0, WARN, ERROR, DBUG };

static void _stp_vlog (enum code type, const char *func, int line,
		       const char *fmt, va_list args)
	__attribute ((format (printf, 4, 0)));

static void _stp_vlog (enum code type, const char *func, int line,
		       const char *fmt, va_list args)
{
	size_t start = 0;
	size_t num;
	char local_buffer[STP_LOG_BUF_LEN];
	char *buf;

	/* If we're writing a debug message, just use the temporary
	 * buffer. These messages end up going through the normal
	 * transport path, not the OOB data path. */
	if (type == DBUG) {
		buf = local_buffer;
	}
	else {
		/* If we can't get a buffer, the transport must be not
		 * up yet.  Instead use our temporary buffer. */
		buf = _stp_dyninst_transport_log_buffer();
		if (buf == NULL)
			buf = local_buffer;
	}

	if (type == DBUG) {
		start = snprintf(buf, STP_LOG_BUF_LEN, "%s:%d: ", func, line);
	}
	else if (type == WARN) {
		/* This strcpy() is OK, since we know STP_LOG_BUF_LEN
		 * is > sizeof(WARN_STRING). */
		strcpy(buf, WARN_STRING);
		start = sizeof(WARN_STRING)- 1;
	}
	else if (type == ERROR) {
		/* This strcpy() is OK, since we know STP_LOG_BUF_LEN
		 * is > sizeof(ERR_STRING) (which is <
		 * sizeof(WARN_STRING). */
		strcpy(buf, ERR_STRING);
		start = sizeof(ERR_STRING) - 1;
	}

	/* Note that if the message is too long it will just get truncated. */
	num = vsnprintf(buf + start, STP_LOG_BUF_LEN - start - 1, fmt, args);
	if ((num + start) == 0)
		return;

	/* Mimic vscnprintf's length computation.  */
	if (num >= STP_LOG_BUF_LEN - start - 1)
		num = STP_LOG_BUF_LEN - start - 2;

	/* If the last character is not a newline, then add one. */
	if (buf[num + start - 1] != '\n') {
		buf[num + start] = '\n';
		num++;
		buf[num + start] = '\0';
	}

	if (buf != local_buffer) {
		/* If we successfully got log space, send it as OOB now.
		 * NB: don't explicitly send the \0 terminator. */
		_stp_dyninst_transport_write_oob_data(buf, num + start);
	}
	else if (type == DBUG && _stp_runtime_get_context() != NULL) {
                /* Debug messages go over the normal data path if we have a
                 * context for transport.  */
		_stp_print(buf);
		_stp_print_flush();
	}
	else {
		/* Fallback to local stderr as a last resort.  */
		fprintf(stderr, "%s", buf);
	}
}

/** Prints warning.
 * This function sends a warning message immediately to staprun. It
 * will also be sent over the bulk transport (relayfs) if it is
 * being used. If the last character is not a newline, then one 
 * is added. 
 * @param fmt A variable number of args.
 */
static void _stp_warn (const char *fmt, ...)
{
	va_list args;
	va_start(args, fmt);
	_stp_vlog (WARN, NULL, 0, fmt, args);
	va_end(args);
}


/** Prints error message and exits.
 * This function sends an error message immediately to staprun. It
 * will also be sent over the bulk transport (relayfs) if it is
 * being used. If the last character is not a newline, then one 
 * is added. 
 *
 * After the error message is displayed, the module will be unloaded.
 * @param fmt A variable number of args.
 * @sa _stp_exit().
 */
static void _stp_error (const char *fmt, ...)
{
	va_list args;
	va_start(args, fmt);
	_stp_vlog (ERROR, NULL, 0, fmt, args);
	va_end(args);
// FIXME: need to exit here...
//	_stp_exit();
}


/** Prints error message.
 * This function sends an error message immediately to staprun. It
 * will also be sent over the bulk transport (relayfs) if it is
 * being used. If the last character is not a newline, then one 
 * is added. 
 *
 * @param fmt A variable number of args.
 * @sa _stp_error
 */
static void _stp_softerror (const char *fmt, ...)
{
	va_list args;
	va_start(args, fmt);
	_stp_vlog (ERROR, NULL, 0, fmt, args);
	va_end(args);
}


static void _stp_dbug (const char *func, int line, const char *fmt, ...)
{
	va_list args;
	va_start(args, fmt);
	_stp_vlog (DBUG, func, line, fmt, args);
	va_end(args);
}

static void _stp_exit (void)
{
	_stp_dyninst_transport_request_exit();
}

#endif /* _STAPDYN_IO_C_ */