예제 #1
0
/**
 * Print printf-like formatted output to logfile and sends it to the client.
 * \note don't add a the "huh? " to the message. This is done by this
 *   method
 * \param fd socket
 * \param format a printf format */
int
sock_printf_error(int fd, const char *format, .../*args*/ )
{
	static const char huh[] = "huh? ";
	char buf[MAXMSG];
	va_list ap;
	int size = 0;

	strncpy(buf, huh, sizeof(huh)); // note: sizeof(huh) < MAXMSG

	va_start(ap, format);
	size = vsnprintf(buf + (sizeof(huh)-1), sizeof(buf) - (sizeof(huh)-1), format, ap);
	buf[sizeof(buf)-1] = '\0';
	va_end(ap);

	if (size < 0) {
		//report(RPT_ERR, "sock_printf_error: vsnprintf failed");
		return -1;
	}
	//if (size >= sizeof(buf) - (sizeof(huh)-1))
		//report(RPT_WARNING, "sock_printf_error: vsnprintf truncated message");

	//report(RPT_ERR, "error: %s", buf);
	return sock_send_string(fd, buf);
}
예제 #2
0
/*************************************************************************
 * menu_del_item_func
 *
 * Deletes an item from a menu
 *
 * Usage: menu_del_item <menuid> <itemid>
 * The given item in the given menu will be deleted. If you have deleted all
 * the items from your client menu, that menu will automatically be removed.
 */
int
menu_del_item_func (Client * c, int argc, char **argv)
{
	Menu * menu;
	MenuItem * item;
	char * menu_id;
	char * item_id;

	if (!c->ack)
		return 1;

	if (argc != 3 ) {
		sock_send_error(c->sock, "Usage: menu_del_item <menuid> <itemid>\n");
		return 0;
	}

	menu_id = argv[1];
	item_id = argv[2];

	/* Does the client have a menu already ? */
	if (!c->menu) {
		sock_send_error(c->sock, "Client has no menu\n");
		return 0;
	}

	if ( menu_id[0] == 0 ) {
		/* No menu specified = client's main menu */
		menu = c->menu;
	} else {
		/* A specified menu */
		menu = menu_find_item (c->menu, menu_id, true);
	}
	if (!menu) {
		sock_send_error(c->sock, "Cannot find menu id\n");
		return 0;
	}

	item = menu_find_item (c->menu, item_id, true);
	if (!item) {
		sock_send_error(c->sock, "Cannot find item\n");
		return 0;
	}
	menuscreen_inform_item_destruction (item);
	menu_remove_item (menu, item);
	menuscreen_inform_item_modified (item->parent);
	menuitem_destroy (item);

	/* Was it the last item in the client's menu ? */
	if (menu_getfirst_item(c->menu) == NULL) {
		menuscreen_inform_item_destruction (c->menu);
		menu_remove_item (main_menu, c->menu);
		menuscreen_inform_item_modified (main_menu);
		menu_destroy (c->menu);
		c->menu = NULL;
	}
	sock_send_string(c->sock, "success\n");
	return 0;
}
/**
 * Does nothing, returns "noop complete" message.
 *
 * This is useful for shell scripts or programs that want to talk
 *    with LCDproc and not get deadlocked.  Send a noop after each
 *    command and look for the "noop complete" message.
 */
int
noop_func(Client *c, int argc, char **argv)
{
	if (c->state != ACTIVE)
		return 1;

	sock_send_string(c->sock, "noop complete\n");
	return 0;
}
예제 #4
0
파일: socket.c 프로젝트: lb1a/avfs
/* Send the given line down the socket with CRLF appended. 
 * Returns 0 on success or SOCK_* on failure. */
int sock_sendline(nsocket *sock, const char *line) 
{
    char *buffer;
    int ret;
    CONCAT2(buffer, line, "\r\n");
    ret = sock_send_string(sock, buffer);
    free(buffer);
    return ret;
}
/**
 * Sets the state of the output port (such as on MtxOrb LCDs)
 *
 *\verbatim
 * Usage: output <on|off|int>
 *\endverbatim
 */
int
output_func(Client *c, int argc, char **argv)
{
	if (c->state != ACTIVE)
		return 1;

	if (argc != 2) {
		sock_send_error(c->sock, "Usage: output {on|off|<num>}\n");
		return 0;
	}

	if (0 == strcmp(argv[1], "on"))
		output_state = ALL_OUTPUTS_ON;
	else if (0 == strcmp(argv[1], "off"))
		output_state = ALL_OUTPUTS_OFF;
	else {
		long out;
		char *endptr;

		/* Note that there is no valid range set for
		 * output_state; thus a value in the 12 digits
		 * is not considered out of range.
		 */

		/* set errno to be able to detect errors in strtol() */
		errno = 0;

		out = strtol(argv[1], &endptr, 0);

		if (errno) {
			sock_printf_error(c->sock, "number argument: %s\n", strerror(errno));
			return 0;
		}
		else if ((*argv[1] != '\0') && (*endptr == '\0')) {
			output_state = out;
		}
		else {
			sock_send_error(c->sock, "invalid parameter...\n");
			return 0;
		}
	}

	sock_send_string(c->sock, "success\n");

	/* Makes sense to me to set the output immediately;
	 * however, the outputs are currently set in
	 * draw_screen(screen *s, int timer)
	 * Whatever for? */

	/* drivers_output(output_state); */

	report(RPT_NOTICE, "output states changed");
	return 0;
}
void
screenlist_switch(Screen *s)
{
	Client *c;
	char str[256];

	if (!s) return;

	report(RPT_DEBUG, "%s(s=[%.40s])", __FUNCTION__, s->id);

	if (s == current_screen) {
		/* Nothing to be done */
		return;
	}

	if (current_screen) {
		c = current_screen->client;
		if (c) {
			/* Tell the client we're not listening any more...*/
			snprintf(str, sizeof(str), "ignore %s\n", current_screen->id);
			sock_send_string(c->sock, str);
		} else {
			/* It's a server screen, no need to inform it. */
		}
	}
	c = s->client;
	if (c) {
		/* Tell the client we're paying attention...*/
		snprintf(str, sizeof(str), "listen %s\n", s->id);
		sock_send_string(c->sock, str);
	} else {
		/* It's a server screen, no need to inform it. */
	}
	report(RPT_INFO, "%s: switched to screen [%.40s]", __FUNCTION__, s->id);
	current_screen = s;
	current_screen_start_time = timer;
}
예제 #7
0
/**
 * MiniClock Screen displays the current time with hours & minutes only
 *
 *\verbatim
 *
 * +--------------------+	+--------------------+
 * |                    |	|       11:32        |
 * |       11:32        |	|                    |
 * |                    |	+--------------------+
 * |                    |
 * +--------------------+
 *
 *\endverbatim
 *
 * \param rep        Time since last screen update
 * \param display    1 if screen is visible or data should be updated
 * \param flags_ptr  Mode flags
 * \return  Always 0
 */
int
mini_clock_screen(int rep, int display, int *flags_ptr)
{
	char now[40];
	time_t thetime;
	struct tm *rtime;
	static const char *timeFormat = NULL;
	static int heartbeat = 0;
	int xoffs;

	/* toggle colon display */
	heartbeat ^= 1;

	if ((*flags_ptr & INITIALIZED) == 0) {
		*flags_ptr |= INITIALIZED;

		/* get config values */
		timeFormat = config_get_string("MiniClock", "TimeFormat", 0, "%H:%M");

		sock_send_string(sock, "screen_add N\n");
		sock_send_string(sock, "screen_set N -name {Mini Clock Screen} -heartbeat off\n");
		sock_send_string(sock, "widget_add N one string\n");
	}

	time(&thetime);
	rtime = localtime(&thetime);

	if (strftime(now, sizeof(now), timeFormat, rtime) == 0)
		*now = '\0';
	tickTime(now, heartbeat);

	xoffs = (lcd_wid > strlen(now)) ? (((lcd_wid - strlen(now)) / 2) + 1) : 1;
	sock_printf(sock, "widget_set N one %d %d {%s}\n", xoffs, (lcd_hgt / 2), now);

	return 0;
}				/* End mini_clock_screen() */
예제 #8
0
파일: input.c 프로젝트: mezcua/lcdproc
void input_send_to_client(Client *c, const char *key)
{
	char *s;
	size_t size = strlen(key) + sizeof("key %s\n"); // this is large enough

	debug(RPT_DEBUG, "%s(client=[%d], key=\"%.40s\")", __FUNCTION__, c->sock, key);

	/* Allocate just as much as we need */
	s = calloc(1, size);
	if (s != NULL) {
		snprintf(s, size, "key %s\n", key);
		sock_send_string(c->sock, s);
		free(s);
	}	
	else
		report(RPT_ERR, "%s: malloc failure", __FUNCTION__);
}
예제 #9
0
/**
 * Send printf-like formatted output.
 * \param fd      Socket file descriptor
 * \param format  Format string
 * \param ...     Arguments to the format string
 * \return  Number of bytes sent.
 */
int
sock_printf(int fd, const char *format, .../*args*/ )
{
	char buf[MAXMSG];
	va_list ap;
	int size = 0;

	va_start(ap, format);
	size = vsnprintf(buf, sizeof(buf), format, ap);
	va_end(ap);

	if (size < 0) {
		//report(RPT_ERR, "sock_printf: vsnprintf failed");
		return -1;
	}
	//if (size > sizeof(buf))
		//report(RPT_WARNING, "sock_printf: vsnprintf truncated message");

	return sock_send_string(fd, buf);
}
예제 #10
0
/***************************************************************
 * Requests the menu system to set the entry point into the menu system. 
 *
 * Usage: menu_set_main <id>
 */
