This is the mail archive of the cygwin-developers@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Egor's daemon


Attached is a slightly reworked daemon that will not impact 95 in speed
(well at dll load for non-forked process's it will, but not after that
first request).

Egors original message with changelogs describing this beast is
available
http://sources.redhat.com/ml/cygwin-patches/2001-q1/msg00260.html here.

I've altered the layout slightly - I consider the daemon more core than
(say) cygcheck, so I placed it all in cygwin.

The point of all this is that while this daemon won't run on 95, 95
users won't suffer *should* it get added post 1.3.3....

Rob
? currentstate.patch
? cygserver.cc
? cygserver.cygwin.ChangeLog
? cygserver.diff
? cygserver.utils.ChangeLog
? cygserver_client.cc
? daemon.patch
? fhandler_ums.cc
? host_dependent.cc
? mutexsviacriticalsections.patch
? pthchange
? umsdos_gen.h
? virtualquery.patch
? include/cygwin/cygserver.h
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/Makefile.in,v
retrieving revision 1.60
diff -u -p -r1.60 Makefile.in
--- Makefile.in	2001/09/11 20:01:00	1.60
+++ Makefile.in	2001/09/12 11:47:41
@@ -116,13 +116,13 @@ MALLOC_OFILES=@MALLOC_OFILES@
 
 DLL_IMPORTS:=$(w32api_lib)/libkernel32.a
 
-DLL_OFILES:=assert.o autoload.o cygheap.o dcrt0.o debug.o delqueue.o dir.o \
+DLL_OFILES:=assert.o autoload.o cygheap.o cygserver_client.o dcrt0.o debug.o delqueue.o dir.o \
 	dlfcn.o dll_init.o dtable.o environ.o  errno.o exceptions.o exec.o \
 	external.o fcntl.o fhandler.o fhandler_clipboard.o fhandler_console.o \
 	fhandler_dsp.o fhandler_floppy.o fhandler_mem.o fhandler_random.o \
 	fhandler_raw.o fhandler_serial.o fhandler_socket.o fhandler_tape.o \
 	fhandler_termios.o fhandler_tty.o fhandler_windows.o fhandler_zero.o \
-	fork.o glob.o grp.o heap.o init.o ioctl.o localtime.o malloc.o \
+	fork.o glob.o grp.o heap.o host_dependent.o init.o ioctl.o localtime.o malloc.o \
 	miscfuncs.o mmap.o net.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o \
 	pthread.o regexp.o regerror.o regsub.o registry.o resource.o scandir.o \
 	sched.o sec_acl.o sec_helper.o security.o select.o shared.o shortcut.o signal.o sigproc.o \
@@ -144,14 +144,17 @@ install_host=@install_host@
 
 all: new-$(DLL_NAME) $(all_host) all_target
 
-all_target: $(LIBGMON_A) $(LIB_NAME) automode.o binmode.o textmode.o
+all_target: $(LIBGMON_A) $(LIB_NAME) automode.o binmode.o textmode.o cygserver.exe
 
 all_host: new-$(LIB_NAME) cygrun.exe
 
 force:
 
-install: install-libs install-headers $(install_host) $(install_target)
+install: install-bin install-libs install-headers $(install_host) $(install_target)
 
+install-bin: cygserver.exe
+	$(INSTALL_PROGRAM) cygserver.exe $(bindir)/cygserver.exe	
+
 install-libs: $(LIB_NAME)
 	$(INSTALL_DATA) new-$(DLL_NAME) $(bindir)/$(DLL_NAME); \
 	for i in $(LIB_NAME) $(GMON_START) $(LIBGMON_A) automode.o binmode.o textmode.o ; do \
@@ -218,6 +221,14 @@ winver_stamp: mkvers.sh include/cygwin/v
 cygrun.exe : cygrun.o $(LIB_NAME) $(w32api_lib)/libuser32.a \
 	     $(w32api_lib)/libshell32.a $(w32api_lib)/libkernel32.a
 	$(CC) -nodefaultlibs -o $@ $^
+
+cygserver.exe: cygserver.cc host_dependent.cc smallprint.o
+ifdef VERBOSE
+	$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS)
+else
+	@echo $(CXX) -o $@ ${wordlist 1,3,$^} ${filter-out -B%, $(MINGW_CXXFLAGS) $(MINGW_LDFLAGS)};\
+	$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS)
+endif
 
 #
 
