/* mail slot version of ndc for windows NT/Win 95 by l. kahn
 (c) 1996 */

#include <stdio.h>
#include <windows.h>
#include <io.h>
#include <process.h>
#include "../conf/portability.h"

void usage();
void start_up_bind();

void
main(argc, argv)
	int argc;
	char *argv[];
{

#define              SZ_NAME_BUF 30
char    inbuf[40];
char    outbuf[120];
char    commonbuf[100];
DWORD   bytesRead, bytesWritten;
BOOL    ret, ret2, ret3;
#define               SZ_SLOT_NAME_BUF 50
UCHAR   ucSlotNameBuf[SZ_SLOT_NAME_BUF] = "";
LPTSTR  lpszSlotName = (LPTSTR)&ucSlotNameBuf;
BOOL onnt = TRUE;
OSVERSIONINFO myver;
UCHAR   ucOperation = '\0';
UCHAR   ucMchNameBuf[SZ_NAME_BUF] = "";
LPTSTR  lpszMchName = (LPTSTR)&ucMchNameBuf;
char myname[100];
DWORD nsize = 99;
char myname2[102];
HANDLE outslot;
HANDLE inslot;
BOOL running;
char tickbuf[20];
BOOL onlocalmachine = FALSE;
BOOL rv = FALSE;

myver.dwOSVersionInfoSize = sizeof(myver);
(void)GetVersionEx(&myver);

if (myver.dwPlatformId != VER_PLATFORM_WIN32_NT)
   onnt = FALSE;


  rv = GetComputerName((char *)&myname,&nsize);
  if (rv != TRUE)
    { 
      fprintf(stderr,"GetComputerName failed %d \n",WSAGetLastError());
      exit(1);
    }

  strcpy(myname2, "\\\\");
  strcat(myname2,myname);

	if (argc < 2 || argc > 3) {
		usage();
		exit(1);
	}

   if (argc == 2)
     strcpy(lpszMchName,myname2);
   else
    {
     strcpy(lpszMchName,argv[2]);
    }



  onlocalmachine = TRUE;
  if (strcmp(myname2,lpszMchName) != 0)
       onlocalmachine = FALSE;
    
  strcpy(lpszSlotName,lpszMchName);
  strcat(lpszSlotName,"\\mailslot\\sd_bind");

  outbuf[0] = ucOperation;
  outbuf[1] = '\0';

  // because of a bug in the mailbox stuff we have to put the tickcount as the first param otherwise it gets the
  // message once for each bound transport...
   strcpy(commonbuf,myname);
   strcat(commonbuf," ");
   strcat(commonbuf,"sd_ndc ");


	if (!stricmp(argv[1], "start"))
          {
           BOOL running = FALSE;
           // lgk first try status command to see if already running
           // so we don't start it again.
           if (onnt)
             {
               fprintf(stderr,"Use \"ndc start\" to start the service under Windows NT!\n");
               fprintf(stderr,"\"ndc95 start\" is only for use under Windows 95!\n");
               exit(1);
             }

            if (!onlocalmachine)
             {
               fprintf(stderr,"You cannot start up bind on a remote machine using ndc95.\n");
               fprintf(stderr,"This is due to restrictions with WIN95.\n");
               fprintf(stderr,"Please log on %s directly to start bind!\n",lpszMchName);
               exit(1);
             }

             // open our slot for responses 
             // open our mail slot no security needed on incomming...
             inslot = CreateMailslot("\\\\.\\mailslot\\sd_ndc",0,7000,NULL);

             if (inslot)
               {
                // possibley running .. not sure yet as this returns true if checking a remote machine
                strcpy(outbuf,commonbuf);
                strcat(outbuf,"status ");
                sprintf(tickbuf,"%d",GetTickCount());
                strcat(outbuf,tickbuf);
                outslot = CreateFile(lpszSlotName,GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,
                               FILE_ATTRIBUTE_NORMAL,NULL);

                 // outslot should always open regardless
                 if (outslot == INVALID_HANDLE_VALUE)
                  {
     	          fprintf(stderr, "Error: Couldn't create mail slot (outgoing) %s ... errorcode = %d \n",lpszSlotName,GetLastError());
                    CloseHandle(inslot);
                    exit(1);
                  }

                  // go on now both mail slots are open
                  ret = FALSE;
                  ret2 = FALSE;
                  ret = WriteFile(
                     outslot,       // file to write to
                     &outbuf,         // address of output buffer
                     strlen(outbuf) + 1, // number of bytes to write
                     &bytesWritten,  // number of bytes written
                     NULL);          // overlapped stuff, not needed
    
                 if (ret) // wrote ok if id didn't the server may not be runing even though the inslot 
                          // opened ok due to the fact that it may be on a remote machine..
                   {
                    ret2 = ReadFile(
                        inslot,     // file to read from
                        &inbuf,          // address of input buffer
                        sizeof(inbuf),  // number of bytes to read
                        &bytesRead,     // number of bytes read
                        NULL);          // overlapped stuff, not needed

                   // ok if ret2 is true it means it is already running
                   if (ret2)
                     {
                      running = TRUE;
                      }
                   else // not running
                    {
                     running = FALSE;
                    }

                  } // ret ok or not

                 else // write did't work not running
                 {
                  running = FALSE;
                 }

                } // inslot opened ok or not

              else // open inslot didn't work .. not running
                 {
                  running = FALSE;
                 }

            // now based on running handle it
            if (!running)
             {
              // set to start
              CloseHandle(inslot);
              CloseHandle(outslot);
              start_up_bind();
	      fprintf(stdout, "Name Server Started\n");
	      exit(0);
             }
            else // already running
             {
     	      fprintf(stderr, "Domain Name Service already running\n");
              CloseHandle(inslot);
              CloseHandle(outslot);
              exit(1);
             }
   } // end of start

 else if (!stricmp(argv[1], "restart"))
   {
     if (onnt)
       {
          fprintf(stderr,"Use \"ndc restart\" to restart the service under Windows NT!\n");
          fprintf(stderr,"\"ndc95 restart\" is only for use under Windows 95!\n");
          exit(1);
       }

       
            if (!onlocalmachine)
             {
               fprintf(stderr,"You cannot restar bind on a remote machine using ndc95.\n");
               fprintf(stderr,"This is due to restrictions with WIN95.\n");
               fprintf(stderr,"Please log on %s directly to start bind!\n",lpszMchName);
               exit(1);
             }

             // open our slot for responses 
             // open our mail slot no security needed on incomming...
             inslot = CreateMailslot("\\\\.\\mailslot\\sd_ndc",0,7000,NULL);

             if (inslot)
               {
                // possibly running .. not sure yet as this returns true if checking a remote machine
                strcpy(outbuf,commonbuf);
                strcat(outbuf,"status ");
                sprintf(tickbuf,"%d",GetTickCount());
                strcat(outbuf,tickbuf);
  
                outslot = CreateFile(lpszSlotName,GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,
                               FILE_ATTRIBUTE_NORMAL,NULL);

                 // outslot should always open regardless
                 if (outslot == INVALID_HANDLE_VALUE)
                  {
     	          fprintf(stderr, "Error: Couldn't create mail slot (outgoing) %s ... errorcode = %d \n",lpszSlotName,GetLastError());
                    CloseHandle(inslot);
                    exit(1);
                  }

                  // go on now both mail slots are open
                  ret = FALSE;
                  ret2 = FALSE;
                  ret = WriteFile(
                     outslot,       // file to write to
                     &outbuf,         // address of output buffer
                     strlen(outbuf) + 1, // number of bytes to write
                     &bytesWritten,  // number of bytes written
                     NULL);          // overlapped stuff, not needed
    
                 if (ret) // wrote ok if id didn't the server may not be runing even though the inslot 
                          // opened ok due to the fact that it may be on a remote machine..
                   {
                    ret2 = ReadFile(
                        inslot,     // file to read from
                        &inbuf,          // address of input buffer
                        sizeof(inbuf),  // number of bytes to read
                        &bytesRead,     // number of bytes read
                        NULL);          // overlapped stuff, not needed

                   // ok if ret2 is true it means it is already running
                   if (ret2)
                     {
                      running = TRUE;
                      }
                   else // not running
                    {
                     running = FALSE;
                    }

                  } // ret ok or not

                 else // write did't work not running
                 {
                  running = FALSE;
                 }

                } // inslot opened ok or not

              else // open inslot didn't work .. not running
                 {
                  running = FALSE;
                 }

            if (!running)
              {
                // it is not running so just start it
                // set to start
                CloseHandle(outslot);
                CloseHandle(inslot);
                start_up_bind();
	        fprintf(stdout, "Name Server Restarted\n");
	        exit(0);
              }
             else
               // aleady running stop/start it
               {
                 // stop it first
                 ret3 = FALSE;
                 strcpy(outbuf,commonbuf);
                 strcat(outbuf,"stop ");
                 sprintf(tickbuf,"%d",GetTickCount());
                 strcat(outbuf,tickbuf);

                 ret3 = WriteFile(
                        outslot,       // file to write to
                        &outbuf,         // address of output buffer
                        strlen(outbuf) + 1, // number of bytes to write
                        &bytesWritten,  // number of bytes written
                        NULL);          // overlapped stuff, not needed
                  if (!ret3)
                    {
	             fprintf(stderr, "Unable to restart the Domain Name Service: %d\n", GetLastError());
                     CloseHandle(inslot);
                     CloseHandle(outslot);
                     exit(1);
                    }  
                  else // shutdown ok
                   { // now give it time to stop
                     CloseHandle(outslot);
                     CloseHandle(inslot);
                     Sleep(7000);
                     start_up_bind();
                     fprintf(stdout,"Name Server Restarted\n");
                     exit(0);
                   } // shutdown ok
             } // already running

	   } // end of restart
      else // not start/restart
       { 
	  
	if (!stricmp(argv[1], "stop")) {
		fprintf(stdout, "Name Server Stopped\n");
	} else if (!stricmp(argv[1], "status")) {
	} else if (!stricmp(argv[1], "dumpdb")) {
		fprintf(stdout, "Dumping Database\n");
	} else if (!stricmp(argv[1], "reload")) {
		fprintf(stdout, "Reloading Database\n");
	} else if (!stricmp(argv[1], "stats")) {
		fprintf(stdout, "Dumping Statistics\n");
	} else if (!stricmp(argv[1], "trace")) {
		fprintf(stdout, "Trace Level Incremented\n");
	} else if (!stricmp(argv[1], "notrace")) {
		fprintf(stdout, "Tracing Cleared\n");
	} else if (!stricmp(argv[1], "querylog")
			  || !stricmp(argv[1], "qrylog")) {
		fprintf(stdout, "QueryLogging Toggled\n");
	} else
             {
		usage();
		exit(1);
	     }

       strcpy(outbuf,commonbuf);
       strcat(outbuf,argv[1]);
       strcat(outbuf," ");
       sprintf(tickbuf,"%d",GetTickCount());
       strcat(outbuf,tickbuf);

       ret = FALSE;
       ret2 = FALSE;
       outslot = CreateFile(lpszSlotName,GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,
                               FILE_ATTRIBUTE_NORMAL,NULL);

          if (outslot == INVALID_HANDLE_VALUE)
            {
     	    fprintf(stderr, "Error: Couldn't create mail slot (outgoing) %s ... errorcode = %d \n",lpszSlotName,GetLastError());
            exit(1);
            }

         // open our mail slot no security needed on incomming...
         inslot = CreateMailslot("\\\\.\\mailslot\\sd_ndc",0,7000,NULL);

         if (inslot == INVALID_HANDLE_VALUE)
            {
     	    fprintf(stderr, "Error: Couldn't create mail slot (incoming) %s ... errorcode = %d \n",lpszSlotName,GetLastError());
     	    fprintf(stderr, "Error: The server may not be running!\n");
            CloseHandle(outslot);
            exit(1);
            }

            // now write the data
            ret = WriteFile(
                      outslot,       // file to write to
                      &outbuf,         // address of output buffer
                      strlen(outbuf) + 1, // number of bytes to write
                      &bytesWritten,  // number of bytes written
                      NULL);          // overlapped stuff, not needed

            if (!ret)
              {
             if (ERROR_ACCESS_DENIED == GetLastError())
               {
                fprintf(stderr,"\nAccess denied\n on trying to send data to server via mail slot!");
               }
              else if (ERROR_BAD_NETPATH == GetLastError())
               {
                fprintf(stderr,"\nMachine %s not found\n",lpszMchName);
               }
             else
             {
              fprintf(stderr,"\nError trying to send data to server via mail slot! errorcode =  %d \n",GetLastError());
             }
            exit(1);
           }

            CloseHandle(outslot);
            // no response for stop
            if(stricmp(argv[1], "stop") == 0)
            {
             CloseHandle(inslot);
             exit(0);
            }

           // now get the response via other mailslot
           ret2 = ReadFile(
                   inslot,     // file to read from
                   &inbuf,          // address of input buffer
                   sizeof(inbuf),  // number of bytes to read
                   &bytesRead,     // number of bytes read
                   NULL);          // overlapped stuff, not needed

            if (!ret2)
              {
           //  if (ERROR_ACCESS_DENIED == GetLastError())
           //    {
           //     fprintf(stderr,"\nAccess denied\n on trying to get data from server via mail slot!");
           //    }
            //  else 
               if (ERROR_BAD_NETPATH == GetLastError())
               {
                fprintf(stderr,"\nMachine %s not found\n",lpszMchName);
               }
             else
             {
              fprintf(stderr,"\nError trying to get data from server via mail slot! errorcode =  %d \n",GetLastError());
             }
            CloseHandle(inslot);
            exit(1);              
           }
               

	if (strcmp(argv[1], "status") == 0)
          {
  		printf("\nStatus of Domain Name Service:\n");
  		printf("%s\n",inbuf);
                CloseHandle(inslot);
                exit(0);
	 }

       else // not status so then all rest should return ok..
        {
          if (strncmp(inbuf,"Ok",2) == 0)
            {
               CloseHandle(inslot);
               exit(0);
            }
          else
            {
              fprintf(stderr,"Error command failed (invalid response): errorcode = %d \n",GetLastError());
              exit(1);       

            }
	}

   } // not start/restart
 }



