Пример #1
0
int main(int argc, char** args) {
    char* default_configfn = "astrometry.cfg";
    char* default_config_path = "../etc";

	int c;
	char* configfn = NULL;
	int i;
	engine_t* engine;
    char* mydir = NULL;
    char* basedir = NULL;
    char* me;
    anbool help = FALSE;
    sl* strings = sl_new(4);
    char* cancelfn = NULL;
    char* solvedfn = NULL;
    int loglvl = LOG_MSG;
    anbool tostderr = FALSE;
    char* infn = NULL;
    FILE* fin = NULL;
    anbool fromstdin = FALSE;

	bl* opts = opts_from_array(myopts, sizeof(myopts)/sizeof(an_option_t), NULL);
	sl* inds = sl_new(4);

	char* datalog = NULL;

	engine = engine_new();

	while (1) {
		c = opts_getopt(opts, argc, args);
		if (c == -1)
			break;
		switch (c) {
		case 'D':
			datalog = optarg;
			break;
		case 'p':
			engine->inparallel = TRUE;
			break;
		case 'i':
			sl_append(inds, optarg);
			break;
		case 'd':
		  basedir = optarg;
		  break;
        case 'f':
            infn = optarg;
            fromstdin = streq(infn, "-");
            break;
        case 'E':
            tostderr = TRUE;
            break;
		case 'h':
            help = TRUE;
			break;
        case 'v':
            loglvl++;
            break;
		case 's':
		  solvedfn = optarg;
        case 'C':
            cancelfn = optarg;
            break;
		case 'c':
			configfn = strdup(optarg);
			break;
		case '?':
			break;
		default:
            printf("Unknown flag %c\n", c);
			exit( -1);
		}
	}

	if (optind == argc && !infn) {
		// Need extra args: filename
		printf("You must specify at least one input file!\n\n");
		help = TRUE;
	}
	if (help) {
		print_help(args[0], opts);
		exit(0);
	}
	bl_free(opts);

	gslutils_use_error_system();

    log_init(loglvl);
    if (tostderr)
        log_to(stderr);

	if (datalog) {
		datalogfid = fopen(datalog, "wb");
		if (!datalogfid) {
			SYSERROR("Failed to open data log file \"%s\" for writing", datalog);
			return -1;
		}
		atexit(close_datalogfid);
		data_log_init(100);
		data_log_enable_all();
		data_log_to(datalogfid);
		data_log_start();
	}

    if (infn) {
        logverb("Reading input filenames from %s\n", (fromstdin ? "stdin" : infn));
        if (!fromstdin) {
            fin = fopen(infn, "rb");
            if (!fin) {
                ERROR("Failed to open file %s for reading input filenames", infn);
                exit(-1);
            }
        } else
            fin = stdin;
    }

    // directory containing the 'engine' executable:
    me = find_executable(args[0], NULL);
    if (!me)
        me = strdup(args[0]);
    mydir = sl_append(strings, dirname(me));
    free(me);

	// Read config file
    if (!configfn) {
        int i;
        sl* trycf = sl_new(4);
        sl_appendf(trycf, "%s/%s/%s", mydir, default_config_path, default_configfn);
        // if I'm in /usr/bin, look for config file in /etc
        if (streq(mydir, "/usr/bin")) {
            sl_appendf(trycf, "/etc/%s", default_configfn);
        }
        sl_appendf(trycf, "%s/%s", mydir, default_configfn);
        sl_appendf(trycf, "./%s", default_configfn);
        sl_appendf(trycf, "./%s/%s", default_config_path, default_configfn);
        for (i=0; i<sl_size(trycf); i++) {
            char* cf = sl_get(trycf, i);
            if (file_exists(cf)) {
                configfn = strdup(cf);
                logverb("Using config file \"%s\"\n", cf);
                break;
            } else {
                logverb("Config file \"%s\" doesn't exist.\n", cf);
            }
        }
        if (!configfn) {
            char* cflist = sl_join(trycf, "\n  ");
            logerr("Couldn't find config file: tried:\n  %s\n", cflist);
            free(cflist);
        }
        sl_free2(trycf);
    }

	if (!streq(configfn, "none")) {
		if (engine_parse_config_file(engine, configfn)) {
			logerr("Failed to parse (or encountered an error while interpreting) config file \"%s\"\n", configfn);
			exit( -1);
		}
	}

	if (sl_size(inds)) {
		// Expand globs.
		for (i=0; i<sl_size(inds); i++) {
			char* s = sl_get(inds, i);
			glob_t myglob;
			int flags = GLOB_TILDE | GLOB_BRACE;
			if (glob(s, flags, NULL, &myglob)) {
				SYSERROR("Failed to expand wildcards in index-file path \"%s\"", s);
				exit(-1);
			}
			for (c=0; c<myglob.gl_pathc; c++) {
				if (engine_add_index(engine, myglob.gl_pathv[c])) {
					ERROR("Failed to add index \"%s\"", myglob.gl_pathv[c]);
					exit(-1);
				}
			}
			globfree(&myglob);
		}
	}

	if (!pl_size(engine->indexes)) {
		logerr("\n\n"
			   "---------------------------------------------------------------------\n"
			   "You must list at least one index in the config file (%s)\n\n"
			   "See http://astrometry.net/use.html about how to get some index files.\n"
			   "---------------------------------------------------------------------\n"
			   "\n", configfn);
		exit(-1);
	}

	if (engine->minwidth <= 0.0 || engine->maxwidth <= 0.0) {
		logerr("\"minwidth\" and \"maxwidth\" in the config file %s must be positive!\n", configfn);
		exit(-1);
	}

    free(configfn);

    if (!il_size(engine->default_depths)) {
        parse_depth_string(engine->default_depths,
                           "10 20 30 40 50 60 70 80 90 100 "
                           "110 120 130 140 150 160 170 180 190 200");
    }

    engine->cancelfn = cancelfn;
    engine->solvedfn = solvedfn;

    i = optind;
    while (1) {
		char* jobfn;
        job_t* job;
		struct timeval tv1, tv2;

        if (infn) {
            // Read name of next input file to be read.
            logverb("\nWaiting for next input filename...\n");
            jobfn = read_string_terminated(fin, "\n\r\0", 3, FALSE);
            if (strlen(jobfn) == 0)
                break;
        } else {
            if (i == argc)
                break;
            jobfn = args[i];
            i++;
        }
        gettimeofday(&tv1, NULL);
        logmsg("Reading file \"%s\"...\n", jobfn);
        job = engine_read_job_file(engine, jobfn);
        if (!job) {
            ERROR("Failed to read job file \"%s\"", jobfn);
            exit(-1);
        }

	if (basedir) {
	  logverb("Setting job's output base directory to %s\n", basedir);
	  job_set_output_base_dir(job, basedir);
	}

		if (engine_run_job(engine, job))
			logerr("Failed to run_job()\n");

		job_free(job);
        gettimeofday(&tv2, NULL);
		logverb("Spent %g seconds on this field.\n", millis_between(&tv1, &tv2)/1000.0);
	}

	engine_free(engine);
    sl_free2(strings);
	sl_free2(inds);

    if (fin && !fromstdin)
        fclose(fin);

    return 0;
}
Пример #2
0
int main(int argc, char** args) {
	int c;
	anbool help = FALSE;
	char* outdir = NULL;
	char* cmd;
	int i, j, f;
    int inputnum;
	int rtn;
	sl* engineargs;
	int nbeargs;
	anbool fromstdin = FALSE;
	anbool overwrite = FALSE;
	anbool cont = FALSE;
    anbool skip_solved = FALSE;
    anbool makeplots = TRUE;
	double plotscale = 1.0;
	char* inbgfn = NULL;
    char* bgfn = NULL;
    char* me;
    anbool verbose = FALSE;
    int loglvl = LOG_MSG;
    char* outbase = NULL;
	anbool usecurl = TRUE;
    bl* opts;
    augment_xylist_t theallaxy;
    augment_xylist_t* allaxy = &theallaxy;
    int nmyopts;
    char* removeopts = "ixo\x01";
    char* newfits;
    char* kmz = NULL;
    char* scamp = NULL;
    char* scampconfig = NULL;
    char* index_xyls;
	anbool just_augment = FALSE;
	anbool engine_batch = FALSE;
	bl* batchaxy = NULL;
	bl* batchsf = NULL;
	sl* outfiles;
	sl* tempfiles;
    // these are deleted after the outer loop over input files
	sl* tempfiles2;
	sl* tempdirs;
	anbool timestamp = FALSE;
    anbool tempaxy = FALSE;

    errors_print_on_exit(stderr);
    fits_use_error_system();

    me = find_executable(args[0], NULL);

	engineargs = sl_new(16);
	append_executable(engineargs, "astrometry-engine", me);

	// output filenames.
	outfiles = sl_new(16);
	tempfiles = sl_new(4);
	tempfiles2 = sl_new(4);
	tempdirs = sl_new(4);

	rtn = 0;

    nmyopts = sizeof(options)/sizeof(an_option_t);
    opts = opts_from_array(options, nmyopts, NULL);
    augment_xylist_add_options(opts);

    // remove duplicate short options.
    for (i=0; i<nmyopts; i++) {
        an_option_t* opt1 = bl_access(opts, i);
        for (j=nmyopts; j<bl_size(opts); j++) {
            an_option_t* opt2 = bl_access(opts, j);
            if (opt2->shortopt == opt1->shortopt)
                bl_remove_index(opts, j);
        }
    }

    // remove unwanted augment-xylist options.
    for (i=0; i<strlen(removeopts); i++) {
        for (j=nmyopts; j<bl_size(opts); j++) {
            an_option_t* opt2 = bl_access(opts, j);
            if (opt2->shortopt == removeopts[i])
                bl_remove_index(opts, j);
        }
    }

	// which options are left?
	/*{
		char options[256];
		memset(options, 0, 256);
		printf("options:\n");
		for (i=0; i<bl_size(opts); i++) {
			an_option_t* opt = bl_access(opts, i);
			printf("  %c (%i) %s\n", opt->shortopt, (int)opt->shortopt, opt->name);
			options[(int)((opt->shortopt + 256) % 256)] = 1;
		}
		printf("Remaining short opts:\n");
		for (i=0; i<256; i++) {
			if (!options[i])
				printf("  %c (%i, 0x%x)\n", (char)i, i, i);
		}
	 }*/

    augment_xylist_init(allaxy);

    // default output filename patterns.
    allaxy->axyfn    = "%s.axy";
    allaxy->matchfn  = "%s.match";
    allaxy->rdlsfn   = "%s.rdls";
    allaxy->solvedfn = "%s.solved";
    allaxy->wcsfn    = "%s.wcs";
    allaxy->corrfn   = "%s.corr";
    newfits          = "%s.new";
    index_xyls = "%s-indx.xyls";

	while (1) {
        int res;
		c = opts_getopt(opts, argc, args);
		//printf("option %c (%i)\n", c, (int)c);
        if (c == -1)
            break;
        switch (c) {
        case '\x91':
            allaxy->axyfn = optarg;
            break;
        case '\x90':
            tempaxy = TRUE;
            break;
		case '\x88':
			timestamp = TRUE;
			break;
		case '\x84':
			plotscale = atof(optarg);
			break;
		case '\x85':
			inbgfn = optarg;
			break;
		case '\x87':
			allaxy->assume_fits_image = TRUE;
			break;
		case '(':
			engine_batch = TRUE;
			break;
		case '@':
			just_augment = TRUE;
			break;
        case 'U':
            index_xyls = optarg;
            break;
        case 'n':
            scampconfig = optarg;
            break;
        case 'i':
            scamp = optarg;
            break;
        case 'Z':
            kmz = optarg;
            break;
        case 'N':
            newfits = optarg;
            break;
		case 'h':
			help = TRUE;
			break;
        case 'v':
            sl_append(engineargs, "--verbose");
            verbose = TRUE;
			allaxy->verbosity++;
            loglvl++;
            break;
		case 'D':
			outdir = optarg;
			break;
        case 'o':
            outbase = optarg;
            break;
		case 'b':
		case '\x89':
			sl_append(engineargs, "--config");
			append_escape(engineargs, optarg);
			break;
		case 'f':
			fromstdin = TRUE;
			break;
        case 'O':
            overwrite = TRUE;
            break;
        case 'p':
            makeplots = FALSE;
            break;
        case 'G':
            usecurl = FALSE;
            break;
        case 'K':
            cont = TRUE;
            break;
        case 'J':
            skip_solved = TRUE;
            break;
        default:
            res = augment_xylist_parse_option(c, optarg, allaxy);
            if (res) {
                rtn = -1;
                goto dohelp;
            }
        }
    }

	if ((optind == argc) && !fromstdin) {
		printf("ERROR: You didn't specify any files to process.\n");
		help = TRUE;
	}

	if (help) {
    dohelp:
		print_help(args[0], opts);
		exit(rtn);
	}
    bl_free(opts);

    // --dont-augment: advertised as just write xy file,
    // so quit after doing that.
    if (allaxy->dont_augment) {
        just_augment = TRUE;
    }

    log_init(loglvl);
	if (timestamp)
		log_set_timestamp(TRUE);

    if (kmz && starts_with(kmz, "-"))
        logmsg("Do you really want to save KMZ to the file named \"%s\" ??\n", kmz);

    if (starts_with(newfits, "-")) {
        logmsg("Do you really want to save the new FITS file to the file named \"%s\" ??\n", newfits);
    }

	if (engine_batch) {
		batchaxy = bl_new(16, sizeof(augment_xylist_t));
		batchsf  = bl_new(16, sizeof(solve_field_args_t));
	}

    // Allow (some of the) default filenames to be disabled by setting them to "none".
    allaxy->matchfn  = none_is_null(allaxy->matchfn);
    allaxy->rdlsfn   = none_is_null(allaxy->rdlsfn);
    allaxy->solvedfn = none_is_null(allaxy->solvedfn);
    allaxy->solvedinfn = none_is_null(allaxy->solvedinfn);
    allaxy->wcsfn    = none_is_null(allaxy->wcsfn);
    allaxy->corrfn   = none_is_null(allaxy->corrfn);
    newfits          = none_is_null(newfits);
    index_xyls = none_is_null(index_xyls);

	if (outdir) {
        if (mkdir_p(outdir)) {
            ERROR("Failed to create output directory %s", outdir);
            exit(-1);
        }
	}

	// number of engine args not specific to a particular file
	nbeargs = sl_size(engineargs);

	f = optind;
    inputnum = 0;
	while (1) {
		char* infile = NULL;
		anbool isxyls;
		char* reason;
		int len;
		char* base;
        char* basedir;
        char* basefile = NULL;
		char *objsfn=NULL;
		char *ppmfn=NULL;
        char* downloadfn = NULL;
        char* suffix = NULL;
		sl* cmdline;
        anbool ctrlc;
        anbool isurl;
        augment_xylist_t theaxy;
        augment_xylist_t* axy = &theaxy;
        int j;
		solve_field_args_t thesf;
		solve_field_args_t* sf = &thesf;
		anbool want_pnm = FALSE;

        // reset augment-xylist args.
        memcpy(axy, allaxy, sizeof(augment_xylist_t));

		memset(sf, 0, sizeof(solve_field_args_t));

		if (fromstdin) {
            char fnbuf[1024];
			if (!fgets(fnbuf, sizeof(fnbuf), stdin)) {
				if (ferror(stdin))
					SYSERROR("Failed to read a filename from stdin");
				break;
			}
			len = strlen(fnbuf);
			if (fnbuf[len-1] == '\n')
				fnbuf[len-1] = '\0';
			infile = fnbuf;
            logmsg("Reading input file \"%s\"...\n", infile);
		} else {
			if (f == argc)
				break;
			infile = args[f];
			f++;
            logmsg("Reading input file %i of %i: \"%s\"...\n",
                   f - optind, argc - optind, infile);
		}
        inputnum++;

        cmdline = sl_new(16);

		if (!engine_batch) {
			// Remove arguments that might have been added in previous trips through this loop
			sl_remove_from(engineargs,  nbeargs);
		}

		// Choose the base path/filename for output files.
        if (outbase)
            asprintf_safe(&basefile, outbase, inputnum, infile);
        else
			basefile = basename_safe(infile);
        //logverb("Base filename: %s\n", basefile);

        isurl = (!file_exists(infile) &&
                 (starts_with(infile, "http://") ||
                  starts_with(infile, "ftp://")));

		if (outdir)
            basedir = strdup(outdir);
		else {
            if (isurl)
                basedir = strdup(".");
            else
				basedir = dirname_safe(infile);
        }
        //logverb("Base directory: %s\n", basedir);

        asprintf_safe(&base, "%s/%s", basedir, basefile);
        //logverb("Base name for output files: %s\n", base);

        // trim .gz, .bz2
        // hmm, we drop the suffix in this case...
		len = strlen(base);
        if (ends_with(base, ".gz"))
            base[len-3] = '\0';
        else if (ends_with(base, ".bz2"))
            base[len-4] = '\0';
		len = strlen(base);
		// trim .xx / .xxx / .xxxx
		if (len >= 5) {
            for (j=3; j<=5; j++) {
                if (base[len - j] == '/')
                    break;
                if (base[len - j] == '.') {
                    base[len - j] = '\0';
                    suffix = base + len - j + 1;
                    break;
                }
            }
		}
        logverb("Base: \"%s\", basefile \"%s\", basedir \"%s\", suffix \"%s\"\n", base, basefile, basedir, suffix);

        if (tempaxy) {
            axy->axyfn = create_temp_file("axy", axy->tempdir);
            sl_append_nocopy(tempfiles2, axy->axyfn);
        } else
            axy->axyfn    = sl_appendf(outfiles, axy->axyfn,       base);
        if (axy->matchfn)
            axy->matchfn  = sl_appendf(outfiles, axy->matchfn,     base);
        if (axy->rdlsfn)
            axy->rdlsfn   = sl_appendf(outfiles, axy->rdlsfn,      base);
        if (axy->solvedfn)
            axy->solvedfn = sl_appendf(outfiles, axy->solvedfn,    base);
        if (axy->wcsfn)
            axy->wcsfn    = sl_appendf(outfiles, axy->wcsfn,       base);
        if (axy->corrfn)
            axy->corrfn   = sl_appendf(outfiles, axy->corrfn,      base);
        if (axy->cancelfn)
            axy->cancelfn  = sl_appendf(outfiles, axy->cancelfn, base);
        if (axy->keepxylsfn)
            axy->keepxylsfn  = sl_appendf(outfiles, axy->keepxylsfn, base);
        if (axy->pnmfn)
            axy->pnmfn  = sl_appendf(outfiles, axy->pnmfn, base);
        if (newfits)
            sf->newfitsfn  = sl_appendf(outfiles, newfits,  base);
		if (kmz)
			sf->kmzfn = sl_appendf(outfiles, kmz, base);
        if (index_xyls)
            sf->indxylsfn  = sl_appendf(outfiles, index_xyls, base);
		if (scamp)
			sf->scampfn = sl_appendf(outfiles, scamp, base);
		if (scampconfig)
			sf->scampconfigfn = sl_appendf(outfiles, scampconfig, base);
        if (makeplots) {
            objsfn     = sl_appendf(outfiles, "%s-objs.png",  base);
            sf->redgreenfn = sl_appendf(outfiles, "%s-indx.png",  base);
            sf->ngcfn      = sl_appendf(outfiles, "%s-ngc.png",   base);
        }
        if (isurl) {
            if (suffix)
                downloadfn = sl_appendf(outfiles, "%s.%s", base, suffix);
            else
                downloadfn = sl_appendf(outfiles, "%s", base);
        }

        if (axy->solvedinfn)
            asprintf_safe(&axy->solvedinfn, axy->solvedinfn, base);

        // Do %s replacement on --verify-wcs entries...
        if (sl_size(axy->verifywcs)) {
            sl* newlist = sl_new(4);
            for (j=0; j<sl_size(axy->verifywcs); j++)
                sl_appendf(newlist, sl_get(axy->verifywcs, j), base);
            axy->verifywcs = newlist;
        }

        // ... and plot-bg
        if (inbgfn)
            asprintf_safe(&bgfn, inbgfn, base);

        if (axy->solvedinfn && axy->solvedfn && streq(axy->solvedfn, axy->solvedinfn)) {
            // solved input and output files are the same: don't delete the input!
            sl_remove_string(outfiles, axy->solvedfn);
            free(axy->solvedfn);
            axy->solvedfn = axy->solvedinfn;
        }

        free(basedir);
        free(basefile);

        if (skip_solved) {
            char* tocheck[] = { axy->solvedinfn, axy->solvedfn };
            for (j=0; j<sizeof(tocheck)/sizeof(char*); j++) {
                if (!tocheck[j])
                    continue;
                logverb("Checking for solved file %s\n", tocheck[j]);
                if (file_exists(tocheck[j])) {
                    logmsg("Solved file exists: %s; skipping this input file.\n", tocheck[j]);
                    goto nextfile;
                } else {
                    logverb("File \"%s\" does not exist.\n", tocheck[j]);
                }
            }
        }

        // Check for overlap between input and output filenames
		for (i = 0; i < sl_size(outfiles); i++) {
			char* fn = sl_get(outfiles, i);
            if (streq(fn, infile)) {
                logmsg("Output filename \"%s\" is the same as your input file.\n"
                       "Refusing to continue.\n"
                       "You can either choose a different output filename, or\n"
                       "rename your input file to have a different extension.\n", fn);
                goto nextfile;
            }
        }

		// Check for (and possibly delete) existing output filenames.
		for (i = 0; i < sl_size(outfiles); i++) {
			char* fn = sl_get(outfiles, i);
			if (!file_exists(fn))
				continue;
            if (cont) {
            } else if (overwrite) {
				if (unlink(fn)) {
					SYSERROR("Failed to delete an already-existing output file \"%s\"", fn);
					exit(-1);
				}
			} else {
				logmsg("Output file already exists: \"%s\".\n"
				       "Use the --overwrite flag to overwrite existing files,\n"
                       " or the --continue  flag to not overwrite existing files but still try solving.\n", fn);
				logmsg("Continuing to next input file.\n");
                goto nextfile;
			}
		}

		// if we're making "redgreen" plot, we need:
		if (sf->redgreenfn) {
			// -- index xylist
			if (!sf->indxylsfn) {
				sf->indxylsfn = create_temp_file("indxyls", axy->tempdir);
				sl_append_nocopy(tempfiles, sf->indxylsfn);
			}
			// -- match file.
			if (!axy->matchfn) {
				axy->matchfn = create_temp_file("match", axy->tempdir);
				sl_append_nocopy(tempfiles, axy->matchfn);
			}
		}

		// if index xyls file is needed, we need:
		if (sf->indxylsfn) {
			// -- wcs
			if (!axy->wcsfn) {
				axy->wcsfn = create_temp_file("wcs", axy->tempdir);
				sl_append_nocopy(tempfiles, axy->wcsfn);
			}
			// -- rdls
			if (!axy->rdlsfn) {
				axy->rdlsfn = create_temp_file("rdls", axy->tempdir);
				sl_append_nocopy(tempfiles, axy->rdlsfn);
			}
		}

        // Download URL...
        if (isurl) {

            sl_append(cmdline, usecurl ? "curl" : "wget");
            if (!verbose)
                sl_append(cmdline, usecurl ? "--silent" : "--quiet");
            sl_append(cmdline, usecurl ? "--output" : "-O");
            append_escape(cmdline, downloadfn);
            append_escape(cmdline, infile);

            cmd = sl_implode(cmdline, " ");

            logmsg("Downloading...\n");
            if (run_command(cmd, &ctrlc)) {
                ERROR("%s command %s", sl_get(cmdline, 0),
                      (ctrlc ? "was cancelled" : "failed"));
                exit(-1);
            }
            sl_remove_all(cmdline);
            free(cmd);

            infile = downloadfn;
        }

		if (makeplots)
			want_pnm = TRUE;

		if (axy->assume_fits_image) {
			axy->imagefn = infile;
			if (axy->pnmfn)
				want_pnm = TRUE;
		} else {
			logverb("Checking if file \"%s\" ext %i is xylist or image: ",
                    infile, axy->extension);
			fflush(NULL);
			reason = NULL;
			isxyls = xylist_is_file_xylist(infile, axy->extension,
                                           axy->xcol, axy->ycol, &reason);
			logverb(isxyls ? "xyls\n" : "image\n");
			if (!isxyls)
				logverb("  (not xyls because: %s)\n", reason);
			free(reason);
			fflush(NULL);

			if (isxyls)
				axy->xylsfn = infile;
			else {
				axy->imagefn = infile;
				want_pnm = TRUE;
			}
		}

		if (want_pnm && !axy->pnmfn) {
            ppmfn = create_temp_file("ppm", axy->tempdir);
            sl_append_nocopy(tempfiles, ppmfn);
            axy->pnmfn = ppmfn;
            axy->force_ppm = TRUE;
		}

        axy->keep_fitsimg = (newfits || scamp);

        if (augment_xylist(axy, me)) {
            ERROR("augment-xylist failed");
            exit(-1);
        }

		if (just_augment)
			goto nextfile;

        if (makeplots) {
            // Check that the plotting executables were built...
            char* exec = find_executable("plotxy", me);
            free(exec);
            if (!exec) {
                logmsg("Couldn't find \"plotxy\" executable - maybe you didn't build the plotting programs?\n");
                logmsg("Disabling plots.\n");
                makeplots = FALSE;
            }
        }
        if (makeplots) {
            // source extraction overlay
            if (plot_source_overlay(axy, me, objsfn, plotscale, bgfn))
                makeplots = FALSE;
        }

		append_escape(engineargs, axy->axyfn);

		if (file_readable(axy->wcsfn))
			axy->wcs_last_mod = file_get_last_modified_time(axy->wcsfn);
		else
			axy->wcs_last_mod = 0;

		if (!engine_batch) {
			run_engine(engineargs);
			after_solved(axy, sf, makeplots, me, verbose,
						 axy->tempdir, tempdirs, tempfiles, plotscale, bgfn);
		} else {
			bl_append(batchaxy, axy);
			bl_append(batchsf,  sf );
		}
        fflush(NULL);

        // clean up and move on to the next file.
    nextfile:        
		free(base);
        sl_free2(cmdline);

		if (!engine_batch) {
			free(axy->fitsimgfn);
			free(axy->solvedinfn);
            free(bgfn);
			// erm.
			if (axy->verifywcs != allaxy->verifywcs)
				sl_free2(axy->verifywcs);
			sl_remove_all(outfiles);
			if (!axy->no_delete_temp)
				delete_temp_files(tempfiles, tempdirs);
		}
        errors_print_stack(stdout);
        errors_clear_stack();
        logmsg("\n");
	}

	if (engine_batch) {
		run_engine(engineargs);
		for (i=0; i<bl_size(batchaxy); i++) {
			augment_xylist_t* axy = bl_access(batchaxy, i);
			solve_field_args_t* sf = bl_access(batchsf, i);

			after_solved(axy, sf, makeplots, me, verbose,
						 axy->tempdir, tempdirs, tempfiles, plotscale, bgfn);
			errors_print_stack(stdout);
			errors_clear_stack();
			logmsg("\n");

			free(axy->fitsimgfn);
			free(axy->solvedinfn);
			// erm.
			if (axy->verifywcs != allaxy->verifywcs)
				sl_free2(axy->verifywcs);
		}
		if (!allaxy->no_delete_temp)
			delete_temp_files(tempfiles, tempdirs);
		bl_free(batchaxy);
		bl_free(batchsf);
	}

    if (!allaxy->no_delete_temp)
        delete_temp_files(tempfiles2, NULL);

	sl_free2(outfiles);
	sl_free2(tempfiles);
	sl_free2(tempfiles2);
	sl_free2(tempdirs);
	sl_free2(engineargs);
    free(me);
    augment_xylist_free_contents(allaxy);

	return 0;
}