Index: dcrt0.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/dcrt0.cc,v
retrieving revision 1.108
diff -u -p -r1.108 dcrt0.cc
--- dcrt0.cc	2001/09/11 08:15:39	1.108
+++ dcrt0.cc	2001/09/12 11:47:42
@@ -35,6 +35,7 @@ details. */
 #include "cygwin_version.h"
 #include "dll_init.h"
 #include "host_dependent.h"
+#include "cygwin/cygserver.h"
 
 #define MAX_AT_FILE_LEVEL 10
 
@@ -155,94 +156,8 @@ do_global_ctors (void (**in_pfunc)(), in
     atexit (do_global_dtors);
 }
 
-/* remember the type of Win32 OS being run for future use. */
-os_type NO_COPY os_being_run;
-char NO_COPY osname[40];
-bool iswinnt;
-
-/* set_os_type: Set global variable os_being_run with type of Win32
-   operating system being run.  This information is used internally
-   to manage the inconsistency in Win32 API calls between Win32 OSes. */
-/* Cygwin internal */
-static void
-set_os_type ()
-{
-  OSVERSIONINFO os_version_info;
-  const char *os;
-
-  memset (&os_version_info, 0, sizeof os_version_info);
-  os_version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
-  GetVersionEx (&os_version_info);
-
-  iswinnt = 0;
-  switch (os_version_info.dwPlatformId)
-    {
-      case VER_PLATFORM_WIN32_NT:
-	os_being_run = winNT;
-	os = "NT";
-	iswinnt = 1;
-	break;
-      case VER_PLATFORM_WIN32_WINDOWS:
-	if (os_version_info.dwMinorVersion == 0)
-	  {
-	    os_being_run = win95;
-	    os = "95";
-	  }
-	else if (os_version_info.dwMinorVersion < 90)
-	  {
-	    os_being_run = win98;
-	    os = "98";
-	  }
-	else /* os_version_info.dwMinorVersion == 90 */
-	  {
-	    os_being_run = winME;
-	    os = "ME";
-	  }
-	break;
-      default:
-	os_being_run = unknown;
-	os = "??";
-	break;
-    }
-  __small_sprintf (osname, "%s-%d.%d", os, os_version_info.dwMajorVersion,
-		   os_version_info.dwMinorVersion);
-}
-
 host_dependent_constants NO_COPY host_dependent;
 
-/* Constructor for host_dependent_constants.  */
-
-void
-host_dependent_constants::init ()
-{
-  extern DWORD chunksize;
-  /* fhandler_disk_file::lock needs a platform specific upper word
-     value for locking entire files.
-
-     fhandler_base::open requires host dependent file sharing
-     attributes.  */
-
-  switch (os_being_run)
-    {
-    case winNT:
-      win32_upper = 0xffffffff;
-      shared = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
-      break;
-
-    case winME:
-    case win98:
-    case win95:
-    case win32s:
-      win32_upper = 0x00000000;
-      shared = FILE_SHARE_READ | FILE_SHARE_WRITE;
-      chunksize = 32 * 1024 * 1024;
-      break;
-
-    default:
-      api_fatal ("unrecognized system type");
-    }
-}
-
 /*
  * Replaces -@file in the command line with the contents of the file.
  * There may be multiple -@file's in a single command line
@@ -777,6 +692,8 @@ dll_crt0_1 ()
 
   /* Initialize signal/subprocess handling. */
   sigproc_init ();
+
+  cygserver_init ();
 
   /* Connect to tty. */
   tty_init ();
Index: fhandler.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler.h,v
retrieving revision 1.76
diff -u -p -r1.76 fhandler.h
--- fhandler.h	2001/09/11 20:01:00	1.76
+++ fhandler.h	2001/09/12 11:47:43
@@ -832,6 +832,8 @@ public:
   off_t lseek (off_t, int) { return 0; }
   select_record *select_read (select_record *s);
   int ready_for_read (int fd, DWORD howlong, int ignra);
+
+  int cygserver_attach_tty (HANDLE*, HANDLE*);
 };
 
 class fhandler_pty_master: public fhandler_tty_common
