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)
 | 
						|
{
 | 
						|
  ;
 | 
						|
}
 |