Пример #1
0
PtpClock *
ptpdStartup(int argc, char **argv, Integer16 * ret, RunTimeOpts * rtOpts)
{
	PtpClock * ptpClock;
	TimeInternal tmpTime;
	int i = 0;

	/*
	 * Set the default mode for all newly created files - previously
	 * this was not the case for log files. This adds consistency
	 * and allows to use FILE* vs. fds everywhere
	 */
	umask(~DEFAULT_FILE_PERMS);

	/* get some entropy in... */
	getTime(&tmpTime);
	srand(tmpTime.seconds ^ tmpTime.nanoseconds);

	/**
	 * If a required setting, such as interface name, or a setting
	 * requiring a range check is to be set via getopts_long,
	 * the respective currentConfig dictionary entry should be set,
	 * instead of just setting the rtOpts field.
	 *
	 * Config parameter evaluation priority order:
	 * 	1. Any dictionary keys set in the getopt_long loop
	 * 	2. CLI long section:key type options
	 * 	3. Any built-in config templates
	 *	4. Any templates loaded from template file
	 * 	5. Config file (parsed last), merged with 2. and 3 - will be overwritten by CLI options
	 * 	6. Defaults and any rtOpts fields set in the getopt_long loop
	**/

	/**
	 * Load defaults. Any options set here and further inside loadCommandLineOptions()
	 * by setting rtOpts fields, will be considered the defaults
	 * for config file and section:key long options.
	 */
	loadDefaultSettings(rtOpts);
	/* initialise the config dictionary */
	rtOpts->candidateConfig = dictionary_new(0);
	rtOpts->cliConfig = dictionary_new(0);

	/* parse all long section:key options and clean up argv for getopt */
	loadCommandLineKeys(rtOpts->cliConfig,argc,argv);
	/* parse the normal short and long options, exit on error */
	if (!loadCommandLineOptions(rtOpts, rtOpts->cliConfig, argc, argv, ret)) {
	    goto fail;
	}

	/* Display startup info and argv if not called with -? or -H */
		NOTIFY("%s version %s starting\n",USER_DESCRIPTION, USER_VERSION);
		dump_command_line_parameters(argc, argv);
	/*
	 * we try to catch as many error conditions as possible, but before we call daemon().
	 * the exception is the lock file, as we get a new pid when we call daemon(),
	 * so this is checked twice: once to read, second to read/write
	 */
	if(geteuid() != 0)
	{
		printf("Error: "PTPD_PROGNAME" daemon can only be run as root\n");
			*ret = 1;
			goto fail;
		}

	/* Have we got a config file? */
	if(strlen(rtOpts->configFile) > 0) {
		/* config file settings overwrite all others, except for empty strings */
		INFO("Loading configuration file: %s\n",rtOpts->configFile);
		if(loadConfigFile(&rtOpts->candidateConfig, rtOpts)) {
			dictionary_merge(rtOpts->cliConfig, rtOpts->candidateConfig, 1, 1, "from command line");
		} else {
		    *ret = 1;
			dictionary_merge(rtOpts->cliConfig, rtOpts->candidateConfig, 1, 1, "from command line");
		    goto configcheck;
		}
	} else {
		dictionary_merge(rtOpts->cliConfig, rtOpts->candidateConfig, 1, 1, "from command line");
	}
	/**
	 * This is where the final checking  of the candidate settings container happens.
	 * A dictionary is returned with only the known options, explicitly set to defaults
	 * if not present. NULL is returned on any config error - parameters missing, out of range,
	 * etc. The getopt loop in loadCommandLineOptions() only sets keys verified here.
	 */
	if( ( rtOpts->currentConfig = parseConfig(CFGOP_PARSE, NULL, rtOpts->candidateConfig,rtOpts)) == NULL ) {
	    *ret = 1;
	    dictionary_del(&rtOpts->candidateConfig);
	    goto configcheck;
	}

	/* we've been told to print the lock file and exit cleanly */
	if(rtOpts->printLockFile) {
	    printf("%s\n", rtOpts->lockFile);
	    *ret = 0;
	    goto fail;
	}

	/* we don't need the candidate config any more */
	dictionary_del(&rtOpts->candidateConfig);

	/* Check network before going into background */
	if(!testInterface(rtOpts->primaryIfaceName, rtOpts)) {
	    ERROR("Error: Cannot use %s interface\n",rtOpts->primaryIfaceName);
	    *ret = 1;
	    goto configcheck;
	}
	if(rtOpts->backupIfaceEnabled && !testInterface(rtOpts->backupIfaceName, rtOpts)) {
	    ERROR("Error: Cannot use %s interface as backup\n",rtOpts->backupIfaceName);
	    *ret = 1;
	    goto configcheck;
	}


configcheck:
	/*
	 * We've been told to check config only - clean exit before checking locks
	 */
	if(rtOpts->checkConfigOnly) {
	    if(*ret != 0) {
		printf("Configuration has errors\n");
		*ret = 1;
		}
	    else
		printf("Configuration OK\n");
	    goto fail;
	}

	/* Previous errors - exit */
	if(*ret !=0)
		goto fail;

	/* First lock check, just to be user-friendly to the operator */
	if(!rtOpts->ignore_daemon_lock) {
		if(!writeLockFile(rtOpts)){
			/* check and create Lock */
			ERROR("Error: file lock failed (use -L or global:ignore_lock to ignore lock file)\n");
			*ret = 3;
			goto fail;
		}
		/* check for potential conflicts when automatic lock files are used */
		if(!checkOtherLocks(rtOpts)) {
			*ret = 3;
			goto fail;
		}
	}

	/* Manage log files: stats, log, status and quality file */
	restartLogging(rtOpts);

	/* Allocate memory after we're done with other checks but before going into daemon */
	ptpClock = (PtpClock *) calloc(1, sizeof(PtpClock));
	if (!ptpClock) {
		PERROR("Error: Failed to allocate memory for protocol engine data");
		*ret = 2;
		goto fail;
	} else {
		DBG("allocated %d bytes for protocol engine data\n",
		    (int)sizeof(PtpClock));


		ptpClock->foreign = (ForeignMasterRecord *)
			calloc(rtOpts->max_foreign_records,
			       sizeof(ForeignMasterRecord));
		if (!ptpClock->foreign) {
			PERROR("failed to allocate memory for foreign "
			       "master data");
			*ret = 2;
			free(ptpClock);
			goto fail;
		} else {
			DBG("allocated %d bytes for foreign master data\n",
			    (int)(rtOpts->max_foreign_records *
				  sizeof(ForeignMasterRecord)));
		}
	}

	if(rtOpts->statisticsLog.logEnabled)
		ptpClock->resetStatisticsLog = TRUE;

	/* Init to 0 net buffer */
	memset(ptpClock->msgIbuf, 0, PACKET_SIZE);
	memset(ptpClock->msgObuf, 0, PACKET_SIZE);
	
	/* Init outgoing management message */
	ptpClock->outgoingManageTmp.tlv = NULL;
	

	/*  DAEMON */
#ifdef PTPD_NO_DAEMON
	if(!rtOpts->nonDaemon){
		rtOpts->nonDaemon=TRUE;
	}
#endif

	if(!rtOpts->nonDaemon){
		/*
		 * fork to daemon - nochdir non-zero to preserve the working directory:
		 * allows relative paths to be used for log files, config files etc.
		 * Always redirect stdout/err to /dev/null
		 */
		if (daemon(1,0) == -1) {
			PERROR("Failed to start as daemon");
			*ret = 3;
			goto fail;
		}
		INFO("  Info:    Now running as a daemon\n");
		/*
		 * Wait for the parent process to terminate, but not forever.
		 * On some systems this happened after we tried re-acquiring
		 * the lock, so the lock would fail. Hence, we wait.
		 */
		for (i = 0; i < 1000000; i++) {
			/* Once we've been reaped by init, parent PID will be 1 */
			if(getppid() == 1)
				break;
			usleep(1);
		}
	}

	/* Second lock check, to replace the contents with our own new PID and re-acquire the advisory lock */
	if(!rtOpts->nonDaemon && !rtOpts->ignore_daemon_lock){
		/* check and create Lock */
		if(!writeLockFile(rtOpts)){
			ERROR("Error: file lock failed (use -L or global:ignore_lock to ignore lock file)\n");
			*ret = 3;
			goto fail;
		}
	}

#if (defined(linux) && defined(HAVE_SCHED_H)) || defined(HAVE_SYS_CPUSET_H) || defined(__QNXNTO__)
	/* Try binding to a single CPU core if configured to do so */
	if(rtOpts->cpuNumber > -1) {
    		if(setCpuAffinity(rtOpts->cpuNumber) < 0) {
		    ERROR("Could not bind to CPU core %d\n", rtOpts->cpuNumber);
		} else {
		    INFO("Successfully bound "PTPD_PROGNAME" to CPU core %d\n", rtOpts->cpuNumber);
		}
	}
#endif

	/* set up timers */
	if(!timerSetup(ptpClock->timers)) {
		PERROR("failed to set up event timers");
		*ret = 2;
		free(ptpClock);
		goto fail;
	}

	/* establish signal handlers */
	signal(SIGINT,  catchSignals);
	signal(SIGTERM, catchSignals);
	signal(SIGHUP,  catchSignals);

	signal(SIGUSR1, catchSignals);
	signal(SIGUSR2, catchSignals);

#if defined PTPD_SNMP
	/* Start SNMP subsystem */
	if (rtOpts->snmp_enabled)
		snmpInit(rtOpts, ptpClock);
#endif



	NOTICE(USER_DESCRIPTION" started successfully on %s using \"%s\" preset (PID %d)\n",
			    rtOpts->ifaceName,
			    (getPtpPreset(rtOpts->selectedPreset,rtOpts)).presetName,
			    getpid());
	ptpClock->resetStatisticsLog = TRUE;

#ifdef PTPD_STATISTICS

	outlierFilterSetup(&ptpClock->oFilterMS);
	outlierFilterSetup(&ptpClock->oFilterSM);

	ptpClock->oFilterMS.init(&ptpClock->oFilterMS,&rtOpts->oFilterMSConfig, "delayMS");
	ptpClock->oFilterSM.init(&ptpClock->oFilterSM,&rtOpts->oFilterSMConfig, "delaySM");


	if(rtOpts->filterMSOpts.enabled) {
		ptpClock->filterMS = createDoubleMovingStatFilter(&rtOpts->filterMSOpts,"delayMS");
	}

	if(rtOpts->filterSMOpts.enabled) {
		ptpClock->filterSM = createDoubleMovingStatFilter(&rtOpts->filterSMOpts, "delaySM");
	}

#endif

#ifdef PTPD_PCAP
		ptpClock->netPath.pcapEventSock = -1;
		ptpClock->netPath.pcapGeneralSock = -1;
#endif /* PTPD_PCAP */

		ptpClock->netPath.generalSock = -1;
		ptpClock->netPath.eventSock = -1;

	*ret = 0;

	return ptpClock;
	
fail:
	dictionary_del(&rtOpts->cliConfig);
	dictionary_del(&rtOpts->candidateConfig);
	dictionary_del(&rtOpts->currentConfig);
	return 0;
}
Пример #2
0
/**
 * Main program entry point
 *
 * This function is the one called by the operating system to start Luna.
 * 
 * This function sets {@link appArgc appArgc} and {@link appArgv appArgv}.
 * 
 * @see appArgc
 * @see appArgv
 *
 * @param	argc		Number of command-line arguments
 * @param	argv		Pointer to list of char* of each of the arguments
 *
 * @return			0 = success, anything else = failure
 */