Index: fhandler_tty.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_tty.cc,v
retrieving revision 1.47
diff -u -p -r1.47 fhandler_tty.cc
--- fhandler_tty.cc	2001/09/07 21:32:04	1.47
+++ fhandler_tty.cc	2001/09/12 11:47:44
@@ -25,6 +25,7 @@ details. */
 #include "pinfo.h"
 #include "cygheap.h"
 #include "shared_info.h"
+#include "cygwin/cygserver.h"
 
 /* Tty master stuff */
 
@@ -523,42 +524,74 @@ fhandler_tty_slave::open (const char *, 
       return 0;
     }
 
-  HANDLE tty_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
-				     get_ttyp ()->master_pid);
-  if (tty_owner == NULL)
-    {
-      termios_printf ("can't open tty (%d) handle process %d",
-		      ttynum, get_ttyp ()->master_pid);
-      __seterrno ();
-      return 0;
-    }
+  HANDLE from_master_local, to_master_local;
 
-  HANDLE nh;
-  if (!DuplicateHandle (tty_owner, get_ttyp ()->from_master, hMainProc, &nh, 0, TRUE,
-			DUPLICATE_SAME_ACCESS))
+  if (!cygserver_running || !cygserver_attach_tty ( &from_master_local, &to_master_local))
     {
-      termios_printf ("can't duplicate input, %E");
-      __seterrno ();
-      return 0;
-    }
-  set_io_handle (nh);
-  ProtectHandle1 (nh, from_pty);
-  termios_printf ("duplicated from_master %p->%p from tty_owner %p",
-		  get_ttyp ()->from_master, nh, tty_owner);
-  if (!DuplicateHandle (tty_owner, get_ttyp ()->to_master, hMainProc, &nh, 0, TRUE,
-			DUPLICATE_SAME_ACCESS))
-    {
-      termios_printf ("can't duplicate output, %E");
-      __seterrno ();
-      return 0;
-    }
-  set_output_handle (nh);
-  ProtectHandle1 (nh, to_pty);
-  CloseHandle (tty_owner);
+      termios_printf ("cannot dup handles via server. using old method.");
 
+      HANDLE tty_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
+				         get_ttyp ()->master_pid);
+      if (tty_owner == NULL)
+        {
+          termios_printf ("can't open tty (%d) handle process %d",
+	 	          ttynum, get_ttyp ()->master_pid);
+          __seterrno ();
+          return 0;
+        }
+
+      if (!DuplicateHandle (tty_owner, get_ttyp ()->from_master, 
+			  hMainProc, &from_master_local, 0, TRUE,
+			    DUPLICATE_SAME_ACCESS))
+        {
+          termios_printf ("can't duplicate input, %E");
+          __seterrno ();
+          return 0;
+        }
+      termios_printf ("duplicated from_master %p->%p from tty_owner %p",
+		     get_ttyp ()->from_master, from_master_local, tty_owner);
+
+      if (!DuplicateHandle (tty_owner, get_ttyp ()->to_master, 
+			  hMainProc, &to_master_local, 0, TRUE,
+			  DUPLICATE_SAME_ACCESS))
+        {
+          termios_printf ("can't duplicate output, %E");
+          __seterrno ();
+          return 0;
+        }
+      termios_printf ("duplicated to_master %p->%p from tty_owner %p",
+      		     get_ttyp ()->to_master, to_master_local, tty_owner);
+      CloseHandle (tty_owner);
+    }
+
+  set_io_handle (from_master_local);
+  ProtectHandle1 (from_master_local, from_pty);
+  set_output_handle (to_master_local);
+  ProtectHandle1 (to_master_local, to_pty);
+
   set_open_status ();
   termios_printf ("tty%d opened", ttynum);
 
+  return 1;
+}
+
+int
+fhandler_tty_slave::cygserver_attach_tty (HANDLE* from_master_ptr,
+                                        HANDLE* to_master_ptr)
+{
+  if (!from_master_ptr || !to_master_ptr)
+    return 0;
+
+  struct request_attach_tty req;
+  INIT_REQUEST (req, CYGSERVER_REQUEST_ATTACH_TTY);
+  req.pid = GetCurrentProcessId ();
+  req.master_pid = get_ttyp ()->master_pid;
+  req.from_master = get_ttyp ()->from_master;
+  req.to_master = get_ttyp ()->to_master;
+  if (cygserver_request ((struct request_header*) &req) != 0)
+    return 0;
+  *from_master_ptr = req.from_master;
+  *to_master_ptr = req.to_master;
   return 1;
 }
 