int
menu_set_main_func (Client * c, int argc, char **argv)
{
	char * menu_id;
	Menu * menu;

	debug (RPT_DEBUG, "%s( Client [%d], %s, %s )",
	       __FUNCTION__, c->sock, (argc > 1 ? argv[1] : "<null>"),
	       (argc > 2 ? argv[2] : "<null>") );
	if (!c->ack)
		return 1;

	if (argc != 2 ) {
		sock_send_error(c->sock, "Usage: menu_set_main <menuid>\n");
		return 0;
	}

	menu_id = argv[1];

	if ( menu_id[0] == 0 ) {
		/* No menu specified = client's main menu */
		menu = c->menu;
	}
	else if (strcmp(menu_id, "_main_") == 0) {
		menu = NULL;
	}
	else {
		/* A specified menu */
		menu = menu_find_item (c->menu, menu_id, true);
		if ( ! menu) {
			sock_send_error(c->sock, "Cannot find menu id\n");
			return 0;
		}
	}

	menuscreen_set_main(menu);

	sock_send_string(c->sock, "success\n");
	return 0;
}
예제 #11
0
/***************************************************************
 * Requests the menu system to display the given menu screen.  Depending on
 * the setting of the LCDPROC_PERMISSIVE_MENU_GOTO it is impossible
 * to go to a menu of another client (or the server menus). Same
 * restriction applies to the optional predecessor_id
 *
 * Usage: menu_goto <id> [<predecessor_id>]
 */
int
menu_goto_func (Client * c, int argc, char **argv)
{
	char * menu_id;
	Menu * menu;

	debug (RPT_DEBUG, "%s( Client [%d], %s, %s )",
	       __FUNCTION__, c->sock, (argc > 1 ? argv[1] : "<null>"),
	       (argc > 2 ? argv[2] : "<null>") );
	if (!c->ack)
		return 1;

	if ((argc < 2 ) || (argc > 3)) {
		sock_send_error(c->sock, "Usage: menu_goto <menuid> [<predecessor_id>]\n");
		return 0;
	}

	menu_id = argv[1];

	if ( menu_id[0] == 0 ) {
		/* No menu specified = client's main menu */
		menu = c->menu;
	} else {
		/* A specified menu */
		menu = menuitem_search(menu_id, c);
	}

	if (!menu) {
		sock_send_error(c->sock, "Cannot find menu id\n");
		return 0;
	}

	if (argc > 2 )
		set_predecessor(menu, argv[2], c);

	menuscreen_goto (menu);
	/* Failure is not returned (Robijn) */
	sock_send_string(c->sock, "success\n");
	return 0;
}
/**
 * The client requests that the server forget about a screen
 *
 *\verbatim
 * Usage: screen_del <screenid>
 *\endverbatim
 */
int
screen_del_func(Client *c, int argc, char **argv)
{
	int err = 0;
	Screen *s;

	if (c->state != ACTIVE)
		return 1;

	if (argc != 2) {
		sock_send_error(c->sock, "Usage: screen_del <screenid>\n");
		return 0;
	}

	debug(RPT_DEBUG, "screen_del: Deleting screen %s", argv[1]);

	s = client_find_screen(c, argv[1]);
	if (s == NULL) {
		sock_send_error(c->sock, "Unknown screen id\n");
		return 0;
	}

	err = client_remove_screen(c, s);
	if (err == 0) {
		sock_send_string(c->sock, "success\n");
	}
	else if (err < 0) {
		sock_send_error(c->sock, "failed to remove screen\n");
	}
	else {
		sock_send_error(c->sock, "Unknown screen id\n");
	}

	report(RPT_INFO, "Client on socket %d removed screen \"%s\"", c->sock, s->id);

	screen_destroy(s);
	return 0;
}
/**
 * Tells the server the client has another screen to offer
 *
 *\verbatim
 * Usage: screen_add <id>
 *\endverbatim
 */
int
screen_add_func(Client *c, int argc, char **argv)
{
	int err = 0;
	Screen *s;

	if (c->state != ACTIVE)
		return 1;

	if (argc != 2) {
		sock_send_error(c->sock, "Usage: screen_add <screenid>\n");
		return 0;
	}

	debug(RPT_DEBUG, "screen_add: Adding screen %s", argv[1]);

	s = client_find_screen(c, argv[1]);
	if (s != NULL) {
		sock_send_error(c->sock, "Screen already exists\n");
		return 0;
	}

	s = screen_create(argv[1], c);
	if (s == NULL) {
		sock_send_error(c->sock, "failed to create screen\n");
		return 0;
	}

	err = client_add_screen(c, s);

	if (err == 0) {
		sock_send_string(c->sock, "success\n");
	} else {
		sock_send_error(c->sock, "failed to add screen\n");
	}
	report(RPT_INFO, "Client on socket %d added added screen \"%s\"", c->sock, s->id);
	return 0;
}
예제 #14
0
파일: cpu_smp.c 프로젝트: mezcua/lcdproc
//////////////////////////////////////////////////////////////////////////
// CPU screen shows info about percentage of the CPU being used
//
int
cpu_smp_screen (int rep, int display, int *flags_ptr)
{
#undef CPU_BUF_SIZE
#define CPU_BUF_SIZE 4
	int z;
	static float cpu[MAX_CPUS][CPU_BUF_SIZE + 1];	// last buffer is scratch
	load_type load[MAX_CPUS];
	int num_cpus = MAX_CPUS;
	int bar_size;
	int lines_used;

	// get SMP load - inform about max #CPUs allowed
	machine_get_smpload(load, &num_cpus);

	// restrict num_cpus to max. twice the display height
	if (num_cpus > 2 * lcd_hgt)
		num_cpus = 2 * lcd_hgt;

	// 2 CPUs per line if more CPUs than lines
	bar_size = (num_cpus > lcd_hgt) ? (lcd_wid / 2 - 6) : (lcd_wid - 6);
	lines_used = (num_cpus > lcd_hgt) ? (num_cpus + 1) / 2 : num_cpus;

	if ((*flags_ptr & INITIALIZED) == 0) {
		*flags_ptr |= INITIALIZED;

		sock_send_string(sock, "screen_add P\n");
		
		// print title if he have room for it
		if (lines_used < lcd_hgt) {
			sock_send_string(sock, "widget_add P title title\n");
			sock_printf(sock, "widget_set P title {SMP CPU %s}\n", get_hostname());
		}
		else {
			sock_send_string(sock, "screen_set P -heartbeat off\n");
		}	

		sock_printf(sock, "screen_set P -name {CPU Use: %s}\n", get_hostname());

		for (z = 0; z < num_cpus; z++) {
			int y_offs = (lines_used < lcd_hgt) ? 2 : 1;
			int x = (num_cpus > lcd_hgt) ? ((z % 2) * (lcd_wid/2) + 1) : 1;
			int y = (num_cpus > lcd_hgt) ? (z/2 + y_offs) : (z + y_offs);

			sock_printf(sock, "widget_add P cpu%d_title string\n", z);
			sock_printf(sock, "widget_set P cpu%d_title %d %d \"CPU%d[%*s]\"\n",
					z, x, y, z, bar_size, "");
			sock_printf(sock, "widget_add P cpu%d_bar hbar\n", z);
		}

		return 0;
	}

	for (z = 0; z < num_cpus; z++) {
		int y_offs = (lines_used < lcd_hgt) ? 2 : 1;
		int x = (num_cpus > lcd_hgt) ? ((z % 2) * (lcd_wid/2) + 6) : 6;
		int y = (num_cpus > lcd_hgt) ? (z/2 + y_offs) : (z + y_offs);
		float value = 0.0;
		int i, n;

		// Shift values over by one
		for (i = 0; i < (CPU_BUF_SIZE - 1); i++)
			cpu[z][i] = cpu[z][i + 1];

		// Read new data
		cpu[z][CPU_BUF_SIZE-1] = (load[z].total > 0L)
				    ? (((float) load[z].user + (float) load[z].system + (float) load[z].nice) / (float) load[z].total) * 100.0
				    : 0.0;

		// Average values for final result
		for (i = 0; i < CPU_BUF_SIZE; i++) {
			value += cpu[z][i];
		}
		value /= CPU_BUF_SIZE;

		n = (int) ((value * lcd_cellwid * bar_size) / 100.0 + 0.5);
		sock_printf(sock, "widget_set P cpu%d_bar %d %d %d\n", z, x, y, n);
	}

	return 0;
}										  // End cpu_screen()
예제 #15
0
파일: main.c 프로젝트: emteejay/lcdproc
int
menus_init()
{
	int k;

	for (k = 0; sequence[k].which; k++) {
		if (sequence[k].longname) {
			sock_printf(sock, "menu_add_item {} %c checkbox {%s} -value %s\n",
				    sequence[k].which, sequence[k].longname,
			       (sequence[k].flags & ACTIVE) ? "on" : "off");
		}
	}

#ifdef LCDPROC_CLIENT_TESTMENUS
	/*
	 * to be entered on escape from test_menu (but overwritten for
	 * test_{checkbox,ring}
	 */
	sock_send_string(sock, "menu_add_item {} ask menu {Leave menus?} -is_hidden true\n");
	sock_send_string(sock, "menu_add_item {ask} ask_yes action {Yes} -next _quit_\n");
	sock_send_string(sock, "menu_add_item {ask} ask_no action {No} -next _close_\n");
	sock_send_string(sock, "menu_add_item {} test menu {Test}\n");
	sock_send_string(sock, "menu_add_item {test} test_action action {Action}\n");
	sock_send_string(sock, "menu_add_item {test} test_checkbox checkbox {Checkbox}\n");
	sock_send_string(sock, "menu_add_item {test} test_ring ring {Ring} -strings {one\ttwo\tthree}\n");
	sock_send_string(sock, "menu_add_item {test} test_slider slider {Slider} -mintext < -maxtext > -value 50\n");
	sock_send_string(sock, "menu_add_item {test} test_numeric numeric {Numeric} -value 42\n");
	sock_send_string(sock, "menu_add_item {test} test_alpha alpha {Alpha} -value abc\n");
	sock_send_string(sock, "menu_add_item {test} test_ip ip {IP} -v6 false -value 192.168.1.1\n");
	sock_send_string(sock, "menu_add_item {test} test_menu menu {Menu}\n");
	sock_send_string(sock, "menu_add_item {test_menu} test_menu_action action {Submenu's action}\n");
	/*
	 * no successor for menus. Since test_checkbox and test_ring have
	 * their own predecessors defined the "ask" rule will not work for
	 * them.
	 */
	sock_send_string(sock, "menu_set_item {} test -prev {ask}\n");

	sock_send_string(sock, "menu_set_item {test} test_action -next {test_checkbox}\n");
	sock_send_string(sock, "menu_set_item {test} test_checkbox -next {test_ring} -prev test_action\n");
	sock_send_string(sock, "menu_set_item {test} test_ring -next {test_slider} -prev {test_checkbox}\n");
	sock_send_string(sock, "menu_set_item {test} test_slider -next {test_numeric} -prev {test_ring}\n");
	sock_send_string(sock, "menu_set_item {test} test_numeric -next {test_alpha} -prev {test_slider}\n");
	sock_send_string(sock, "menu_set_item {test} test_alpha -next {test_ip} -prev {test_numeric}\n");
	sock_send_string(sock, "menu_set_item {test} test_ip -next {test_menu} -prev {test_alpha}\n");
	sock_send_string(sock, "menu_set_item {test} test_menu_action -next {_close_}\n");
#endif				/* LCDPROC_CLIENT_TESTMENUS */

	return 0;
}
예제 #16
0
파일: main.c 프로젝트: emteejay/lcdproc
int
main(int argc, char **argv)
{
	int cfgresult;
	int c;

	/* set locale for cwdate & time formatting in chrono.c */
	setlocale(LC_TIME, "");

	/* get uname information */
	if (uname(&unamebuf) == -1) {
		perror("uname");
		return (EXIT_FAILURE);
	}

	/* setup error handlers */
	signal(SIGINT, exit_program);	/* Ctrl-C */
	signal(SIGTERM, exit_program);	/* "regular" kill */
	signal(SIGHUP, exit_program);	/* kill -HUP */
	signal(SIGPIPE, exit_program);	/* write to closed socket */
	signal(SIGKILL, exit_program);	/* kill -9 [cannot be trapped; but ...] */

	/* No error output from getopt */
	opterr = 0;

	/* get options from command line */
	while ((c = getopt(argc, argv, "s:p:e:c:fhv")) > 0) {
		char *end;

		switch (c) {
			/* c is for config file */
			case 'c':
				configfile = optarg;
				break;
			/* s is for server */
			case 's':
				server = optarg;
				break;
			/* p is for port */
			case 'p':
				port = strtol(optarg, &end, 0);
				if ((*optarg == '\0') || (*end != '\0') ||
				    (port <= 0) || (port >= 0xFFFF)) {
					fprintf(stderr, "Illegal port value %s\n", optarg);
					exit(EXIT_FAILURE);
				}
				break;
			case 'e':
				islow = strtol(optarg, &end, 0);
				if ((*optarg == '\0') || (*end != '\0') || (islow < 0)) {
					fprintf(stderr, "Illegal delay value %s\n", optarg);
					exit(EXIT_FAILURE);
				}
				break;
			case 'f':
				foreground = TRUE;
				break;
			case 'h':
				HelpScreen(EXIT_SUCCESS);
				break;
			case 'v':
				fprintf(stderr, "LCDproc %s\n", version);
				exit(EXIT_SUCCESS);
				break;
			/* otherwise...  Get help! */
			case '?':	/* unknown option or missing argument */
				/* FALLTHROUGH */
			default:
				HelpScreen(EXIT_FAILURE);
				break;
		}
	}

	/* Read config file */
	cfgresult = process_configfile(configfile);
	if (cfgresult < 0) {
		fprintf(stderr, "Error reading config file\n");
		exit(EXIT_FAILURE);
	}

	/* Set default reporting options */
	if (report_dest == UNSET_INT)
		report_dest = DEFAULT_REPORTDEST;
	if (report_level == UNSET_INT)
		report_level = DEFAULT_REPORTLEVEL;

	/* Set reporting settings */
	set_reporting("lcdproc", report_level, report_dest);

	/* parse non-option arguments: modes to add/delete */
	if (argc > max(optind, 1)) {
		int i;

		/*
		 * if no config file was read, ignore hard coded default
		 * modes
		 */
		if (cfgresult == 0)
			clear_modes();

		/* turn additional options on or off (using ! as prefix) */
		for (i = max(optind, 1); i < argc; i++) {
			int state = (*argv[i] == '!') ? 0 : 1;
			char *name = (state) ? argv[i] : argv[i] + 1;
			int shortname = (strlen(name) == 1) ? name[0] : '\0';
			int found = set_mode(shortname, name, state);

			if (!found) {
				fprintf(stderr, "Invalid Screen: %s\n", name);
				return (EXIT_FAILURE);
			}
		}
	}

	if (server == NULL)
		server = DEFAULT_SERVER;

	/* Connect to the server... */
	sock = sock_connect(server, port);
	if (sock < 0) {
		fprintf(stderr, "Error connecting to LCD server %s on port %d.\n"
			"Check to see that the server is running and operating normally.\n",
			server, port);
		return (EXIT_FAILURE);
	}

	sock_send_string(sock, "hello\n");
	usleep(500000);		/* wait for the server to say hi. */

	/* We grab the real values below, from the "connect" line. */
	lcd_wid = 20;
	lcd_hgt = 4;
	lcd_cellwid = 5;
	lcd_cellhgt = 8;

	if (foreground != TRUE) {
		if (daemon(1, 0) != 0) {
			fprintf(stderr, "Error: daemonize failed\n");
			return (EXIT_FAILURE);
		}

		if (pidfile != NULL) {
			FILE *pidf = fopen(pidfile, "w");

			if (pidf) {
				fprintf(pidf, "%d\n", (int)getpid());
				fclose(pidf);
				pidfile_written = TRUE;
			}
			else {
				fprintf(stderr, "Error creating pidfile %s: %s\n",
					pidfile, strerror(errno));
				return (EXIT_FAILURE);
			}
		}
	}

	/* Init the status gatherers... */
	mode_init();

	/* And spew stuff! */
	main_loop();
	exit_program(EXIT_SUCCESS);

	/* NOTREACHED */
	return EXIT_SUCCESS;
}
예제 #17
0
/**
 * TimeDate Screen displays current time and date, uptime, OS ver...
 *
 *\verbatim
 *
 * +--------------------+	+--------------------+
 * |## Linux 2.6.11 ###@|	|### TIME: myhost ##@|
 * |Up xxx days hh:mm:ss|	|17.05.2005 11:32:57a|
 * |  Wed May 17, 1998  |	+--------------------+
 * |11:32:57a  100% idle|
 * +--------------------+
 *
 *\endverbatim
 *
 * \param rep        Time since last screen update
 * \param display    1 if screen is visible or data should be updated
 * \param flags_ptr  Mode flags
 * \return  Always 0
 */
