29d52c8a27
calculated mask in debugging output. * sigproc.h (set_signal_mask): Reflect above change in declaration. * path.cc (mount_item::build_win32): Take path apart before feeding it to fnmunge. Throughout, change use of _reent_winsup()-> to _my_tls.locals. instead. Throughout, remove obsolete MT_SAFE/_CYG_THREAD_FAILSAFE considerations. Througout, add cygtls.h include. * Makefile.in (DLL_OFILES): Add cygtls.o. Add some more objects to the -fomit-frame-pointer list. * acconfig.h: Remove obsolete settings. * config.h.in: Ditto. * bsdlib.cc: Add cygtls.h include. * configure.in: Remove --enable-extra-threadsafe-checking. * configure: Regenerate. * cygtls.h (_local_storage): New struct renamed from _winsup_t (sic). (_threadinfo:local_clib): Add new field. (_threadinfo::locals): Ditto. (_threadinfo::init_thread): Accept second _reent * argument. (_threadinfo::call): Define as regparm. (CYGTLS_PADSIZE): Remove unnecessary slop. (_getreent): Define as a macro. * thread.h: Remove _CYG_THREAD_FAILSAFE and MT_SAFE stuff. (_winsup_t): Move to cygtls.h. (ResourceLocks::ResourceLocks): Eliminate empty constructor. (MTinterface::reents): Eliminate. (MTinterface::thread_self_key): Eliminate. (MTinterface::MTinterface): Eliminate. * dcrt0.cc: Include stdio.h for _impure_ptr initialization. (do_global_ctors): Remove run_ctors_p (sic) considerations. Don't call atexit here. (__main): Initialize destructors for user here. (dll_crt0_1): Accept a dummy argument. Don't call init_thread here. Don't set _impure_ptr here. Call do_global_ctors after more things have been initialized. (_dll_crt0): Define zeros buffer as max of needed size of CYGTLS_PADSIZE so that it can be used for two purposes while minimizing stack usage. Initialize _impure_ptr specifically, for speed. Call dll_crt0_1 with buffer argument. (cygwin_dll_init): Call dll_crt0_1 with dummy argument. * dtable.cc (dtable::find_unused_handle): Remove call to AssertResourceOwner. * exceptions.cc: Move _threadinfo stuff to new file. * cygtls.cc: New file. * gentls_offsets: Accommodate increasing complexity of cygtls.h. * hires.h (hires_base::~hires_base): Remove. * init.cc (dll_entry): Remove setting of reents. * thread.cc: Remove syslog.h include. (__getreent): Simplify to use _my_tls. (_reent_winsup): Delete. (AssertResourceOwner): Delete. (MTinterface::Init): Remove setting of _clib and _winsup, with all that entails. (MTinterface::fixup_after_fork): Ditto. (pthread::thread_init_wrapper): Ditto. Also remove call to set_tls_self_pointer. (pthread::set_tls_self_pointer): Eliminate. (pthread::get_tls_self_pointer): Just return _my_tls.tid; (__reent_t::init_clib): Eliminate. * tlsoffsets.h: Regenerate.
403 lines
9.3 KiB
C++
403 lines
9.3 KiB
C++
/* syslog.cc
|
|
|
|
Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc.
|
|
|
|
This file is part of Cygwin.
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
details. */
|
|
|
|
#include "winsup.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <syslog.h>
|
|
#include <stdarg.h>
|
|
#include <unistd.h>
|
|
#include "security.h"
|
|
#include "path.h"
|
|
#include "fhandler.h"
|
|
#include "dtable.h"
|
|
#include "cygerrno.h"
|
|
#include "cygheap.h"
|
|
#include "thread.h"
|
|
#include "cygtls.h"
|
|
|
|
/* FIXME: These should probably be in the registry. */
|
|
/* FIXME: The Win95 path should be whatever slash is */
|
|
|
|
#define WIN95_EVENT_LOG_PATH "C:\\CYGWIN_SYSLOG.TXT"
|
|
#define CYGWIN_LOG_NAME "Cygwin"
|
|
|
|
/*
|
|
* Utility function to help enable moving
|
|
* WIN95_EVENT_LOG_PATH into registry later.
|
|
*/
|
|
static const char *
|
|
get_win95_event_log_path ()
|
|
{
|
|
return WIN95_EVENT_LOG_PATH;
|
|
}
|
|
|
|
/* openlog: save the passed args. Don't open the
|
|
system log (NT) or log file (95) yet. */
|
|
extern "C" void
|
|
openlog (const char *ident, int logopt, int facility)
|
|
{
|
|
debug_printf ("openlog called with (%s, %d, %d)",
|
|
ident ? ident : "<NULL>", logopt, facility);
|
|
|
|
if (_my_tls.locals.process_ident != NULL)
|
|
{
|
|
free (_my_tls.locals.process_ident);
|
|
_my_tls.locals.process_ident = 0;
|
|
}
|
|
if (ident)
|
|
{
|
|
_my_tls.locals.process_ident = (char *) malloc (strlen (ident) + 1);
|
|
if (_my_tls.locals.process_ident == NULL)
|
|
{
|
|
debug_printf ("failed to allocate memory for _my_tls.locals.process_ident");
|
|
return;
|
|
}
|
|
strcpy (_my_tls.locals.process_ident, ident);
|
|
}
|
|
_my_tls.locals.process_logopt = logopt;
|
|
_my_tls.locals.process_facility = facility;
|
|
}
|
|
|
|
/* setlogmask: set the log priority mask and return previous mask.
|
|
If maskpri is zero, just return previous. */
|
|
int
|
|
setlogmask (int maskpri)
|
|
{
|
|
if (maskpri == 0)
|
|
return _my_tls.locals.process_logmask;
|
|
|
|
int old_mask = _my_tls.locals.process_logmask;
|
|
_my_tls.locals.process_logmask = maskpri & LOG_PRIMASK;
|
|
|
|
return old_mask;
|
|
}
|
|
|
|
/* Private class used to handle formatting of syslog message
|
|
It is named pass_handler because it does a two-pass handling of log
|
|
strings. The first pass counts the length of the string, and the second
|
|
one builds the string. */
|
|
|
|
class pass_handler
|
|
{
|
|
private:
|
|
FILE *fp_;
|
|
char *message_;
|
|
int total_len_;
|
|
|
|
void shutdown ();
|
|
|
|
/* Explicitly disallow copies */
|
|
pass_handler (const pass_handler &);
|
|
pass_handler & operator = (const pass_handler &);
|
|
|
|
public:
|
|
pass_handler ();
|
|
~pass_handler ();
|
|
|
|
int initialize (int);
|
|
|
|
int print (const char *,...);
|
|
int print_va (const char *, va_list);
|
|
char *get_message () const { return message_; }
|
|
void set_message (char *s) { message_ = s; *message_ = '\0'; }
|
|
};
|
|
|
|
pass_handler::pass_handler () : fp_ (0), message_ (0), total_len_ (0)
|
|
{
|
|
;
|
|
}
|
|
|
|
pass_handler::~pass_handler ()
|
|
{
|
|
shutdown ();
|
|
}
|
|
|
|
void
|
|
pass_handler::shutdown ()
|
|
{
|
|
if (fp_ != NULL)
|
|
{
|
|
fclose (fp_);
|
|
fp_ = 0;
|
|
}
|
|
}
|
|
|
|
int
|
|
pass_handler::initialize (int pass_number)
|
|
{
|
|
shutdown ();
|
|
if (pass_number)
|
|
return total_len_ + 1;
|
|
|
|
fp_ = fopen ("/dev/null", "wb");
|
|
if (fp_ == NULL)
|
|
{
|
|
debug_printf ("failed to open /dev/null");
|
|
return -1;
|
|
}
|
|
total_len_ = 0;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
pass_handler::print (const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start (ap, fmt);
|
|
int ret = print_va (fmt, ap);
|
|
va_end (ap);
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
pass_handler::print_va (const char *fmt, va_list list)
|
|
{
|
|
if (fp_ != NULL)
|
|
{
|
|
int len = vfprintf (fp_, fmt, list);
|
|
if (len < 0)
|
|
return -1;
|
|
total_len_ += len;
|
|
return 0;
|
|
}
|
|
else if (message_ != NULL)
|
|
{
|
|
char *printpos = &message_[strlen (message_)];
|
|
vsprintf (printpos, fmt, list);
|
|
return 0;
|
|
}
|
|
debug_printf ("FAILURE ! fp_ and message_ both 0!! ");
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* syslog: creates the log message and writes to system
|
|
* log (NT) or log file (95). FIXME. WinNT log error messages
|
|
* don't look pretty, but in order to fix this we have to
|
|
* embed resources in the code and tell the NT registry
|
|
* where we are, blech (what happens if we move ?).
|
|
* We could, however, add the resources in Cygwin and
|
|
* always point to that.
|
|
*/
|
|
|
|
extern "C" void
|
|
vsyslog (int priority, const char *message, va_list ap)
|
|
{
|
|
debug_printf ("%x %s", priority, message);
|
|
/* If the priority fails the current mask, reject */
|
|
if (((priority & LOG_PRIMASK) & _my_tls.locals.process_logmask) == 0)
|
|
{
|
|
debug_printf ("failing message %x due to priority mask %x",
|
|
priority, _my_tls.locals.process_logmask);
|
|
return;
|
|
}
|
|
|
|
/* Translate %m in the message to error text */
|
|
char *errtext = strerror (get_errno ());
|
|
int errlen = strlen (errtext);
|
|
int numfound = 0;
|
|
|
|
for (const char *cp = message; *cp; cp++)
|
|
if (*cp == '%' && cp[1] == 'm')
|
|
numfound++;
|
|
|
|
char *newmessage = (char *) alloca (strlen (message) +
|
|
(errlen * numfound) + 1);
|
|
|
|
if (newmessage == NULL)
|
|
{
|
|
debug_printf ("failed to allocate newmessage");
|
|
return;
|
|
}
|
|
|
|
char *dst = newmessage;
|
|
for (const char *cp2 = message; *cp2; cp2++)
|
|
if (*cp2 == '%' && cp2[1] == 'm')
|
|
{
|
|
cp2++;
|
|
strcpy (dst, errtext);
|
|
while (*dst)
|
|
dst++;
|
|
}
|
|
else
|
|
*dst++ = *cp2;
|
|
|
|
*dst = '\0';
|
|
message = newmessage;
|
|
|
|
/* Work out the priority type - we ignore the facility for now.. */
|
|
WORD eventType;
|
|
switch (LOG_PRI (priority))
|
|
{
|
|
case LOG_EMERG:
|
|
case LOG_ALERT:
|
|
case LOG_CRIT:
|
|
case LOG_ERR:
|
|
eventType = EVENTLOG_ERROR_TYPE;
|
|
break;
|
|
case LOG_WARNING:
|
|
eventType = EVENTLOG_WARNING_TYPE;
|
|
break;
|
|
case LOG_NOTICE:
|
|
case LOG_INFO:
|
|
case LOG_DEBUG:
|
|
eventType = EVENTLOG_INFORMATION_TYPE;
|
|
break;
|
|
default:
|
|
eventType = EVENTLOG_ERROR_TYPE;
|
|
break;
|
|
}
|
|
|
|
/* We need to know how long the buffer needs to be.
|
|
The only legal way I can see of doing this is to
|
|
do a vfprintf to /dev/null, and count the bytes
|
|
output, then do it again to a malloc'ed string. This
|
|
is ugly, slow, but prevents core dumps :-).
|
|
*/
|
|
pass_handler pass;
|
|
for (int pass_number = 0; pass_number < 2; ++pass_number)
|
|
{
|
|
int n = pass.initialize (pass_number);
|
|
if (n == -1)
|
|
return;
|
|
else if (n > 0)
|
|
pass.set_message ((char *) alloca (n));
|
|
|
|
/* Deal with ident_string */
|
|
if (_my_tls.locals.process_ident != NULL)
|
|
{
|
|
if (pass.print ("%s : ", _my_tls.locals.process_ident) == -1)
|
|
return;
|
|
}
|
|
if (_my_tls.locals.process_logopt & LOG_PID)
|
|
{
|
|
if (pass.print ("PID %u : ", getpid ()) == -1)
|
|
return;
|
|
}
|
|
|
|
if (!wincap.has_eventlog ())
|
|
{
|
|
/* Add a priority string - not needed for systems with
|
|
eventlog capability. */
|
|
switch (LOG_PRI (priority))
|
|
{
|
|
case LOG_EMERG:
|
|
pass.print ("%s : ", "LOG_EMERG");
|
|
break;
|
|
case LOG_ALERT:
|
|
pass.print ("%s : ", "LOG_ALERT");
|
|
break;
|
|
case LOG_CRIT:
|
|
pass.print ("%s : ", "LOG_CRIT");
|
|
break;
|
|
case LOG_ERR:
|
|
pass.print ("%s : ", "LOG_ERR");
|
|
break;
|
|
case LOG_WARNING:
|
|
pass.print ("%s : ", "LOG_WARNING");
|
|
break;
|
|
case LOG_NOTICE:
|
|
pass.print ("%s : ", "LOG_NOTICE");
|
|
break;
|
|
case LOG_INFO:
|
|
pass.print ("%s : ", "LOG_INFO");
|
|
break;
|
|
case LOG_DEBUG:
|
|
pass.print ("%s : ", "LOG_DEBUG");
|
|
break;
|
|
default:
|
|
pass.print ("%s : ", "LOG_ERR");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Print out the variable part */
|
|
if (pass.print_va (message, ap) == -1)
|
|
return;
|
|
|
|
}
|
|
const char *msg_strings[1];
|
|
char *total_msg = pass.get_message ();
|
|
int len = strlen (total_msg);
|
|
if (len != 0 && (total_msg[len - 1] == '\n'))
|
|
total_msg[len - 1] = '\0';
|
|
|
|
msg_strings[0] = total_msg;
|
|
|
|
if (wincap.has_eventlog ())
|
|
{
|
|
/* For NT, open the event log and send the message */
|
|
HANDLE hEventSrc = RegisterEventSourceA (NULL, (_my_tls.locals.process_ident != NULL) ?
|
|
_my_tls.locals.process_ident : CYGWIN_LOG_NAME);
|
|
if (hEventSrc == NULL)
|
|
{
|
|
debug_printf ("RegisterEventSourceA failed with %E");
|
|
return;
|
|
}
|
|
if (!ReportEventA (hEventSrc, eventType, 0, 0,
|
|
cygheap->user.sid (), 1, 0, msg_strings, NULL))
|
|
debug_printf ("ReportEventA failed with %E");
|
|
DeregisterEventSource (hEventSrc);
|
|
}
|
|
else
|
|
{
|
|
/* Under Windows 95, append the message to the log file */
|
|
char timestamp[24];
|
|
time_t ctime;
|
|
FILE *fp = fopen (get_win95_event_log_path (), "a");
|
|
if (fp == NULL)
|
|
{
|
|
debug_printf ("failed to open file %s",
|
|
get_win95_event_log_path ());
|
|
return;
|
|
}
|
|
strftime (timestamp, sizeof timestamp, "%Y-%m-%d %H:%M:%S : ",
|
|
localtime (&(ctime = time (NULL))));
|
|
|
|
/* Now to prevent several syslog messages from being
|
|
interleaved, we must lock the first byte of the file
|
|
This works on Win32 even if we created the file above.
|
|
*/
|
|
HANDLE fHandle = cygheap->fdtab[fileno (fp)]->get_handle ();
|
|
for (int i = 0;; i++)
|
|
if (LockFile (fHandle, 0, 0, 1, 0) == FALSE)
|
|
if (i == 3)
|
|
{
|
|
debug_printf ("failed to lock file %s", get_win95_event_log_path ());
|
|
fclose (fp);
|
|
return;
|
|
}
|
|
else
|
|
usleep (1000);
|
|
else
|
|
break;
|
|
fputs (timestamp, fp);
|
|
fputs (msg_strings[0], fp);
|
|
fputc ('\n', fp);
|
|
fclose (fp);
|
|
}
|
|
}
|
|
|
|
extern "C" void
|
|
syslog (int priority, const char *message, ...)
|
|
{
|
|
va_list ap;
|
|
va_start (ap, message);
|
|
vsyslog (priority, message, ap);
|
|
va_end (ap);
|
|
}
|
|
|
|
extern "C" void
|
|
closelog (void)
|
|
{
|
|
;
|
|
}
|