Ejemplo n.º 1
0
int main(int argc, char* argv[])
{
	signal(SIGPIPE, SIG_IGN);
	char path[PATH_MAX];
	bool foundConfig = false;
#ifdef TOOLBAR_ICON	
	bool userConfig = false;
#endif
	
	// store for later
	_argc = argc;
	_argv = argv;

	/* syslog */
	int logOpt = LOG_PID | LOG_CONS | LOG_PERROR;
	openlog("mmserver", logOpt, LOG_DAEMON); 

	/* parse configuration */
	Configuration appConfig;
	if (argc == 1) {
		/* look for config file in user or system directory */		
		if (CheckUserConfig(path, sizeof path)) {
			foundConfig = true;
#ifdef TOOLBAR_ICON
			userConfig = true;
#endif
		} else if (CheckSystemConfig(path, sizeof path)) {
			foundConfig = true;
		}
	} else if (argc == 2) {
		/* interpret the argument as the path to a particular config file */
		snprintf(path, sizeof path, "%s", argv[1]);
		foundConfig = true;
	} else {
		fprintf(stderr, "Mobile Mouse Server for Linux (%s.%s.%s)\n",
				MMSERVER_VERSION_MAJOR, MMSERVER_VERSION_MINOR, MMSERVER_VERSION_PATCH);
		fprintf(stderr, "Website: https://github.com/anoved/mmserver/\n");
		fprintf(stderr, "Usage: %s [/path/to/mmserver.conf]\n", argv[0]);
		return 1;
	}

	if (foundConfig) {
		syslog(LOG_INFO, "reading configuration from %s", path);
		try {
			appConfig.Read(path);
		}
		catch (const libconfig::FileIOException &err) {
			syslog(LOG_ERR, "Cannot read configuration from: %s", path);
			exit(1);
		}
	} else {
		syslog(LOG_INFO, "no configuration file found; using internal defaults");
	}

	if (!appConfig.getKeyboardEnabled()) {
		syslog(LOG_INFO, "keyboard input ignored");
	}

	syslog(LOG_INFO, "started on port %d", appConfig.getPort());
	daemon(1, 1);

	if (appConfig.getZeroconf()) {
		StartAvahi(appConfig);
	}
	
	/* bind.. */
	struct sockaddr_in serv_addr;
	bzero((char *)&serv_addr, sizeof serv_addr);
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = INADDR_ANY;
	serv_addr.sin_port = htons(appConfig.getPort());

	/* setup network.. */
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0)
	{
		syslog(LOG_ERR, "socket: %s", strerror(errno));
		exit(1);
	}

	int optval = 1;
	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) < 0)
	{
		syslog(LOG_ERR, "setsockopt: %s", strerror(errno));
		exit(1);
	}

	if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof serv_addr) < 0)
	{
		syslog(LOG_ERR, "bind: %s", strerror(errno));
		exit(1);
	}

	if (listen(sockfd, 1) < 0)
	{
		syslog(LOG_ERR, "listen: %s", strerror(errno));
		exit(1);
	}

#ifdef TOOLBAR_ICON
	pthread_t toolbarpid;
	if (pthread_create(&toolbarpid, 0x0, GTKStartup, (void*)(userConfig ? path : NULL)) == -1)
	{
		syslog(LOG_WARNING, "pthread_create failed: %s", strerror(errno));
	}