int
time_screen(int rep, int display, int *flags_ptr)
{
	char now[40];
	char today[40];
	int xoffs;
	int days, hour, min, sec;
	static int heartbeat = 0;
	static const char *timeFormat = NULL;
	static const char *dateFormat = NULL;
	time_t thetime;
	struct tm *rtime;
	double uptime, idle;

	if ((*flags_ptr & INITIALIZED) == 0) {
		*flags_ptr |= INITIALIZED;

		/* get config values */
		timeFormat = config_get_string("TimeDate", "TimeFormat", 0, "%H:%M:%S");
		dateFormat = config_get_string("TimeDate", "DateFormat", 0, "%b %d %Y");

		sock_send_string(sock, "screen_add T\n");
		sock_printf(sock, "screen_set T -name {Time Screen: %s}\n", get_hostname());
		sock_send_string(sock, "widget_add T title title\n");
		sock_send_string(sock, "widget_add T one string\n");
		if (lcd_hgt >= 4) {
			sock_send_string(sock, "widget_add T two string\n");
			sock_send_string(sock, "widget_add T three string\n");

			/* write title bar: OS name, OS version, hostname */
			sock_printf(sock, "widget_set T title {%s %s: %s}\n",
				get_sysname(), get_sysrelease(), get_hostname());
		}
		else {
			/* write title bar: hostname */
			sock_printf(sock, "widget_set T title {TIME: %s}\n", get_hostname());
		}
	}

	/* toggle colon display */
	heartbeat ^= 1;

	time(&thetime);
	rtime = localtime(&thetime);

	if (strftime(today, sizeof(today), dateFormat, rtime) == 0)
		*today = '\0';
	if (strftime(now, sizeof(now), timeFormat, rtime) == 0)
		*now = '\0';
	tickTime(now, heartbeat);

	if (lcd_hgt >= 4) {
		char tmp[40];	/* should be large enough */

		machine_get_uptime(&uptime, &idle);

		/* display the uptime... */
		days = (int) uptime / 86400;
		hour = ((int) uptime % 86400) / 3600;
		min  = ((int) uptime % 3600) / 60;
		sec  = ((int) uptime % 60);

		if (lcd_wid >= 20)
			sprintf(tmp, "Up %3d day%s %02d:%02d:%02d",
				days, ((days != 1) ? "s" : ""), hour, min, sec);
		else
			sprintf(tmp, "Up %dd %02d:%02d:%02d", days, hour, min, sec);

		xoffs = (lcd_wid > strlen(tmp)) ? ((lcd_wid - strlen(tmp)) / 2) + 1 : 1;
		if (display)
			sock_printf(sock, "widget_set T one %i 2 {%s}\n", xoffs, tmp);

		/* display the date */
		xoffs = (lcd_wid > strlen(today)) ? ((lcd_wid - strlen(today)) / 2) + 1 : 1;
		if (display)
			sock_printf(sock, "widget_set T two %i 3 {%s}\n", xoffs, today);

		/* display the time & idle time... */
		sprintf(tmp, "%s %3i%% idle", now, (int) idle);
		xoffs = (lcd_wid > strlen(tmp)) ? ((lcd_wid - strlen(tmp)) / 2) + 1 : 1;
		if (display)
			sock_printf(sock, "widget_set T three %i 4 {%s}\n", xoffs, tmp);
	}
	else {			/* 2 line version of the screen */
		xoffs = (lcd_wid > (strlen(today) + strlen(now) + 1))
			? ((lcd_wid - ((strlen(today) + strlen(now) + 1))) / 2) + 1 : 1;
		if (display)
			sock_printf(sock, "widget_set T one %i 2 {%s %s}\n", xoffs, today, now);
	}

	return 0;
}				/* End time_screen() */
예제 #18
0
/**
 * Big Clock Screen displays current time...
 *
 *\verbatim
 *
 * +--------------------+
 * |    _   _      _  _ |
 * |  ||_ . _||_|. _|  ||
 * |  ||_|. _|  |.|_   ||
 * |                    |
 * +--------------------+
 *
 *\endverbatim
 *
 * \param rep        Time since last screen update
 * \param display    1 if screen is visible or data should be updated
 * \param flags_ptr  Mode flags
 * \return  Always 0
 */
