Ejemplo n.º 1
0
int parse_file(char * filename, struct configobj **newcfg) 
{
    int fd;
    int x;
    struct stat statbuf;
    char *filebuf = NULL;
    struct configobj * mycfg;
    struct cfgsearchobj *mycs;    
    char * srchtmp;

    if (stat(filename, &statbuf)) {
	printf("Error stat on file %s\n", filename);
	return 1;
    } 

    if (NULL== (filebuf = malloc(statbuf.st_size + 1))) {
	printf("Error: malloc failed for %d bytes.\n", (int)statbuf.st_size);
	return 1;
    }

    if (0 == (fd = open(filename, O_RDONLY))) {
	printf("Error on open file %s\n", filename);
	return 1;
    }

    x = read(fd, filebuf, (int)statbuf.st_size);
    filebuf[(int)statbuf.st_size] = (char)0;

    *newcfg = NULL;    
    if ((mycfg = config_new(NULL))) {
        *newcfg = mycfg;
	config_parse(mycfg, filebuf);
	printf("\nDumping has table key/value pairs.\n");
	dump_string_ht(mycfg->config_options);
	printf("\n");

	printf("running a search for first...\n");
	if ((mycs = config_search_init(mycfg, NULL, NULL))) {
	  printf("get first thing got key=");
	  srchtmp = config_search_string_firstkey(mycs);
	  if (srchtmp) {
	    printf("'%s'\n", srchtmp);
	  } else {
	    printf("NULL\n");
	  }
	} else {
	  printf("search init failed\n");
	}

	printf("running a search for string 'uri'...\n");
	if ((mycs = config_search_init(mycfg, NULL, "uri"))) {
	  printf("get first thing got key=");
	  srchtmp = config_search_string_firstkey(mycs);
	  if (srchtmp) {
	    printf("'%s'\n", srchtmp);
	  } else {
	    printf("NULL\n");
	  }
	} else {
	  printf("search init failed\n");
	}

/*   	config_destroy(mycfg); */
    }

    if (fd) 
	close(fd);

    if (filebuf)
	free(filebuf);

    return 0;
}
Ejemplo n.º 2
0
static int add_dbus(const char *path, const char *fname, const char *type) {
        _cleanup_free_ char *name = NULL, *exec = NULL, *user = NULL, *service = NULL;

        const ConfigTableItem table[] = {
                { "D-BUS Service", "Name", config_parse_string, 0, &name },
                { "D-BUS Service", "Exec", config_parse_string, 0, &exec },
                { "D-BUS Service", "User", config_parse_string, 0, &user },
                { "D-BUS Service", "SystemdService", config_parse_string, 0, &service },
                { },
        };

        char *p;
        int r;

        assert(path);
        assert(fname);

        p = strjoina(path, "/", fname);
        r = config_parse(NULL, p, NULL,
                         "D-BUS Service\0",
                         config_item_table_lookup, table,
                         true, false, true, NULL);
        if (r < 0)
                return r;

        if (!name) {
                log_warning("Activation file %s lacks name setting, ignoring.", p);
                return 0;
        }

        if (!service_name_is_valid(name)) {
                log_warning("Bus service name %s is not valid, ignoring.", name);
                return 0;
        }

        if (streq(name, "org.freedesktop.systemd1")) {
                log_debug("Skipping %s, identified as systemd.", p);
                return 0;
        }

        if (service) {
                if (!unit_name_is_valid(service, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
                        log_warning("Unit name %s is not valid, ignoring.", service);
                        return 0;
                }
                if (!endswith(service, ".service")) {
                        log_warning("Bus names can only activate services, ignoring %s.", p);
                        return 0;
                }
        } else {
                if (streq(exec, "/bin/false") || !exec) {
                        log_warning("Neither service name nor binary path specified, ignoring %s.", p);
                        return 0;
                }

                if (exec[0] != '/') {
                        log_warning("Exec= in %s does not start with an absolute path, ignoring.", p);
                        return 0;
                }
        }

        return create_dbus_files(p, name, service, exec, user, type);
}
Ejemplo n.º 3
0
Result httpwn_setup(char *serverconfig_localpath)
{
	Result ret = 0;
	u64 http_sysmodule_titleid = 0x0004013000002902ULL;
	AM_TitleEntry title_entry;

	u8 *cert = (u8*)builtin_rootca_der;
	u32 certsize = builtin_rootca_der_size;

	u8 *filebuffer;
	u32 filebuffer_size = 0x100000;
	u32 statuscode = 0;

	configctx config;
	targeturlctx *first_targeturlctx = NULL;

	FILE *f;

	memset(&config, 0, sizeof(configctx));
	config.first_targeturlctx = &first_targeturlctx;

	ret = amInit();
	if(ret!=0)
	{
		printf("Failed to initialize AM: 0x%08x.\n", (unsigned int)ret);
		if(ret==0xd8e06406)
		{
			printf("The AM service is inaccessible. With the *hax payloads this should never happen. This is normal with plain ninjhax v1.x: this app isn't usable from ninjhax v1.x without any further hax.\n");
		}
		return ret;
	}

	ret = AM_ListTitles(0, 1, &http_sysmodule_titleid, &title_entry);
	amExit();
	if(ret!=0)
	{
		printf("Failed to get the HTTP sysmodule title-version: 0x%08x.\n", (unsigned int)ret);
		return ret;
	}

	http_codebin_buf = NULL;
	http_codebin_buf32 = NULL;
	http_codebin_size = 0;

	ret = loadcodebin(http_sysmodule_titleid, MEDIATYPE_NAND, &http_codebin_buf, &http_codebin_size);
	if(R_FAILED(ret))
	{
		printf("Failed to load the HTTP sysmodule codebin: 0x%08x.\n", (unsigned int)ret);
		return ret;
	}

	http_codebin_buf32 = (u32*)http_codebin_buf;

	ret = httpcInit(0x1000);
	if(ret!=0)
	{
		printf("Failed to initialize HTTPC: 0x%08x.\n", (unsigned int)ret);
		if(ret==0xd8e06406)
		{
			printf("The HTTPC service is inaccessible. With the *hax payload this may happen if the process this app is running under doesn't have access to that service. Please try rebooting the system, boot *hax payload, then directly launch the app.\n");
		}

		free(http_codebin_buf);

		return ret;
	}

	filebuffer = malloc(filebuffer_size);
	if(filebuffer==NULL)
	{
		printf("Failed to allocate the config filebuffer.\n");
		ret = -2;
		httpcExit();
		free(http_codebin_buf);
		return ret;
		
	}
	memset(filebuffer, 0, filebuffer_size);

	printf("Downloading config...\n");
	ret = download_config("https://yls8.mtheall.com/ctr-httpwn/config.php", cert, certsize, filebuffer, filebuffer_size-1, &statuscode);
	if(ret!=0)
	{
		printf("Config downloading failed: 0x%08x.\n", (unsigned int)ret);

		if(statuscode==500)
		{
			printf("HTTP status-code 500 was returned, server reply:\n%s\n", (char*)filebuffer);
		}

		f = fopen(serverconfig_localpath, "rb");
		if(f)
		{
			printf("Use the cached server_config from SD instead?\nPress the A button to continue, B to abort.\n");
			while(1)
			{
				gspWaitForVBlank();
				hidScanInput();
				if(hidKeysDown() & KEY_A)break;
				if(hidKeysDown() & KEY_B)
				{
					fclose(f);
					httpcExit();
					free(http_codebin_buf);
					return ret;
				}
			}

			memset(filebuffer, 0, filebuffer_size);
			fread(filebuffer, 1, filebuffer_size-1, f);
			fclose(f);
		}
		else
		{
			httpcExit();
			free(http_codebin_buf);
			return ret;
		}
	}
	else
	{
		unlink(serverconfig_localpath);
		f = fopen(serverconfig_localpath, "wb");
		if(f)
		{
			fwrite(filebuffer, 1, strlen((char*)filebuffer), f);
			fclose(f);
		}
	}

	ret = config_parse(&config, (char*)filebuffer);

	if(ret==0)
	{
		if(title_entry.version != 13318)
		{
			printf("The installed HTTP sysmodule version(v%u) is not supported.", title_entry.version);
			if(config.incompatsysver_message[0])printf(" %s", config.incompatsysver_message);
			printf("\n");

			httpcExit();
			free(http_codebin_buf);
			free(filebuffer);

			return -1;
		}

		if(display_config_message(&config, "Message from the server:"))
		{
			httpcExit();
			free(http_codebin_buf);
			free(filebuffer);
			return 0;
		}
	}

	if(ret==0)
	{
		f = fopen("user_config.xml", "rb");
		if(f)
		{
			printf("Loading+parsing user_config.xml since it exists on SD...\n");

			memset(filebuffer, 0, filebuffer_size);
			fread(filebuffer, 1, filebuffer_size-1, f);
			fclose(f);

			ret = config_parse(&config, (char*)filebuffer);

			if(ret==0)
			{
				if(display_config_message(&config, "Message from the user_config:"))
				{
					httpcExit();
					free(http_codebin_buf);
					free(filebuffer);
					return 0;
				}
			}
		}
	}

	if(ret!=0)
	{
		printf("Config parsing failed: 0x%08x.\n", (unsigned int)ret);
		httpcExit();
		free(http_codebin_buf);
		free(filebuffer);
		return ret;
	}

	f = fopen("user_nim_rootcertchain_rootca.der", "rb");
	if(f)
	{
		printf("Loading user_nim_rootcertchain_rootca.der since it exists on SD, which will be used instead of the built-in ctr-httpwn cert...\n");

		memset(filebuffer, 0, filebuffer_size);
		certsize = fread(filebuffer, 1, filebuffer_size, f);
		fclose(f);

		cert = filebuffer;
	}

	printf("Preparing the haxx...\n");
	ret = http_haxx("http://localhost/", cert, certsize, first_targeturlctx);//URL doesn't matter much since this won't actually be requested over the network.
	config_freemem(&config);
	httpcExit();
	free(http_codebin_buf);
	free(filebuffer);
	if(ret!=0)
	{
		printf("Haxx setup failed: 0x%08x.\n", (unsigned int)ret);
		return ret;
	}

	return ret;
}
Ejemplo n.º 4
0
// TODO : Reload of individual physical parameters is not handled
static int
rehash_daemon(struct radclock_handle *handle, uint32_t param_mask)
{
	struct radclock_config *conf;
	int err;

	JDEBUG

	conf = handle->conf;

	verbose(LOG_NOTICE, "Update of configuration parameters");
	/* Parse the configuration file */
	if (!(config_parse(conf, &param_mask, handle->is_daemon))) {
		verbose(LOG_ERR, "Error: Rehash of configuration file failed");
		return (1);
	}
	
	if (HAS_UPDATE(param_mask, UPDMASK_SYNCHRO_TYPE))
		verbose(LOG_WARNING, "It is not possible to change the type of client "
				"synchronisation on the fly!");
	
	//XXX Should check we have only one input selected
	if (HAS_UPDATE(param_mask, UPDMASK_NETWORKDEV) ||
			HAS_UPDATE(param_mask, UPDMASK_SYNC_IN_PCAP) ||
			HAS_UPDATE(param_mask, UPDMASK_SYNC_IN_ASCII))
	{
		verbose(LOG_WARNING, "It is not possible to change the type of input "
				"on the fly!");
		verbose(LOG_WARNING, "Parameter is parsed and saved but not taken "
				"into account");
		CLEAR_UPDATE(param_mask, UPDMASK_NETWORKDEV);
		CLEAR_UPDATE(param_mask, UPDMASK_SYNC_IN_PCAP);
		CLEAR_UPDATE(param_mask, UPDMASK_SYNC_IN_ASCII);
	}

// TODO The old naming convention for server IPC could be changed for clarity.
// Would require an update of config file parsing.
	if (HAS_UPDATE(param_mask, UPDMASK_SERVER_IPC)) {
		switch (conf->server_ipc) {
		case BOOL_ON:
			err = shm_init_writer(handle->clock);
			if (err)
				return (1);
			verbose(LOG_NOTICE, "IPC Shared Memory ready");
			break;
		case BOOL_OFF:
			/* Detach for SHM segment, but do not destroy it */
			shm_detach(handle->clock);
			break;
		}
	}

	if (HAS_UPDATE(param_mask, UPDMASK_SERVER_NTP)) {
		switch (conf->server_ntp) {
		case BOOL_ON:
			/* We start NTP server */
			start_thread_NTP_SERV(handle);
			break;
		case BOOL_OFF:
			/* We stop the NTP server */
			handle->pthread_flag_stop |= PTH_NTP_SERV_STOP;
// TODO should we join the thread in here ... requires testing
//			pthread_join(handle->threads[PTH_NTP_SERV], &thread_status);
			break;
		}
	}

	if (HAS_UPDATE(param_mask, UPDMASK_SERVER_VM_UDP)) {
		switch (conf->server_vm_udp) {
		case BOOL_ON:	
			/* We start NTP server */
			start_thread_VM_UDP_SERV(handle);
			break;
		case BOOL_OFF:
			/* We stop the NTP server */
			clock_handle->pthread_flag_stop |= PTH_VM_UDP_SERV_STOP; 
// TODO should we join the thread in here ... requires testing
//			pthread_join(clock_handle->threads[PTH_VM_UDP_SERV], &thread_status);
			break;
		}
	}

	/* Management of output files */
	if (HAS_UPDATE(param_mask, UPDMASK_SYNC_OUT_ASCII)) {
		close_output_stamp(handle);
		open_output_stamp(handle);
		CLEAR_UPDATE(param_mask, UPDMASK_SYNC_OUT_ASCII);
	}

	if (HAS_UPDATE(param_mask, UPDMASK_CLOCK_OUT_ASCII)) {
		close_output_matlab(handle);
		open_output_matlab(handle);
		CLEAR_UPDATE(param_mask, UPDMASK_CLOCK_OUT_ASCII);
	}

	if (HAS_UPDATE(param_mask, UPDMASK_SYNC_OUT_PCAP)) {
		err = update_dumpout_source(handle, (struct stampsource *)handle->stamp_source);
		if (err != 0) {
			verbose(LOG_ERR, "Things are probably out of control. Bye !");
			exit (1);
		}
		CLEAR_UPDATE(param_mask, UPDMASK_SYNC_OUT_PCAP);
	}


	/* Change the filter on the open BPF device */
	if (HAS_UPDATE(param_mask, UPDMASK_SYNCHRO_TYPE) ||
			HAS_UPDATE(param_mask, UPDMASK_SERVER_NTP) ||
			HAS_UPDATE(param_mask, UPDMASK_TIME_SERVER) ||
			HAS_UPDATE(param_mask, UPDMASK_HOSTNAME))
	{
		err = update_filter_source(handle, (struct stampsource *)handle->stamp_source);
		if (err != 0)  {
			verbose(LOG_ERR, "Things are probably out of control. Bye !");
			exit (1);
		}
		CLEAR_UPDATE(param_mask, UPDMASK_TIME_SERVER);
		CLEAR_UPDATE(param_mask, UPDMASK_HOSTNAME);
	}

	/*  Print configuration actually used */
	config_print(LOG_NOTICE, conf);

	/* Reinit rehash flag */
//	handle->unix_signal = 0;

	/* Push param_mask into the config so that the algo sees it,
	 * since only algo related thing should be remaining
	 */
	conf->mask = param_mask;

	return (0);
}
Ejemplo n.º 5
0
int
main(int argc, char *argv[])
{
	struct radclock_handle *handle;
	struct radclock_config *conf;
	int is_daemon = 0;

	/* File and command line reading */
	int ch;
	
	/* Mask variable used to know which parameter to update */
	uint32_t param_mask = 0;

	/* PID lock file for daemon */
	int daemon_pid_fd 		= 0;

	/* Initialize PID lockfile to a default value */
	const char *pid_lockfile = DAEMON_LOCK_FILE;

	/* Misc */
	int err;

	/* turn off buffering to allow results to be seen immediately if JDEBUG*/
	#ifdef WITH_JDEBUG
	setvbuf(stdout, (char *)NULL, _IONBF, 0);
	setvbuf(stderr, (char *)NULL, _IONBF, 0);
	#endif

	/*
	 * Register Signal handlers. We use sigaction() instead of signal() to catch
	 * signals. The main reason concerns the SIGHUP signal. In Linux, the
	 * syscalls are restarted as soon as the signal handler returns. This
	 * prevent pcap_breakloop() to do its job (see pcap man page). Using
	 * sigaction() we can overwrite the default flag to prevent this behavior
	 */
	sigset_t block_mask;
	sigfillset (&block_mask);
	struct sigaction sig_struct;


	sig_struct.sa_handler = signal_handler;
	sig_struct.sa_mask = block_mask;
	sig_struct.sa_flags = 0;

	sigaction(SIGHUP,  &sig_struct, NULL); /* hangup signal (1) */
	sigaction(SIGTERM, &sig_struct, NULL); /* software termination signal (15) */
	sigaction(SIGUSR1, &sig_struct, NULL); /* user signal 1 (30) */
	sigaction(SIGUSR2, &sig_struct, NULL); /* user signal 2 (31) */


	/* Initialise verbose data to defaults */
	verbose_data.handle = NULL;
	verbose_data.is_daemon = 0;
	verbose_data.verbose_level = 0;
	verbose_data.fd = NULL;
	strcpy(verbose_data.logfile, "");
	pthread_mutex_init(&(verbose_data.vmutex), NULL);


	/* Management of configuration options */
	conf = (struct radclock_config *) malloc(sizeof(struct radclock_config));
	JDEBUG_MEMORY(JDBG_MALLOC, conf);
	memset(conf, 0, sizeof(struct radclock_config));

	/*
	 * The command line arguments are given the priority and override possible
	 * values of the configuration file But the configuration file is parsed
	 * after the command line because we need to know if we are running a daemon
	 * or not (configuration file is different if we run a daemon or not). Use
	 * the param_mask variable to indicate which values have to be updated from
	 * the config file
	 */

	/* Initialize the physical parameters, and other config parameters. */
	config_init(conf);

	/* Init the mask we use to signal configuration updates */
	param_mask = UPDMASK_NOUPD;

	/* Reading the command line arguments */
	while ((ch = getopt(argc, argv, "dxvhc:i:l:n:t:r:w:s:a:o:p:P:U:D:V")) != -1)
		switch (ch) {
		case 'x':
			SET_UPDATE(param_mask, UPDMASK_SERVER_IPC);
			conf->server_ipc = BOOL_OFF;
			break;
		case 'c':
			strcpy(conf->conffile, optarg);
			break;
		case 'd':
			is_daemon = 1;
			break;
		case 'l':
			strcpy(conf->logfile, optarg);
			break;
		case 'n':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_HOSTNAME);
			strcpy(conf->hostname, optarg);
			break;
		case 'p':
			SET_UPDATE(param_mask, UPDMASK_POLLPERIOD);
			if ( atoi(optarg) < RAD_MINPOLL ) {
				conf->poll_period = RAD_MINPOLL;
				fprintf(stdout, "Warning: Poll period too small, set to %d\n",
					conf->poll_period);
			}
			else
				conf->poll_period = atoi(optarg);
			if ( conf->poll_period > RAD_MAXPOLL ) {
				conf->poll_period = RAD_MAXPOLL;
				fprintf(stdout, "Warning: Poll period too big, set to %d\n",
						conf->poll_period);
			}
			break;
		case 't':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_TIME_SERVER);
			strcpy(conf->time_server, optarg);
			break;
		case 'i':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_NETWORKDEV);
			strcpy(conf->network_device, optarg);
			break;
		case 'r':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_SYNC_IN_PCAP);
			strcpy(conf->sync_in_pcap, optarg);
			break;
		case 'w':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_SYNC_OUT_PCAP);
			strcpy(conf->sync_out_pcap, optarg);
			break;
		case 's':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_SYNC_IN_ASCII);
			strcpy(conf->sync_in_ascii, optarg);
			break;
		case 'a':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_SYNC_OUT_ASCII);
			strcpy(conf->sync_out_ascii, optarg);
			break;
		case 'o':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_CLOCK_OUT_ASCII);
			strcpy(conf->clock_out_ascii, optarg);
			break;
		case 'P':
			if (strlen(optarg) > MAXLINE) {
				fprintf(stdout, "ERROR: parameter too long\n");
				exit (1);
			}
			SET_UPDATE(param_mask, UPDMASK_PID_FILE);
			pid_lockfile = optarg;
			break;
		case 'v':
			SET_UPDATE(param_mask, UPDMASK_VERBOSE);
			conf->verbose_level++;
			break;
		case 'U':
			SET_UPDATE(param_mask, UPD_NTP_UPSTREAM_PORT);
			conf->ntp_upstream_port = atoi(optarg);
			break;
		case 'D':
			SET_UPDATE(param_mask, UPD_NTP_DOWNSTREAM_PORT);
			conf->ntp_downstream_port = atoi(optarg);
			break;
		case 'V':
			fprintf(stdout, "%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
		case 'h':
		case '?':
		default:
			usage();
		}

	argc -= optind;
	argv += optind;

	/* Little hack to deal with parsing of long options in the command line */
	if (conf->verbose_level > 0)
		SET_UPDATE(param_mask, UPDMASK_VERBOSE);


	/* Create the radclock handle */
	clock_handle = create_handle(conf, is_daemon);
	if (!clock_handle) {
		verbose(LOG_ERR, "Could not create clock handle");
		return (-1);
	}
	handle = clock_handle;


	/*
	 * Have not parsed the config file yet, so will have to do it again since it
	 * may not be the right settings. Handles config parse messages in the right
	 * log file though. So far clock has not been sent to init, no syscall
	 * registered, pass a NULL pointer to verbose.
	 */
	set_verbose(handle, handle->conf->verbose_level, 0);
	set_logger(logger_verbose_bridge);
	
	/* Daemonize now, so that we can open the log files and close connection to
	 * stdin since we parsed the command line
	 */
	if (handle->is_daemon) {
		struct stat sb;
		if (stat(RADCLOCK_RUN_DIRECTORY, &sb) < 0) {
			if (mkdir(RADCLOCK_RUN_DIRECTORY, 0755) < 0) {
				verbose(LOG_ERR, "Cannot create %s directory. Run as root or "
						"(!daemon && !server)", RADCLOCK_RUN_DIRECTORY);
				return (1);
			}
		}
		/* Check this everytime in case something happened */
		chmod(RADCLOCK_RUN_DIRECTORY, 00755);

		if (!(daemonize(pid_lockfile, &daemon_pid_fd))) {
			fprintf(stderr, "Error: did not manage to create the daemon\n");
			exit(EXIT_FAILURE);
		}
	}

	/*
	 * Retrieve configuration from the config file (write it down if it does not
	 * exist) That should be the only occasion when get_config() is called and
	 * the param_mask is not positioned to UPDMASK_NOUPD !!!  Only the
	 * parameters not specified on the command line are updated
	 */
	if (!config_parse(handle->conf, &param_mask, handle->is_daemon))
		return (0);

	/*
	 * Now that we have the configuration to use (verbose level),  let's
	 * initialise the verbose level to correct value
	 */
	set_verbose(handle, handle->conf->verbose_level, 0);
	set_logger(logger_verbose_bridge);

	/* Check for incompatible configurations and correct them */
	if (( handle->conf->synchro_type == SYNCTYPE_SPY ) ||
		( handle->conf->synchro_type == SYNCTYPE_PIGGY ))
	{
		if (handle->conf->server_ntp == BOOL_ON) {
			verbose(LOG_ERR, "Configuration error. Disabling NTP server "
					"(incompatible with spy or piggy mode).");
			handle->conf->server_ntp = BOOL_OFF;
		}
		if ( handle->conf->adjust_sysclock == BOOL_ON )
		{
			verbose(LOG_ERR, "Configuration error. Disabling adjust system "
					"clock (incompatible with spy or piggy mode).");
			handle->conf->adjust_sysclock = BOOL_OFF;
		}
	}
	
	/* Diagnosis output for the configuration used */
	config_print(LOG_NOTICE, handle->conf);

	/* Reinit the mask that counts updated values */
	param_mask = UPDMASK_NOUPD;


	// TODO extract extra checks from is_live_source and make an input fix 
	// function instead, would be clearer
	// TODO the conf->network_device business is way too messy


	/*
	 * Need to know if we are replaying data or not. If not, no need to create
	 * shared global data on the system or open a BPF. This define input to the
	 * init of the radclock handle
	 */
	if (!is_live_source(handle))
		handle->run_mode = RADCLOCK_SYNC_DEAD;
	else
		handle->run_mode = RADCLOCK_SYNC_LIVE;

	/* Init clock handle and private data */
	if (handle->run_mode == RADCLOCK_SYNC_LIVE) {
		err = clock_init_live(handle->clock, &handle->rad_data);
		if (err) {
			verbose(LOG_ERR, "Could not initialise the RADclock");
			return (1);
		}
	}

	/* Init radclock specific stuff */
	err = init_handle(handle);
	if (err) {
		verbose(LOG_ERR, "Radclock process specific init failed.");
		return (1);
	}

	/*
	 * Now 2 cases. Either we are running live or we are replaying some data.
	 * If we run live, we will spawn some threads and do some smart things.  If
	 * we replay data, no need to do all of that, we access data and process it
	 * in the same thread.
	 */
	if (handle->run_mode == RADCLOCK_SYNC_DEAD) {

// TODO : manage peers better !!

		struct bidir_peer peer;
		/* Some basic initialisation which is required */
		init_peer_stamp_queue(&peer);
		peer.stamp_i = 0;
		// TODO XXX Need to manage peers better !!
		/* Register active peer */
		handle->active_peer = (void *)&peer;
		while (1) {
			err = process_rawdata(handle, &peer);
			if (err < 0)
				break;
		}

		destroy_peer_stamp_queue(&peer);
	}

	/*
	 * We loop in here in case we are rehashed. Threads are (re-)created every
	 * time we loop in
	 */
	else {
		while (err == 0) {
			err = start_live(handle);
			if (err == 0) {
				if (rehash_daemon(handle, param_mask))
					verbose(LOG_ERR, "SIGHUP - Failed to rehash daemon !!.");
			}
		}
	}


	// TODO: look into making the stats a separate structure. Could be much
	// TODO: easier to manage
	long int n_stamp;
	unsigned int ref_count;
	n_stamp = ((struct bidir_output *)handle->algo_output)->n_stamps;
	ref_count = ((struct stampsource*)(handle->stamp_source))->ntp_stats.ref_count;
	verbose(LOG_NOTICE, "%u NTP packets captured", ref_count);
	verbose(LOG_NOTICE,"%ld missed NTP packets", ref_count - 2 * n_stamp);
	verbose(LOG_NOTICE, "%ld valid timestamp tuples extracted", n_stamp);

	/* Close output files */
	close_output_stamp(handle);

	/* Print out last good phat value */
	verbose(LOG_NOTICE, "Last estimate of the clock source period: %12.10lg",
			RAD_DATA(handle)->phat);

	/* Say bye and close syslog */
	verbose(LOG_NOTICE, "RADclock stopped");
	if (handle->is_daemon)
		closelog ();
	unset_verbose();

	/* Free the lock file */
	if (handle->is_daemon) {
		write(daemon_pid_fd, "", 0);
		lockf(daemon_pid_fd, F_ULOCK, 0);
	}

	// TODO:  all the destructors have to be re-written
	destroy_source(handle, (struct stampsource *)(handle->stamp_source));


	/* Clear thread stuff */
	pthread_mutex_destroy(&(handle->globaldata_mutex));
	pthread_mutex_destroy(&(handle->wakeup_mutex));
	pthread_cond_destroy(&(handle->wakeup_cond));

	/* Detach IPC shared memory if were running as IPC server. */
	if (handle->conf->server_ipc == BOOL_ON)
		shm_detach(handle->clock);

	/* Free the clock structure. All done. */
	pthread_mutex_destroy(&(handle->pcap_queue->rdb_mutex));
	pthread_mutex_destroy(&(handle->ieee1588eq_queue->rdb_mutex));
	free(handle->pcap_queue);
	free(handle->ieee1588eq_queue);
	free(handle);
	handle = NULL;
	clock_handle = NULL;

	exit(EXIT_SUCCESS);
}
Ejemplo n.º 6
0
int parse_sleep_config(const char *verb, char ***_modes, char ***_states) {

        _cleanup_strv_free_ char
                **suspend_mode = NULL, **suspend_state = NULL,
                **hibernate_mode = NULL, **hibernate_state = NULL,
                **hybrid_mode = NULL, **hybrid_state = NULL;
        char **modes, **states;

        const ConfigTableItem items[] = {
                { "Sleep",   "SuspendMode",      config_parse_strv,  0, &suspend_mode  },
                { "Sleep",   "SuspendState",     config_parse_strv,  0, &suspend_state },
                { "Sleep",   "HibernateMode",    config_parse_strv,  0, &hibernate_mode  },
                { "Sleep",   "HibernateState",   config_parse_strv,  0, &hibernate_state },
                { "Sleep",   "HybridSleepMode",  config_parse_strv,  0, &hybrid_mode  },
                { "Sleep",   "HybridSleepState", config_parse_strv,  0, &hybrid_state },
                {}
        };

        int r;
        _cleanup_fclose_ FILE *f;

        f = fopen(PKGSYSCONFDIR "/sleep.conf", "re");
        if (!f)
                log_full(errno == ENOENT ? LOG_DEBUG: LOG_WARNING,
                         "Failed to open configuration file " PKGSYSCONFDIR "/sleep.conf: %m");
        else {
                r = config_parse(NULL, PKGSYSCONFDIR "/sleep.conf", f, "Sleep\0",
                                 config_item_table_lookup, (void*) items, false, false, NULL);
                if (r < 0)
                        log_warning("Failed to parse configuration file: %s", strerror(-r));
        }

        if (streq(verb, "suspend")) {
                /* empty by default */
                USE(modes, suspend_mode);

                if (suspend_state)
                        USE(states, suspend_state);
                else
                        states = strv_new("mem", "standby", "freeze", NULL);

        } else if (streq(verb, "hibernate")) {
                if (hibernate_mode)
                        USE(modes, hibernate_mode);
                else
                        modes = strv_new("platform", "shutdown", NULL);

                if (hibernate_state)
                        USE(states, hibernate_state);
                else
                        states = strv_new("disk", NULL);

        } else if (streq(verb, "hybrid-sleep")) {
                if (hybrid_mode)
                        USE(modes, hybrid_mode);
                else
                        modes = strv_new("suspend", "platform", "shutdown", NULL);

                if (hybrid_state)
                        USE(states, hybrid_state);
                else
                        states = strv_new("disk", NULL);

        } else
                assert_not_reached("what verb");

        if ((!modes && !streq(verb, "suspend")) || !states) {
                strv_free(modes);
                strv_free(states);
                return log_oom();
        }

        *_modes = modes;
        *_states = states;
        return 0;
}
Ejemplo n.º 7
0
static int module_init(void)
{
	config_parse(conf_cur());
	aufilt_register(&preproc);
	return 0;
}
Ejemplo n.º 8
0
int main(int argc, char **argv) {

	log_file_disable();
	log_shell_enable();
	log_level_set(LOG_NOTICE);

	progname = malloc(16);
	strcpy(progname, "pilight-control");

	struct options_t *options = NULL;
	struct ssdp_list_t *ssdp_list = NULL;

	int sockfd = 0;
    char *recvBuff = NULL;
	char *message = NULL;
	char *pch = NULL;
	steps_t steps = WELCOME;

	char device[50];
	char location[50];
	char state[10] = {'\0'};
	char values[255] = {'\0'};
	struct conf_locations_t *slocation = NULL;
	struct conf_devices_t *sdevice = NULL;
	int has_values = 0;

	char *server = NULL;
	unsigned short port = 0;

	JsonNode *json = NULL;
	JsonNode *jconfig = NULL;
	JsonNode *jcode = NULL;
	JsonNode *jvalues = NULL;

	/* Define all CLI arguments of this program */
	options_add(&options, 'H', "help", no_value, 0, NULL);
	options_add(&options, 'V', "version", no_value, 0, NULL);
	options_add(&options, 'l', "location", has_value, 0, NULL);
	options_add(&options, 'd', "device", has_value, 0,  NULL);
	options_add(&options, 's', "state", has_value, 0,  NULL);
	options_add(&options, 'v', "values", has_value, 0,  NULL);
	options_add(&options, 'S', "server", has_value, 0, "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
	options_add(&options, 'P', "port", has_value, 0, "[0-9]{1,4}");

	/* Store all CLI arguments for later usage
	   and also check if the CLI arguments where
	   used correctly by the user. This will also
	   fill all necessary values in the options struct */
	while(1) {
		int c;
		c = options_parse(&options, argc, argv, 1, &optarg);
		if(c == -1)
			break;
		if(c == -2)
			c = 'H';
		switch(c) {
			case 'H':
				printf("\t -H --help\t\t\tdisplay this message\n");
				printf("\t -V --version\t\t\tdisplay version\n");
				printf("\t -S --server=x.x.x.x\t\tconnect to server address\n");
				printf("\t -P --port=xxxx\t\t\tconnect to server port\n");
				printf("\t -l --location=location\t\tthe location in which the device resides\n");
				printf("\t -d --device=device\t\tthe device that you want to control\n");
				printf("\t -s --state=state\t\tthe new state of the device\n");
				printf("\t -v --values=values\t\tspecific comma separated values, e.g.:\n");
				printf("\t\t\t\t\t-v dimlevel=10\n");
				exit(EXIT_SUCCESS);
			break;
			case 'V':
				printf("%s %s\n", progname, VERSION);
				exit(EXIT_SUCCESS);
			break;
			case 'l':
				strcpy(location, optarg);
			break;
			case 'd':
				strcpy(device, optarg);
			break;
			case 's':
				strcpy(state, optarg);
			break;
			case 'v':
				strcpy(values, optarg);
			break;
			case 'S':
				server = realloc(server, strlen(optarg)+1);
				strcpy(server, optarg);
			break;
			case 'P':
				port = (unsigned short)atoi(optarg);
			break;
			default:
				printf("Usage: %s -l location -d device -s state\n", progname);
				exit(EXIT_SUCCESS);
			break;
		}
	}
	options_delete(options);

	if(strlen(location) == 0 || strlen(device) == 0 || strlen(state) == 0) {
		printf("Usage: %s -l location -d device -s state\n", progname);
		exit(EXIT_SUCCESS);
	}

	if(server && port > 0) {
		if((sockfd = socket_connect(server, port)) == -1) {
			logprintf(LOG_ERR, "could not connect to pilight-daemon");
			exit(EXIT_FAILURE);
		}
	} else if(ssdp_seek(&ssdp_list) == -1) {
		logprintf(LOG_ERR, "no pilight ssdp connections found");
		goto close;
	} else {
		if((sockfd = socket_connect(ssdp_list->ip, ssdp_list->port)) == -1) {
			logprintf(LOG_ERR, "could not connect to pilight-daemon");
			goto close;
		}
		sfree((void *)&ssdp_list);
	}

	protocol_init();

	while(1) {
		if(steps > WELCOME) {
			/* Clear the receive buffer again and read the welcome message */
			if(steps == CONFIG) {
				if((recvBuff = socket_read_big(sockfd)) != NULL) {
					json = json_decode(recvBuff);
					json_find_string(json, "message", &message);
				} else {
					goto close;
				}
			} else {
				if((recvBuff = socket_read(sockfd)) != NULL) {
					json = json_decode(recvBuff);
					json_find_string(json, "message", &message);
				} else {
					goto close;
				}
			}
		usleep(100);
		}
		switch(steps) {
			case WELCOME:
				socket_write(sockfd, "{\"message\":\"client controller\"}");
				steps=IDENTIFY;
			break;
			case IDENTIFY:
				if(strcmp(message, "accept client") == 0) {
					steps=REQUEST;
				}
				if(strcmp(message, "reject client") == 0) {
					steps=REJECT;
				}
			case REQUEST:
				socket_write(sockfd, "{\"message\":\"request config\"}");
				steps=CONFIG;
				json_delete(json);
			break;
			case CONFIG:
				if((jconfig = json_find_member(json, "config")) != NULL) {
					config_parse(jconfig);
					if(config_get_location(location, &slocation) == 0) {
						if(config_get_device(location, device, &sdevice) == 0) {
							JsonNode *joutput = json_mkobject();
							jcode = json_mkobject();
							jvalues = json_mkobject();

							json_append_member(jcode, "location", json_mkstring(location));
							json_append_member(jcode, "device", json_mkstring(device));

							pch = strtok(values, ",=");
							while(pch != NULL) {
								char *name = strdup(pch);
								pch = strtok(NULL, ",=");
								if(pch == NULL) {
									break;
								} else {
									char *val = strdup(pch);
									if(pch != NULL) {
										if(config_valid_value(location, device, name, val) == 0) {
											if(isNumeric(val) == EXIT_SUCCESS) {
												json_append_member(jvalues, name, json_mknumber(atoi(val)));
											} else {
												json_append_member(jvalues, name, json_mkstring(val));
											}
											has_values = 1;
										} else {
											logprintf(LOG_ERR, "\"%s\" is an invalid value for device \"%s\"", name, device);
											goto close;
										}
									} else {
										logprintf(LOG_ERR, "\"%s\" is an invalid value for device \"%s\"", name, device);
										goto close;
									}
									pch = strtok(NULL, ",=");
									if(pch == NULL) {
										break;
									}
								}
							}

							if(config_valid_state(location, device, state) == 0) {
								json_append_member(jcode, "state", json_mkstring(state));
							} else {
								logprintf(LOG_ERR, "\"%s\" is an invalid state for device \"%s\"", state, device);
								goto close;
							}

							if(has_values == 1) {
								json_append_member(jcode, "values", jvalues);
							} else {
								json_delete(jvalues);
							}

							json_append_member(joutput, "message", json_mkstring("send"));
							json_append_member(joutput, "code", jcode);
							char *output = json_stringify(joutput, NULL);
							socket_write(sockfd, output);
							sfree((void *)&output);
							json_delete(joutput);
						} else {
							logprintf(LOG_ERR, "the device \"%s\" does not exist", device);
							goto close;
						}
					} else {
						logprintf(LOG_ERR, "the location \"%s\" does not exist", location);
						goto close;
					}
				}
				json_delete(json);
				goto close;
			break;
			case REJECT:
			default:
				json_delete(json);
				goto close;
			break;
		}
	}
close:
	if(sockfd > 0) {
		socket_close(sockfd);
	}
	if(server) {
		sfree((void *)&server);
	}
	log_shell_disable();
	config_gc();
	protocol_gc();
	socket_gc();
	options_gc();
	log_gc();
	sfree((void *)&progname);

return EXIT_SUCCESS;
}
Ejemplo n.º 9
0
int main(int argc, char *argv[])
{
	int sd = -1;
	char *conf_file = NULL;
	struct mosquitto *mosq;
	struct module *md;
	struct device *dev;
	int rc;
	int i;
	
	gbuf[0] = 0;

	if (!quiet) printf("Version: %s\n", version);

    signal(SIGINT, handle_signal);
    signal(SIGTERM, handle_signal);
	signal(SIGUSR1, handle_signal);
	signal(SIGUSR2, handle_signal);
	signal(SIGALRM, each_sec);
	
	for (i=1; i<argc; i++) {
		if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")){
			if(i==argc-1){
                fprintf(stderr, "Error: -c argument given but no file specified.\n\n");
				print_usage(argv[0]);
                return 1;
            }else{
				conf_file = argv[i+1];
			}
			i++;
		}else if(!strcmp(argv[i], "--quiet")){
				quiet = true;
		}else{
				fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]);
				print_usage(argv[0]);
				return 1;
		}
	}
	
	if (!conf_file) {
		fprintf(stderr, "Error: No config file given.\n");
		return 1;
	}

	memset(&config, 0, sizeof(struct bridge_config));
	if (config_parse(conf_file, &config)) return 1;
	
	if (quiet) config.debug = 0;
	if (config.debug != 0) printf("Debug: %d\n", config.debug);

	rc = bridge_init(&bridge, config.id, MODULES_BRIDGE_ID);
	if (rc) {
		if (config.debug) printf("Error: Failed to initialize bridge: %d\n", rc);
		return 1;
	}

	mosquitto_lib_init();
	mosq = mosquitto_new(config.id, true, NULL);
	if(!mosq){
		fprintf(stderr, "Error creating mqtt instance.\n");
		switch(errno){
			case ENOMEM:
				fprintf(stderr, " out of memory.\n");
				break;
			case EINVAL:
				fprintf(stderr, " invalid id.\n");
				break;
		}
		return 1;
	}
	snprintf(gbuf, GBUF_SIZE, "%d", PROTOCOL_TIMEOUT);
	mosquitto_will_set(mosq, bridge.bridge_dev->status_topic, strlen(gbuf), gbuf, config.mqtt_qos, MQTT_RETAIN);

	mosquitto_connect_callback_set(mosq, on_mqtt_connect);
	mosquitto_disconnect_callback_set(mosq, on_mqtt_disconnect);
	mosquitto_message_callback_set(mosq, on_mqtt_message);
	mosquitto_user_data_set(mosq, &sd);

	md = bridge_add_module(bridge.bridge_dev, MODULES_MQTT_ID, true);
	if (!md) {
		fprintf(stderr, "Failed to add MQTT module.\n");
		return 1;
	}

	if (config.scripts_folder) {
		if (access(config.scripts_folder, R_OK )) {
			fprintf(stderr, "Couldn't open scripts folder: %s\n", config.scripts_folder);
			return 1;
		}
		md = bridge_add_module(bridge.bridge_dev, MODULES_SCRIPT_ID, true);
		if (!md) {
			fprintf(stderr, "Failed to add script module.\n");
			return 1;
		}
	}

	if (config.interface) {
		//TODO: check if interface exists
		if (access("/proc/net/dev", R_OK )) {
			fprintf(stderr, "Couldn't open /proc/net/dev\n");
			return 1;
		}
		md = bridge_add_module(bridge.bridge_dev, MODULES_BANDWIDTH_ID, true);
		if (!md) {
			fprintf(stderr, "Failed to add bandwidth module.\n");
			return 1;
		}
		bandwidth = true;
	}

	if (config.serial.port) {
		sd = serialport_init(config.serial.port, config.serial.baudrate);
		if( sd == -1 ) {
			fprintf(stderr, "Couldn't open serial port.\n");
			return 1;
		} else {
			md = bridge_add_module(bridge.bridge_dev, MODULES_SERIAL_ID, true);
			if (!md) {
				fprintf(stderr, "Failed to add serial module.\n");
				return 1;
			}
			serialport_flush(sd);
			bridge.serial_ready = true;

			if (config.debug) printf("Serial ready.\n");
		}
	}

	if (config.debug > 2) bridge_print_modules(bridge.bridge_dev);

	rc = mosquitto_connect(mosq, config.mqtt_host, config.mqtt_port, 60);
	if (rc) {
		fprintf(stderr, "ERROR: %s\n", mosquitto_strerror(rc));
		return -1;
	}

	alarm(1);

	while (run) {
		if (bridge.serial_ready) {
			rc = serial_in(sd, mosq, MODULES_SERIAL_ID);
			if (rc == -1) {
				serial_hang(mosq);
			} else if (rc > 0) {
				bridge.serial_alive = DEVICE_ALIVE_MAX;
			}
		}

		if (user_signal) {
			if (config.debug > 2) printf("Signal - SIGUSR: %d\n", user_signal);
			signal_usr(sd, mosq);
		}

		rc = mosquitto_loop(mosq, 100, 1);
		if (run && rc) {
			if (config.debug > 2) printf("MQTT loop: %s\n", mosquitto_strerror(rc));
			usleep(100000);	// wait 100 msec
			mosquitto_reconnect(mosq);
		}
		usleep(20);

		if (every1s) {
			every1s = false;

			for (dev = bridge.dev_list; dev != NULL; dev = dev->next) {
				if (dev->alive) {
					dev->alive--;
					if (!dev->alive) {
						if (connected) {
							snprintf(gbuf, GBUF_SIZE, "%d", PROTOCOL_TIMEOUT);
							mqtt_publish(mosq, dev->status_topic, gbuf);
							rc = mosquitto_unsubscribe(mosq, NULL, dev->config_topic);
							if (rc)
								fprintf(stderr, "Error: MQTT unsubscribe returned: %s\n", mosquitto_strerror(rc));
						}
						if (config.debug) printf("Device: %s - Timeout.\n", dev->id);
						bridge_remove_device(&bridge, dev->id);
					}
				}
			}
		}

		if (every30s) {
			every30s = false;

			if (connected) {
				send_alive(mosq);

				if (bandwidth) {
					md = bridge_get_module(bridge.bridge_dev, MODULES_BANDWIDTH_ID);
					if (md) {
						snprintf(gbuf, GBUF_SIZE, "%.0f,%.0f", upspeed, downspeed);
						mqtt_publish(mosq, md->topic, gbuf);
						if (config.debug > 2) printf("down: %f - up: %f\n", downspeed, upspeed);
					}
				}
			} else {
				if (config.debug) printf("MQTT Offline.\n");
			}

			if (bridge.serial_alive) {
				bridge.serial_alive--;
				if (!bridge.serial_alive) {
					if (config.debug > 1) printf("Serial timeout.\n");
					serial_hang(mosq);
				}
			} else {
				if (config.serial.port && !bridge.serial_ready) {
					if (config.debug > 1) printf("Trying to reconnect serial port.\n");
					serialport_close(sd);
					sd = serialport_init(config.serial.port, config.serial.baudrate);
					if( sd == -1 ) {
						fprintf(stderr, "Couldn't open serial port.\n");
					} else {
						serialport_flush(sd);
						bridge.serial_ready = true;
						snprintf(gbuf, GBUF_SIZE, "%d", MODULES_SERIAL_OPEN);
						mqtt_publish(mosq, md->topic, gbuf);
						if (config.debug) printf("Serial reopened.\n");
					}
				}
			}
		}
	}

	if (bridge.serial_ready) {
		serialport_close(sd);
	}

	mosquitto_destroy(mosq);

	mosquitto_lib_cleanup();
	config_cleanup(&config);

	printf("Exiting..\n\n");

	return 0;
}
Ejemplo n.º 10
0
int main(int argc, char *argv[])
{
	int sd = -1;
	char *conf_file = NULL;
	struct mosquitto *mosq;
	struct module *md;
	struct device *dev;
	int rc;
	int i;
	
	if (!quiet) printf("Version: %s\n", version);

    signal(SIGINT, handle_signal);
    signal(SIGTERM, handle_signal);
	signal(SIGUSR1, handle_signal);
	signal(SIGUSR2, handle_signal);
	signal(SIGALRM, each_sec);
	
	for (i=1; i<argc; i++) {
		if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")){
			if(i==argc-1){
                fprintf(stderr, "Error: -c argument given but no file specified.\n\n");
				print_usage(argv[0]);
                return 1;
            }else{
				conf_file = argv[i+1];
			}
			i++;
		}else if(!strcmp(argv[i], "--quiet")){
				quiet = true;
		}else{
				fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]);
				print_usage(argv[0]);
				return 1;
		}
	}
	
	if(!conf_file) {
		fprintf(stderr, "Error: No config file given.\n");
		return 1;
	}

	memset(&config, 0, sizeof(struct bridge_config));
	if(config_parse(conf_file, &config)) return 1;
	
	if (quiet) config.debug = 0;
	if (config.debug != 0) printf("Debug: %d\n", config.debug);

	if (!device_isValid_id(config.id)) {
		fprintf(stderr, "Invalid id.\n");
		return -1;
	}
	if (device_init(&bridge, config.id) == -1)
		return 1;

	mosquitto_lib_init();
	mosq = mosquitto_new(config.id, true, NULL);
	if(!mosq){
		fprintf(stderr, "Error creating mqtt instance.\n");
		switch(errno){
			case ENOMEM:
				fprintf(stderr, " out of memory.\n");
				break;
			case EINVAL:
				fprintf(stderr, " invalid id.\n");
				break;
		}
		return 1;
	}
	snprintf(gbuf, GBUF_SIZE, "%d", PROTO_ST_TIMEOUT);
	mosquitto_will_set(mosq, bridge.status_topic, strlen(gbuf), gbuf, config.mqtt_qos, MQTT_RETAIN);
	mosquitto_connect_callback_set(mosq, on_mqtt_connect);
	mosquitto_disconnect_callback_set(mosq, on_mqtt_disconnect);
	mosquitto_message_callback_set(mosq, on_mqtt_message);
	mosquitto_user_data_set(mosq, &sd);

	if (config.debug > 1) printf("Subscribe topic: %s\n", bridge.config_topic);

	rc = device_add_module(&bridge, MODULE_MQTT_ID, bridge.id);				//TODO: autogen id?
	if (rc) {
		fprintf(stderr, "Failed to add mqtt module.\n");
		return 1;
	}

	if (config.scripts_folder) {
		if (access(config.scripts_folder, R_OK )) {
			fprintf(stderr, "Couldn't open scripts folder: %s\n", config.scripts_folder);
			return 1;
		}
		rc = device_add_module(&bridge, MODULE_SCRIPT_ID, bridge.id);		//TODO: autogen id?
		if (rc) {
			fprintf(stderr, "Failed to add script module.\n");
			return 1;
		}
	}
	if (config.interface) {
		//TODO: check if interface exists
		if (access("/proc/net/dev", R_OK )) {
			fprintf(stderr, "Couldn't open /proc/net/dev\n");
			return 1;
		}
		rc = device_add_module(&bridge, MODULE_BANDWIDTH_ID, bridge.id);		//TODO: autogen id?
		if (rc) {
			fprintf(stderr, "Failed to add bandwidth module.\n");
			return 1;
		}
		bandwidth = true;
	}
	if (config.serial.port) {
		sd = serialport_init(config.serial.port, config.serial.baudrate);
		if( sd == -1 ) {
			fprintf(stderr, "Couldn't open serial port.\n");
			return 1;
		} else {
			rc = device_add_module(&bridge, MODULE_SERIAL_ID, bridge.id);		//TODO: autogen id?
			if (rc) {
				fprintf(stderr, "Failed to add serial module.\n");
				return 1;
			}
			serialport_flush(sd);
			bridge.serial_ready = true;

			if (config.debug) printf("Serial ready.\n");
		}
	}

	rc = device_add_module(&bridge, MODULE_SIGUSR1_ID, bridge.id);			//TODO: autogen id?
	if (rc) {
		fprintf(stderr, "Failed to add sigusr1 module.\n");
		return 1;
	}

	rc = device_add_module(&bridge, MODULE_SIGUSR2_ID, bridge.id);			//TODO: autogen id?
	if (rc) {
		fprintf(stderr, "Failed to add sigusr2 module.\n");
		return 1;
	}

	device_print_modules(&bridge);

	rc = mosquitto_connect(mosq, config.mqtt_host, config.mqtt_port, 60);
	if (rc) {
		fprintf(stderr, "Wrong MQTT parameters. Check your config.\n");
		return -1;
	}

	alarm(1);

	while (run) {
		if (bridge.serial_ready) {
			rc = serial_in(sd, mosq, MODULE_SERIAL_ID);
			if (rc == -1) {
				serial_hang(mosq);
			} else if (rc > 0) {
				bridge.serial_alive = ALIVE_CNT;
			}
		}

		if (user_signal) {
			if (config.debug > 1) printf("Signal - SIGUSR: %d\n", user_signal);
			signal_usr(sd, mosq);
		}

		rc = mosquitto_loop(mosq, -1, 1);
		if (run && rc) {
			if (config.debug > 2) printf("MQTT loop: %s\n", mosquitto_strerror(rc));
			usleep(100000);	// wait 100 msec
			mosquitto_reconnect(mosq);
		}

		if (every30s) {
			every30s = false;

			bridge.controller = false;
			for (i = 0; i < bridge.devices_len; i++) {
				dev = &bridge.devices[i];
				if (dev->alive) {
					dev->alive--;
					if (!dev->alive) {
						snprintf(gbuf, GBUF_SIZE, "%d,%s", PROTO_ST_TIMEOUT, dev->id);
						mqtt_publish(mosq, bridge.status_topic, gbuf);

						if (dev->md_deps->type == MODULE_MQTT && dev->type == DEVICE_TYPE_NODE) {
							snprintf(gbuf, GBUF_SIZE, "status/%s", dev->id);
							rc = mosquitto_unsubscribe(mosq, NULL, gbuf);
							if (rc)
								fprintf(stderr, "Error: MQTT unsubscribe returned: %s\n", mosquitto_strerror(rc));
						}

						if (config.debug) printf("Device timeout - id: %s\n", dev->id);
					} else {
						if (dev->type == DEVICE_TYPE_CONTROLLER)
							bridge.controller = true;
					}
				}
			}

			if (!bridge.controller)
				bridge.modules_update = false;

			if (connected) {
				snprintf(gbuf, GBUF_SIZE, "%d,%d", PROTO_ST_ALIVE, bridge.modules_len);
				mqtt_publish(mosq, bridge.status_topic, gbuf);

				if (bridge.modules_update) {
					snprintf(gbuf, GBUF_SIZE, "%d", PROTO_ST_MODULES_UP);
					if (mqtt_publish(mosq, bridge.status_topic, gbuf))
						bridge.modules_update = false;
				}

				if (bandwidth) {
					md = device_get_module(&bridge, MODULE_BANDWIDTH_ID);
					if (md) {
						if (mqtt_publish_bandwidth(mosq, md->topic) == -1)
							break;
					}
				}
			} else {
				if (config.debug != 0) printf("MQTT Offline.\n");
			}

			if (bridge.serial_alive) {
				bridge.serial_alive--;
				if (!bridge.serial_alive) {
					if (config.debug > 1) printf("Serial timeout.\n");
					serial_hang(mosq);
				}
			} else {
				if (config.serial.port && !bridge.serial_ready) {
					if (config.debug > 1) printf("Trying to reconnect serial port.\n");
					serialport_close(sd);
					sd = serialport_init(config.serial.port, config.serial.baudrate);
					if( sd == -1 )
						fprintf(stderr, "Couldn't open serial port.\n");
					else {
						serialport_flush(sd);
						bridge.serial_ready = true;
						if (config.debug) printf("Serial reopened.\n");
					}
				}
			}
		}
		usleep(20);
	}

	if (bridge.serial_ready) {
		serialport_close(sd);
	}

	mosquitto_destroy(mosq);

	mosquitto_lib_cleanup();
	config_cleanup(&config);

	printf("Exiting..\n\n");

	return 0;
}
Ejemplo n.º 11
0
int main(int argc, char **argv) {
	// memtrack();

	atomicinit();
	struct options_t *options = NULL;
	struct ssdp_list_t *ssdp_list = NULL;
	struct devices_t *dev = NULL;
	struct JsonNode *json = NULL;
	struct JsonNode *tmp = NULL;
	char *recvBuff = NULL, *message = NULL, *output = NULL;
	char *device = NULL, *state = NULL, *values = NULL;
	char *server = NULL;
	int has_values = 0, sockfd = 0, hasconfarg = 0;
	unsigned short port = 0, showhelp = 0, showversion = 0;

	log_file_disable();
	log_shell_enable();
	log_level_set(LOG_NOTICE);

#ifndef _WIN32
	wiringXLog = logprintf;
#endif

	if((progname = MALLOC(16)) == NULL) {
		fprintf(stderr, "out of memory\n");
		exit(EXIT_FAILURE);
	}
	strcpy(progname, "pilight-control");

	/* Define all CLI arguments of this program */
	options_add(&options, 'H', "help", OPTION_NO_VALUE, 0, JSON_NULL, NULL, NULL);
	options_add(&options, 'V', "version", OPTION_NO_VALUE, 0, JSON_NULL, NULL, NULL);
	options_add(&options, 'd', "device", OPTION_HAS_VALUE, 0,  JSON_NULL, NULL, NULL);
	options_add(&options, 's', "state", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, NULL);
	options_add(&options, 'v', "values", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, NULL);
	options_add(&options, 'S', "server", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
	options_add(&options, 'P', "port", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, "[0-9]{1,4}");
	options_add(&options, 'C', "config", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, NULL);

	/* Store all CLI arguments for later usage
	   and also check if the CLI arguments where
	   used correctly by the user. This will also
	   fill all necessary values in the options struct */
	while(1) {
		int c;
		c = options_parse(&options, argc, argv, 1, &optarg);
		if(c == -1)
			break;
		if(c == -2) {
			showhelp = 1;
			break;
		}
		switch(c) {
			case 'H':
				showhelp = 1;
			break;
			case 'V':
				showversion = 1;
			break;
			case 'd':
				if((device = REALLOC(device, strlen(optarg)+1)) == NULL) {
					fprintf(stderr, "out of memory\n");
					exit(EXIT_FAILURE);
				}
				strcpy(device, optarg);
			break;
			case 's':
				if((state = REALLOC(state, strlen(optarg)+1)) == NULL) {
					fprintf(stderr, "out of memory\n");
					exit(EXIT_FAILURE);
				}
				strcpy(state, optarg);
			break;
			case 'v':
				if((values = REALLOC(values, strlen(optarg)+1)) == NULL) {
					fprintf(stderr, "out of memory\n");
					exit(EXIT_FAILURE);
				}
				strcpy(values, optarg);
			break;
			case 'C':
				if(config_set_file(optarg) == EXIT_FAILURE) {
					return EXIT_FAILURE;
				}
				hasconfarg = 1;
			break;
			case 'S':
				if(!(server = REALLOC(server, strlen(optarg)+1))) {
					fprintf(stderr, "out of memory\n");
					exit(EXIT_FAILURE);
				}
				strcpy(server, optarg);
			break;
			case 'P':
				port = (unsigned short)atoi(optarg);
			break;
			default:
				printf("Usage: %s -l location -d device -s state\n", progname);
				goto close;
			break;
		}
	}
	options_delete(options);

	if(showversion == 1) {
		printf("%s v%s\n", progname, PILIGHT_VERSION);
		goto close;
	}
	if(showhelp == 1) {
		printf("\t -H --help\t\t\tdisplay this message\n");
		printf("\t -V --version\t\t\tdisplay version\n");
		printf("\t -S --server=x.x.x.x\t\tconnect to server address\n");
		printf("\t -C --config\t\t\tconfig file\n");
		printf("\t -P --port=xxxx\t\t\tconnect to server port\n");
		printf("\t -d --device=device\t\tthe device that you want to control\n");
		printf("\t -s --state=state\t\tthe new state of the device\n");
		printf("\t -v --values=values\t\tspecific comma separated values, e.g.:\n");
		printf("\t\t\t\t\t-v dimlevel=10\n");
		goto close;
	}
	if(device == NULL || state == NULL ||
	   strlen(device) == 0 || strlen(state) == 0) {
		printf("Usage: %s -d device -s state\n", progname);
		goto close;
	}

	if(server && port > 0) {
		if((sockfd = socket_connect(server, port)) == -1) {
			logprintf(LOG_ERR, "could not connect to pilight-daemon");
			goto close;
		}
	} else if(ssdp_seek(&ssdp_list) == -1) {
		logprintf(LOG_NOTICE, "no pilight ssdp connections found");
		goto close;
	} else {
		if((sockfd = socket_connect(ssdp_list->ip, ssdp_list->port)) == -1) {
			logprintf(LOG_ERR, "could not connect to pilight-daemon");
			goto close;
		}
	}
	if(ssdp_list) {
		ssdp_free(ssdp_list);
	}

	protocol_init();
	config_init();
	if(hasconfarg == 1) {
		if(config_read() != EXIT_SUCCESS) {
			goto close;
		}
	}

	socket_write(sockfd, "{\"action\":\"identify\"}");
	if(socket_read(sockfd, &recvBuff, 0) != 0
	   || strcmp(recvBuff, "{\"status\":\"success\"}") != 0) {
		goto close;
	}

	json = json_mkobject();
	json_append_member(json, "action", json_mkstring("request config"));
	output = json_stringify(json, NULL);
	socket_write(sockfd, output);
	json_free(output);
	json_delete(json);

	if(socket_read(sockfd, &recvBuff, 0) == 0) {
		if(json_validate(recvBuff) == true) {
			json = json_decode(recvBuff);
			if(json_find_string(json, "message", &message) == 0) {
				if(strcmp(message, "config") == 0) {
					struct JsonNode *jconfig = NULL;
					if((jconfig = json_find_member(json, "config")) != NULL) {
						int match = 1;
						while(match) {
							struct JsonNode *jchilds = json_first_child(jconfig);
							match = 0;
							while(jchilds) {
								if(strcmp(jchilds->key, "devices") != 0) {
									json_remove_from_parent(jchilds);
									tmp = jchilds;
									match = 1;
								}
								jchilds = jchilds->next;
								if(tmp != NULL) {
									json_delete(tmp);
								}
								tmp = NULL;
							}
						}
						config_parse(jconfig);
						if(devices_get(device, &dev) == 0) {
							JsonNode *joutput = json_mkobject();
							JsonNode *jcode = json_mkobject();
							JsonNode *jvalues = json_mkobject();
							json_append_member(jcode, "device", json_mkstring(device));

							if(values != NULL) {
								char **array = NULL;
								unsigned int n = explode(values, ",=", &array), q = 0;
								for(q=0;q<n;q+=2) {
									char *name = MALLOC(strlen(array[q])+1);
									if(name == NULL) {
										logprintf(LOG_ERR, "out of memory\n");
										exit(EXIT_FAILURE);
									}
									strcpy(name, array[q]);
									if(q+1 == n) {
										array_free(&array, n);
										logprintf(LOG_ERR, "\"%s\" is missing a value for device \"%s\"", name, device);
										FREE(name);
										break;
									} else {
										char *val = MALLOC(strlen(array[q+1])+1);
										if(val == NULL) {
											logprintf(LOG_ERR, "out of memory\n");
											exit(EXIT_FAILURE);
										}
										strcpy(val, array[q+1]);
										if(devices_valid_value(device, name, val) == 0) {
											if(isNumeric(val) == EXIT_SUCCESS) {
												json_append_member(jvalues, name, json_mknumber(atof(val), nrDecimals(val)));
											} else {
												json_append_member(jvalues, name, json_mkstring(val));
											}
											has_values = 1;
										} else {
											logprintf(LOG_ERR, "\"%s\" is an invalid value for device \"%s\"", name, device);
											array_free(&array, n);
											FREE(name);
											json_delete(json);
											goto close;
										}
									}
									FREE(name);
								}
								array_free(&array, n);
							}

							if(devices_valid_state(device, state) == 0) {
								json_append_member(jcode, "state", json_mkstring(state));
							} else {
								logprintf(LOG_ERR, "\"%s\" is an invalid state for device \"%s\"", state, device);
								json_delete(json);
								goto close;
							}

							if(has_values == 1) {
								json_append_member(jcode, "values", jvalues);
							} else {
								json_delete(jvalues);
							}
							json_append_member(joutput, "action", json_mkstring("control"));
							json_append_member(joutput, "code", jcode);
							output = json_stringify(joutput, NULL);
							socket_write(sockfd, output);
							json_free(output);
							json_delete(joutput);
							if(socket_read(sockfd, &recvBuff, 0) != 0
							   || strcmp(recvBuff, "{\"status\":\"success\"}") != 0) {
								logprintf(LOG_ERR, "failed to control %s", device);
							}
						} else {
							logprintf(LOG_ERR, "the device \"%s\" does not exist", device);
							json_delete(json);
							goto close;
						}
					}
				}
			}
			json_delete(json);
		}
	}
close:
	if(recvBuff) {
		FREE(recvBuff);
	}
	if(sockfd > 0) {
		socket_close(sockfd);
	}
	if(server != NULL) {
		FREE(server);
	}
	if(device != NULL) {
		FREE(device);
	}
	if(state != NULL) {
		FREE(state);
	}
	if(values != NULL) {
		FREE(values);
	}
	log_shell_disable();
	socket_gc();
	config_gc();
	protocol_gc();
	options_gc();
#ifdef EVENTS
	events_gc();
#endif
	dso_gc();
	log_gc();
	threads_gc();
	gc_clear();
	FREE(progname);
	xfree();

#ifdef _WIN32
	WSACleanup();
#endif

	return EXIT_SUCCESS;
}
Ejemplo n.º 12
0
/* Parse a variable assignment line */
static int parse_line(const char* unit,
                      const char *filename,
                      unsigned line,
                      const char *sections,
                      ConfigItemLookup lookup,
                      const void *table,
                      bool relaxed,
                      bool allow_include,
                      char **section,
                      unsigned *section_line,
                      bool *section_ignored,
                      char *l,
                      void *userdata) {

        char *e;

        assert(filename);
        assert(line > 0);
        assert(lookup);
        assert(l);

        l = strstrip(l);

        if (!*l)
                return 0;

        if (strchr(COMMENTS "\n", *l))
                return 0;

        if (startswith(l, ".include ")) {
                _cleanup_free_ char *fn = NULL;

                /* .includes are a bad idea, we only support them here
                 * for historical reasons. They create cyclic include
                 * problems and make it difficult to detect
                 * configuration file changes with an easy
                 * stat(). Better approaches, such as .d/ drop-in
                 * snippets exist.
                 *
                 * Support for them should be eventually removed. */

                if (!allow_include) {
                        log_syntax(unit, LOG_ERR, filename, line, 0, ".include not allowed here. Ignoring.");
                        return 0;
                }

                fn = file_in_same_dir(filename, strstrip(l+9));
                if (!fn)
                        return -ENOMEM;

                return config_parse(unit, fn, NULL, sections, lookup, table, relaxed, false, false, userdata);
        }

        if (*l == '[') {
                size_t k;
                char *n;

                k = strlen(l);
                assert(k > 0);

                if (l[k-1] != ']') {
                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid section header '%s'", l);
                        return -EBADMSG;
                }

                n = strndup(l+1, k-2);
                if (!n)
                        return -ENOMEM;

                if (sections && !nulstr_contains(sections, n)) {

                        if (!relaxed && !startswith(n, "X-"))
                                log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown section '%s'. Ignoring.", n);

                        free(n);
                        *section = mfree(*section);
                        *section_line = 0;
                        *section_ignored = true;
                } else {
                        free(*section);
                        *section = n;
                        *section_line = line;
                        *section_ignored = false;
                }

                return 0;
        }

        if (sections && !*section) {

                if (!relaxed && !*section_ignored)
                        log_syntax(unit, LOG_WARNING, filename, line, 0, "Assignment outside of section. Ignoring.");

                return 0;
        }

        e = strchr(l, '=');
        if (!e) {
                log_syntax(unit, LOG_WARNING, filename, line, 0, "Missing '='.");
                return -EINVAL;
        }

        *e = 0;
        e++;

        return next_assignment(unit,
                               filename,
                               line,
                               lookup,
                               table,
                               *section,
                               *section_line,
                               strstrip(l),
                               strstrip(e),
                               relaxed,
                               userdata);
}
Ejemplo n.º 13
0
int main(int argc, char* argv[]) {
  printf("Moonlight Embedded %d.%d.%d (%s)\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, COMPILE_OPTIONS);

  CONFIGURATION config;
  config_parse(argc, argv, &config);

  if (config.action == NULL || strcmp("help", config.action) == 0)
    help();
  
  enum platform system = platform_check(config.platform);
  if (system == 0) {
    fprintf(stderr, "Platform '%s' not found\n", config.platform);
    exit(-1);
  }
  config.stream.supportsHevc = config.stream.supportsHevc || platform_supports_hevc(system);
  
  if (strcmp("map", config.action) == 0) {
    if (config.address == NULL) {
      perror("No filename for mapping");
      exit(-1);
    }
    udev_init(!inputAdded, config.mapping);
    for (int i=0;i<config.inputsCount;i++)
      evdev_create(config.inputs[i].path, config.inputs[i].mapping);
    
    evdev_map(config.address);
    exit(0);
  }

  if (config.address == NULL) {
    config.address = malloc(MAX_ADDRESS_SIZE);
    if (config.address == NULL) {
      perror("Not enough memory");
      exit(-1);
    }
    config.address[0] = 0;
    printf("Searching for server...\n");
    gs_discover_server(config.address);
    if (config.address[0] == 0) {
      fprintf(stderr, "Autodiscovery failed. Specify an IP address next time.\n");
      exit(-1);
    }
  }
  
  char host_config_file[128];
  sprintf(host_config_file, "hosts/%s.conf", config.address);
  if (access(host_config_file, R_OK) != -1)
    config_file_parse(host_config_file, &config);

  SERVER_DATA server;
  server.address = config.address;
  printf("Connect to %s...\n", server.address);

  int ret;
  if ((ret = gs_init(&server, config.key_dir)) == GS_OUT_OF_MEMORY) {
    fprintf(stderr, "Not enough memory\n");
    exit(-1);
  } else if (ret == GS_INVALID) {
    fprintf(stderr, "Invalid data received from server: %s\n", config.address, gs_error);
    exit(-1);
  } else if (ret == GS_UNSUPPORTED_VERSION) {
    if (!config.unsupported_version) {
      fprintf(stderr, "Unsupported version: %s\n", gs_error);
      exit(-1);
    }
  } else if (ret != GS_OK) {
    fprintf(stderr, "Can't connect to server %s\n", config.address);
    exit(-1);
  }

  printf("NVIDIA %s, GFE %s (protocol version %d)\n", server.gpuType, server.gfeVersion, server.serverMajorVersion);

  if (strcmp("list", config.action) == 0) {
    pair_check(&server);
    applist(&server);
  } else if (strcmp("stream", config.action) == 0) {
    pair_check(&server);
    if (IS_EMBEDDED(system)) {
      for (int i=0;i<config.inputsCount;i++) {
        printf("Add input %s (mapping %s)...\n", config.inputs[i].path, config.inputs[i].mapping);
        evdev_create(config.inputs[i].path, config.inputs[i].mapping);
      }

      udev_init(!inputAdded, config.mapping);
      evdev_init();
      #ifdef HAVE_LIBCEC
      cec_init();
      #endif /* HAVE_LIBCEC */
    }
    #ifdef HAVE_SDL
    else if (system == SDL)
      sdl_init(config.stream.width, config.stream.height, config.fullscreen);
    #endif

    stream(&server, &config, system);
  } else if (strcmp("pair", config.action) == 0) {
    char pin[5];
    sprintf(pin, "%d%d%d%d", (int)random() % 10, (int)random() % 10, (int)random() % 10, (int)random() % 10);
    printf("Please enter the following PIN on the target PC: %s\n", pin);
    if (gs_pair(&server, &pin[0]) != GS_OK) {
      fprintf(stderr, "Failed to pair to server: %s\n", gs_error);
    } else {
      printf("Succesfully paired\n");
    }
  } else if (strcmp("unpair", config.action) == 0) {
    if (gs_unpair(&server) != GS_OK) {
      fprintf(stderr, "Failed to unpair to server: %s\n", gs_error);
    } else {
      printf("Succesfully unpaired\n");
    }
  } else if (strcmp("quit", config.action) == 0) {
    pair_check(&server);
    gs_quit_app(&server);
  } else
    fprintf(stderr, "%s is not a valid action\n", config.action);
}
Ejemplo n.º 14
0
int main(int argc, char **argv) {

	disable_file_log();
	enable_shell_log();
	set_loglevel(LOG_NOTICE);

	progname = malloc((10*sizeof(char))+1);
	progname = strdup("433-control");

	options = malloc(255*sizeof(struct options_t));

	int sockfd = 0;
    char *recvBuff = NULL;
	char *message;
	steps_t steps = WELCOME;

	char device[50];
	char location[50];
	char state[10] = {'\0'};
	struct conf_locations_t *slocation = NULL;
	struct conf_devices_t *sdevice = NULL;
	
	char server[16] = "127.0.0.1";
	unsigned short port = PORT;
	
	JsonNode *json = json_mkobject();
	JsonNode *config = json_mkobject();
	JsonNode *code = json_mkobject();

	/* Define all CLI arguments of this program */
	addOption(&options, 'h', "help", no_value, 0, NULL);
	addOption(&options, 'v', "version", no_value, 0, NULL);
	addOption(&options, 'l', "location", has_value, 0, NULL);
	addOption(&options, 'd', "device", has_value, 0,  NULL);
	addOption(&options, 's', "state", has_value, 0,  NULL);
	addOption(&options, 'S', "server", has_value, 0, "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
	addOption(&options, 'P', "port", has_value, 0, "[0-9]{1,4}");

	/* Store all CLI arguments for later usage
	   and also check if the CLI arguments where
	   used correctly by the user. This will also
	   fill all necessary values in the options struct */
	while(1) {
		int c;
		c = getOptions(&options, argc, argv, 1);
		if(c == -1)
			break;
		switch(c) {
			case 'h':
				printf("\t -h --help\t\t\tdisplay this message\n");
				printf("\t -v --version\t\t\tdisplay version\n");
				printf("\t -S --server=%s\t\tconnect to server address\n", server);
				printf("\t -P --port=%d\t\t\tconnect to server port\n", port);
				printf("\t -l --location=location\t\tthe location in which the device resides\n");
				printf("\t -d --device=device\t\tthe device that you want to control\n");
				printf("\t -s --state=state\t\tthe new state of the device\n");
				exit(EXIT_SUCCESS);
			break;
			case 'v':
				printf("%s %s\n", progname, "1.0");
				exit(EXIT_SUCCESS);
			break;
			case 'l':
				strcpy(location, optarg);
			break;
			case 'd':
				strcpy(device, optarg);
			break;
			case 's':
				strcpy(state, optarg);
			break;
			case 'S':
				strcpy(server, optarg);
			break;
			case 'P':
				port = (unsigned short)atoi(optarg);
			break;			
			default:
				printf("Usage: %s -l location -d device\n", progname);
				exit(EXIT_SUCCESS);
			break;
		}
	}

	if(strlen(location) == 0 || strlen(device) == 0) {
		printf("Usage: %s -l location -d device\n", progname);
		exit(EXIT_SUCCESS);
	}

	if((sockfd = connect_to_server(strdup(server), port)) == -1) {
		logprintf(LOG_ERR, "could not connect to 433-daemon");
		exit(EXIT_FAILURE);
	}

	/* Initialize peripheral modules */
	hw_init();

	while(1) {
		if(steps > WELCOME) {
			/* Clear the receive buffer again and read the welcome message */
			if(steps == REQUEST) {
				if((recvBuff = socket_read_big(sockfd)) != NULL) {
					json = json_decode(recvBuff);
					json_find_string(json, "message", &message);
				} else {
					goto close;
				}
			} else {
				if((recvBuff = socket_read(sockfd)) != NULL) {
					json = json_decode(recvBuff);
					json_find_string(json, "message", &message);
				} else {
					goto close;
				}
			}
			usleep(250);
		}
		switch(steps) {
			case WELCOME:
				socket_write(sockfd, "{\"message\":\"client controller\"}");
				steps=IDENTIFY;
			break;
			case IDENTIFY:
				if(strcmp(message, "accept client") == 0) {
					steps=REQUEST;
				}
				if(strcmp(message, "reject client") == 0) {
					steps=REJECT;
				}
			case REQUEST:
				socket_write(sockfd, "{\"message\":\"request config\"}");
				steps=CONFIG;
			break;
			case CONFIG:
				if((config = json_find_member(json, "config")) != NULL) {
					config_parse(config);
					if(config_get_location(location, &slocation) == 0) {
						if(config_get_device(location, device, &sdevice) == 0) {
							json_delete(json);

							json = json_mkobject();
							code = json_mkobject();

							json_append_member(code, "location", json_mkstring(location));
							json_append_member(code, "device", json_mkstring(device));

							if(strlen(state) > 0) {
								if(config_valid_state(location, device, state) == 0) {
									json_append_member(code, "state", json_mkstring(state));
								} else {
									logprintf(LOG_ERR, "\"%s\" is an invalid state for device \"%s\"", state, device);
									goto close;
								}
							}

							json_append_member(json, "message", json_mkstring("send"));
							json_append_member(json, "code", code);

							socket_write(sockfd, json_stringify(json, NULL));

						} else {
							logprintf(LOG_ERR, "the device \"%s\" does not exist", device);
							goto close;
						}
					} else {
						logprintf(LOG_ERR, "the location \"%s\" does not exist", location);
						goto close;
					}
				}
				goto close;
			break;
			case REJECT:
			default:
				goto close;
			break;
		}
	}
close:
	json_delete(json);
	socket_close(sockfd);
return EXIT_SUCCESS;
}