X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?p=ypp-sc-tools.web-live.git;a=blobdiff_plain;f=pctb%2Fconvert.c;fp=pctb%2Fconvert.c;h=0000000000000000000000000000000000000000;hp=1f1385057d152a1bf1e28bd7d74ae3e818d4b164;hb=c68fb80a6bbf7acbcac4b2cb2143f5fea745cd2b;hpb=b9cce976550d000f15e5a8f2b690740bdae1e468 diff --git a/pctb/convert.c b/pctb/convert.c deleted file mode 100644 index 1f13850..0000000 --- a/pctb/convert.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * ypp-commodities main program: argument parsing etc. - */ -/* - * This is part of ypp-sc-tools, a set of third-party tools for assisting - * players of Yohoho Puzzle Pirates. - * - * Copyright (C) 2009 Ian Jackson - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Yohoho and Puzzle Pirates are probably trademarks of Three Rings and - * are used without permission. This program is not endorsed or - * sponsored by Three Rings. - */ - -#include "convert.h" - -void debug_flush(void) { - sysassert(!ferror(debug)); - sysassert(!fflush(debug)); -} - -const char *get_vardir(void) { return "."; } -const char *get_libdir(void) { return "."; } - - -enum outmodekind { - omk_unset, omk_upload, omk_str, omk_raw, omk_none -}; -static enum outmodekind o_outmode_kind; -static const char *o_outmode_str= 0; - -static char *o_screenshot_fn; -static const char *o_serv_pctb, *o_serv_dict_fetch, *o_serv_dict_submit; - -const char *o_resolver= "./dictionary-manager"; -FILE *screenshot_file; -const char *o_ocean, *o_pirate; -int o_quiet; - -static pid_t screenshot_compressor=-1; - -enum mode o_mode= mode_all; -enum flags o_flags= - ff_charset_allowedit | - ff_dict_fetch|ff_dict_submit|ff_dict_pirate; - -static void vbadusage(const char *fmt, va_list) FMT(1,0) NORET; -static void vbadusage(const char *fmt, va_list al) { - fputs("bad usage: ",stderr); - vfprintf(stderr,fmt,al); - fputc('\n',stderr); - exit(12); -} -DEFINE_VWRAPPERF(static, badusage, NORET); - -static void open_screenshot_file(int for_write) { - if (!fnmatch("*.gz",o_screenshot_fn,0)) { - int mode= for_write ? O_WRONLY|O_CREAT|O_TRUNC : O_RDONLY; - sysassert(! gzopen(o_screenshot_fn, mode, &screenshot_file, - &screenshot_compressor, "-1") ); - } else { - screenshot_file= fopen(o_screenshot_fn, for_write ? "w" : "r"); - if (!screenshot_file) - fatal("could not open screenshots file `%s': %s", - o_screenshot_fn, strerror(errno)); - } -} - -static void run_analysis(void) { - FILE *tf; - - sysassert( tf= tmpfile() ); - progress("running recognition..."); - analyse(tf); - - if (o_flags & ff_upload) { - if (npages<=1) - fatal("Recognition successful, but refusing to upload partial data\n" - " (--single-page specified). Specify an output mode?"); - } - - sysassert( fseek(tf,0,SEEK_SET) == 0); - - progress_log("processing results (--%s)...", o_outmode_str); - pid_t processor; - sysassert( (processor= fork()) != -1 ); - - if (!processor) { - sysassert( dup2(fileno(tf),0) ==0 ); - EXECLP_HELPER("commod-results-processor", o_outmode_str, (char*)0); - } - - waitpid_check_exitstatus(processor, "output processor/uploader", 0); - fclose(tf); - progress_log("all complete."); -} - -static void rsync_core(const char *stem, const char *suffix, - const char *zopt) { - pid_t fetcher; - - progress("Updating dictionary %s...",stem); - - sysassert( (fetcher= fork()) != -1 ); - if (!fetcher) { - const char *rsync= getenv("YPPSC_PCTB_RSYNC"); - if (!rsync) rsync= "rsync"; - - const char *src= getenv("YPPSC_PCTB_DICT_UPDATE"); - char *remote= masprintf("%s/master-%s.txt%s", src, stem, suffix); - char *local= masprintf("_master-%s.txt%s", stem, suffix); - if (DEBUGP(rsync)) - fprintf(stderr,"executing rsync to fetch %s to %s\n",remote,local); - char *opts= masprintf("-Lt%s%s", - zopt, - DEBUGP(rsync) ? "v" : ""); - execlp(rsync, "rsync",opts,"--",remote,local,(char*)0); - sysassert(!"exec rsync failed"); - } - - waitpid_check_exitstatus(fetcher, "rsync", 0); -} - -void fetch_with_rsync_gz(const char *stem) { rsync_core(stem,".gz",""); } -void fetch_with_rsync(const char *stem) { rsync_core(stem,"","z"); } - -static void set_server(const char *envname, const char *defprotocol, - const char *defvalue, const char *defvalue_test, - const char *userspecified, - int enable) { - const char *value; - - if (!enable) { value= "0"; goto ok; } - - if (userspecified) - value= userspecified; - else if ((value= getenv(envname))) - ; - else if (o_flags & ff_testservers) - value= defvalue_test; - else - value= defvalue; - - if (value[0]=='/' || (value[0]=='.' && value[1]=='/')) - /* absolute or relative pathname - or anyway, something with no hostname */ - goto ok; - - const char *colon= strchr(value, ':'); - const char *slash= strchr(value, '/'); - - if (colon && (!slash || colon < slash)) - /* colon before the first slash, if any */ - /* rsync :: protocol specification - anyway, adding scheme:// won't help */ - goto ok; - - int vallen= strlen(value); - - value= masprintf("%s%s%s", defprotocol, value, - vallen && value[vallen-1]=='/' ? "" : "/"); - - ok: - sysassert(! setenv(envname,value,1) ); -} - -int main(int argc, char **argv) { - const char *arg; - - sysassert( setlocale(LC_MESSAGES,"") ); - sysassert( setlocale(LC_CTYPE,"en_GB.UTF-8") || - setlocale(LC_CTYPE,"en.UTF-8") ); - -#define ARGVAL ((*++argv) ? *argv : \ - (badusage("missing value for option %s",arg),(char*)0)) - -#define IS(s) (!strcmp(arg,(s))) - - while ((arg=*++argv)) { - if (IS("--find-window-only")) o_mode= mode_findwindow; - else if (IS("--screenshot-only")) o_mode= mode_screenshot; - else if (IS("--show-charset")) o_mode= mode_showcharset; - else if (IS("--analyse-only") || - IS("--same")) o_mode= mode_analyse; - else if (IS("--everything")) o_mode= mode_all; - else if (IS("--find-island")) o_flags |= ffs_printisland; - else if (IS("--single-page")) o_flags |= ff_singlepage; - else if (IS("--quiet")) o_quiet= 1; - else if (IS("--edit-charset")) o_flags |= ff_charset_edit; - else if (IS("--no-edit-charset")) o_flags &= ~(ffm_charset); - else if (IS("--test-servers")) o_flags |= ff_testservers; - else if (IS("--dict-local-only")) o_flags &= ~ffs_dict; - else if (IS("--dict-read-only")) o_flags &= (~ffs_dict | ff_dict_fetch); - else if (IS("--dict-anon")) o_flags &= ~ff_dict_pirate; - else if (IS("--dict-submit")) o_flags |= ff_dict_fetch|ff_dict_submit; - else if (IS("--raw-tsv")) o_outmode_kind= omk_raw; - else if (IS("--upload")) o_outmode_kind= omk_upload; - else if (IS("--arbitrage") || - IS("--tsv") || - IS("--best-prices")) o_outmode_kind=omk_str, - o_outmode_str=arg+2; - - else if (IS("--screenshot-file")|| - IS("--screenshots-file")) o_screenshot_fn= ARGVAL; - else if (IS("--pctb-server")) o_serv_pctb= ARGVAL; - else if (IS("--dict-submit-server")) o_serv_dict_submit= ARGVAL; - else if (IS("--dict-update-server")) o_serv_dict_fetch= ARGVAL; - else if (IS("--ocean")) o_ocean= ARGVAL; - else if (IS("--pirate")) o_pirate= ARGVAL; -#define DF(f) \ - else if (IS("-D" #f)) \ - debug_flags |= dbg_##f; - DEBUG_FLAG_LIST -#undef DF - else if (IS("--window-id")) { - char *ep; - unsigned long windowid= strtoul(ARGVAL,&ep,0); - if (*ep) badusage("invalid window id"); - set_yppclient_window(windowid); - } else - badusage("unknown option `%s'",arg); - } - - /* Consequential changes to options */ - - if (o_mode & mf_analyse) { - if (!o_outmode_kind) { - if (o_flags & ff_printisland) { - o_outmode_kind= omk_none; - o_flags |= ff_singlepage; - } else { - o_outmode_kind= omk_upload; - } - } - - if (o_outmode_kind==omk_upload) { - o_flags |= ffs_upload; - o_outmode_str= "upload"; - } - } - - /* Defaults */ - - set_server("YPPSC_PCTB_PCTB", - "http://", "pctb.ilk.org" /*pctb.crabdance.com*/, - "pctb.ilk.org", - o_serv_pctb, o_flags & (ff_needisland|ff_upload)); - - set_server("YPPSC_PCTB_DICT_UPDATE", - "rsync://", "rsync.pctb.chiark.greenend.org.uk/pctb", - "rsync.pctb.chiark.greenend.org.uk/pctb/test", - o_serv_dict_fetch, o_flags & ff_dict_fetch); - - set_server("YPPSC_PCTB_DICT_SUBMIT", - "http://", "dictup.pctb.chiark.greenend.org.uk", - "dictup.pctb.chiark.greenend.org.uk/test", - o_serv_dict_submit, o_flags & ff_dict_submit); - - if (!o_screenshot_fn) - o_screenshot_fn= masprintf("%s/_pages.ppm.gz", get_vardir()); - - /* Actually do the work */ - - canon_colour_prepare(); - - if (o_mode & mf_findwindow) { - screenshot_startup(); - find_yppclient_window(); - } - if (!ocean) ocean= o_ocean; - if (!pirate) pirate= o_pirate; - - if (o_flags & ff_needisland) - if (!ocean) - badusage("need --ocean option when not using actual YPP client window" - " (consider supplying --pirate too)"); - if (ocean) - sysassert(! setenv("YPPSC_OCEAN",ocean,1) ); - if (pirate && (o_flags & ff_dict_pirate)) - sysassert(! setenv("YPPSC_PIRATE",pirate,1) ); - - switch (o_mode & mfm_special) { - case 0: break; - case mode_showcharset: ocr_showcharsets(); exit(0); - default: abort(); - } - - if (o_mode & mf_screenshot) { - open_screenshot_file(1); - if (o_flags & ff_singlepage) take_one_screenshot(); - else take_screenshots(); - progress_log("OK for you to move the mouse now, and you can" - " use the YPP client again."); - progress("Finishing handling screenshots..."); - gzclose(&screenshot_file,&screenshot_compressor,"screenshots output"); - } - if (o_mode & mf_readscreenshot) { - if ((o_flags & ff_upload) && !(o_flags & ff_testservers)) - badusage("must not reuse screenshots for upload to live PCTB database"); - open_screenshot_file(0); - if (o_flags & ff_singlepage) read_one_screenshot(); - else read_screenshots(); - gzclose(&screenshot_file,&screenshot_compressor,"screenshots input"); - } - if (o_mode & mf_analyse) { - if (o_flags & ff_needisland) { - find_islandname(); - if (o_flags & ff_printisland) - printf("%s, %s\n", archipelago, island); - sysassert(! setenv("YPPSC_ISLAND",island,1) ); - } - switch (o_outmode_kind) { - case omk_upload: case omk_str: run_analysis(); break; - case omk_raw: analyse(stdout); break; - case omk_none: break; - default: abort(); - } - } - progress_log("Finished."); - return 0; -} - - - - -DEFINE_VWRAPPERF(, progress, ) -DEFINE_VWRAPPERF(, progress_log, ) -DEFINE_VWRAPPERF(, progress_spinner, ) -DEFINE_VWRAPPERF(, warning, ) -DEFINE_VWRAPPERF(, fatal, NORET) - -static int last_progress_len; - -static void vprogress_core(int spinner, const char *fmt, va_list al) { - int r; - - if (o_quiet) return; - if (!debug_flags && !isatty(2)) return; - - if (last_progress_len) - putc('\r',stderr); - - r= vfprintf(stderr,fmt,al); - - if (spinner) { - putc(spinner,stderr); - r++; - } - - if (r < last_progress_len) { - fprintf(stderr,"%*s", last_progress_len - r, ""); - if (!r) putc('\r', stderr); - else while (last_progress_len-- > r) putc('\b',stderr); - } - last_progress_len= r; - - if (ferror(stderr) || fflush(stderr)) _exit(16); -} - -void vprogress(const char *fmt, va_list al) { vprogress_core(0,fmt,al); } -void vprogress_spinner(const char *fmt, va_list al) { - static const char spinchars[]="/-\\"; - static int spinner; - - vprogress_core(spinchars[spinner],fmt,al); - spinner++; - spinner %= (sizeof(spinchars)-1); -} - -void vprogress_log(const char *fmt, va_list al) { - if (o_quiet) return; - - progress(""); - vfprintf(stderr,fmt,al); - putc('\n',stderr); - fflush(stderr); -} - -void vwarning(const char *fmt, va_list al) { - progress(""); - fputs("Warning: ",stderr); - vfprintf(stderr,fmt,al); - fputs("\n",stderr); - fflush(stderr); -} - -void vfatal(const char *fmt, va_list al) { - progress(""); - fputs("\n\nFatal error: ",stderr); - vfprintf(stderr,fmt,al); - fflush(stderr); - fputs("\n\n",stderr); - _exit(4); -} - -void sysassert_fail(const char *file, int line, const char *what) { - int e= errno; - progress(""); - fprintf(stderr, - "\nfatal operational error:\n" - " unsuccessful execution of: %s\n" - " %s:%d: %s\n\n", - what, file,line, strerror(e)); - _exit(16); -} - -void waitpid_check_exitstatus(pid_t pid, const char *what, int sigpipeok) { - pid_t got; - int st; - for (;;) { - got= waitpid(pid, &st, 0); - if (pid==-1) { sysassert(errno==EINTR); continue; } - break; - } - sysassert( got==pid ); - - if (WIFEXITED(st)) { - if (WEXITSTATUS(st)) - fatal("%s failed with nonzero exit status %d", - what, WEXITSTATUS(st)); - } else if (WIFSIGNALED(st)) { - if (!sigpipeok || WTERMSIG(st) != SIGPIPE) - fatal("%s died due to signal %s%s", what, - strsignal(WTERMSIG(st)), WCOREDUMP(st)?" (core dumped)":""); - } else { - fatal("%s gave strange wait status %d", what, st); - } -} - -char *masprintf(const char *fmt, ...) { - char *r; - va_list al; - va_start(al,fmt); - sysassert( vasprintf(&r,fmt,al) >= 0); - sysassert(r); - va_end(al); - return r; -}