2
|
1 |
/*
|
|
2 |
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
|
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 |
*
|
|
5 |
* This code is free software; you can redistribute it and/or modify it
|
|
6 |
* under the terms of the GNU General Public License version 2 only, as
|
|
7 |
* published by the Free Software Foundation. Sun designates this
|
|
8 |
* particular file as subject to the "Classpath" exception as provided
|
|
9 |
* by Sun in the LICENSE file that accompanied this code.
|
|
10 |
*
|
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that
|
|
15 |
* accompanied this code).
|
|
16 |
*
|
|
17 |
* You should have received a copy of the GNU General Public License version
|
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
20 |
*
|
|
21 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
22 |
* CA 95054 USA or visit www.sun.com if you need additional information or
|
|
23 |
* have any questions.
|
|
24 |
*/
|
|
25 |
|
|
26 |
#include "util.h"
|
|
27 |
|
|
28 |
#include <time.h>
|
|
29 |
#include <errno.h>
|
|
30 |
#include <sys/types.h>
|
|
31 |
|
|
32 |
#include "proc_md.h"
|
|
33 |
|
|
34 |
#include "log_messages.h"
|
|
35 |
|
|
36 |
#ifdef JDWP_LOGGING
|
|
37 |
|
|
38 |
#define MAXLEN_INTEGER 20
|
|
39 |
#define MAXLEN_FILENAME 256
|
|
40 |
#define MAXLEN_TIMESTAMP 80
|
|
41 |
#define MAXLEN_LOCATION (MAXLEN_FILENAME+MAXLEN_INTEGER+16)
|
|
42 |
#define MAXLEN_MESSAGE 256
|
|
43 |
#define MAXLEN_EXEC (MAXLEN_FILENAME*2+MAXLEN_INTEGER+16)
|
|
44 |
|
|
45 |
static MUTEX_T my_mutex = MUTEX_INIT;
|
|
46 |
|
|
47 |
/* Static variables (should be protected with mutex) */
|
|
48 |
static int logging;
|
|
49 |
static FILE * log_file;
|
|
50 |
static char logging_filename[MAXLEN_FILENAME+1+6];
|
|
51 |
static char location_stamp[MAXLEN_LOCATION+1];
|
|
52 |
static PID_T processPid;
|
|
53 |
static int open_count;
|
|
54 |
|
|
55 |
/* Ascii id of current native thread. */
|
|
56 |
static void
|
|
57 |
get_time_stamp(char *tbuf, size_t ltbuf)
|
|
58 |
{
|
|
59 |
char format[MAXLEN_TIMESTAMP+1];
|
|
60 |
unsigned millisecs = 0;
|
|
61 |
time_t t = 0;
|
|
62 |
|
|
63 |
GETMILLSECS(millisecs);
|
|
64 |
if ( time(&t) == (time_t)(-1) )
|
|
65 |
t = 0;
|
|
66 |
(void)strftime(format, sizeof(format),
|
|
67 |
/* Break this string up for SCCS's sake */
|
|
68 |
"%" "d.%" "m.%" "Y %" "T.%%.3d %" "Z", localtime(&t));
|
|
69 |
(void)snprintf(tbuf, ltbuf, format, (int)(millisecs));
|
|
70 |
}
|
|
71 |
|
|
72 |
/* Get basename of filename */
|
|
73 |
static const char *
|
|
74 |
file_basename(const char *file)
|
|
75 |
{
|
|
76 |
char *p1;
|
|
77 |
char *p2;
|
|
78 |
|
|
79 |
if ( file==NULL )
|
|
80 |
return "unknown";
|
|
81 |
p1 = strrchr(file, '\\');
|
|
82 |
p2 = strrchr(file, '/');
|
|
83 |
p1 = ((p1 > p2) ? p1 : p2);
|
|
84 |
if (p1 != NULL) {
|
|
85 |
file = p1 + 1;
|
|
86 |
}
|
|
87 |
return file;
|
|
88 |
}
|
|
89 |
|
|
90 |
/* Fill in the exact source location of the LOG entry. */
|
|
91 |
static void
|
|
92 |
fill_location_stamp(const char *flavor, const char *file, int line)
|
|
93 |
{
|
|
94 |
(void)snprintf(location_stamp, sizeof(location_stamp),
|
|
95 |
"%s:\"%s\":%d;",
|
|
96 |
flavor, file_basename(file), line);
|
|
97 |
location_stamp[sizeof(location_stamp)-1] = 0;
|
|
98 |
}
|
|
99 |
|
|
100 |
/* Begin a log entry. */
|
|
101 |
void
|
|
102 |
log_message_begin(const char *flavor, const char *file, int line)
|
|
103 |
{
|
|
104 |
MUTEX_LOCK(my_mutex); /* Unlocked in log_message_end() */
|
|
105 |
if ( logging ) {
|
|
106 |
location_stamp[0] = 0;
|
|
107 |
fill_location_stamp(flavor, file, line);
|
|
108 |
}
|
|
109 |
}
|
|
110 |
|
|
111 |
/* Standard Logging Format Entry */
|
|
112 |
static void
|
|
113 |
standard_logging_format(FILE *fp,
|
|
114 |
const char *datetime,
|
|
115 |
const char *level,
|
|
116 |
const char *product,
|
|
117 |
const char *module,
|
|
118 |
const char *optional,
|
|
119 |
const char *messageID,
|
|
120 |
const char *message)
|
|
121 |
{
|
|
122 |
const char *format;
|
|
123 |
|
|
124 |
/* "[#|Date&Time&Zone|LogLevel|ProductName|ModuleID|
|
|
125 |
* OptionalKey1=Value1;OptionalKeyN=ValueN|MessageID:MessageText|#]\n"
|
|
126 |
*/
|
|
127 |
|
|
128 |
format="[#|%s|%s|%s|%s|%s|%s:%s|#]\n";
|
|
129 |
|
|
130 |
print_message(fp, "", "", format,
|
|
131 |
datetime,
|
|
132 |
level,
|
|
133 |
product,
|
|
134 |
module,
|
|
135 |
optional,
|
|
136 |
messageID,
|
|
137 |
message);
|
|
138 |
}
|
|
139 |
|
|
140 |
/* End a log entry */
|
|
141 |
void
|
|
142 |
log_message_end(const char *format, ...)
|
|
143 |
{
|
|
144 |
if ( logging ) {
|
|
145 |
va_list ap;
|
|
146 |
THREAD_T tid;
|
|
147 |
char datetime[MAXLEN_TIMESTAMP+1];
|
|
148 |
const char *level;
|
|
149 |
const char *product;
|
|
150 |
const char *module;
|
|
151 |
char optional[MAXLEN_INTEGER+6+MAXLEN_INTEGER+6+MAXLEN_LOCATION+1];
|
|
152 |
const char *messageID;
|
|
153 |
char message[MAXLEN_MESSAGE+1];
|
|
154 |
|
|
155 |
/* Grab the location, start file if needed, and clear the lock */
|
|
156 |
if ( log_file == NULL && open_count == 0 && logging_filename[0] != 0 ) {
|
|
157 |
open_count++;
|
|
158 |
log_file = fopen(logging_filename, "w");
|
|
159 |
if ( log_file!=NULL ) {
|
|
160 |
(void)setvbuf(log_file, NULL, _IOLBF, BUFSIZ);
|
|
161 |
} else {
|
|
162 |
logging = 0;
|
|
163 |
}
|
|
164 |
}
|
|
165 |
|
|
166 |
if ( log_file != NULL ) {
|
|
167 |
|
|
168 |
/* Get the rest of the needed information */
|
|
169 |
tid = GET_THREAD_ID();
|
|
170 |
level = "FINEST"; /* FIXUP? */
|
|
171 |
product = "J2SE1.5"; /* FIXUP? */
|
|
172 |
module = "jdwp"; /* FIXUP? */
|
|
173 |
messageID = ""; /* FIXUP: Unique message string ID? */
|
|
174 |
(void)snprintf(optional, sizeof(optional),
|
|
175 |
"LOC=%s;PID=%d;THR=t@%d",
|
|
176 |
location_stamp,
|
|
177 |
(int)processPid,
|
|
178 |
(int)tid);
|
|
179 |
|
|
180 |
/* Construct message string. */
|
|
181 |
va_start(ap, format);
|
|
182 |
(void)vsnprintf(message, sizeof(message), format, ap);
|
|
183 |
va_end(ap);
|
|
184 |
|
|
185 |
get_time_stamp(datetime, sizeof(datetime));
|
|
186 |
|
|
187 |
/* Send out standard logging format message */
|
|
188 |
standard_logging_format(log_file,
|
|
189 |
datetime,
|
|
190 |
level,
|
|
191 |
product,
|
|
192 |
module,
|
|
193 |
optional,
|
|
194 |
messageID,
|
|
195 |
message);
|
|
196 |
}
|
|
197 |
location_stamp[0] = 0;
|
|
198 |
}
|
|
199 |
MUTEX_UNLOCK(my_mutex); /* Locked in log_message_begin() */
|
|
200 |
}
|
|
201 |
|
|
202 |
#endif
|
|
203 |
|
|
204 |
/* Set up the logging with the name of a logging file. */
|
|
205 |
void
|
|
206 |
setup_logging(const char *filename, unsigned flags)
|
|
207 |
{
|
|
208 |
#ifdef JDWP_LOGGING
|
|
209 |
FILE *fp = NULL;
|
|
210 |
|
|
211 |
/* Turn off logging */
|
|
212 |
logging = 0;
|
|
213 |
gdata->log_flags = 0;
|
|
214 |
|
|
215 |
/* Just return if not doing logging */
|
|
216 |
if ( filename==NULL || flags==0 )
|
|
217 |
return;
|
|
218 |
|
|
219 |
/* Create potential filename for logging */
|
|
220 |
processPid = GETPID();
|
|
221 |
(void)snprintf(logging_filename, sizeof(logging_filename),
|
|
222 |
"%s.%d", filename, (int)processPid);
|
|
223 |
|
|
224 |
/* Turn on logging (do this last) */
|
|
225 |
logging = 1;
|
|
226 |
gdata->log_flags = flags;
|
|
227 |
|
|
228 |
#endif
|
|
229 |
}
|
|
230 |
|
|
231 |
/* Finish up logging, flush output to the logfile. */
|
|
232 |
void
|
|
233 |
finish_logging(int exit_code)
|
|
234 |
{
|
|
235 |
#ifdef JDWP_LOGGING
|
|
236 |
MUTEX_LOCK(my_mutex);
|
|
237 |
if ( logging ) {
|
|
238 |
logging = 0;
|
|
239 |
if ( log_file != NULL ) {
|
|
240 |
(void)fflush(log_file);
|
|
241 |
(void)fclose(log_file);
|
|
242 |
log_file = NULL;
|
|
243 |
}
|
|
244 |
}
|
|
245 |
MUTEX_UNLOCK(my_mutex);
|
|
246 |
#endif
|
|
247 |
}
|