int
big_clock_screen(int rep, int display, int *flags_ptr)
{
	time_t thetime;
	struct tm *rtime;
	int pos[] = {1, 4, 8, 11, 15, 18};
	char fulltxt[16];
	static char old_fulltxt[16];
	static int heartbeat = 0;
	static int TwentyFourHour = 1;
	int j = 0;
	int digits = (lcd_wid >= 20) ? 6 : 4;
	int xoffs = (lcd_wid + 1 - (pos[digits - 1] + 2)) / 2;

	/* toggle colon display */
	heartbeat ^= 1;

	if ((*flags_ptr & INITIALIZED) == 0) {
		*flags_ptr |= INITIALIZED;

		sock_send_string(sock, "screen_add K\n");
		sock_send_string(sock, "screen_set K -name {Big Clock Screen} -heartbeat off\n");
		sock_send_string(sock, "widget_add K d0 num\n");
		sock_send_string(sock, "widget_add K d1 num\n");
		sock_send_string(sock, "widget_add K d2 num\n");
		sock_send_string(sock, "widget_add K d3 num\n");
		sock_send_string(sock, "widget_add K c0 num\n");

		if (digits > 4) {
			sock_send_string(sock, "widget_add K d4 num\n");
			sock_send_string(sock, "widget_add K d5 num\n");
			sock_send_string(sock, "widget_add K c1 num\n");
		}

		strcpy(old_fulltxt, "      ");
	}

	time(&thetime);
	rtime = localtime(&thetime);

	sprintf(fulltxt, "%02d%02d%02d",
			((TwentyFourHour) ? rtime->tm_hour : (((rtime->tm_hour + 11) % 12) + 1)),
			rtime->tm_min, rtime->tm_sec);

	for (j = 0; j < digits; j++) {
		if (fulltxt[j] != old_fulltxt[j]) {
			sock_printf(sock, "widget_set K d%d %d %c\n", j, xoffs+pos[j], fulltxt[j]);
			old_fulltxt[j] = fulltxt[j];
		}
	}

	if (heartbeat) {	/* 10 means: colon */
		sock_printf(sock, "widget_set K c0 %d 10\n", xoffs + 7);
		if (digits > 4)
			sock_printf(sock, "widget_set K c1 %d 10\n", xoffs + 14);
	}
	else {			/* kludge: use illegal number to clear colon display */
		sock_printf(sock, "widget_set K c0 %d 11\n", xoffs + 7);
		if (digits > 4)
			sock_printf(sock, "widget_set K c1 %d 11\n", xoffs + 14);
	}

	return 0;
}				/* End big_clock_screen() */
예제 #19
0
/**
 * Uptime Screen shows info about system uptime and OS version
 *
 *\verbatim
 *
 * +--------------------+	+--------------------+
 * |## SYSTEM UPTIME ##@|	|# Linux 2.6.11: my#@|
 * |       myhost       |	| xxx days hh:mm:ss  |
 * | xxx days hh:mm:ss  |	+--------------------+
 * |   Linux 2.6.11     |
 * +--------------------+
 *
 *\endverbatim
 *
 * \param rep        Time since last screen update
 * \param display    1 if screen is visible or data should be updated
 * \param flags_ptr  Mode flags
 * \return  Always 0
 */
int
uptime_screen(int rep, int display, int *flags_ptr)
{
	int xoffs;
	int days, hour, min, sec;
	double uptime, idle;
	static int heartbeat = 0;
	char tmp[257];	/* should be large enough for host name */

	if ((*flags_ptr & INITIALIZED) == 0) {
		*flags_ptr |= INITIALIZED;

		sock_send_string(sock, "screen_add U\n");
		sock_printf(sock, "screen_set U -name {Uptime Screen: %s}\n", get_hostname());
		sock_send_string(sock, "widget_add U title title\n");
		if (lcd_hgt >= 4) {
			sock_send_string(sock, "widget_add U one string\n");
			sock_send_string(sock, "widget_add U two string\n");
			sock_send_string(sock, "widget_add U three string\n");

			sock_send_string(sock, "widget_set U title {SYSTEM UPTIME}\n");

			sprintf(tmp, "%s", get_hostname());
			xoffs = (lcd_wid > strlen(tmp)) ? (((lcd_wid - strlen(tmp)) / 2) + 1) : 1;
			sock_printf(sock, "widget_set U one %i 2 {%s}\n", xoffs, tmp);

			sprintf(tmp, "%s %s", get_sysname(), get_sysrelease());
			xoffs = (lcd_wid > strlen(tmp)) ? (((lcd_wid - strlen(tmp)) / 2) + 1) : 1;
			sock_printf(sock, "widget_set U three %i 4 {%s}\n", xoffs, tmp);
		}
		else {
			sock_send_string(sock, "widget_add U one string\n");

			sock_printf(sock, "widget_set U title {%s %s: %s}\n",
					get_sysname(), get_sysrelease(), get_hostname());
		}
	}

	/* toggle colon display */
	heartbeat ^= 1;

	machine_get_uptime(&uptime, &idle);
	days = (int) uptime / 86400;
	hour = ((int) uptime % 86400) / 3600;
	min =  ((int) uptime % 3600) / 60;
	sec =  ((int) uptime % 60);
	if (lcd_wid >= 20)
		sprintf(tmp, "%d day%s %02d:%02d:%02d",
			days, ((days != 1) ? "s" : ""), hour, min, sec);
	else
		sprintf(tmp, "%dd %02d:%02d:%02d", days, hour, min, sec);

	if (display) {
		xoffs = (lcd_wid > strlen(tmp)) ? (((lcd_wid - strlen(tmp)) / 2) + 1) : 1;
		if (lcd_hgt >= 4)
			sock_printf(sock, "widget_set U two %d 3 {%s}\n", xoffs, tmp);
		else
			sock_printf(sock, "widget_set U one %d 2 {%s}\n", xoffs, tmp);
	}

	return 0;
}				/* End uptime_screen() */
/**
 * Tells the server the client would NOT like to accept keypresses
 * of a particular type when the given screen is active on the display
 *
 *\verbatim
 * Usage: screen_del_key <screenid> <keylist>
 *\endverbatim
 */
int
screen_del_key_func(Client *c, int argc, char **argv)
{
	Screen *s;  /* Attached to a specific screen */
	char *id;  /* Screen ID */
	char *keys;  /* Keys wanted */

	if (c->state != ACTIVE)
		return 1;

	if (argc != 3) {
		switch (argc) {
			case 1:
				sock_send_error(c->sock, "Usage: screen_del_key <screenid> <keylist>\n");
				break;
			case 2:
				sock_send_error(c->sock, "You must specify a key list\n");
				break;
			default:
				sock_send_error(c->sock, "Too many parameters\n");
				break;
		}
		return 0;
	}

	id = argv[1];
	keys = argv[2];
	debug(RPT_DEBUG, "screen_del_key: Deleting key(s) %s from screen %s", keys, id);

	/* Find the screen*/
	s = client_find_screen(c, id);
	if (s == NULL) {
		sock_send_error(c->sock, "Unknown screen id\n");
		return 0;
	}

	/* Do we have keys?*/
	if (s->keys != NULL) {
		/* Have keys, remove keys from the list
		 * NOTE: We let malloc/realloc remember the length
		 *    of the allocated storage.  If keys are later
		 *    added, realloc (in add_key above) will make
		 *    sure there is enough space at s->keys
		 */
		char *from;
		char *to;

		to = from = s->keys;
		while (*from != '\0') {
			/* Is this key to be deleted from the list? */
			if (strchr(keys, *from) == 0) {
				/* Yes, skip it */
				++from;
			}
			else {
				/* No, save it */
				*to++ = *from++;
			}
		}
		to = '\0';	/* terminates the new keys string...*/
	}

	sock_send_string(c->sock, "success\n");

	return 0;
}
/**
 * Gives disk stats.
 * Stays onscreen until it is done; rolls over all mounted file systems
 *
 *\verbatim
 *
 * +--------------------+	+--------------------+
 * |## DISKS: myhost ##@|	|## DISKS: myhost ##@|
 * |/       18.3G E--  F|	|-local  18.3G E--- F|
 * |-local  18.3G E--- F|	+--------------------+
 * |/boot  949.6M E-   F|
 * +--------------------+
 *
 *\endverbatim
 *
 * \param rep        Time since last screen update
 * \param display    1 if screen is visible or data should be updated
 * \param flags_ptr  Mode flags
 * \return  Always 0
 */