#endif

	/* server loop.. */
	while(1)
	{
		struct sockaddr_in caddr;
		int clen = sizeof caddr;

		/* accept client.. */
		int client = accept(sockfd, (struct sockaddr *)&caddr, (socklen_t*)&clen);
		if (client < 0)
		{
			syslog(LOG_WARNING, "accept failed: %s", strerror(errno));
			continue;
		}

		/* start new session.. */
		SessionContext * clientContext = new SessionContext(appConfig,
				client,
				inet_ntoa(caddr.sin_addr));

#ifdef TOOLBAR_ICON
		gtk_status_icon_set_tooltip(tray, std::string(clientContext->m_address + " connected").c_str());
		gtk_status_icon_set_from_pixbuf(tray, connected_icon);
#endif

		pthread_t pid;
		if (pthread_create(&pid, 0x0, MobileMouseSession, (void*)clientContext) == -1)
		{
			syslog(LOG_WARNING, "pthread_create failed: %s", strerror(errno));
			delete clientContext;
			close(client);
		} else 
			pthread_join(pid, 0x0);

#ifdef TOOLBAR_ICON
		gtk_status_icon_set_tooltip(tray, TOOLBAR_LABEL_DEFAULT);
		gtk_status_icon_set_from_pixbuf(tray, idle_icon);
#endif
	}

	return 0;
}
INT main( INT argc, PCHAR argv[] )
{
 // Сбрасываем свойства приложения.
 bzero( &Enhancer, sizeof( ENHANCER ) );

 // Определяем приложение в системе.
 Enhancer.Application = WinInitialize( 0 );

 // Если это сделать не удалось - выход.
 if( Enhancer.Application == NULLHANDLE )
  {
   // Звук - ошибка.
   WinAlarm( HWND_DESKTOP, WA_ERROR );
   // Выход.
   DosExit( EXIT_PROCESS, 0 );
  }

 // Создаем очередь сообщений.
 HMQ Message_queue = WinCreateMsgQueue( Enhancer.Application, 0 );

 // Если очередь создать не удалось - выход.
 if( Message_queue == NULLHANDLE )
  {
   // Звук - ошибка.
   WinAlarm( HWND_DESKTOP, WA_ERROR );
   // Выход.
   WinTerminate( Enhancer.Application );
   DosExit( EXIT_PROCESS, 0 );
  }

 // Проверяем системные настройки.
 CheckSystemConfig();

 // Запускаем составляющие приложения.
 StdLib_Start();
 Strings_Start();
 Files_Start();

 Environment_Start();
 EnhancerProperties_Start();

 Loader_Start();
 Launcher_Start();

 // Узнаем, что надо сделать.
 if( argc == 2 )
  {
   if( stristr( "hide",    argv[ 1 ] ) ) Enhancer.Launcher_mode = 1;
   if( stristr( "mini",    argv[ 1 ] ) ) Enhancer.Launcher_mode = 1;
   if( stristr( "launch",  argv[ 1 ] ) ) Enhancer.Launcher_mode = 1;
   if( stristr( "enhance", argv[ 1 ] ) ) Enhancer.Enhancer_mode = 1;
  }

 // Возможно, надо вызвать окно настроек.
 if( argc == 2 )
  {
   if( strstr( "ControlCenter", argv[ 1 ] ) )
    {
     CHAR Path_to_ControlCenter[ SIZE_OF_PATH ] = "";
     GetCurrentPath( Path_to_ControlCenter );
     strcat( Path_to_ControlCenter, "\\Nice-eCS.exe" );

     Execute( Path_to_ControlCenter, argv[ 1 ] );

     WinDestroyMsgQueue( Message_queue );
     WinTerminate( Enhancer.Application );
     DosExit( EXIT_PROCESS, 0 );
    }
  }

 // Если действие не распознано - выход.
 if( !Enhancer.Enhancer_mode && !Enhancer.Launcher_mode )
  {
   WinDestroyMsgQueue( Message_queue );
   WinTerminate( Enhancer.Application );
   DosExit( EXIT_PROCESS, 0 );
  }

 // Если окно приложения уже есть - выход.
 {
  CHAR Semaphore_name[] = "\\SEM32\\NICE-OS2!L"; HMTX hmtxAlreadyRunning = NULLHANDLE;
  if( Enhancer.Enhancer_mode ) Semaphore_name[ strlen( Semaphore_name ) - 1 ] = 'E';

  if( DosOpenMutexSem( Semaphore_name, &hmtxAlreadyRunning ) == NO_ERROR )
   {
    WinDestroyMsgQueue( Message_queue );
    WinTerminate( Enhancer.Application );
    DosExit( EXIT_PROCESS, 0 );
   }
  else
   {
    DosCreateMutexSem( Semaphore_name, &hmtxAlreadyRunning, DC_SEM_SHARED, 1 );
   }
 }

 // Загрузчик должен запускаться до расширителя.
 if( Enhancer.Launcher_mode )
  {
   CHAR Semaphore_name[] = "\\SEM32\\NICE-OS2!E"; HMTX hmtxAlreadyRunning = NULLHANDLE;

   if( DosOpenMutexSem( Semaphore_name, &hmtxAlreadyRunning ) == NO_ERROR )
    {
     WinDestroyMsgQueue( Message_queue );
     WinTerminate( Enhancer.Application );
     DosExit( EXIT_PROCESS, 0 );
    }
  }

 // Расширитель должен запускаться после загрузчика
 if( Enhancer.Enhancer_mode )
  {
   CHAR Semaphore_name[] = "\\SEM32\\NICE-OS2!L"; HMTX hmtxAlreadyRunning = NULLHANDLE;

   if( DosOpenMutexSem( Semaphore_name, &hmtxAlreadyRunning ) != NO_ERROR )
    {
     WinDestroyMsgQueue( Message_queue );
     WinTerminate( Enhancer.Application );
     DosExit( EXIT_PROCESS, 0 );
    }
  }

 // Если надо вызвать загрузчик:
 if( Enhancer.Launcher_mode )
  {
   // Создаем поток для запуска расширителя.
   DosCreateThread( &Threads.Launcher, (PFNTHREAD) LauncherThread, 0, 0, STACK_SIZE );
  }

 // Если надо вызвать расширитель:
 if( Enhancer.Enhancer_mode )
  {
   // Пробуем найти окно загрузчика.
   HWND Launcher_window = NULLHANDLE; CHAR Launcher_title[] = "Nice-OS2!L";

   {
    // Перебираем окна в окне рабочего стола.
    HENUM Enumeration = WinBeginEnumWindows( WinQueryDesktopWindow( Enhancer.Application, NULLHANDLE ) ); HWND Window = NULLHANDLE;
    while( ( Window = WinGetNextWindow( Enumeration ) ) != NULLHANDLE )
     {
      // Узнаем заголовок окна.
      CHAR Window_title[ SIZE_OF_TITLE ] = "";
      WinQueryWindowText( WinWindowFromID( Window, FID_TITLEBAR ), SIZE_OF_TITLE, Window_title );

      // Если это окно расширителя - запоминаем его.
      if( strc( Window_title, Launcher_title ) )
       {
        Launcher_window = Window;
        break;
       }
     }
    WinEndEnumWindows( Enumeration );
   }

   // Если загрузчика нет - выход.
   // Вообще-то он должен быть, раз найден семафор, но кто знает...
   if( !Launcher_window )
    {
     WinTerminate( Enhancer.Application );
     DosExit( EXIT_PROCESS, 0 );
    }

   // Создаем потоки, устанавливаем обработчики событий.
   BYTE Success = NiceLoadEnhancer( Enhancer.Application, 0, Launcher_window );

   // Если это сделать не удалось - выход.
   if( !Success )
    {
     WinTerminate( Enhancer.Application );
     DosExit( EXIT_PROCESS, 0 );
    }

   // Читаем настройки и загружаем изображения в расширитель.
   // Этот метод выполняется внутри Nice-os2.dll, но так как DLL использует
   // адресное пространство приложения, все данные остаются в этом приложении.
   NiceReadSettings( 0 );

   // Включаем слежение за сообщениями.
   NiceRunEnhancer();
  }

 // Создаем окно рабочей области.
 CHAR Class_name[] = "NiceOS2WndClass!L";
 if( Enhancer.Enhancer_mode ) Class_name[ strlen( Class_name ) - 1 ] = 'E';
 WinRegisterClass( Enhancer.Application, Class_name, (PFNWP) Enhancer_MainWindowProc, 0, 0 );

 // Создаем окно рамки.
 CHAR MainWindow_title[] = "Nice-OS2!L";
 if( Enhancer.Enhancer_mode ) Class_name[ strlen( Class_name ) - 1 ] = 'E';

 ULONG Creation_flags = FCF_TITLEBAR | FCF_SYSMENU;
 Enhancer.Frame_window = WinCreateStdWindow( HWND_DESKTOP, CS_FRAME, &Creation_flags, Class_name, MainWindow_title, 0, NULLHANDLE, 0, &Enhancer.Client_window );
 WinShowWindow( Enhancer.Frame_window, 0 );

 // Выбираем сообщения из очереди.
 QMSG Message; bzero( &Message, sizeof( QMSG ) );
 while( WinGetMsg( Enhancer.Application, &Message, 0, 0, 0 ) ) WinDispatchMsg( Enhancer.Application, &Message );

 // Закрываем окна.
 WinDestroyWindow( Enhancer.Client_window );
 WinDestroyWindow( Enhancer.Frame_window );

 // Если вызван расширитель:
 if( Enhancer.Enhancer_mode )
  {
   // Отключаем обработчики событий, завершаем работу потоков.
   NiceReleaseEnhancer( Enhancer.Application, 0 );
  }

 // Удаляем файлы отладочной версии.
 DosForceDelete( "_log.txt" ); DosForceDelete( "XTest.exe" );

 // Сбрасываем очередь сообщений.
 WinDestroyMsgQueue( Message_queue );

 // Выход.
 WinTerminate( Enhancer.Application );
 DosExit( EXIT_PROCESS, 0 );
}