#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "fonts.h" #include "input_gadgets.h" #include "multiplexer.h" void drop_privileges(); void handle_signals(int signo); t_scroll_data scroll_data; time_t next_update = 0; int main(int argc, char **argv) { int ret_val; #define TEXT_BUFFER_LENGTH SCROLL_BUF_LEN / 5 char *text_buffer; char *text_buffer_end; // Set up gpi pointer for direct register access ret_val = multiplexer_setup_root(); if (ret_val) return ret_val; // Drop root privileges drop_privileges(); // set up / register signal handler struct sigaction new_action, old_action; new_action.sa_handler = handle_signals; sigemptyset (&new_action.sa_mask); new_action.sa_flags = 0; const int fetch_signals[4] = { SIGINT, SIGHUP, SIGTERM, SIGUSR1 }; for (int i = 0; i < sizeof(fetch_signals)/sizeof(fetch_signals[0]); i++) { sigaction (fetch_signals[i], NULL, &old_action); if (old_action.sa_handler != SIG_IGN) sigaction (fetch_signals[i], &new_action, NULL); } init_symbols_boundaries(); /************************************************************************\ * You are about to change the GPIO settings of your computer. * * Mess this up and it will stop working! * * It might be a good idea to 'sync' before running this program * * so at least you still have your code changes written to the SD-card! * \************************************************************************/ // configure the gpio pins and start the multiplexer thread multiplexer_setup_scroll(&scroll_data); text_buffer = malloc(TEXT_BUFFER_LENGTH); if (text_buffer == NULL) { fprintf(stderr, "malloc failed to allocate %d bytes\n", TEXT_BUFFER_LENGTH); turn_off_display(); return EXIT_FAILURE; } scroll_data . shine_until = time(NULL) + 10; int i=0; while (scroll_data . keep_running) { if (got_input()) { next_update = 0; // update now! scroll_data . shine_until = time(NULL) + 60; } if ((time(NULL) >= next_update) && (scroll_data . update == 0)) { next_update = time(NULL) + 600; // 10 minutes ahead memset(text_buffer, 0, TEXT_BUFFER_LENGTH); text_buffer_end = text_buffer; double temperature, humidity; text_buffer_end = gadgets_retrieve_weather_warnings(text_buffer_end,text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end); if (text_buffer_end == NULL) { fprintf(stderr, "gadgets_retrieve_weather_warnings failed\n"); free(text_buffer); turn_off_display(); return EXIT_FAILURE; } if (text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end > 0) text_buffer_end += snprintf(text_buffer_end, text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end, "; "); text_buffer_end = gadgets_retrieve_current_temperature(text_buffer_end, text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end, &temperature, &humidity); if (text_buffer_end == NULL) { fprintf(stderr, "gadgets_retrieve_current_temperature failed\n"); free(text_buffer); turn_off_display(); return EXIT_FAILURE; } if (text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end > 0) text_buffer_end += snprintf(text_buffer_end, text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end, "; "); text_buffer_end = gadgets_retrieve_weather_forecast(text_buffer_end,text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end); if (text_buffer_end == NULL) { fprintf(stderr, "gadgets_retrieve_weather_forecast failed\n"); free(text_buffer); turn_off_display(); return EXIT_FAILURE; } struct tm time_struct; memset(&time_struct, 0, sizeof(time_struct)); localtime_r(&next_update, &time_struct); for (int i = 0; i < (time_struct . tm_wday + 6) % 7 + 1; i++) { if (text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end <= 0) break; text_buffer_end += snprintf( text_buffer_end, text_buffer + TEXT_BUFFER_LENGTH - text_buffer_end, "%c%c%c%c", 0xEE, i==0 ? 0x01 : 0x03 + 2 * (i & 0x01), 0xEE, i==0 ? 0x02 : 0x04 + 2 * (i & 0x01) ); } scroll_data . input_len = render( text_buffer, text_buffer_end - text_buffer, scroll_data . input, sizeof(scroll_data . input), 1 ); scroll_data . update = 1; } usleep(100000); } free(text_buffer); pthread_join(scroll_data . thread_id, NULL); turn_off_display(); return EXIT_SUCCESS; } // main // // Drop (root) privileges // void drop_privileges() { /* Drop superuser privileges in correct order */ int is_already_unprivileged = 0; if (setgid(65534) == -1) { // nobody perror("can't drop group privileges"); if (! (is_already_unprivileged = (errno == 1))) exit(-1); } if (setuid(65534) == -1) { // nobody perror("can't drop user privileges"); if (is_already_unprivileged != (errno == 1)) exit(-1); } } // drop_root void handle_signals(int signo) { switch (signo) { case SIGINT: case SIGHUP: case SIGTERM: fprintf(stderr, "stopping\n"); scroll_data . keep_running = 0; break; case SIGUSR1: next_update = 0; scroll_data . shine_until = time(NULL) + 60; break; } }