int
disk_screen(int rep, int display, int *flags_ptr)
{
	static mounts_type mnt[256];
	static int count = 0;

	/* Holds info to display (avoid recalculating it) */
	struct disp {
		char dev[16];
		char cap[8];
		int full;
	} table[256];
	int i;
	static int num_disks = 0;
	static int dev_wid = 6;
	static int gauge_wid = 6;

#define huge long long int
	huge size;

	if ((*flags_ptr & INITIALIZED) == 0) {
		*flags_ptr |= INITIALIZED;

		dev_wid = (lcd_wid >= 20) ? (lcd_wid - 8) / 2 : (lcd_wid / 2) - 1;
		gauge_wid = (lcd_wid >= 20) ? (lcd_wid - dev_wid - 10) : (lcd_wid - dev_wid - 3);

		sock_send_string(sock, "screen_add D\n");
		sock_printf(sock, "screen_set D -name {Disk Use: %s}\n", get_hostname());
		sock_send_string(sock, "widget_add D title title\n");
		sock_printf(sock, "widget_set D title {DISKS: %s}\n", get_hostname());
		sock_send_string(sock, "widget_add D f frame\n");
		sock_printf(sock, "widget_set D f 1 2 %i %i %i %i v 12\n", lcd_wid, lcd_hgt, lcd_wid, lcd_hgt - 1);
		sock_send_string(sock, "widget_add D err1 string\n");
		sock_send_string(sock, "widget_add D err2 string\n");
		sock_send_string(sock, "widget_set D err1 5 2 {  Reading  }\n");
		sock_send_string(sock, "widget_set D err2 5 3 {Filesystems}\n");
	}

	/* Get rid of old, unmounted filesystems... */
	machine_get_fs(mnt, &count);

	/* Fill the display structure... */
	if (count) {
		sock_send_string(sock, "widget_set D err1 0 0 .\n");
		sock_send_string(sock, "widget_set D err2 0 0 .\n");
		for (i = 0; i < count; i++) {
			if (strlen(mnt[i].mpoint) > dev_wid)
				sprintf(table[i].dev, "-%s", (mnt[i].mpoint) + (strlen(mnt[i].mpoint) - (dev_wid - 1)));
			else
				sprintf(table[i].dev, "%s", mnt[i].mpoint);

			table[i].full = (huge) (lcd_cellwid * gauge_wid)
				* (huge) (mnt[i].blocks - mnt[i].bfree)
				/ (huge) mnt[i].blocks;

			size = (huge) mnt[i].bsize * (huge) mnt[i].blocks;
			memset(table[i].cap, '\0', 8);

			sprintf_memory(table[i].cap, (double) size, 1);
		}
	}
	else {
		sock_send_string(sock, "widget_set D err1 1 2 {Error Retrieving}\n");
		sock_send_string(sock, "widget_set D err2 1 3 {Filesystem Stats}\n");
		return 0;
	}

	/*
	 * Display stuff...  (show for two seconds, then scroll once per
	 * second, then hold at the end for two seconds)
	 */
	sock_printf(sock, "widget_set D f 1 2 %i %i %i %i v 12\n", lcd_wid, lcd_hgt, lcd_wid, count);
	for (i = 0; i < count; i++) {
		char tmp[lcd_wid + 1];	/* should be large enough */

		if (table[i].dev[0] == '\0')
			continue;

		if (i >= num_disks) {	/* Make sure we have enough lines... */
			sock_printf(sock, "widget_add D s%i string -in f\n", i);
			sock_printf(sock, "widget_add D h%i hbar -in f\n", i);
		}
		if (lcd_wid >= 20) {	/* 20+x columns */
			sprintf(tmp, "%-*s %6s E%*sF", dev_wid, table[i].dev, table[i].cap, gauge_wid, "");
			sock_printf(sock, "widget_set D s%i 1 %i {%s}\n", i, i + 1, tmp);
			sock_printf(sock, "widget_set D h%i %i %i %i\n", i, 10 + dev_wid, i + 1, table[i].full);
		}
		else {		/* < 20 columns */
			sprintf(tmp, "%-*s E%*sF", dev_wid, table[i].dev, gauge_wid, "");
			sock_printf(sock, "widget_set D s%i 1 %i {%s}\n", i, i + 1, tmp);
			sock_printf(sock, "widget_set D h%i %i %i %i\n", i, 3 + dev_wid, i + 1, table[i].full);
		}
	}

	/* Now remove extra widgets... */
	for (; i < num_disks; i++) {
		sock_printf(sock, "widget_del D s%i\n", i);
		sock_printf(sock, "widget_del D h%i\n", i);
	}

	num_disks = count;

#undef huge

	return 0;
}
/**
 * Configures info about a particular screen, such as its
 *  name, priority, or duration
 *
 *\verbatim
 * Usage: screen_set <id> [-name <name>] [-wid <width>] [-hgt <height>]
 *     [-priority <prio>] [-duration <int>] [-timeout <int>]
 *     [-heartbeat <type>] [-backlight <type>]
 *     [-cursor <type>] [-cursor_x <xpos>] [-cursor_y <ypos>]
 *\endverbatim
 */
int
screen_set_func(Client *c, int argc, char **argv)
{
	int i;

	int number;
	char *id;
	Screen * s;

	if (c->state != ACTIVE)
		return 1;

	if (argc == 1) {
		sock_send_error(c->sock, "Usage: screen_set <id> [-name <name>]"
				" [-wid <width>] [-hgt <height>] [-priority <prio>]"
				" [-duration <int>] [-timeout <int>]"
				" [-heartbeat <type>] [-backlight <type>]"
				" [-cursor <type>]"
				" [-cursor_x <xpos>] [-cursor_y <ypos>]\n");
		return 0;
	}
	else if (argc == 2) {
		sock_send_error(c->sock, "What do you want to set?\n");
		return 0;
	}

	id = argv[1];
	s = client_find_screen(c, id);
	if (s == NULL) {
		sock_send_error(c->sock, "Unknown screen id\n");
		return 0;
	}
	/* Handle the rest of the parameters*/
	for (i = 2; i < argc; i++) {
		char *p = argv[i];

		/* ignore leading '-' in options: we allow both forms */
		if (*p == '-')
			p++;

		/* Handle the "name" parameter*/
		if (strcmp(p, "name") == 0) {
			if (argc > i + 1) {
				i++;
				debug(RPT_DEBUG, "screen_set: name=\"%s\"", argv[i]);

				/* set the name...*/
				if (s->name != NULL)
					free(s->name);
				s->name = strdup(argv[i]);
				sock_send_string(c->sock, "success\n");
			}
			else {
				sock_send_error(c->sock, "-name requires a parameter\n");
			}
		}
		/* Handle the "priority" parameter*/
		else if (strcmp(p, "priority") == 0) {
			if (argc > i + 1) {
				i++;
				debug(RPT_DEBUG, "screen_set: priority=\"%s\"", argv[i]);

				/* first try to interpret it as a number */
				number = atoi(argv[i]);
				if (number > 0) {
					if (number <= 64)
						number = PRI_FOREGROUND;
					else if (number < 192)
						number = PRI_INFO;
					else
						number = PRI_BACKGROUND;
				}
				else {
					/* Try if it is a priority class */
					number = screen_pri_name_to_pri(argv[i]);
				}
				if (number >= 0) {
					s->priority = number;
					sock_send_string(c->sock, "success\n");
				}
				else {
					sock_send_error(c->sock, "invalid argument at -priority\n");
				}
			}
			else {
				sock_send_error(c->sock, "-priority requires a parameter\n");
			}
		}
		/* Handle the "duration" parameter*/
		else if (strcmp(p, "duration") == 0) {
			if (argc > i + 1) {
				i++;
				debug(RPT_DEBUG, "screen_set: duration=\"%s\"", argv[i]);

				/* set the duration...*/
				number = atoi(argv[i]);
				if (number > 0)
					s->duration = number;
				sock_send_string(c->sock, "success\n");
			}
			else {
				sock_send_error(c->sock, "-duration requires a parameter\n");
			}
		}
		/* Handle the "heartbeat" parameter*/
		else if (strcmp(p, "heartbeat") == 0) {
			if (argc > i + 1) {
				i++;
				debug(RPT_DEBUG, "screen_set: heartbeat=\"%s\"", argv[i]);

				/* set the heartbeat type...*/
				if (0 == strcmp(argv[i], "on"))
					s->heartbeat = HEARTBEAT_ON;
				else if (0 == strcmp(argv[i], "off"))
					s->heartbeat = HEARTBEAT_OFF;
				else if (0 == strcmp(argv[i], "open"))
					s->heartbeat = HEARTBEAT_OPEN;
				sock_send_string(c->sock, "success\n");
			}
			else {
				sock_send_error(c->sock, "-heartbeat requires a parameter\n");
			}
		}
		/* Handle the "wid" parameter*/
		else if (strcmp(p, "wid") == 0) {
			if (argc > i + 1) {
				i++;
				debug(RPT_DEBUG, "screen_set: wid=\"%s\"", argv[i]);

				/* set the duration...*/
				number = atoi(argv[i]);
				if (number > 0)
					s->width = number;
				sock_send_string(c->sock, "success\n");
			}
			else {
				sock_send_error(c->sock, "-wid requires a parameter\n");
			}

		}
		/* Handle the "hgt" parameter*/
		else if (strcmp(p, "hgt") == 0) {
			if (argc > i + 1) {
				i++;
				debug(RPT_DEBUG, "screen_set: hgt=\"%s\"", argv[i]);

				/* set the duration...*/
				number = atoi(argv[i]);
				if (number > 0)
					s->height = number;
				sock_send_string(c->sock, "success\n");
			}
			else {
				sock_send_error(c->sock, "-hgt requires a parameter\n");
			}
		}
		/* Handle the "timeout" parameter*/
		else if (strcmp(p, "timeout") == 0) {
			if (argc > i + 1) {
				i++;
				debug(RPT_DEBUG, "screen_set: timeout=\"%s\"", argv[i]);
				/* set the duration...*/
				number = atoi(argv[i]);
				/* Add the timeout value (count of TIME_UNITS)
				 *  to struct,  TIME_UNIT is 1/8th of a second
				 */
				if (number > 0) {
					s->timeout = number;
					report(RPT_NOTICE, "Timeout set.");
				}
				sock_send_string(c->sock, "success\n");
			}
			else {
				sock_send_error(c->sock, "-timeout requires a parameter\n");
			}
		}
		/* Handle the "backlight" parameter*/
		else if (strcmp(p, "backlight") == 0) {
			if (argc > i + 1) {
				i++;
				debug(RPT_DEBUG, "screen_set: backlight=\"%s\"", argv[i]);
				/* set the backlight status based on what the client has set*/
				switch(c->backlight) {
					case BACKLIGHT_OPEN:
						if (strcmp("on", argv[i]) == 0)
							s->backlight = BACKLIGHT_ON;

						if (strcmp("off", argv[i]) == 0)
							s->backlight = BACKLIGHT_OFF;

						if (strcmp("toggle", argv[i]) == 0) {
							if (s->backlight == BACKLIGHT_ON)
								s->backlight = BACKLIGHT_OFF;
							else if (s-backlight == BACKLIGHT_OFF)
								s->backlight = BACKLIGHT_ON;
						}

						if (strcmp("blink", argv[i]) == 0)
							s->backlight  |= BACKLIGHT_BLINK;

						if (strcmp("flash", argv[i]) == 0)
							s->backlight |= BACKLIGHT_FLASH;
					break;
					default:
						/*If the backlight is not OPEN then inherit its state*/
						s->backlight = c->backlight;
					break;
				}
				sock_send_string(c->sock, "success\n");
			}
			else {
				sock_send_error(c->sock, "-backlight requires a parameter\n");
			}
		}
		/* Handle the "cursor" parameter */
		else if (strcmp(p, "cursor") == 0) {
			if (argc > i + 1) {
				i++;
				debug(RPT_DEBUG, "screen_set: cursor=\"%s\"", argv[i]);

				/* set the heartbeat type...*/
				if (0 == strcmp(argv[i], "off"))
					s->cursor = CURSOR_OFF;
				if (0 == strcmp(argv[i], "on"))
					s->cursor = CURSOR_DEFAULT_ON;
				if (0 == strcmp(argv[i], "under"))
					s->cursor = CURSOR_UNDER;
				if (0 == strcmp(argv[i], "block"))
					s->cursor = CURSOR_BLOCK;
				sock_send_string(c->sock, "success\n");
			}
			else {
				sock_send_error(c->sock, "-cursor requires a parameter\n");
			}
		}
		/* Handle the "cursor_x" parameter */
		else if (strcmp(p, "cursor_x") == 0) {
			if (argc > i + 1) {
				i++;
				debug(RPT_DEBUG, "screen_set: cursor_x=\"%s\"", argv[i]);

				/* set the position...*/
				number = atoi(argv[i]);
				if (number > 0 && number <= s->width) {
					s->cursor_x = number;
					sock_send_string(c->sock, "success\n");
				}
				else {
					sock_send_error(c->sock, "Cursor position outside screen\n");
				}
			}
			else {
				sock_send_error(c->sock, "-cursor_x requires a parameter\n");
			}
		}
		/* Handle the "cursor_y" parameter */
		else if (strcmp(p, "cursor_y") == 0) {
			if (argc > i + 1) {
				i++;
				debug(RPT_DEBUG, "screen_set: cursor_y=\"%s\"", argv[i]);

				/* set the position...*/
				number = atoi(argv[i]);
				if (number > 0 && number <= s->height) {
					s->cursor_y = number;
					sock_send_string(c->sock, "success\n");
				}
				else {
					sock_send_error(c->sock, "Cursor position outside screen\n");
				}
			}
			else {
				sock_send_error(c->sock, "-cursor_y requires a parameter\n");
			}
		}

		else sock_send_error(c->sock, "invalid parameter\n");
	}/* done checking argv*/
	return 0;
}
예제 #23
0
/*************************************************************************
 * menu_add_item_func
 *
 * Adds an item to a menu
 *
 * Usage: menu_add_item <menuid> <newitemid> <type> [<text>]
 * You should use "" as id for the client's main menu. This menu will be
 * created automatically when you add an item to it the first time.
 * You (currently?) cannot create a menu in the main level yourself.
 * The names you use for items should be unique for your client.
 * The text is the visible text for the item.
 *
 * The following types are available:
 * - menu
 * - action
 * - checkbox
 * - ring (a kind of listbox of one line)
 * - slider
 * - numeric
 * - alpha
 * - ip
 */