Index: fork.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fork.cc,v
retrieving revision 1.62
diff -u -p -r1.62 fork.cc
--- fork.cc	2001/09/11 08:15:39	1.62
+++ fork.cc	2001/09/12 11:47:44
@@ -35,7 +35,7 @@ static int npid_max;
 static pid_t fork_pids[100];
 #endif
 
-DWORD NO_COPY chunksize = 0;
+extern DWORD chunksize;
 /* Timeout to wait for child to start, parent to init child, etc.  */
 /* FIXME: Once things stabilize, bump up to a few minutes.  */
 #define FORK_WAIT_TIMEOUT (300 * 1000)     /* 300 seconds */
Index: host_dependent.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/host_dependent.h,v
retrieving revision 1.2
diff -u -p -r1.2 host_dependent.h
--- host_dependent.h	2001/06/24 22:26:51	1.2
+++ host_dependent.h	2001/09/12 11:47:44
@@ -28,3 +28,4 @@ class host_dependent_constants
 };
 
 extern host_dependent_constants host_dependent;
+extern void set_os_type();
Index: tty.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/tty.cc,v
retrieving revision 1.28
diff -u -p -r1.28 tty.cc
--- tty.cc	2001/09/06 04:41:59	1.28
+++ tty.cc	2001/09/12 11:47:44
@@ -23,6 +23,7 @@ details. */
 #include "sync.h"
 #include "sigproc.h"
 #include "pinfo.h"
+#include "cygwin/cygserver.h"
 #include "shared_info.h"
 
 extern fhandler_tty_master *tty_master;