void
usage()
{
	fprintf(stderr, "usage: ndc95 (status|dumpdb|reload|stats|trace|notrace\
					|querylog|start|stop|restart) [\\\\server]\n");
	exit(1);
}

#ifdef WIN95

//--------------------------------------------------------------------------------------------------
/* lgk code to start up bind hidden under win95 since there are no services */

void start_up_bind()
{

   STARTUPINFO StartInfo;
   BOOLEAN rvalue;
   PROCESS_INFORMATION phandle;
   static char cline[100] = "named95.exe";
  
    /* Set up members of STARTUPINFO structure. */

    StartInfo.cb = sizeof(STARTUPINFO);
    StartInfo.lpReserved = NULL;
    StartInfo.lpReserved2 = NULL;
    StartInfo.cbReserved2 = 0;
    StartInfo.lpDesktop = NULL;

    // set noshow in case it is a win app
    StartInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USEPOSITION;

    StartInfo.lpTitle = NULL;
    StartInfo.dwX = 1000;
    StartInfo.dwY = 1000;
    StartInfo.dwXSize = 0;
    StartInfo.dwYSize = 0;
    StartInfo.dwXCountChars= 0;
    StartInfo.dwYCountChars = 0;
    StartInfo.dwFillAttribute = 0;
    StartInfo.hStdInput = NULL;
    StartInfo.hStdOutput = NULL;
    StartInfo.hStdError = NULL;
    StartInfo.wShowWindow = SW_HIDE;

     rvalue = CreateProcess(NULL,(LPSTR)&cline,NULL,NULL,FALSE,DETACHED_PROCESS,NULL,NULL,&StartInfo,&phandle);
 
	if (rvalue == FALSE)
	  {
 	   
           int ecode = GetLastError();
	   if (ecode == 2)
	     {
	       printf("Startup of named95.exe failed errorcode = 2 (FILE_NOT_FOUND)\n");
	     }
	   else
	     {
	      printf("Startup of named95.exe failed errorcode = %d \n",ecode);
	   	 }

	   fflush(stdout);
	   Sleep(10000);
	   }
	   
	     {
	      DWORD waitval = WaitForInputIdle(phandle.hProcess,5000);
	     }

  	   CloseHandle(phandle.hThread);
	   CloseHandle(phandle.hProcess);

	   }

#endif // win95 code