int
menu_add_item_func (Client * c, int argc, char **argv)
{
	char * menu_id;
	char * item_id;
	char * text = NULL;
	Menu * menu = NULL;
	MenuItem * item;
	MenuItemType itemtype;
	char** argv_set = NULL;

	debug (RPT_DEBUG, "%s( Client [%d], %s, %s )",
	       __FUNCTION__, c->sock, argv[1], argv[2]);
	if (!c->ack)
		return 1;

	if (!c->name) {
		sock_send_error(c->sock, "You need to give your client a name first\n");
		return 0;
	}

	if ((argc < 4 )) {
		sock_send_error(c->sock, "Usage: menu_add_item <menuid> <newitemid> <type> [<text>]\n");
		return 0;
	}

	menu_id = argv[1];
	item_id = argv[2];

	/* Does the client have a menu already ? */
	if (!c->menu) {
		/* We need to create it */
		report( RPT_INFO, "Client [%d] is using the menu", c->sock );
		c->menu = menu_create ("_client_menu_", menu_commands_handler, c->name, c);
		menu_add_item (main_menu, c->menu);
	}

	if ( menu_id[0] == 0 ) {
		/* No menu specified = client's main menu */
		menu = c->menu;
	} else {
		/* A specified menu */
		menu = menu_find_item (c->menu, menu_id, true);
	}
	if (!menu) {
		sock_send_error(c->sock, "Cannot find menu id\n");
		return 0;
	}

	item = menu_find_item (c->menu, item_id, true);
	if (item) {
		sock_send_error(c->sock, "Item id already in use\n");
		return 0;
	}

	/* Find menuitem type */
	itemtype = menuitem_typename_to_type (argv[3]);
	if (itemtype == -1) {
		sock_send_error(c->sock, "Invalid menuitem type\n");
		return 0;
	}

	/* Is a text given (options don't count)? */
	if (argc >= 5 && argv[4][0] != '-') {
		text = argv[4];
	}
	else {
		text = "";
	}

	/* Create the menuitem */
	switch (itemtype) {
	  case MENUITEM_MENU:
		item = menu_create (item_id, menu_commands_handler, text, c);
		break;
	  case MENUITEM_ACTION:
		item = menuitem_create_action (item_id, menu_commands_handler, text, c,
				MENURESULT_NONE);
		break;
	  case MENUITEM_CHECKBOX:
		item = menuitem_create_checkbox (item_id, menu_commands_handler, text, c,
				false, false);
		break;
	  case MENUITEM_RING:
		item = menuitem_create_ring (item_id, menu_commands_handler, text, c,
				"", 0);
		break;
	  case MENUITEM_SLIDER:
		item = menuitem_create_slider (item_id, menu_commands_handler, text, c,
				 "", "", 0, 100, 1, 25);
		break;
	  case MENUITEM_NUMERIC:
		item = menuitem_create_numeric (item_id, menu_commands_handler, text, c,
				0, 100, 0);
		break;
	  case MENUITEM_ALPHA:
		item = menuitem_create_alpha (item_id, menu_commands_handler, text, c,
				0, 0, 10, true, false, true, "-./", "");
		break;
	  case MENUITEM_IP:
		item = menuitem_create_ip (item_id, menu_commands_handler, text, c,
				0, "192.168.1.245");
		break;
	 default:
	   assert(!"unexpected menuitem type");
	}
	menu_add_item (menu, item);
	menuscreen_inform_item_modified (menu);
	sock_send_string(c->sock, "success\n");

	/* are there any options (starting with '-')?
	 * - create a temporary argv for menu_set_item() call */
	if (argc > 5 || argv[4][0] == '-') {
		// menu_add_item <menuid> <newitemid> <type> [<text>]
		// menu_set_item <menuid> <itemid> {<option>}+
		int i, j;
		argv_set = malloc(argc * sizeof(char*));
		assert(argv_set);
		argv_set[0] = "menu_set_item";
		for (i = j = 1; i < argc; ++i)
		{
			/* skip "type" */
			if (i == 3)
				continue;
			/* skip "text" */
			if (i == 4 && argv[4][0] != '-')
				continue;

			argv_set[j++] = argv[i];
		}
		menu_set_item_func(c, j, argv_set);
		free(argv_set);
	}
	return 0;
}
예제 #24
0
/**************************************************************************
 * menu_set_item_func
 * Sets the info about a menu item
 *
 * For example, text displayed, value, etc...
 *
 * Usage: menu_set_item <menuid> <itemid> {<option>}+
 * The following parameters can be set per item:
 * (you should include the - in the option)
 *
 * For all types:
 * -text "text"			("")
 *	Sets the visible text.
 * -is_hidden false|true	(false)
 *	If the item currently should not appear in a menu.
 * -prev id			()
 *	Sets the predecessor of this item (what happens after "Escape")
 *
 * For all except menus:
 * -next id			()
 *	Sets the successor of this item (what happens after "Enter")
 *
 * action:
 * -menu_result none|close|quit	(none)
 *	Sets what to do with the menu when this action is selected:
 *	- none: the menu stays as it is.
 *	- close: the menu closes and returns to a higher level.
 *	- quit: quits the menu completely so you can foreground your app.
 *
 * checkbox:
 * -value off|on|gray		(off)
 *	Sets its current value.
 * -allow_gray false|true	(false)
 *	Sets if a grayed checkbox is allowed.
 *
 * ring:
 * -value <int>			(0)
 *	Sets the index in the stringlist that is currently selected.
 * -strings <string>		(empty)
 *	The subsequent strings that can be selected. They should be
 *	tab-separated in ONE string.
 *
 * slider:
 * -value <int>			(0)
 *	Sets its current value.
 * -mintext <string>		("")
 * -maxtex <string>		("")
 *	Text at the minimal and maximal side. On small displays these might
 *	not be displayed.
 * -minvalue <int>		(0)
 * -maxvalue <int>		(100)
 *	The minimum and maximum value of the slider.
 * -stepsize <int>		(1)
 *	The stepsize of the slider. If you use 0, you can control it yourself
 *	completely.
 *
 * numeric:
 * -value <int>			(0)
 *	Sets its current value.
 * -minvalue <int>		(0)
 * -maxvalue <int>		(100)
 *	The minimum and maximum value that are allowed. If you make one of
 *	them negative, the user will be able to enter negative numbers too.
 * Maybe floats will work too in the future.
 *
 * alpha:
 * -value <string>
 *	Sets its current value.	("")
 * -password_char <char>	(none)
 * -minlength <int>		(0)
 * -maxlength <int>		(10)
 *	Set the minimum and maximum allowed length.
 * -allow_caps false|true	(true)
 * -allow_noncaps false|true	(false)
 * -allow_numbers false|true	(true)
 *	Allows these groups of characters.
 * -allowed_extra <string>	("")
 *	The chars in this string are also allowed.
 *
 * ip:
 * -value <string>
 *	Sets its current value.	("")
 * -v6 false|true
 *
 * Hmm, this is getting very big. We might need a some real parser after all.
 */
