* fhandler.cc (fhandler_base::set_no_inheritance): Always use
SetHandleInformation. * fhandler_disk_file.cc (fhandler_disk_file::lock): Always use UnlockFileEx/LockFileEx functions. * net.cc (fdsock): Don't bother to duplicate socket for inheritance. * sysconf.cc (get_nproc_values): Take NT for granted. (get_avphys): Ditto. * syslog.cc (WIN95_EVENT_LOG_PATH): Remove define. (get_win95_event_log_path): Remove. (vsyslog): Fix formatting. Take NT for granted. * wincap.cc: Remove has_lock_file_ex, has_signal_object_and_wait, has_eventlog, has_set_handle_information, has_set_handle_information_on_console_handles and supports_smp throughout. * wincap.h: Ditto.
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
/* syslog.cc
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||
2006 Red Hat, Inc.
|
||||
2006, 2007 Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
@ -28,22 +28,8 @@ details. */
|
||||
#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
|
||||
@ -286,212 +272,137 @@ try_connect_syslogd (int priority, const char *msg, int len)
|
||||
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 ((LOG_MASK (LOG_PRI (priority)) & _my_tls.locals.process_logmask) == 0)
|
||||
debug_printf ("%x %s", priority, message);
|
||||
/* If the priority fails the current mask, reject */
|
||||
if ((LOG_MASK (LOG_PRI (priority)) & _my_tls.locals.process_logmask) == 0)
|
||||
{
|
||||
debug_printf ("failing message %x due to priority mask %x",
|
||||
priority, _my_tls.locals.process_logmask);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add default facility if not in the given priority. */
|
||||
if (!(priority & LOG_FACMASK))
|
||||
priority |= _my_tls.locals.process_facility;
|
||||
|
||||
/* 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')
|
||||
{
|
||||
debug_printf ("failing message %x due to priority mask %x",
|
||||
priority, _my_tls.locals.process_logmask);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add default facility if not in the given priority. */
|
||||
if (!(priority & LOG_FACMASK))
|
||||
priority |= _my_tls.locals.process_facility;
|
||||
|
||||
/* 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] = '\0';
|
||||
|
||||
msg_strings[0] = total_msg;
|
||||
|
||||
if (_my_tls.locals.process_logopt & LOG_PERROR)
|
||||
{
|
||||
write (STDERR_FILENO, total_msg, len);
|
||||
write (STDERR_FILENO, "\n", 1);
|
||||
}
|
||||
|
||||
int fd;
|
||||
if ((fd = try_connect_syslogd (priority, total_msg, len + 1)) >= 0)
|
||||
;
|
||||
else 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);
|
||||
cp2++;
|
||||
strcpy (dst, errtext);
|
||||
while (*dst)
|
||||
dst++;
|
||||
}
|
||||
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))));
|
||||
*dst++ = *cp2;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
*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;
|
||||
}
|
||||
|
||||
/* 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] = '\0';
|
||||
|
||||
msg_strings[0] = total_msg;
|
||||
|
||||
if (_my_tls.locals.process_logopt & LOG_PERROR)
|
||||
{
|
||||
write (STDERR_FILENO, total_msg, len);
|
||||
write (STDERR_FILENO, "\n", 1);
|
||||
}
|
||||
|
||||
int fd;
|
||||
if ((fd = try_connect_syslogd (priority, total_msg, len + 1)) < 0)
|
||||
{
|
||||
/* If syslogd isn't present, 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);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
|
Reference in New Issue
Block a user