@@ -393,6 +394,7 @@ tty::common_init (fhandler_pty_master *p
   /* Allow the others to open us (for handle duplication) */
 
   if ((iswinnt) &&
+      !cygserver_running &&
       (SetKernelObjectSecurity (hMainProc, DACL_SECURITY_INFORMATION,
 			       get_null_sd ()) == FALSE))
     small_printf ("Can't set process security, %E");
Index: winsup.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/winsup.h,v
retrieving revision 1.68
diff -u -p -r1.68 winsup.h
--- winsup.h	2001/09/09 16:52:37	1.68
+++ winsup.h	2001/09/12 11:47:45
@@ -72,6 +72,8 @@ extern bool iswinnt;
 enum codepage_type {ansi_cp, oem_cp};
 extern codepage_type current_codepage;
 
+extern int cygserver_running;
+
 /* Used to check if Cygwin DLL is dynamically loaded. */
 extern int dynamically_loaded;
 
/* cygserver.cc

   Copyright 2001 Red Hat Inc.

   Written by Egor Duda <deo@logos-m.ru>

   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 <errno.h>
#include <stdio.h>
#include <windows.h>

#include "cygwin/cygserver.h"

SECURITY_ATTRIBUTES sec_none_nih, sec_all_nih;
GENERIC_MAPPING pipe_mapping;

DWORD request_count = 0;

void
init_security ()
{
  static SECURITY_DESCRIPTOR sd;

  InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
  SetSecurityDescriptorDacl (&sd, TRUE, 0, FALSE);

  sec_none_nih.nLength = sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES);
  sec_none_nih.bInheritHandle = sec_all_nih.bInheritHandle = FALSE;
  sec_none_nih.lpSecurityDescriptor = NULL;
  sec_all_nih.lpSecurityDescriptor = &sd;

  pipe_mapping.GenericRead = FILE_READ_DATA;
  pipe_mapping.GenericWrite = FILE_WRITE_DATA;
  pipe_mapping.GenericExecute = 0;
  pipe_mapping.GenericAll = FILE_READ_DATA | FILE_WRITE_DATA;
}

BOOL
setup_privileges ()
{
  BOOL rc, ret_val;
  HANDLE hToken = NULL;
  TOKEN_PRIVILEGES sPrivileges;

  rc = OpenProcessToken ( GetCurrentProcess() , TOKEN_ALL_ACCESS , &hToken ) ;
  if ( !rc )
    {
      printf ( "error opening process token (%lu)\n", GetLastError () );
      ret_val = FALSE;
      goto out;
    }
  rc = LookupPrivilegeValue ( NULL, SE_DEBUG_NAME, &sPrivileges.Privileges[0].Luid );
  if ( !rc )
    {
      printf ( "error getting prigilege luid (%lu)\n", GetLastError () );
      ret_val = FALSE;
      goto out;
    }
  sPrivileges.PrivilegeCount = 1 ;
  sPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ;
  rc = AdjustTokenPrivileges ( hToken, FALSE, &sPrivileges, 0, NULL, NULL ) ;
  if ( !rc )
    {
      printf ( "error adjusting prigilege level. (%lu)\n", GetLastError () );
      ret_val = FALSE;
      goto out;
    }

  ret_val = TRUE;

out:
  CloseHandle ( hToken );
  return ret_val;
}

void
get_version (struct request_header* req)
{
  struct request_get_version* request = (struct request_get_version*) req;
  if (req->cb != sizeof (struct request_get_version))
    {
      req->error_code = EINVAL;
      return;
    }
  req->error_code = 0;
  request->major = CYGWIN_SERVER_VERSION_MAJOR;
  request->api   = CYGWIN_SERVER_VERSION_API;
  request->minor = CYGWIN_SERVER_VERSION_MINOR;
  request->patch = CYGWIN_SERVER_VERSION_PATCH;
}

int
check_and_dup_handle (HANDLE from_process, HANDLE to_process,
		      HANDLE from_process_token,
                      DWORD access,
                      HANDLE from_handle,
                      HANDLE* to_handle_ptr)
{
  HANDLE local_handle = NULL;
  int ret_val = EACCES;
  char sd_buf [1024];
  PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR) &sd_buf;
  DWORD bytes_needed;
  PRIVILEGE_SET ps;
  DWORD ps_len = sizeof (ps);
  BOOL status;

  if (!DuplicateHandle (from_process, from_handle,
	                GetCurrentProcess (), &local_handle,
                        0, FALSE,
                        DUPLICATE_SAME_ACCESS))
    {
      printf ( "error getting handle(%d) to server (%lu)\n", from_handle, GetLastError ());
      goto out;
    }

  if (!GetKernelObjectSecurity (local_handle,
  			        OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION	| DACL_SECURITY_INFORMATION,
				sd, sizeof (sd_buf), &bytes_needed))
    {
      printf ( "error getting handle SD (%lu)\n", GetLastError ());
      goto out;
    }

  MapGenericMask (&access, &pipe_mapping);

  if (!AccessCheck (sd, from_process_token, access, &pipe_mapping,
  		    &ps, &ps_len, &access, &status))
    {
      printf ( "error checking access rights (%lu)\n", GetLastError ());
      goto out;
    }

  if (!status)
    {
      printf ( "access to object denied\n");
      goto out;
    }

  if (!DuplicateHandle (from_process, from_handle,
	                to_process, to_handle_ptr,
                        access, FALSE, 0))
    {
      printf ( "error getting handle to client (%lu)\n", GetLastError ());
      goto out;
    }

  ret_val = 0;
                    
out:
  if (local_handle)
    CloseHandle (local_handle);

  return (ret_val);
}

void
attach_tty (HANDLE pipe, struct request_header* req)
{
  HANDLE from_process_handle = NULL;
  HANDLE to_process_handle = NULL;
  HANDLE token_handle = NULL;
  DWORD rc;

  struct request_attach_tty* request = (struct request_attach_tty*) req;

  if (req->cb != sizeof (struct request_attach_tty))
    {
      req->error_code = EINVAL;
      return;
    }

#ifdef DEBUG
  printf ("%d:(%d,%d) -> %d\n", request->master_pid,
  	  			request->from_master, request->to_master,
				request->pid);
#endif

  from_process_handle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, request->master_pid);
  to_process_handle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, request->pid);
  if (!from_process_handle || !to_process_handle)
    {
      printf ("error opening process (%lu)\n", GetLastError ());
      req->error_code = EACCES;
      goto out;
    }

  ImpersonateNamedPipeClient (pipe);
    
  rc = OpenThreadToken (GetCurrentThread (),
  			TOKEN_QUERY,
                        TRUE,
			&token_handle);
  RevertToSelf ();

  if (!rc)
    {
      printf ("error opening thread token (%lu)\n", GetLastError ());
      req->error_code = EACCES;
      goto out;
    }

  if (check_and_dup_handle (from_process_handle, to_process_handle,
                            token_handle,
                            GENERIC_READ,
                            request->from_master,
                            &request->from_master) != 0)
    {
      printf ("error duplicating from_master handle (%lu)\n", GetLastError ());
      req->error_code = EACCES;
      goto out;
    }

  if (request->to_master)
    {
      if (check_and_dup_handle (from_process_handle, to_process_handle,
				token_handle,
				GENERIC_WRITE,
				request->to_master,
				&request->to_master) != 0)
	{
	  printf ("error duplicating to_master handle (%lu)\n", GetLastError ());
	  req->error_code = EACCES;
	  goto out;
	}
    }

#ifdef DEBUG
  printf ("%d -> %d(%d,%d)\n", request->master_pid, request->pid,
  	  			request->from_master, request->to_master);
#endif

  req->error_code = 0;

out:
  if (from_process_handle)
    CloseHandle (from_process_handle);
  if (to_process_handle)
    CloseHandle (to_process_handle);
  if (token_handle)
    CloseHandle (token_handle);
}

int
process_request (HANDLE pipe, struct request_header* req)
{
  if (!req) return -1;
  switch (req->req_id)
    {
    case CYGSERVER_REQUEST_GET_VERSION:
      get_version (req);
      break;
    case CYGSERVER_REQUEST_ATTACH_TTY:
      attach_tty (pipe, req);
      break;
    default:
      req->error_code = ENOSYS;
      break;
    }
}

DWORD
process_client (HANDLE pipe)
{
  DWORD bytes_read, bytes_written, rc;
  char request_buffer [MAX_REQUEST_SIZE];
  struct request_header* req_ptr = (struct request_header*) &request_buffer;

  rc = ReadFile (pipe, &request_buffer,
                 sizeof (struct request_header), &bytes_read, NULL);
  if (!rc || bytes_read != sizeof (struct request_header))
    {
      printf ("error reading from pipe (%lu)\n", GetLastError ());
      goto out;
    }

  if (req_ptr->cb > MAX_REQUEST_SIZE ||
      req_ptr->cb < sizeof (struct request_header))
    {
      printf ("broken request, size (%lu)\n", req_ptr->cb);
      goto out;
    }
  rc = ReadFile (pipe, ((char*) &request_buffer) + sizeof (struct request_header),
                 req_ptr->cb - sizeof (struct request_header),
                 &bytes_read, NULL);
  if (!rc || bytes_read != req_ptr->cb - sizeof (struct request_header))
    {
      printf ("error reading from pipe (%lu)\n", GetLastError ());
      goto out;
    }

  process_request (pipe, req_ptr); 

  rc = WriteFile (pipe, &request_buffer, req_ptr->cb, &bytes_written, NULL);
  if (!rc || bytes_written != req_ptr->cb)
    {
      printf ("error writing to pipe (%lu)\n", GetLastError ());
      goto out;
    }

out:
  FlushFileBuffers (pipe);
  DisconnectNamedPipe (pipe);
  CloseHandle ( pipe );
  return 0;
}

int
serve_requests ()
{
  char pipe_name [MAX_PATH];

  init_security ();

  sprintf (pipe_name, "\\\\.\\pipe\\cygwin_lpc");

  while (TRUE)
    {
      HANDLE pipe = NULL;
      HANDLE thread = NULL;
      DWORD tid;

      pipe = CreateNamedPipe (pipe_name,
			      PIPE_ACCESS_DUPLEX,
			      PIPE_TYPE_BYTE | PIPE_WAIT,
			      PIPE_UNLIMITED_INSTANCES,
			      0, 0, 1000,
			      &sec_all_nih );
      if (pipe == INVALID_HANDLE_VALUE)
        {
	  printf ("error creating pipe (%lu)\n.", GetLastError ());
          goto err;
        }

      if ( !ConnectNamedPipe ( pipe, NULL ) &&
           GetLastError () != ERROR_PIPE_CONNECTED)
        {
	  printf ("error connecting to pipe (%lu)\n.", GetLastError ());
          goto err;
        }

#ifdef DEBUG
      printf ( "request received. total:%8d\n", ++request_count);
#endif

      thread = CreateThread (NULL, 0,
                             (LPTHREAD_START_ROUTINE) process_client,
                             pipe,
			     0,
			     &tid);
      if (!thread)
        {
	  printf ("error creating thread (%lu)\n.", GetLastError ());
          goto err;
        }
      CloseHandle (thread);
      continue;

    err:
      if (pipe && pipe != INVALID_HANDLE_VALUE)
        CloseHandle (pipe);
      Sleep (100);
    }  
  return 0;
}

int
main (int argc, char** argv)
{
  init_security ();
  setup_privileges ();
  serve_requests ();
}
/* cygserver_client.cc

   Copyright 2001 Red Hat Inc.

   Written by Egor Duda <deo@logos-m.ru>

   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 "cygwin/cygserver.h"
#include "security.h"

int cygserver_running;

const char* pipe_name = "\\\\.\\pipe\\cygwin_lpc";

int
cygserver_request (struct request_header* req)
{
  HANDLE pipe = NULL;
  int ret_val = -1;
  DWORD bytes_read, bytes_written;

  if (!cygserver_running)
    return ret_val;

  if (!req || req->cb > MAX_REQUEST_SIZE)
    goto out;

  while (TRUE)
    {
      pipe = CreateFile (pipe_name,
			 GENERIC_READ | GENERIC_WRITE,
			 FILE_SHARE_READ | FILE_SHARE_WRITE,
			 &sec_all_nih,
			 OPEN_EXISTING,
			 0,
			 NULL);
      if (pipe != INVALID_HANDLE_VALUE)
        break;

      if (GetLastError () != ERROR_PIPE_BUSY)
        goto out;
      if (!WaitNamedPipe (pipe_name, 20000))
        system_printf ( "error connecting to server pipe (%lu)\n", GetLastError () );
    }

  if (!WriteFile (pipe, req, req->cb, &bytes_written, NULL) ||
      bytes_written != req->cb)
    goto out;

  if (!ReadFile (pipe, req, sizeof (struct request_header),
                 &bytes_read, NULL) ||
      bytes_read != sizeof (struct request_header) ||
      req->cb > MAX_REQUEST_SIZE ||
      req->cb < sizeof (struct request_header) ||
      !ReadFile (pipe, ((char*) req) + sizeof (struct request_header),
                 req->cb - sizeof (struct request_header),
                 &bytes_read, NULL) ||
      bytes_read != req->cb - sizeof (struct request_header))
    goto out;

  ret_val = req->error_code;

out:
  if (pipe && pipe != INVALID_HANDLE_VALUE)
    CloseHandle (pipe);
  return (ret_val);
}

BOOL
check_cygserver_available ()
{
  BOOL ret_val = FALSE;
  HANDLE pipe = CreateFile (pipe_name,
			    GENERIC_READ | GENERIC_WRITE,
			    FILE_SHARE_READ | FILE_SHARE_WRITE,
			    &sec_all_nih,
			    OPEN_EXISTING,
			    0,
			    NULL);
  if (pipe != INVALID_HANDLE_VALUE || GetLastError () != ERROR_PIPE_BUSY)
    ret_val = TRUE;

  if (pipe && pipe != INVALID_HANDLE_VALUE)
    CloseHandle (pipe);

  return (ret_val);
}

void
cygserver_init ()
{
  int rc;
  struct request_get_version request;

  INIT_REQUEST (request, CYGSERVER_REQUEST_GET_VERSION);
  rc = cygserver_request ((struct request_header*) &request);
  if (rc < 0)
    cygserver_running = FALSE;
  else if (rc > 0)
    api_fatal ( "error connecting to cygwin server. error: %d", rc );
  else if (request.major != CYGWIN_SERVER_VERSION_MAJOR ||
	   request.api != CYGWIN_SERVER_VERSION_API ||
	   request.minor > CYGWIN_SERVER_VERSION_MINOR)
    api_fatal ( "incompatible version of cygwin server.\n\
 client version %d.%d.%d.%d, server version%d.%d.%d.%d",
    CYGWIN_SERVER_VERSION_MAJOR,
    CYGWIN_SERVER_VERSION_API,
    CYGWIN_SERVER_VERSION_MINOR,
    CYGWIN_SERVER_VERSION_PATCH,
    request.major,
    request.api,
    request.minor,
    request.patch );
  else
    cygserver_running = TRUE;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]