int
menu_set_item_func (Client * c, int argc, char **argv)
{
	typedef enum AttrType { NOVALUE, BOOLEAN, CHECKBOX_VALUE, SHORT, INT,
				FLOAT, STRING } AttrType;

	/* This table generalizes the options.
	 * The table lists which options can exist for which menu items,
	 * what kind of parameter they should have and where this scanned
	 * parameter should be stored.
	 */
	struct OptionTable {
		MenuItemType menuitem_type;	/* For what MenuItem type is
						   the option ?
						   Use -1 for ALL types. */
		char * name;			/* The option concerned */
		AttrType attr_type;		/* Type of value */
		int attr_offset;		/* Where to put the value
						   in the structure.
						   Use -1 to process it
						   yourself. */
		/* Watch out with STRING, it will free() the current value
		 * and reallocate for the new value !! If you don't want
		 * that, use -1 for offset, to process it yourself. */
	} option_table[] = {
		{ -1,			"text",		STRING,		offsetof(MenuItem,text) },
		{ -1,			"is_hidden",	BOOLEAN,	offsetof(MenuItem,is_hidden) },
		{ -1,			"prev",	STRING,		-1 },
		{ -1,			"next",		STRING,		-1 },
		{ MENUITEM_ACTION,	"menu_result",	STRING,		-1 },
		{ MENUITEM_CHECKBOX,	"value",	CHECKBOX_VALUE,	offsetof(MenuItem,data.checkbox.value) },
		{ MENUITEM_CHECKBOX,	"allow_gray",	BOOLEAN,	offsetof(MenuItem,data.checkbox.allow_gray) },
		{ MENUITEM_RING,	"value",	SHORT,		offsetof(MenuItem,data.ring.value) },
		{ MENUITEM_RING,	"strings",	STRING,		-1 },
		{ MENUITEM_SLIDER,	"value",	INT,		offsetof(MenuItem,data.slider.value) },
		{ MENUITEM_SLIDER,	"minvalue",	INT,		offsetof(MenuItem,data.slider.minvalue) },
		{ MENUITEM_SLIDER,	"maxvalue",	INT,		offsetof(MenuItem,data.slider.maxvalue) },
		{ MENUITEM_SLIDER,	"stepsize",	INT,		offsetof(MenuItem,data.slider.stepsize) },
		{ MENUITEM_SLIDER,	"mintext",	STRING,		offsetof(MenuItem,data.slider.mintext) },
		{ MENUITEM_SLIDER,	"maxtext",	STRING,		offsetof(MenuItem,data.slider.maxtext) },
		{ MENUITEM_NUMERIC,	"value",	INT,		offsetof(MenuItem,data.numeric.value) },
		{ MENUITEM_NUMERIC,	"minvalue",	INT,		offsetof(MenuItem,data.numeric.minvalue) },
		{ MENUITEM_NUMERIC,	"maxvalue",	INT,		offsetof(MenuItem,data.numeric.maxvalue) },
		/*{ MENUITEM_NUMERIC,	"allow_decimals",BOOLEAN,	offsetof(MenuItem,data.numeric.allow_decimals) },*/
		{ MENUITEM_ALPHA,	"value",	STRING,		-1 /*offsetof(MenuItem,data.alpha.value)*/ },
		{ MENUITEM_ALPHA,	"minlength",	SHORT,		offsetof(MenuItem,data.alpha.minlength) },
		{ MENUITEM_ALPHA,	"maxlength",	SHORT,		offsetof(MenuItem,data.alpha.maxlength) },
		{ MENUITEM_ALPHA,	"password_char",STRING,		-1 },
		{ MENUITEM_ALPHA,	"allow_caps",	BOOLEAN,	offsetof(MenuItem,data.alpha.allow_caps) },
		{ MENUITEM_ALPHA,	"allow_noncaps",BOOLEAN,	offsetof(MenuItem,data.alpha.allow_noncaps) },
		{ MENUITEM_ALPHA,	"allow_numbers",BOOLEAN,	offsetof(MenuItem,data.alpha.allow_numbers) },
		{ MENUITEM_ALPHA,	"allowed_extra",STRING,		offsetof(MenuItem,data.alpha.allowed_extra) },
		{ MENUITEM_IP,		"v6",		BOOLEAN,	offsetof(MenuItem,data.ip.v6) },
		{ MENUITEM_IP,		"value",	STRING,		-1 /*offsetof(MenuItem,data.ip.value)*/ },
		{ -1,			NULL,		-1,		-1 }
	};

	debug (RPT_DEBUG, "%s( Client [%d]: %s)",
	       __FUNCTION__, c->sock, argv2string(argc, argv));
	bool bool_value = false;
	CheckboxValue checkbox_value = CHECKBOX_OFF;
	short short_value = 0;
	int int_value = 0;
	float float_value = 0;
	char * string_value = NULL;

	Menu * menu;
	MenuItem * item;
	char * menu_id;
	char * item_id;
	int argnr;

	if (!c->ack)
		return 1;

	if (argc < 4 ) {
		sock_send_error(c->sock, "Usage: menu_set_item <menuid> <itemid> {<option>}+\n");
		return 0;
	}

	menu_id = argv[1];
	item_id = argv[2];

	if ( menu_id[0] == 0 ) {
		/* No menu specified = client's main menu */
		menu = c->menu;
	} else {
		/* A specified menu */
		menu = menu_find_item (c->menu, menu_id, true);
	}
	if (!menu) {
		sock_send_error(c->sock, "Cannot find menu id\n");
		return 0;
	}

	item = menu_find_item (c->menu, item_id, true);
	if (!item) {
		sock_send_error(c->sock, "Cannot find item\n");
		return 0;
	}

	/* Scan all arguments */
	for( argnr = 3; argnr < argc; argnr ++) {
		int option_nr = -1;
		int found_option_name = 0;
		int error = 0;
		void * location;
		char * p;

		/* Find the option in the table */
		if( argv[argnr][0] == '-' ) {
			int i;
			for( i=0; option_table[i].name; i++ ) {
				if( strcmp( argv[argnr]+1, option_table[i].name ) == 0 ) {
					found_option_name = 1;
					if( item->type == option_table[i].menuitem_type
					|| option_table[i].menuitem_type == -1 ) {
						option_nr = i;
					}
				}
			}
		}
		else {
			sock_printf_error(c->sock, "Found non-option: \"%.40s\"\n", argv[argnr]);
			continue; /* Skip to next arg */
		}
		if( option_nr == -1 ) {
			if( found_option_name ) {
				sock_printf_error(c->sock, "Option not valid for menuitem type: \"%.40s\"\n", argv[argnr]);
			} else {
				sock_printf_error(c->sock, "Unknown option: \"%.40s\"\n", argv[argnr]);
			}
			continue; /* Skip to next arg */
		}

		/* OK, we now know we have an option that is valid for the item type. */

		/* Check for value */
		if( option_table[option_nr].attr_type != NOVALUE ) {
			if( argnr + 1 >= argc ) {
				sock_printf_error(c->sock, "Missing value at option: \"%.40s\"\n", argv[argnr]);
				continue; /* Skip to next arg (probably is not existing :) */
			}
		}
		/* Process the value that goes with the option */
		location = (void*)item + option_table[option_nr].attr_offset;
		switch( option_table[option_nr].attr_type ) {
		  case NOVALUE:
			break;
		  case BOOLEAN:
			if( strcmp( argv[argnr+1], "false" ) == 0 ) {
				bool_value = false;
			} else if( strcmp( argv[argnr+1], "true" ) == 0 ) {
				bool_value = true;
			} else {
				error = 1;
				break;
			}
			if( option_table[option_nr].attr_offset != -1 ) {
				*(bool *)location = bool_value;
			}
			break;
		  case CHECKBOX_VALUE:
			if( strcmp( argv[argnr+1], "off" ) == 0 ) {
				checkbox_value = CHECKBOX_OFF;
			} else if( strcmp( argv[argnr+1], "on" ) == 0 ) {
				checkbox_value = CHECKBOX_ON;
			} else if( strcmp( argv[argnr+1], "gray" ) == 0 ) {
				checkbox_value = CHECKBOX_GRAY;
			} else {
				error = 1;
				break;
			}
			if( option_table[option_nr].attr_offset != -1 ) {
				*(CheckboxValue *)location = checkbox_value;
			}
			break;
		  case SHORT:
			short_value = strtol( argv[argnr+1], &p, 0 );
			if( argv[argnr+1][0] == '\0' || *p != '\0' ) {
				error = 1;
				break;
			}
			if( option_table[option_nr].attr_offset != -1 ) {
				*(short*)location = short_value;
			}
			break;
		  case INT:
			int_value = strtol( argv[argnr+1], &p, 0 );
			if( argv[argnr+1][0] == '\0' || *p != '\0' ) {
				error = 1;
				break;
			}
			if( option_table[option_nr].attr_offset != -1 ) {
				*(int*)location = int_value;
			}
			break;
		  case FLOAT:
			float_value = strtod( argv[argnr+1], &p );
			if( argv[argnr+1][0] == '\0' || *p != '\0' ) {
				error = 1;
				break;
			}
			if( option_table[option_nr].attr_offset != -1 ) {
				*(float*)location = float_value;
			}
			break;
		  case STRING:
		  	string_value = argv[argnr+1];
			if( option_table[option_nr].attr_offset != -1 ) {
				free( *(char**)location );
				*(char**)location = strdup( string_value );
			}
			else if (strcmp(argv[argnr], "-prev") == 0) {
				set_predecessor(item, string_value, c);
			}
			else if (strcmp(argv[argnr], "-next") == 0) {
				set_successor(item, string_value, c);
			}
			break;
		}
		switch( error ) {
		  case 1:
			sock_printf_error(c->sock, "Could not interpret value at option: \"%.40s\"\n", argv[argnr]);
			argnr ++;
			continue; /* Skip current option and the invalid value */
		}

		/* And at last process extra things for certain options.
		 * Most useful for the attr_offset==-1 stuff. */
		switch (item->type) {
		  case MENUITEM_ACTION:
			if( strcmp( argv[argnr]+1, "menu_result" ) == 0 ) {
				if( strcmp( argv[argnr+1], "none" ) == 0 ) {
					set_successor(item, "_none_", c);
				} else if( strcmp( argv[argnr+1], "close" ) == 0 ) {
					set_successor(item, "_close_", c);
				} else if( strcmp( argv[argnr+1], "quit" ) == 0 ) {
					set_successor(item, "_quit_", c);
				} else {
					error = 1;
				}
			}
			break;
		  case MENUITEM_SLIDER:
			if( item->data.slider.value < item->data.slider.minvalue ) {
				item->data.slider.value = item->data.slider.minvalue;
			} else if( item->data.slider.value > item->data.slider.maxvalue ) {
				item->data.slider.value = item->data.slider.maxvalue;
			}
			break;
		  case MENUITEM_RING:
		  	if( strcmp( argv[argnr]+1, "strings" ) == 0 ) {
		  		free (item->data.ring.strings);
		  		item->data.ring.strings = tablist2linkedlist (string_value);
		  	}
			item->data.ring.value %= LL_Length( item->data.ring.strings );
			break;
		  case MENUITEM_NUMERIC:
			menuitem_reset (item);
			break;
		  case MENUITEM_ALPHA:
			if( strcmp( argv[argnr]+1, "password_char" ) == 0 ) {
				item->data.alpha.password_char = string_value[0];
			}
			else if( strcmp( argv[argnr]+1, "maxlength" ) == 0 ) {
				char * new_buf;
				if( short_value < 0 || short_value > 1000 ) {
					error = 2;
					break;
				}
				new_buf = malloc( short_value + 1 );
				strncpy( new_buf, item->data.alpha.value, short_value );
				new_buf[short_value] = '\0'; /* terminate */
				free( item->data.alpha.value );
				item->data.alpha.value = new_buf;
				free( item->data.alpha.edit_str );
				item->data.alpha.edit_str = malloc( short_value + 1 );
				item->data.alpha.edit_str[0] = '\0';
			}
			else if( strcmp( argv[argnr]+1, "value" ) == 0 ) {
				strncpy( item->data.alpha.value, string_value, item->data.alpha.maxlength );
				item->data.alpha.value[ item->data.alpha.maxlength ] = 0; /* terminate */
			}
			menuitem_reset (item);
			break;
		  case MENUITEM_IP:
			if( strcmp( argv[argnr]+1, "v6" ) == 0 ) {
				char * new_buf;
                		/* set max lenth depending ob boolean option v6 */
				item->data.ip.maxlength = (bool_value == 0) ? 15 : 39;

				new_buf = malloc(item->data.ip.maxlength + 1 );
				strncpy( new_buf, item->data.ip.value, item->data.ip.maxlength);

				new_buf[item->data.ip.maxlength] = '\0'; /* terminate */
				free( item->data.ip.value );
				item->data.ip.value = new_buf;
				free( item->data.ip.edit_str );
				item->data.ip.edit_str = malloc( item->data.ip.maxlength +1);
				item->data.ip.edit_str[0] = '\0';
			}
			else if( strcmp( argv[argnr]+1, "value" ) == 0 ) {
				strncpy( item->data.ip.value, string_value, item->data.ip.maxlength );
				item->data.ip.value[item->data.ip.maxlength] = '\0'; /* terminate */
			}
			menuitem_reset (item);
			break;
		  default:
			break;
		}
		switch( error ) {
		  case 1:
			sock_printf_error(c->sock, "Could not interpret value at option: \"%.40s\"\n", argv[argnr]);
			continue; /* Skip to next arg and retry it as an option */
		  case 2:
			sock_printf_error(c->sock, "Value out of range at option: \"%.40s\"\n", argv[argnr]);
			argnr ++;
			continue; /* Skip current option and the invalid value */
		}
		menuscreen_inform_item_modified (item);
		if( option_table[option_nr].attr_type != NOVALUE ) {
			/* Skip the now used argument */
			argnr ++;
		}
	}
	sock_send_string(c->sock, "success\n");
	return 0;
}
예제 #25
0
/**
 * OldTime Screen displays current time and date...
 *
 *\verbatim
 *
 * +--------------------+	+--------------------+
 * |## DATE & TIME ####@|	|### TIME: myhost ##@|
 * |       myhost       |	|2005-05-17 11:32:57a|
 * |11:32:75a Wednesday,|	+--------------------+
 * |       May 17, 2005 |
 * +--------------------+
 *
 * Alternate 2-line version without the title bar:
 *
 * +----------------+
 * |   2012-12-27  @|
 * |    15:07:01    |
 * +----------------+
 *
 *\endverbatim
 *
 * \param rep        Time since last screen update
 * \param display    1 if screen is visible or data should be updated
 * \param flags_ptr  Mode flags
 * \return  Always 0
 */
