int main(int argc, char **argv, char **env) { /*=========== GENERIC VARIABLES ===========*/ FILE *f_output = NULL, *f_input = NULL; int c, i; char *end; /*=========== GETOPT VARIABLES ===========*/ char const *const optstr = "hi:o:f:c:w:b:n:t:"; #ifdef _GNU_SOURCE static struct option long_opts[] = { {"help", 0, NULL, 'h'}, {"infile", 1, NULL, 'i'}, {"outfile", 1, NULL, 'o'}, {"format", 1, NULL, 'f'}, {"colors", 1, NULL, 'c'}, {"width", 1, NULL, 'w'}, {"bgcolor", 1, NULL, 'b'}, {"newcolor", 1, NULL, 'n'}, {"color-tolerance", 1, NULL, 't'}, {NULL, 0, NULL, 0}, }; #endif /*=========== IMAGE-RELATED VARIABLES ===========*/ int x, y; int color_idx = 0; int img_orig_h = 0, img_orig_w = 0; int img_targ_h = 0, img_targ_w = 0; int top = -1, bottom = -1, top_prev = -1, bottom_prev = -1; int color = -1, color_prev = -1; gdImagePtr image_data = NULL; gdImagePtr image_resized = NULL; gdImageCreateFunction image_openers[] = { NULL, (gdImageCreateFunction) gdImageCreateFromJpeg, (gdImageCreateFunction) gdImageCreateFromPng, (gdImageCreateFunction) gdImageCreateFromGif, (gdImageCreateFunction) gdImageCreateFromWBMP, (gdImageCreateFunction) gdImageCreateFromXpm /* Accepts char * as first argument! */ }; while (true) { #ifdef _GNU_SOURCE c = getopt_long(argc, argv, optstr, long_opts, NULL); #else /* not _GNU_SOURCE */ c = getopt(argc, argv, optstr); #endif /* _GNU_SOURCE */ if (c == -1) break; switch (c) { case 'h': help(stdout, EXEC_NAME); exit(ALL_OK); break; case 'i': i = strlen(optarg); if (i2u_conf.m_infile != NULL) free(i2u_conf.m_infile); if ((i2u_conf.m_infile = (char *) calloc(i+1, sizeof(char))) == NULL) { fprintf(stderr, "calloc() failed!\n"); cleanup_main(); exit(ERR_OUT_OF_MEMORY); } strncpy(i2u_conf.m_infile, optarg, i); break; case 'o': if (strncmp("-", optarg, 2) == 0) { if (i2u_conf.m_outfile != NULL) free(i2u_conf.m_outfile); i2u_conf.m_outfile = NULL; break; } else { i = strlen(optarg); if (i2u_conf.m_outfile != NULL) free(i2u_conf.m_outfile); if ((i2u_conf.m_outfile = (char *) calloc(i+1, sizeof(char))) == NULL) { fprintf(stderr, "calloc() failed!\n"); cleanup_main(); exit(ERR_OUT_OF_MEMORY); } strncpy(i2u_conf.m_outfile, optarg, i); break; } case 'f': i = (int) strtol(optarg, &end, 10); if (optarg != end) { i2u_conf.m_outformat = (i > 8) ? unicode : ansi; } else { if (strncasecmp(optarg, "ansi", 5) == 0) i2u_conf.m_outformat = ansi; else { if (strncmp(optarg, "unicode", 8) == 0) i2u_conf.m_outformat = unicode; else fprintf(stderr, "Warning: invalid format specified. Defaulting to Unicode.\n"); } } break; case 'c': i = (int) strtol(optarg, &end, 10); if (optarg != end) { if (i < 9) i2u_conf.m_colors = low; else { if (i < 17) i2u_conf.m_colors = basic; else i2u_conf.m_colors = extended; } } else fprintf(stderr, "Warning: invalid color depth specified. Defaulting to 256.\n"); break; case 'w': i = (int) strtol(optarg, &end, 10); if (optarg != end) i2u_conf.m_targ_width = i; else fprintf(stderr, "Warning: invalid width specified. Defaulting to 80.\n"); break; case 't': i = (int) strtol(optarg, &end, 10); if (optarg != end) i2u_conf.m_toleranceradius = (i > 0) ? i : 0; else fprintf(stderr, "Warning: invalid color-tolerance radius specified. Defaulting to zero.\n"); break; case 'b': i = strtol(optarg, &end, 16); if (optarg != end) i2u_conf.m_bgcolor = i; else fprintf(stderr, "Warning: invalid background color specified. No background-substitution will occur.\n"); break; case 'n': i = strtol(optarg, &end, 16); if (optarg != end) i2u_conf.m_newcolor = i; else fprintf(stderr, "Warning: invalid substitution color specified. No background-substitution will occur.\n"); break; case '?': default: help(stderr, EXEC_NAME); exit(ERR_INVALID_ARG); } if (c == 'x') break; } if (i2u_conf.m_infile == NULL) { fprintf(stderr, "Error: input file not set. Use option" #ifdef _GNU_SOURCE "s -i or --infile" #else /* not _GNU_SOURCE */ " -i" #endif /* _GNU_SOURCE */ " to specify one.\n"); cleanup_main(); exit(ERR_INVALID_ARG); } /*=========== GD PART ==========*/ i2u_conf.m_ftype = get_image_type(i2u_conf.m_infile); if (i2u_conf.m_ftype == UNKNOWN) { fprintf(stderr, "Error: unsupported input file type!\n" ); cleanup_main(); exit(ERR_UNSUPPORTED_FORMAT); } if (i2u_conf.m_ftype != xpm) { if ((f_input = fopen(i2u_conf.m_infile, "r")) == NULL) { perror("fopen(): "); cleanup_main(); exit(ERR_FOPEN_FAIL); } image_data = image_openers[i2u_conf.m_ftype](f_input); fclose(f_input); } else { if ((image_data = image_openers[i2u_conf.m_ftype](i2u_conf.m_infile)) == NULL) { fprintf(stderr, "gdImageCreateFromXpm(): Error occured while opening file \'%s\'\n", i2u_conf.m_infile); cleanup_main(); exit(ERR_GD_XPMOPEN_FAIL); } } img_orig_w = image_data->sx; img_orig_h = image_data->sy; img_targ_w = i2u_conf.m_targ_width; img_targ_h = (int) round(((double) img_targ_w)/((double) img_orig_w)*((double) img_orig_h)); /* if (i2u_conf.m_outformat == ansi) img_targ_w /= 2; */ /* change background, if requested */ if ((i2u_conf.m_bgcolor > -1) && (i2u_conf.m_newcolor > -1)) { int bg_r, bg_g, bg_b; int nc_r, nc_g, nc_b; int bgcolor, newcolor; int radius = i2u_conf.m_toleranceradius; bg_r = (i2u_conf.m_bgcolor & 0x00ff0000) >> 16; bg_g = (i2u_conf.m_bgcolor & 0x0000ff00) >> 8; bg_b = (i2u_conf.m_bgcolor & 0x000000ff); nc_r = (i2u_conf.m_newcolor & 0x00ff0000) >> 16; nc_g = (i2u_conf.m_newcolor & 0x0000ff00) >> 8; nc_b = (i2u_conf.m_newcolor & 0x000000ff); if ((bgcolor = gdImageColorExact(image_data, bg_r, bg_g, bg_b)) != -1) { color_idx = gdImageGetPixel(image_data, 0, 0); newcolor = gdImageColorResolve(image_data, nc_r, nc_g, nc_b); for (y=0; y<img_orig_h; y++) { for (x=0; x<img_orig_w; x++) { color_idx = gdImageGetPixel(image_data, x, y); if (get_color_distance(gdImageRed(image_data, color_idx), gdImageRed(image_data, bgcolor), gdImageGreen(image_data, color_idx), gdImageGreen(image_data, bgcolor), gdImageBlue(image_data, color_idx), gdImageBlue(image_data, bgcolor)) <= radius) gdImageSetPixel(image_data, x, y, newcolor); } } } }
int API main (int argc, char *argv[], char *envp[]) { initalize_syslog (); struct state state; /* TODO(wad) EVENT_BASE_FLAG_PRECISE_TIMER | EVENT_BASE_FLAG_PRECISE_TIMER */ struct event_base *base = event_base_new(); if (!base) { fatal ("could not allocated new event base"); } /* Add three priority levels: * 0 - time saving. Must be done before any other events are handled. * 1 - network synchronization events * 2 - any other events (wake, platform, etc) */ event_base_priority_init (base, MAX_EVENT_PRIORITIES); memset (&state, 0, sizeof (state)); set_conf_defaults (&state.opts); parse_argv (&state.opts, argc, argv); check_conf (&state); load_conf (&state.opts); check_conf (&state); if (!state.opts.sources) add_source_to_conf (&state.opts, DEFAULT_HOST, DEFAULT_PORT, DEFAULT_PROXY); state.base = base; state.envp = envp; state.backoff = state.opts.wait_between_tries; /* TODO(wad) move this into setup_time_setter */ /* grab a handle to /dev/rtc for time-setter. */ if (state.opts.should_sync_hwclock && platform->rtc_open(&state.hwclock)) { pinfo ("can't open hwclock fd"); state.opts.should_sync_hwclock = 0; } /* install the SIGCHLD handler for the setter and tlsdate */ if (setup_sigchld_event (&state, 1)) { error ("Failed to setup SIGCHLD event"); goto out; } /* fork off the privileged helper */ info ("spawning time setting helper . . ."); if (setup_time_setter (&state)) { error ("could not fork privileged coprocess"); goto out; } /* release the hwclock now that the time-setter is running. */ if (state.opts.should_sync_hwclock) { platform->rtc_close (&state.hwclock); } /* drop privileges before touching any untrusted data */ drop_privs_to (state.opts.user, state.opts.group); /* register a signal handler to save time at shutdown */ if (state.opts.should_save_disk) { struct event *event = event_new (base, SIGTERM, EV_SIGNAL|EV_PERSIST, action_sigterm, &state); if (!event) fatal ("Failed to create SIGTERM event"); event_priority_set (event, PRI_SAVE); event_add (event, NULL); } if (state.opts.should_dbus && init_dbus (&state)) { error ("Failed to initialize DBus"); goto out; } /* Register the tlsdate event before any listeners could show up. */ state.events[E_TLSDATE] = event_new (base, -1, EV_TIMEOUT, action_run_tlsdate, &state); if (!state.events[E_TLSDATE]) { error ("Failed to create tlsdate event"); goto out; } event_priority_set (state.events[E_TLSDATE], PRI_NET); /* The timeout and fd will be filled in per-call. */ if (setup_tlsdate_status (&state)) { error ("Failed to create tlsdate status event"); goto out; } /* TODO(wad) Could use a timeout on this to catch setter death? */ /* EV_READ is for truncation/EPIPE notification */ state.events[E_SAVE] = event_new (base, state.setter_save_fd, EV_READ|EV_WRITE, action_sync_and_save, &state); if (!state.events[E_SAVE]) { error ("Failed to create sync & save event"); goto out; } event_priority_set (state.events[E_SAVE], PRI_SAVE); /* Start by grabbing the system time. */ state.last_sync_type = SYNC_TYPE_RTC; state.last_time = time (NULL); /* If possible, grab disk time and check the two. */ if (state.opts.should_load_disk) { time_t disk_time = state.last_time; if (!load_disk_timestamp (state.timestamp_path, &disk_time)) { info ("disk timestamp available: yes"); if (!is_sane_time (state.last_time) || state.last_time < disk_time) { state.last_sync_type = SYNC_TYPE_DISK; state.last_time = disk_time; } } else { info ("disk timestamp available: no"); } } if (!is_sane_time (state.last_time)) { state.last_sync_type = SYNC_TYPE_BUILD; state.last_time = RECENT_COMPILE_DATE + 1; } /* Save and announce the initial time source. */ trigger_event (&state, E_SAVE, -1); info ("initial time sync type: %s", sync_type_str (state.last_sync_type)); /* Initialize platform specific loop behavior */ if (platform_init_cros (&state)) { error ("Failed to initialize platform code"); goto out; } if (setup_event_route_up (&state)) { error ("Failed to setup route up monitoring"); goto out; } if (setup_event_timer_sync (&state)) { error ("Failed to setup a timer event"); goto out; } if (setup_event_timer_continuity (&state)) { error ("Failed to setup continuity timer"); goto out; } /* Add a forced sync event to the event list. */ action_kickoff_time_sync (-1, EV_TIMEOUT, &state); info ("Entering dispatch . . ."); event_base_dispatch (base); info ("tlsdated terminating gracefully"); out: return cleanup_main (&state); }
image_type get_image_type(const char * const file_name) { image_type retval = UNKNOWN; FILE *p_buf = NULL; char *s_buf = NULL; char *fgets_retval; size_t s_len = 0; /* STAT the input file to see if it's there... */ struct stat stat_buf; if (stat(file_name, &stat_buf) == -1) { perror("stat(): "); cleanup_main(); exit(ERR_STAT_OTHER); } else { if ((stat_buf.st_mode & S_IFMT) != S_IFREG) { fprintf(stderr, "\'%s\' is not a regular file!\n", file_name); cleanup_main(); exit(ERR_INFILE_ACCESS); } if (check_readability(&stat_buf) != true) { fprintf(stderr, "\'%s\' is not a readable for the user/group on whose behalf %s is running on!\n", file_name, EXEC_NAME); cleanup_main(); exit(ERR_INFILE_ACCESS); } } /* run command */ s_len = (strlen(MIME_TYPE_COMMAND)+strlen(file_name)-1); if ((s_buf = (char *) calloc(s_len, sizeof(char))) == NULL) { fprintf(stderr, "calloc() failed!\n"); cleanup_main(); exit(ERR_OUT_OF_MEMORY); } snprintf(s_buf, s_len, MIME_TYPE_COMMAND, file_name); if ((p_buf = popen(s_buf, "r")) == NULL) { perror("popen(): "); cleanup_main(); exit(ERR_POPEN_FAIL); } free(s_buf); /* read output */ if ((s_buf = (char *) calloc(257, sizeof(char))) == NULL) { fprintf(stderr, "calloc() failed!\n"); cleanup_main(); exit(ERR_OUT_OF_MEMORY); } fgets(s_buf+128, 128, p_buf); do { memcpy(s_buf, s_buf+128, 128); memset(s_buf+128, '\0', 128); fgets_retval=fgets(s_buf+128, 128, p_buf); if (strstr(s_buf, JPEG_STRING) != NULL) retval = jpeg; if (strstr(s_buf, PNG_STRING) != NULL) retval = png; if (strstr(s_buf, GIF_STRING) != NULL) retval = gif; if (strstr(s_buf, BMP_STRING) != NULL) retval = bmp; if (strstr(s_buf, XPM_STRING) != NULL) retval = xpm; } while ((fgets_retval != NULL) && (retval == UNKNOWN)); free(s_buf); pclose(p_buf); return retval; }