/*
|
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
*
|
* This code is free software; you can redistribute it and/or modify it
|
* under the terms of the GNU General Public License version 2 only, as
|
* published by the Free Software Foundation. Oracle designates this
|
* particular file as subject to the "Classpath" exception as provided
|
* by Oracle in the LICENSE file that accompanied this code.
|
*
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
* version 2 for more details (a copy is included in the LICENSE file that
|
* accompanied this code).
|
*
|
* You should have received a copy of the GNU General Public License version
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
*
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
* or visit www.oracle.com if you need additional information or have any
|
* questions.
|
*/
|
|
#include "util.h"
|
|
#include <time.h>
|
#include <errno.h>
|
#include <sys/types.h>
|
|
#include "proc_md.h"
|
|
#include "log_messages.h"
|
|
#ifdef JDWP_LOGGING
|
|
#define MAXLEN_INTEGER 20
|
#define MAXLEN_FILENAME 256
|
#define MAXLEN_TIMESTAMP 80
|
#define MAXLEN_LOCATION (MAXLEN_FILENAME+MAXLEN_INTEGER+16)
|
#define MAXLEN_MESSAGE 256
|
#define MAXLEN_EXEC (MAXLEN_FILENAME*2+MAXLEN_INTEGER+16)
|
|
static MUTEX_T my_mutex = MUTEX_INIT;
|
|
/* Static variables (should be protected with mutex) */
|
static int logging;
|
static FILE * log_file;
|
static char logging_filename[MAXLEN_FILENAME+1+6];
|
static char location_stamp[MAXLEN_LOCATION+1];
|
static PID_T processPid;
|
static int open_count;
|
|
/* Ascii id of current native thread. */
|
static void
|
get_time_stamp(char *tbuf, size_t ltbuf)
|
{
|
char format[MAXLEN_TIMESTAMP+1];
|
unsigned millisecs = 0;
|
time_t t = 0;
|
|
GETMILLSECS(millisecs);
|
if ( time(&t) == (time_t)(-1) )
|
t = 0;
|
(void)strftime(format, sizeof(format),
|
/* Break this string up for SCCS's sake */
|
"%" "d.%" "m.%" "Y %" "T.%%.3d %" "Z", localtime(&t));
|
(void)snprintf(tbuf, ltbuf, format, (int)(millisecs));
|
}
|
|
/* Get basename of filename */
|
static const char *
|
file_basename(const char *file)
|
{
|
char *p1;
|
char *p2;
|
|
if ( file==NULL )
|
return "unknown";
|
p1 = strrchr(file, '\\');
|
p2 = strrchr(file, '/');
|
p1 = ((p1 > p2) ? p1 : p2);
|
if (p1 != NULL) {
|
file = p1 + 1;
|
}
|
return file;
|
}
|
|
/* Fill in the exact source location of the LOG entry. */
|
static void
|
fill_location_stamp(const char *flavor, const char *file, int line)
|
{
|
(void)snprintf(location_stamp, sizeof(location_stamp),
|
"%s:\"%s\":%d;",
|
flavor, file_basename(file), line);
|
location_stamp[sizeof(location_stamp)-1] = 0;
|
}
|
|
/* Begin a log entry. */
|
void
|
log_message_begin(const char *flavor, const char *file, int line)
|
{
|
MUTEX_LOCK(my_mutex); /* Unlocked in log_message_end() */
|
if ( logging ) {
|
location_stamp[0] = 0;
|
fill_location_stamp(flavor, file, line);
|
}
|
}
|
|
/* Standard Logging Format Entry */
|
static void
|
standard_logging_format(FILE *fp,
|
const char *datetime,
|
const char *level,
|
const char *product,
|
const char *module,
|
const char *optional,
|
const char *messageID,
|
const char *message)
|
{
|
const char *format;
|
|
/* "[#|Date&Time&Zone|LogLevel|ProductName|ModuleID|
|
* OptionalKey1=Value1;OptionalKeyN=ValueN|MessageID:MessageText|#]\n"
|
*/
|
|
format="[#|%s|%s|%s|%s|%s|%s:%s|#]\n";
|
|
print_message(fp, "", "", format,
|
datetime,
|
level,
|
product,
|
module,
|
optional,
|
messageID,
|
message);
|
}
|
|
/* End a log entry */
|
void
|
log_message_end(const char *format, ...)
|
{
|
if ( logging ) {
|
va_list ap;
|
THREAD_T tid;
|
char datetime[MAXLEN_TIMESTAMP+1];
|
const char *level;
|
const char *product;
|
const char *module;
|
char optional[MAXLEN_INTEGER+6+MAXLEN_INTEGER+6+MAXLEN_LOCATION+1];
|
const char *messageID;
|
char message[MAXLEN_MESSAGE+1];
|
|
/* Grab the location, start file if needed, and clear the lock */
|
if ( log_file == NULL && open_count == 0 && logging_filename[0] != 0 ) {
|
open_count++;
|
log_file = fopen(logging_filename, "w");
|
if ( log_file!=NULL ) {
|
(void)setvbuf(log_file, NULL, _IOLBF, BUFSIZ);
|
} else {
|
logging = 0;
|
}
|
}
|
|
if ( log_file != NULL ) {
|
|
/* Get the rest of the needed information */
|
tid = GET_THREAD_ID();
|
level = "FINEST"; /* FIXUP? */
|
product = "J2SE1.5"; /* FIXUP? */
|
module = "jdwp"; /* FIXUP? */
|
messageID = ""; /* FIXUP: Unique message string ID? */
|
(void)snprintf(optional, sizeof(optional),
|
"LOC=%s;PID=%d;THR=t@%d",
|
location_stamp,
|
(int)processPid,
|
(int)tid);
|
|
/* Construct message string. */
|
va_start(ap, format);
|
(void)vsnprintf(message, sizeof(message), format, ap);
|
va_end(ap);
|
|
get_time_stamp(datetime, sizeof(datetime));
|
|
/* Send out standard logging format message */
|
standard_logging_format(log_file,
|
datetime,
|
level,
|
product,
|
module,
|
optional,
|
messageID,
|
message);
|
}
|
location_stamp[0] = 0;
|
}
|
MUTEX_UNLOCK(my_mutex); /* Locked in log_message_begin() */
|
}
|
|
#endif
|
|
/* Set up the logging with the name of a logging file. */
|
/* ANDROID-CHANGED: Added directlog */
|
void
|
setup_logging(const char *filename, unsigned flags, int directlog)
|
{
|
#ifdef JDWP_LOGGING
|
FILE *fp = NULL;
|
|
/* Turn off logging */
|
logging = 0;
|
gdata->log_flags = 0;
|
|
/* Just return if not doing logging */
|
if ( filename==NULL || flags==0 )
|
return;
|
|
/* Create potential filename for logging */
|
/* ANDROID-CHANGED: Add directlog */
|
if (directlog) {
|
strncpy(logging_filename, filename, sizeof(logging_filename));
|
} else {
|
processPid = GETPID();
|
(void)snprintf(logging_filename, sizeof(logging_filename),
|
"%s.%d", filename, (int)processPid);
|
}
|
|
/* Turn on logging (do this last) */
|
logging = 1;
|
gdata->log_flags = flags;
|
|
#endif
|
}
|
|
/* Finish up logging, flush output to the logfile. */
|
void
|
finish_logging()
|
{
|
#ifdef JDWP_LOGGING
|
MUTEX_LOCK(my_mutex);
|
if ( logging ) {
|
logging = 0;
|
if ( log_file != NULL ) {
|
(void)fflush(log_file);
|
(void)fclose(log_file);
|
log_file = NULL;
|
}
|
}
|
MUTEX_UNLOCK(my_mutex);
|
#endif
|
}
|