int
clock_screen(int rep, int display, int *flags_ptr)
{
	char now[40];
	char today[40];
	int xoffs;
	static int heartbeat = 0;
	static int showTitle = 1;
	static const char *timeFormat = NULL;
	static const char *dateFormat = NULL;
	time_t thetime;
	struct tm *rtime;

	if ((*flags_ptr & INITIALIZED) == 0) {
		char tmp[257];	/* should be large enough for host name */

		*flags_ptr |= INITIALIZED;

		/* get config values */
		timeFormat = config_get_string("OldTime", "TimeFormat", 0, "%H:%M:%S");
		dateFormat = config_get_string("OldTime", "DateFormat", 0, "%b %d %Y");
		showTitle = config_get_bool("OldTime", "ShowTitle", 0, 1);

		sock_send_string(sock, "screen_add O\n");
		sock_printf(sock, "screen_set O -name {Old Clock Screen: %s}\n", get_hostname());
		if (!showTitle)
			sock_send_string(sock, "screen_set O -heartbeat off\n");
		sock_send_string(sock, "widget_add O one string\n");
		if (lcd_hgt >= 4) {
			sock_send_string(sock, "widget_add O title title\n");
			sock_send_string(sock, "widget_add O two string\n");
			sock_send_string(sock, "widget_add O three string\n");

			sock_printf(sock, "widget_set O title {DATE & TIME}\n");

			sprintf(tmp, "%s", get_hostname());
			xoffs = (lcd_wid > strlen(tmp)) ? (((lcd_wid - strlen(tmp)) / 2) + 1) : 1;
			sock_printf(sock, "widget_set O one %i 2 {%s}\n", xoffs, tmp);
		}
		else {
			if (showTitle) {
				sock_send_string(sock, "widget_add O title title\n");
				sock_printf(sock, "widget_set O title {TIME: %s}\n", get_hostname());
			}
			else {
				sock_send_string(sock, "widget_add O two string\n");
			}
		}
	}

	/* toggle colon display */
	heartbeat ^= 1;

	time(&thetime);
	rtime = localtime(&thetime);

	if (strftime(today, sizeof(today), dateFormat, rtime) == 0)
		*today = '\0';
	if (strftime(now, sizeof(now), timeFormat, rtime) == 0)
		*now = '\0';
	tickTime(now, heartbeat);

	if (lcd_hgt >= 4) {	/* 4-line version of the screen */
		xoffs = (lcd_wid > strlen(today)) ? ((lcd_wid - strlen(today)) / 2) + 1 : 1;
		if (display)
			sock_printf(sock, "widget_set O two %i 3 {%s}\n", xoffs, today);

		xoffs = (lcd_wid > strlen(now)) ? ((lcd_wid - strlen(now)) / 2) + 1 : 1;
		if (display)
			sock_printf(sock, "widget_set O three %i 4 {%s}\n", xoffs, now);
	}
	else {			/* 2-line version of the screen */
		if (showTitle) {
			xoffs = (lcd_wid > (strlen(today) + strlen(now) + 1))
				? ((lcd_wid - ((strlen(today) + strlen(now) + 1))) / 2) + 1 : 1;
			if (display)
				sock_printf(sock, "widget_set O one %i 2 {%s %s}\n", xoffs, today, now);
		}
		else {
			xoffs = (lcd_wid > strlen(today)) ? ((lcd_wid - strlen(today)) / 2) + 1 : 1;
			if (display)
				sock_printf(sock, "widget_set O one %i 1 {%s}\n", xoffs, today);
			xoffs = (lcd_wid > strlen(now)) ? ((lcd_wid - strlen(now)) / 2) + 1 : 1;
			if (display)
				sock_printf(sock, "widget_set O two %i 2 {%s}\n", xoffs, now);
		}
	}

	return 0;
}				/* End clock_screen() */
/**
 * Tells the server the client would like to accept keypresses
 * of a particular type when the given screen is active on the display
 *
 *\verbatim
 * Usage: screen_add_key <screenid> <keylist>
 *\endverbatim
 */
int
screen_add_key_func(Client *c, int argc, char **argv)
{
	Screen *s;  /* Attached to a specific screen */
	char *id;  /* Screen ID */
	char *keys;  /* Keys wanted */

	if (c->state != ACTIVE)
		return 1;

	if (argc != 3) {
		switch (argc) {
			case 1:
				sock_send_error(c->sock, "Usage: screen_add_key <screenid> <keylist>\n");
				break;
			case 2:
				sock_send_error(c->sock, "You must specify a key list\n");
				break;
			default:
				sock_send_error(c->sock, "Too many parameters...\n");
				break;
		}
		return 0;
	}

	id = argv[1];
	keys = argv[2];
	debug(RPT_DEBUG, "screen_add_key: Adding key(s) %s to screen %s", keys, id);

	/* Find the screen*/
	s = client_find_screen(c, id);
	if (!s) {
		sock_send_error(c->sock, "Unknown screen id\n");
		return 0;
	}

	/* Save the keys*/
	if (s->keys == NULL) {
		/* Save supplied key list*/
		s->keys = strdup(keys);
	}
	else {
		/* Add supplied keys to existing list
		 * NOTE: There could be duplicates in the resulting list
		 *    That's OK, it's the existence of the key in the list
		 *    that's important.  We'll be more careful in the delete
		 *    key function.
		 */
		char *new_keys;
		new_keys = realloc(s->keys, strlen(s->keys) + strlen(keys) +1);
		if (new_keys) {
			strcpy(new_keys, s->keys);
			strcat(new_keys, keys);
			free(s->keys);
			s->keys = new_keys;
		}
		else {
			sock_send_error(c->sock, "Could not add new keys\n");
			return 0;
		}
	}

	if (s->keys == NULL)
		sock_send_error(c->sock, "failed\n");
	else
		sock_send_string(c->sock, "success\n");

	return 0;
}