static bool lgtd_jsonrpc_type_null(const jsmntok_t *t, const char *json) { return memcmp( &json[t->start], "null", LGTD_MIN(t->size, (int)sizeof("null")) ); }
void test_label(struct lgtd_lifx_bulb *bulb, const char *bulb_label, const char *label, bool expected) { memcpy(bulb->state.label, bulb_label, LGTD_MIN( strlen(bulb_label) + 1, LGTD_LIFX_LABEL_SIZE )); bool rv = lgtd_lifx_bulb_has_label(bulb, label); if (rv != expected) { errx( 1, "bulb_has_label(%s, %s) -> %s (expected %s)", bulb_label, label, rv ? "true" : "false", expected ? "true" : "false" ); } }
char * lgtd_print_duration(uint64_t secs, char *buf, int bufsz) { assert(buf); assert(bufsz > 0); int days = secs / (60 * 60 * 24); int minutes = secs / 60; int hours = minutes / 60; hours = hours % 24; minutes = minutes % 60; int i = 0; if (days) { int n = snprintf(buf, bufsz, "%d days ", days); i = LGTD_MIN(i + n, bufsz); } snprintf(&buf[i], bufsz - i, "%02d:%02d", hours, minutes); return buf; }
int main(int argc, char *argv[], char *envp[]) { char progname[32] = { 0 }; memcpy(progname, argv[0], LGTD_MIN(sizeof(progname) - 1, strlen(argv[0]))); lgtd_daemon_setup_proctitle(argc, argv, envp); lgtd_configure_libevent(); lgtd_setup_signal_handling(); static const struct option long_opts[] = { {"listen", required_argument, NULL, 'l'}, {"command-pipe", required_argument, NULL, 'c'}, {"socket", required_argument, NULL, 's'}, {"foreground", no_argument, NULL, 'f'}, {"daemonize", no_argument, NULL, 'd'}, {"pidfile", required_argument, NULL, 'p'}, {"user", required_argument, NULL, 'u'}, {"group", required_argument, NULL, 'g'}, {"syslog", no_argument, NULL, 'S'}, {"syslog-facility", required_argument, NULL, 'F'}, {"syslog-ident", required_argument, NULL, 'I'}, {"no-timestamps", no_argument, NULL, 't'}, {"help", no_argument, NULL, 'h'}, {"verbosity", required_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {"prefix", no_argument, NULL, 'P'}, {"rundir", no_argument, NULL, 'r'}, {NULL, 0, NULL, 0} }; const char short_opts[] = "l:c:s:fdp:u:g:SF:I:thv:V"; if (argc == 1) { lgtd_usage(progname); } for (int rv = getopt_long(argc, argv, short_opts, long_opts, NULL); rv != -1; rv = getopt_long(argc, argv, short_opts, long_opts, NULL)) { switch (rv) { case 'l': (void)0; char *sep = strrchr(optarg, ':'); if (!sep || !sep[1]) { lgtd_usage(progname); } *sep = '\0'; if (!lgtd_listen_open(optarg, sep + 1)) { exit(1); } break; case 'c': if (!lgtd_command_pipe_open(optarg)) { exit(1); } break; case 's': if (!lgtd_listen_unix_open(optarg)) { exit(1); } break; case 'f': lgtd_opts.foreground = true; break; case 'd': lgtd_opts.foreground = false; break; case 'p': lgtd_opts.pidfile = optarg; break; case 'u': lgtd_opts.user = optarg; break; case 'g': lgtd_opts.group = optarg; break; case 'S': lgtd_opts.syslog = true; break; case 'F': lgtd_opts.syslog_facility = lgtd_daemon_syslog_facilitytoi(optarg); break; case 'I': lgtd_opts.syslog_ident = optarg; break; case 't': lgtd_opts.log_timestamps = false; break; case 'h': lgtd_usage(progname); case 'v': for (int i = 0;;) { const char *verbose_levels[] = { "debug", "info", "warning", "error" }; if (!strcasecmp(optarg, verbose_levels[i])) { lgtd_opts.verbosity = i; break; } if (++i == LGTD_ARRAY_SIZE(verbose_levels)) { lgtd_errx(1, "Unknown verbosity level: %s", optarg); } } break; case 'V': printf("%s %s\n", progname, LGTD_VERSION); lgtd_cleanup(); return 0; case 'P': printf( "%s%s\n", LGTD_INSTALL_PREFIX, LGTD_INSTALL_PREFIX[ LGTD_ARRAY_SIZE(LGTD_INSTALL_PREFIX) - 1 ] != '/' ? "/" : "" ); return 0; case 'r': printf( "%s%s\n", LGTD_RUNTIME_DIRECTORY, LGTD_RUNTIME_DIRECTORY[ LGTD_ARRAY_SIZE(LGTD_RUNTIME_DIRECTORY) - 1 ] != '/' ? "/" : "" ); return 0; default: lgtd_usage(progname); } } argc -= optind; argv += optind; // Ideally we should parse the syslog relation options first and call that // before anything can be logged: lgtd_log_setup(); if (lgtd_opts.user) { lgtd_daemon_set_user(lgtd_opts.user); lgtd_daemon_set_group(lgtd_opts.group); // create the pidfile before we drop privileges: if (lgtd_opts.pidfile && !lgtd_daemon_write_pidfile(lgtd_opts.pidfile)) { lgtd_warn("couldn't write pidfile at %s", lgtd_opts.pidfile); } lgtd_daemon_drop_privileges(); } else if (lgtd_opts.group) { lgtd_errx(1, "please, specify an user with the -u option"); } lgtd_daemon_die_if_running_as_root_unless_requested(lgtd_opts.user); lgtd_lifx_wire_setup(); if (!lgtd_lifx_discovery_setup() || !lgtd_lifx_broadcast_setup()) { lgtd_err(1, "can't setup lightsd"); } if (!lgtd_opts.foreground) { lgtd_info("forking into the background now..."); if (!lgtd_daemon_unleash()) { lgtd_err(1, "can't fork to the background"); } } // update the pidfile after we've forked: if (lgtd_opts.pidfile && !lgtd_daemon_write_pidfile(lgtd_opts.pidfile)) { lgtd_warn("couldn't write pidfile at %s", lgtd_opts.pidfile); } lgtd_lifx_discovery_start(); // update at least once: so that if no bulbs are discovered we still get a // clear status line. lgtd_daemon_update_proctitle(); event_base_dispatch(lgtd_ev_base); if (lgtd_last_signal_received) { lgtd_info( "received signal %d (%s), exiting...", lgtd_last_signal_received, strsignal(lgtd_last_signal_received) ); } lgtd_cleanup(); return 0; }
void lgtd_jsonrpc_uint16_range_to_float_string(uint16_t encoded, int start, int stop, char *out, int size) { assert(out); assert(size > 1); assert(start < stop); if (size < 2) { if (size) { *out = '\0'; } return; } int range; range = stop * LGTD_JSONRPC_FLOAT_PREC - start * LGTD_JSONRPC_FLOAT_PREC; int value = (uint64_t)encoded * (uint64_t)range / UINT16_MAX; if (!value) { out[0] = '0'; out[1] = '\0'; return; } int multiplier = 1; while (value / (multiplier * 10)) { multiplier *= 10; } int i = 0; if (LGTD_JSONRPC_FLOAT_PREC / 10 > multiplier) { out[i++] = '0'; if (i != size) { out[i++] = '.'; } for (int divider = 10; LGTD_JSONRPC_FLOAT_PREC / divider > multiplier && i != size; divider *= 10) { out[i++] = '0'; } } do { if (multiplier == LGTD_JSONRPC_FLOAT_PREC / 10) { if (i == 0) { out[i++] = '0'; } if (i != size) { out[i++] = '.'; } } if (i != size) { out[i++] = '0' + value / multiplier; } value -= value / multiplier * multiplier; multiplier /= 10; } while ((value || multiplier >= LGTD_JSONRPC_FLOAT_PREC) && multiplier && i != size); out[LGTD_MIN(i, size - 1)] = '\0'; assert(i <= size); }