int main( int argc, char** argv)
{
	appArgc = argc;
	appArgv = argv;

	std::set_terminate(generateGoodBacktraceTerminateHandler);

	g_thread_init(NULL);

	const char *renderMode;
#if defined(TARGET_DEVICE) && defined(HAVE_OPENGL)
	::setenv("QT_PLUGIN_PATH", "/usr/plugins", 1);
	renderMode = "HW egl";
#elif defined(TARGET_DEVICE) || defined(TARGET_EMULATOR)
	::setenv("QT_PLUGIN_PATH", "/usr/plugins", 1);	
	renderMode = "Software";
#elif defined(HAVE_OPENGL)
	renderMode = "HW OpenGL";
#else
	renderMode = "Software";
#endif

	WindowServer::markBootStart();

	g_debug("SysMgr compiled against Qt %s, running on %s, %s render mode requested", QT_VERSION_STR, qVersion(), renderMode);

	// Command-Line options
  	parseCommandlineOptions(argc, argv);

    if (s_debugTrapStr && 0 == strcasecmp(s_debugTrapStr, "on")) {
        debugCrashes = true;
    }

	if (s_mallocStatsFileStr) {
		setupMallocStats(s_mallocStatsFileStr);
	}

    sysmgrPid = getpid();

	// Load Settings (first!)
	Settings* settings = Settings::LunaSettings();

	// Initialize logging handler
	g_log_set_default_handler(logFilter, NULL);

#if defined(TARGET_DESKTOP)
	// use terminal logging when running on desktop
	settings->logger_useTerminal = true;
#endif

	// disable color logging using an environment variable. Useful when run from QtCreator
	const char* useColor = ::getenv("COLOR_LOGGING");
	if (useColor)
		settings->logger_useColor = (useColor[0] != 0 && useColor[0] != '0');

	HostBase* host = HostBase::instance();
	// the resolution is just a hint, the actual
	// resolution may get picked up from the fb driver on arm
	host->init(settings->displayWidth, settings->displayHeight);

#if defined(TARGET_DEVICE)
	pid_t animPid= spawnBootupAnimationProcess();
	if(animPid < 0) { // failed to start the Animation process
		return -1;
	}
#endif

#if defined(TARGET_DEVICE) && defined(HAVE_OPENGL) && defined(HAVE_QPA)
	if (settings->forceSoftwareRendering)
		::setenv("QT_QPA_PLATFORM", "palm-soft", 1);
	else
		::setenv("QT_QPA_PLATFORM", "palm", 1);
#endif
	
	
#if defined(TARGET_DEVICE) && defined(HAVE_OPENGL)
	if (!settings->forceSoftwareRendering)
		::setenv("QWS_DISPLAY", "egl", 1);
#endif


	pid_t webKitPid= spawnWebKitProcess();
	if(webKitPid < 0) { // failed to start the WebKit process
		return -1;
	}

	// Tie LunaSysMgr to Processor 0
	setCpuAffinity(getpid(), 1);

	// Tie WebAppMgr to Processor 1
	setCpuAffinity(webKitPid, 0);

	// Safe to create logging threads now
	logInit();

	// Initialize Ipc Server
	(void) IpcServer::instance();

	// Ipc Server is ready, so signal the WebAppMgr process (via pipe) to go ahead and connect
	::write(WebAppMgrPipeFd, &msgOkToContinue, 1);
	::close(WebAppMgrPipeFd);
	WebAppMgrPipeFd = -1;


#if !defined(TARGET_DESKTOP)
	// Set "nice" property
	setpriority(PRIO_PROCESS,getpid(),-1);
#endif

#if !defined(TARGET_DESKTOP) && !defined(HAVE_QPA)
	QWSServer::setDefaultMouse("HiddTp");
	QWSServer::setDefaultKeyboard("HiddKbd");
	::setenv("QWS_DBLCLICK_DISTANCE", QString("%0").arg(Settings::LunaSettings()->tapRadius).toAscii().constData(), 1);
#endif

	qInstallMsgHandler(qtMsgHandler);
	QApplication app(argc, argv);
	QApplication::setStartDragDistance(settings->tapRadius);
	QApplication::setDoubleClickInterval (Settings::LunaSettings()->tapDoubleClickDuration);
	host->show();
	
	initMallocStatsCb(HostBase::instance()->mainLoop(), s_mallocStatsInterval);

	// Initialize Preferences handler
	(void) Preferences::instance();

	// Initialize Localization handler
	(void) Localization::instance();

	//Register vibration/haptics support
	HapticsController::instance()->startService();

	(void) DeviceInfo::instance();

	// Initialize Security handler
	(void) Security::instance();

	// Initialize the System Service
	SystemService::instance()->init();

	// Initialize the application mgr
	ApplicationManager::instance()->init();

	// Initialize the Application Installer
	ApplicationInstaller::instance();

	// Start the window manager
	WindowServer *windowServer = WindowServer::instance();
	windowServer->installEventFilter(windowServer);

	// Initialize the SysMgr MemoryMonitor
	MemoryMonitor::instance();

	// load all set policies
	EASPolicyManager::instance()->load();

	// Launching of the System UI launcher and headless apps has been moved to WebAppMgrProxy::connectWebAppMgr

	// Did user specify an app to launch
	if (s_appToLaunchStr) {
		WebAppMgrProxy::setAppToLaunchUponConnection(s_appToLaunchStr);
	}

	app.exec();
	return 0;
}
Пример #3
0
void
applyConfig(dictionary *baseConfig, RunTimeOpts *rtOpts, PtpClock *ptpClock)
{

	Boolean reloadSuccessful = TRUE;


	/* Load default config to fill in the blanks in the config file */
	RunTimeOpts tmpOpts;
	loadDefaultSettings(&tmpOpts);

	/* Check the new configuration for errors, fill in the blanks from defaults */
	if( ( rtOpts->candidateConfig = parseConfig(CFGOP_PARSE, NULL, baseConfig, &tmpOpts)) == NULL ) {
	    WARNING("Configuration has errors, reload aborted\n");
	    return;
	}

	/* Check for changes between old and new configuration */
	if(compareConfig(rtOpts->candidateConfig,rtOpts->currentConfig)) {
	    INFO("Configuration unchanged\n");
	    goto cleanup;
	}

	/*
	 * Mark which subsystems have to be restarted. Most of this will be picked up by doState()
	 * If there are errors past config correctness (such as non-existent NIC,
	 * or lock file clashes if automatic lock files used - abort the mission
	 */

	rtOpts->restartSubsystems =
	    checkSubsystemRestart(rtOpts->candidateConfig, rtOpts->currentConfig, rtOpts);

	/* If we're told to re-check lock files, do it: tmpOpts already has what rtOpts should */
	if( (rtOpts->restartSubsystems & PTPD_CHECK_LOCKS) &&
	    tmpOpts.autoLockFile && !checkOtherLocks(&tmpOpts)) {
		reloadSuccessful = FALSE;
	}

	/* If the network configuration has changed, check if the interface is OK */
	if(rtOpts->restartSubsystems & PTPD_RESTART_NETWORK) {
		INFO("Network configuration changed - checking interface(s)\n");
		if(!testInterface(tmpOpts.primaryIfaceName, &tmpOpts)) {
		    reloadSuccessful = FALSE;
		    ERROR("Error: Cannot use %s interface\n",tmpOpts.primaryIfaceName);
		}
		if(rtOpts->backupIfaceEnabled && !testInterface(tmpOpts.backupIfaceName, &tmpOpts)) {
		    rtOpts->restartSubsystems = -1;
		    ERROR("Error: Cannot use %s interface as backup\n",tmpOpts.backupIfaceName);
		}
	}
#if (defined(linux) && defined(HAVE_SCHED_H)) || defined(HAVE_SYS_CPUSET_H) || defined(__QNXNTO__)
        /* Changing the CPU affinity mask */
        if(rtOpts->restartSubsystems & PTPD_CHANGE_CPUAFFINITY) {
                NOTIFY("Applying CPU binding configuration: changing selected CPU core\n");

                if(setCpuAffinity(tmpOpts.cpuNumber) < 0) {
                        if(tmpOpts.cpuNumber == -1) {
                                ERROR("Could not unbind from CPU core %d\n", rtOpts->cpuNumber);
                        } else {
                                ERROR("Could bind to CPU core %d\n", tmpOpts.cpuNumber);
                        }
			reloadSuccessful = FALSE;
                } else {
                        if(tmpOpts.cpuNumber > -1)
                                INFO("Successfully bound "PTPD_PROGNAME" to CPU core %d\n", tmpOpts.cpuNumber);
                        else
                                INFO("Successfully unbound "PTPD_PROGNAME" from cpu core CPU core %d\n", rtOpts->cpuNumber);
                }
         }
#endif

	if(!reloadSuccessful) {
		ERROR("New configuration cannot be applied - aborting reload\n");
		rtOpts->restartSubsystems = 0;
		goto cleanup;
	}


		/**
		 * Commit changes to rtOpts and currentConfig
		 * (this should never fail as the config has already been checked if we're here)
		 * However if this DOES fail, some default has been specified out of range -
		 * this is the only situation where parse will succeed but commit not:
		 * disable quiet mode to show what went wrong, then die.
		 */
		if (rtOpts->currentConfig) {
			dictionary_del(&rtOpts->currentConfig);
		}
		if ( (rtOpts->currentConfig = parseConfig(CFGOP_PARSE_QUIET, NULL, rtOpts->candidateConfig,rtOpts)) == NULL) {
			CRITICAL("************ "PTPD_PROGNAME": parseConfig returned NULL during config commit"
				 "  - this is a BUG - report the following: \n");

			if ((rtOpts->currentConfig = parseConfig(CFGOP_PARSE, NULL, rtOpts->candidateConfig,rtOpts)) == NULL)
			    CRITICAL("*****************" PTPD_PROGNAME" shutting down **********************\n");
			/*
			 * Could be assert(), but this should be done any time this happens regardless of
			 * compile options. Anyhow, if we're here, the daemon will no doubt segfault soon anyway
			 */
			abort();
		}

	/* clean up */
	cleanup:

		dictionary_del(&rtOpts->candidateConfig);
}