aboutsummaryrefslogtreecommitdiff
path: root/vendor/voclient/voapps/vodata.c
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /vendor/voclient/voapps/vodata.c
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'vendor/voclient/voapps/vodata.c')
-rw-r--r--vendor/voclient/voapps/vodata.c2387
1 files changed, 2387 insertions, 0 deletions
diff --git a/vendor/voclient/voapps/vodata.c b/vendor/voclient/voapps/vodata.c
new file mode 100644
index 00000000..71614133
--- /dev/null
+++ b/vendor/voclient/voapps/vodata.c
@@ -0,0 +1,2387 @@
+/**
+ * VODATA -- Query VO Data services (Cone, SIAP, etc)
+ *
+ * Usage: vodata [-<flags>] [<service>] [object|file|position]
+ *
+ * Where
+ * -%%,--test run unit tests
+ * -h,--nelp this message
+ * -d,--debug enable debug messages
+ * -r,--return return result from method
+ *
+ *
+ *
+ *
+ * @file vodata.c
+ * @author Mike Fitzpatrick
+ * @date 7/13/07
+ *
+ * @brief Query VO Data services (Cone, SIAP, etc)
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/time.h>
+#include <time.h>
+#include "VOClient.h"
+#include "voAppsP.h"
+#include "samp.h"
+
+
+
+
+#define VOD_DEBUG (getenv("VOD_DBG")||access("/tmp/VOD_DBG",F_OK)==0)
+
+
+/* Task structure.
+ */
+typedef struct {
+ char *name; /* task name */
+ int (*func)(int argc, char **argv, size_t *len, void **result);
+
+ int ntests; /* number of unit tests */
+ int npass; /* number of passed tests */
+ int nfail; /* number of failed tests */
+} Task;
+
+
+
+/* Local processing definitions.
+*/
+svcParams pars[MAX_THREADS]; /* parameter array */
+
+int format = F_CSV; /* output format */
+int apos = 0; /* argv position */
+int sv_apos = -1; /* saved argv position */
+int nservices = 0; /* num. of cone services */
+int nobjects = 0; /* num. objects to query */
+int filenum = 0; /* download file number */
+int rd_stdin = 0; /* reading from stdin? */
+int wr_stdout = 0; /* writing to stdout? */
+int do_votable = 0; /* output a Resource VOTable */
+int svcNumber = -1; /* service number to call */
+int dalOnly = 1; /* only query DAL services? */
+int simple_out = 0; /* use simple output name? */
+
+int inventory = FALSE; /* do inventory? */
+int quiet = FALSE; /* no output at all? */
+int verbose = TRUE; /* DAL verbose level */
+int all_data = FALSE; /* get all the data? */
+int file_get = FALSE; /* file number to get */
+#ifdef REG10_KLUDGE
+int reg10 = FALSE; /* use Registry 1.0 scheme? */
+#endif
+int raw_vizier = FALSE; /* use Registry 1.0 scheme? */
+int count = TRUE; /* return count of results */
+int meta = FALSE; /* metadata return? */
+int extract = EX_NONE; /* extract pos/acrefs? */
+int count_only = FALSE; /* print only matched records? */
+int save_res = TRUE; /* save results? */
+int all_named = FALSE; /* all objects named? */
+int use_name = FALSE; /* use object name in output? */
+int url_proc = FALSE; /* processing URLs only? */
+int force_svc = FALSE; /* assume URLs are ServiceURLs? */
+int svc_list = FALSE; /* list services queried */
+int obj_list = FALSE; /* list objects queried */
+int fixed_svc = FALSE; /* service is fixed on cmdline */
+int fixed_obj = FALSE; /* object is fixed on cmdline */
+int fixed_pos = FALSE; /* position is fixed on cmdline */
+int data_type = DT_ANY; /* data type */
+int proxy = FALSE; /* use proxy server */
+int res_all = FALSE; /* print all results? */
+int force_read = FALSE; /* force reading of input table */
+int longlines = FALSE; /* output long lines? */
+int iportal = FALSE; /* iportal support? */
+int numout = FALSE; /* numeric output sorting? */
+int samp = FALSE; /* broadcast table via SAMP */
+
+int max_download= DEF_DOWNLOADS; /* max download procs to run */
+int max_procs = DEF_NPROCS; /* max children to run */
+int max_threads = DEF_NTHREADS; /* max threads to run */
+
+int table_hskip = 0; /* no. of table eeader to skip */
+int table_nlines= 0; /* max lines of table to read */
+int table_sample= 1; /* table sample */
+
+int group = 0; /* resolve identifiers in groups*/
+int nterms = 0; /* No. of terms */
+char *terms[128]; /* search terms */
+
+char *typestr = (char *) NULL; /* service type string */
+char *bpass = (char *) NULL; /* bandpass type string */
+char *output = (char *) NULL; /* root output filename */
+char *delim = " \t,|;"; /* input table delimiter */
+char *cols = "1,2"; /* input table columns */
+char *ecols = (char *) NULL; /* input table exact columns */
+char *sources = (char *) NULL; /* source file */
+char *resources = (char *) NULL; /* resource file */
+char *sampName = (char *) NULL; /* SAMP appName */
+
+char *d2_band = (char *) NULL; /* DAL2 BAND parameter */
+char *d2_time = (char *) NULL; /* DAL2 TIME parameter */
+char *d2_format = (char *) NULL; /* DAL2 FORMAT parameter */
+char *d2_version = (char *) NULL; /* DAL2 VERSION parameter */
+
+char *tmpdir = "/tmp/"; /* temp directory */
+char wrkdir[SZ_FNAME]; /* working directory */
+
+double sr = DEF_SR; /* default search radius */
+
+int dverbose = 0; /* verbose debug output? */
+int debug = 0; /* debug output? */
+int samp_p = 0; /* SAMP interface handler */
+
+static int status = OK; /* return status */
+
+
+time_t rs_time = (time_t) 0,
+ re_time = (time_t) 0; /* reg/obj resolution times */
+time_t qs_time = (time_t) 0,
+ qe_time = (time_t) 0; /* data query times */
+time_t as_time = (time_t) 0,
+ ae_time = (time_t) 0; /* data access times */
+
+Service *svcList, *svcTail; /* Service linked list */
+Object *objList, *objTail; /* Obj/Posn linked list */
+Acref *acList, *acTail; /* Acref linked list */
+int nacrefs = 0; /* no. of acrefs */
+
+FILE *arg_fd = (FILE *) NULL; /* argument-file descriptor */
+
+
+/* KML Options.
+*/
+int kml_max = 50, /* max placemarks to write */
+ kml_sample = 0, /* output sample step */
+ kml_region = TRUE, /* draw bounding region poly */
+ kml_verbose = TRUE, /* verbose labels */
+ kml_label = TRUE, /* draw placemark labels */
+ kml_byObj = TRUE, /* group by object/position */
+ kml_bySvc = FALSE, /* group by service name */
+ kml_byBoth = FALSE; /* group by both */
+
+/* HTML Options.
+*/
+int html_header = TRUE, /* print a HTML header on page */
+ html_border = TRUE, /* put a border on the table? */
+ html_color = TRUE; /* colorize the table */
+
+
+extern int errno; /* system error code */
+
+extern int ra_col, ra_span, /* table input */
+ dec_col, dec_span,
+ id_col, id_span;
+extern int svcIndex, objIndex;
+
+extern int isDecimal (char *s);
+extern int isSexagesimal (char *s);
+
+extern int vot_parseObjectList (char *list, int isCmdLine);
+extern int vot_countObjectList (void);
+extern int vot_parseServiceList (char *list, int dalOnly);
+extern int vot_countServiceList (void);
+extern int vot_decodeRanges (char *range_string, int *ranges, int max_ranges,
+ int *nvalues);
+extern int is_in_range (int ranges[], int number);
+extern int vot_atoi (char *v);
+
+extern void vot_addToAclist (char *url, char *fname);
+extern void vot_procAclist (void);
+extern void vot_freeAclist (void);
+extern void vot_freeServiceList (void);
+extern void vot_resetServiceCounters (void);
+extern void vot_freeObjectList (void);
+extern void vot_printCountHdr (void);
+extern void vot_readObjFile (char *fname);
+extern void vot_readSvcFile (char *fname, int dalOnly);
+
+extern double vot_atof (char *v);
+
+/* Tasking execution procedure.
+ */
+extern int vo_runTask (char *method, Task *apps, int argc, char **argv,
+ size_t *len, void **result);
+extern int vo_taskTest (Task *self, char *arg, ...);
+extern void vo_taskTestFile (char *str, char *fname);
+extern void vo_taskTestReport (Task self);
+
+extern int vo_setResultFromFile (char *fname, size_t *len, void **data);
+extern int vo_setResultFromString (char *str, size_t *len, void **data);
+extern int vo_setResultFromInt (int value, size_t *len, void **data);
+extern int vo_setResultFromReal (float value, size_t *len, void **data);
+extern int vo_appendResultFromString (char *str, size_t *len, void **data,
+ size_t *maxlen);
+
+
+#ifdef VO_INVENTORY
+extern char *vot_doInventory (void);
+#endif
+extern char *vot_urlFname (char *url);
+extern char *vot_getOFName (svcParams *pars, char *extn, int pid);
+extern char *vot_getOFIndex (svcParams *pars, char *extn, int pid);
+extern char *vot_normalize (char *str);
+extern char *vot_svcTypeCode (int type);
+
+static int vot_parseArgToken (char *arg, char *next, int pos, int *inc);
+static int vot_validateOptions (void);
+static int vot_getNextCmdline (void);
+static void vot_runSvcThreads (void);
+static void vot_printProcStat (Proc *procList, char *svc_name, int fail_only);
+static void vot_setProcStat (Service *svc, int pid, int status);
+
+static void vot_printProcTime ();
+static char *vot_requiredArg (char *arg);
+static char *vot_optionalArg (char *arg);
+static char vot_setArgWord (char *arg, char *val);
+static char *vot_stat2code (int status);
+static char *vizPatch (char *url);
+/*
+static char *vot_cnvType (char *intype);
+*/
+
+static void vot_printUsage (void);
+static void vot_printExamples (void);
+
+void *vot_procObjs (void *arg);
+void vot_printSvcList (Service *sl);
+void vot_printSvcHdr (void);
+
+
+pthread_mutex_t svc_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+
+/* Task specific option declarations.
+ */
+int vodata (int argc, char **argv, size_t *len, void **result);
+
+static int mf = 0;
+static Task self = { "vodata", vodata, 0, 0, 0 };
+
+/* Note: the leading ':' in the opts string is required to suppress errors
+ */
+static char *opts = ":%hrNSACFHIKMO:RTVXab:ce:fgi:mno:p:qr:s:t:uv";
+
+static struct option long_opts[] = {
+ { "test", 2, 0, '%' }, /* test (std) */
+ { "help", 2, 0, 'h' }, /* help (std) */
+ { "return", 2, 0, 'r' }, /* return (std) */
+
+ { "numeric", 2, 0, 'N' }, /* numeric output name */
+ { "simple", 2, 0, 'S' }, /* simple output name */
+
+ { "ascii", 2, 0, 'A' }, /* ASCII output */
+ { "csv", 2, 0, 'C' }, /* CSV output */
+ { "fits", 2, 0, 'F' }, /* FITS table output */
+ { "html", 2, 0, 'H' }, /* HTML output */
+ { "inventory", 2, 0, 'I' }, /* inventory (not used) */
+ { "kml", 2, 0, 'K' }, /* KML output */
+ { "verbmeta", 2, 0, 'M' }, /* verbose metadata */
+ { "output", 2, 0, 'O' }, /* root output name */
+ { "raw", 2, 0, 'R' }, /* Raw output */
+ { "tsv", 2, 0, 'T' }, /* TSV output */
+ { "votable", 2, 0, 'V' }, /* VOTable output */
+ { "xml", 2, 0, 'X' }, /* XML output */
+
+ { "all", 0, 0, 'a' }, /* all data */
+ { "bandpass", 1, 0, 'b' }, /* bandpass */
+ { "count", 2, 0, 'c' }, /* count results */
+ { "debug", 2, 0, 'd' }, /* debug */
+ { "extract", 1, 0, 'e' }, /* extract */
+ { "force", 2, 0, 'f' }, /* force table read */
+ { "get", 2, 0, 'g' }, /* get specific results */
+ { "input", 1, 0, 'i' }, /* get args from input file */
+ { "meta", 2, 0, 'm' }, /* metadata */
+ { "nosave", 2, 0, 'n' }, /* no-save results */
+ { "object", 1, 0, 'o' }, /* query object name */
+ { "pos", 1, 0, 'p' }, /* query position */
+ { "quiet", 2, 0, 'q' }, /* suppress output */
+ { "sr", 1, 0, 'r' }, /* search radius */
+ { "svc", 1, 0, 's' }, /* data service */
+ { "type", 1, 0, 't' }, /* type string */
+ { "url", 2, 0, 'u' }, /* url download */
+ { "verbose", 2, 0, 'v' }, /* verbose */
+
+ { "bandpass", 1, &mf, 1 }, /* req'd arg word */
+ { "cols", 1, &mf, 2 }, /* req'd arg word */
+ { "ecols", 1, &mf, 3 }, /* req'd arg word */
+ { "delim", 1, &mf, 4 }, /* req'd arg word */
+ { "kml", 1, &mf, 5 }, /* req'd arg word */
+ { "max", 1, &mf, 6 }, /* req'd arg word */
+ { "nlines", 1, &mf, 7 }, /* req'd arg word */
+ { "object", 1, &mf, 8 }, /* req'd arg word */
+ { "output", 1, &mf, 9 }, /* req'd arg word */
+ { "pos", 1, &mf, 10 }, /* req'd arg word */
+ { "sample", 1, &mf, 11 }, /* req'd arg word */
+ { "svc", 1, &mf, 12 }, /* req'd arg word */
+ { "type", 1, &mf, 13 }, /* req'd arg word */
+ { "web", 1, &mf, 15 }, /* req'd arg word */
+ { "band", 1, &mf, 16 }, /* req'd arg word */
+ { "time", 1, &mf, 17 }, /* req'd arg word */
+ { "format", 1, &mf, 18 }, /* req'd arg word */
+ { "version", 1, &mf, 19 }, /* req'd arg word */
+
+ { "onefile", 2, &mf, 20 }, /* one-file output */
+ { "extract", 2, &mf, 21 }, /* opt arg word */
+ { "ep", 2, &mf, 22 }, /* opt arg word */
+ { "eu", 2, &mf, 23 }, /* opt arg word */
+ { "eh", 2, &mf, 24 }, /* opt arg word */
+ { "ek", 2, &mf, 25 }, /* opt arg word */
+ { "eK", 2, &mf, 26 }, /* opt arg word */
+ { "hskip", 2, &mf, 27 }, /* opt arg word */
+
+ { "wh", 2, &mf, 30 }, /* opt arg word */
+ { "wb", 2, &mf, 31 }, /* opt arg word */
+ { "wc", 2, &mf, 32 }, /* opt arg word */
+
+ { "webborder", 2, &mf, 40 }, /* no arg word */
+ { "webheader", 2, &mf, 41 }, /* no arg word */
+ { "webcolor", 2, &mf, 42 }, /* no arg word */
+ { "webnoborder", 2, &mf, 43 }, /* no arg word */
+ { "webnoheader", 2, &mf, 44 }, /* no arg word */
+ { "webnocolor", 2, &mf, 45 }, /* no arg word */
+ { "vverbose", 0, &mf, 46 }, /* no arg word */
+
+ { "debug", 0, &mf, 99 }, /* no arg word */
+
+ { NULL, 0, 0, 0 }
+};
+
+extern char **vo_paramInit (int argc, char *argv[],
+ char *opts, struct option long_opts[]);
+extern int vo_paramNext (char *opts, struct option long_opts[],
+ int argc, char *argv[], char *optval, int *posindex);
+extern void vo_paramFree (int argc, char *argv[]);
+
+
+static void Usage (void);
+static void Tests (char *input);
+
+
+
+
+
+/************************************************************************
+** Program main()
+*/
+int
+vodata (int argc, char *argv[], size_t *reslen, void **result)
+{
+ int i, ch, pos=0;
+ char *eval, *argfile, *next_arg, posn[SZ_LINE];
+ char **pargv, optval[SZ_FNAME];
+
+
+ /* Initialize the VOClient code. Error messages are printed by the
+ ** interface so we just quit if there is a problem.
+ */
+ if (voc_initVOClient ("runid=voc.vodata") == ERR) {
+ fprintf (stderr, "Error: cannot connect to VOClient daemon\n");
+ return (ERR);
+ }
+
+
+ /* Initialize the global structs.
+ */
+ memset (&colRange, 0, sizeof (Range));
+ memset (&rowRange, 0, sizeof (Range));
+ memset (&fileRange, 0, sizeof (Range));
+ colRange.nvalues = RANGE_ALL;
+ rowRange.nvalues = RANGE_ALL;
+ fileRange.nvalues = RANGE_NONE;
+
+
+ /* Get some environment definitions. We allow the command-line flags
+ ** to override these values.
+ */
+ if ((eval = getenv("VOC_MAX_DOWNLOADS")))
+ max_download = vot_atoi (eval);
+ if ((eval = getenv("VOC_MAX_PROCS")))
+ max_procs = vot_atoi (eval);
+ if ((eval = getenv("VOC_MAX_THREADS")))
+ max_threads = vot_atoi (eval);
+
+
+ /* Initializations.
+ */
+ *reslen = 0;
+ *result = NULL;
+ apos = 0;
+ svcIndex = 0;
+ objIndex = 0;
+ all_data = 0;
+
+
+ rs_time = time ((time_t) NULL);
+
+ /* Now process the command line arguments.
+ */
+ if (VOD_DEBUG) {
+ fprintf (stderr, "Command:");
+ for (i=0; i < argc; i++) fprintf (stderr, " '%s'", argv[i]);
+ fprintf (stderr, "\n");
+ for (i=0; i < argc; i++) fprintf (stderr, "%s ", argv[i]);
+ fprintf (stderr, "\n\n");
+ }
+
+
+
+ /* Parse the argument list.
+ */
+ pargv = vo_paramInit (argc, argv, opts, long_opts);
+ for (i=1; i < argc; i++) {
+
+ memset (optval, 0, SZ_FNAME);
+ ch = vo_paramNext (opts, long_opts, argc, pargv, optval, &pos);
+#ifdef PARAM_DBG
+ fprintf (stderr, "ch = '%c' %d optval = '%s'\n",
+ ch, ch, (optval[0] ? optval : "N/A"));
+#endif
+
+ if (ch > 0) {
+ switch (ch) {
+ case '?': /* unknown */
+ break;
+
+ case 'h': /* help */
+ Usage ();
+ voc_closeVOClient (0);
+ return (OK);
+
+ case '%': /* unit tests */
+ voc_closeVOClient (0);
+ Tests (optval);
+ return (self.nfail);
+
+ case 'N': /* numeric output name */
+ numout++;
+ break;
+ case 'S': /* simple output name */
+ simple_out++;
+ break;
+
+ case 'A': /* ASCII output */
+ format = F_ASCII;
+ break;
+ case 'C': /* CSV output */
+ format = F_CSV;
+ break;
+ case 'F': /* FITS table output */
+ fprintf (stderr,
+ "FITS tables not yet implemented, using ASCII\n");
+ format = F_ASCII;
+ break;
+ case 'H': /* HTML output */
+ extract |= EX_HTML;
+ format = F_CSV | F_HTML;
+ if (output && output[0] == '-')
+ extract |= EX_COLLECT;
+ break;
+#ifdef VO_INVENTORY
+ case 'I': /* inventory count */
+ inventory++;
+ count++;
+ break;
+#endif
+ case 'K': /* KML output */
+ extract |= EX_KML;
+ format = F_CSV | F_KML;
+ break;
+ case 'R': /* RAW output */
+ case 'V': /* VOTable output */
+ format = F_RAW;
+ if (output && output[0] == '-')
+ extract |= EX_COLLECT;
+ break;
+ case 'T': /* TSV output */
+ format = F_TSV;
+ break;
+ case 'X': /* XML output */
+ extract |= EX_XML;
+ format = F_RAW | F_XML;
+ if (output && output[0] == '-')
+ extract |= EX_COLLECT;
+ break;
+
+ case 'O': /* root output name */
+ //VOT_NEXTARG(argc,argv,i);
+ output = strdup (optval);
+ if (output[0] == '-') {
+ wr_stdout++;
+ quiet++;
+ if ((extract & EX_XML) || (extract & EX_KML))
+ extract |= EX_COLLECT;
+
+ memset (wrkdir, 0, SZ_FNAME);
+ sprintf (wrkdir, "%s/vod%d", tmpdir, (int)getpid());
+ if (access (wrkdir, R_OK|W_OK) != 0)
+ mkdir (wrkdir, (mode_t)0666);
+ chdir (wrkdir);
+ }
+ break;
+
+ case 'a': /* all data */
+ all_data++;
+ res_all++;
+ /*sr = -1.0; */ /* flag to get all data */
+ break;
+ case 'b': /* forced type string */
+ if (optval[0] == '/' || isdigit(optval[0]))
+ d2_band = strdup (optval);
+ else
+ if (strncasecmp (optval, "any", 3) != 0)
+ bpass = strdup (optval);
+ break;
+ case 'c':
+ count++;
+ count_only = TRUE;
+ break;
+
+ case 'e': /* extract pos/acrefs? */
+ if (strncmp (optval, "pos", 3) == 0)
+ extract |= EX_POS;
+ else if (strncmp (optval, "url", 3) == 0)
+ extract |= EX_ACREF;
+ else if (strncmp (optval, "head", 4) == 0)
+ extract |= EX_HTML;
+ else if (strncmp (optval, "kml", 3) == 0)
+ extract |= EX_KML;
+ else if (strncmp (optval, "xml", 3) == 0)
+ extract |= EX_XML;
+ else if (strncmp (optval, "all", 3) == 0)
+ extract = EX_ALL;
+ else
+ extract = EX_ALL, i++;
+ break;
+
+ case 'f': /* force table read */
+ force_read++;
+ break;
+
+ case 'g': /* get specific results */
+ extract |= EX_ACREF;
+ fileRange.nvalues = RANGE_ALL;
+ file_get = RANGE_ALL;
+ break;
+
+ case 'i': /* take remaining args from file */
+ VOT_NEXTARG(argc,argv,i);
+ sv_apos = apos;
+ argfile = strdup (argv[++i]);
+ if (argfile[0] == '-') {
+ if (strlen (argfile) > 1) {
+ fprintf (stderr, "ERROR: the '-i' flag requires ");
+ fprintf (stderr, "a filename or '-' for stdin\n");
+ exit (1);
+ } else if (rd_stdin) {
+ fprintf (stderr,
+ "ERROR: stdin can only be used once\n");
+ exit (1);
+ } else {
+ rd_stdin++;
+ arg_fd = stdin;
+ }
+
+ } else {
+ if (access (argfile, R_OK) == 0) {
+ /* Open the file, we'll process it below.
+ */
+ if ((arg_fd = fopen(argfile,"r")) == (FILE *)NULL) {
+ fprintf (stderr,
+ "ERROR: Cannot open file '%s'\n", argfile);
+ return (ERR);
+ }
+ }
+ }
+ break;
+
+ case 'M': /* verbose meta */
+ meta++, verbose = 3;
+ res_all++;
+ break;
+ case 'm': /* meta flag */
+ meta++;
+ res_all++;
+ break;
+
+ case 'n': /* no-save results */
+ save_res = FALSE;
+ count_only = TRUE;
+ break;
+
+ case 'o': /* query object name */
+ VOT_NEXTARG(argc,argv,i);
+ use_name++;
+ next_arg = argv[i+1];
+ if (next_arg[0] == '-') {
+ if (rd_stdin) {
+ fprintf (stderr,
+ "ERROR: stdin can only be used once\n");
+ exit (1);
+
+ } else {
+ rd_stdin++;
+ fixed_obj++;
+ vot_readObjFile ("-");
+ }
+ i++; /* advance argv */
+ } else if (inventory) {
+ vot_parseObjectList (argv[++i], TRUE);
+ sources = strdup (argv[i]);
+ if (debug)
+ fprintf (stderr, "setting 'obj' sources = '%s'\n",
+ sources);
+ apos++;
+ } else
+ vot_parseObjectList (argv[++i], TRUE);
+ if (svcList)
+ apos++;
+ break;
+
+ case 'p': /* query position */
+ //VOT_NEXTARG(argc,argv,i);
+ next_arg = argv[i+1];
+ memset (posn, 0, SZ_LINE);
+ if (next_arg[0] == '-') {
+ if (strlen (next_arg) > 1) {
+ fprintf (stderr,"ERROR: the '-p' flag requires");
+ fprintf (stderr," coords or '-' for stdin\n");
+ return (ERR);
+ } else if (rd_stdin) {
+ fprintf(stderr, "ERROR: stdin can only be used once\n");
+ exit (1);
+ } else {
+ rd_stdin++, fixed_pos++;
+ vot_readObjFile ("-");
+ }
+ i++; /* advance argv */
+ } else {
+ if (isSexagesimal(optval) || isDecimal(optval)) {
+ vot_parseObjectList (optval, TRUE);
+ } else if (inventory) {
+ vot_parseObjectList (optval, TRUE);
+ sources = strdup (optval);
+ if (debug)
+ fprintf (stderr,
+ "setting pos sources='%s'\n", sources);
+ } else
+ vot_parseObjectList (optval, TRUE);
+ fixed_pos++;
+ }
+ break;
+
+ case 'q':
+ quiet++;
+ break;
+
+ case 'r': /* search radius */
+ VOT_NEXTARG(argc,argv,i);
+ sr = vot_atof (argv[++i]);
+ break;
+
+ case 's': /* data service */
+ VOT_NEXTARG(argc,argv,i);
+ if (strncmp (argv[i+1], "http", 4) == 0)
+ force_svc++;
+ next_arg = argv[i+1];
+ if (next_arg[0] == '-') {
+ if (strlen (next_arg) > 1) {
+ fprintf(stderr,"ERROR: the '-s' flag requires ");
+ fprintf(stderr,"a service name or '-' for stdin\n");
+ exit (1);
+ } else
+ vot_readSvcFile ("-", dalOnly);
+ i++; /* advance argv */
+ } else if (isdigit (argv[i+1][0])) {
+ svcNumber = vot_atoi (argv[++i]);
+ vot_parseServiceList ((resources = strdup (argv[++i])),
+ dalOnly);
+ if (debug)
+ fprintf (stderr, "setting resources = '%s'\n",
+ resources);
+ } else {
+ vot_parseServiceList ((resources = strdup (argv[++i])),
+ dalOnly);
+ if (debug)
+ fprintf (stderr, "setting resources = '%s'\n",
+ resources);
+ }
+ fixed_svc++;
+ apos++;
+ break;
+
+ case 't': /* forced type string */
+ //VOT_NEXTARG(argc,argv,i);
+ if (strncasecmp (optval, "any", 3) != 0)
+ typestr = strdup (optval), i++;
+ break;
+
+ case 'u': /* forced url download */
+ url_proc++;
+ break;
+
+ case 'v': /* verbose flag */
+ verbose = min(3,(verbose+1));
+ break;
+ }
+
+ } else if (ch == 0) {
+ if ((ch=vot_setArgWord((char *)long_opts[pos].name, optval)) == 0) {
+ fprintf (stderr, "unknown long option '%s'\n",
+ long_opts[pos].name);
+ status = ERR;
+ goto cleanup_;
+ }
+
+
+#ifdef ENG_FLAGS
+ } else if (argv[i][0] == '+') {
+ len = strlen (argv[i]); /* "Engineering" flags. */
+ for (j=1; j < len; j++) {
+ switch (argv[i][j]) {
+ case 's':
+ table_hskip = vot_atoi (argv[++i]);
+ break;
+ case 'S':
+ samp++;
+ sampName = strdup (argv[++i]);
+ break;
+ case 'i':
+ iportal++;
+ break;
+ case 'd':
+ debug++;
+ break;
+ case 'l':
+ svc_list = 1;
+ obj_list = 1;
+ break;
+ case 'q':
+ quiet = 0;
+ break;
+ case 'a': /* null all flag */
+ break;
+ case 'n': /* null flag */
+ break;
+
+#ifdef REG10_KLUDGE
+ case 'r':
+ reg10++;
+ break;
+#endif
+ case 'r':
+ raw_vizier = TRUE;
+ break;
+ case 't':
+ tmpdir = strdup (argv[++i]);
+ break;
+ case 'v':
+ dverbose++;
+ break;
+ }
+ }
+#endif
+
+ } else {
+ /* Parse the arguments according to an assumed calling
+ ** order, e.g.
+ **
+ ** vodata [ url_list | [ resource [obj | ra dec] [sr] ]
+ **
+ ** By default we assume 'sr' is in degrees, the ra/dec will
+ ** be assumed to be ICRS J200 and may be sexagesimal or decimal.
+ ** Since we're parsing the argv[], be sure to take into account
+ ** any increments added because of consumed arguments.
+ */
+ int inc = 0;
+
+ for ( ; i < argc; i++) {
+//if (i > 2 && apos == 0) i--;
+//fprintf (stderr, "pos: '%s' '%s' apos=%d i=%d\n", argv[i], argv[i+1], apos, i);
+ if (vot_parseArgToken (argv[i], argv[i+1], apos, &inc) != OK) {
+ exit (1);
+ } else
+ i += inc; /* add the argv[] increment */
+
+ apos++; /* update arg position */
+ }
+ }
+ }
+ re_time = time ((time_t) NULL);
+
+
+ /* Close VOClient connection. Each child process will need to reopen
+ ** their own connection, and if we're processing an argument file we'll
+ ** open/close it again as needed.
+ */
+ voc_closeVOClient (0);
+
+
+ /* If we're broadcasting the result tables, open the SAMP connection
+ ** now and let the child processes simply send the message.
+ if (samp) {
+ samp_p = sampInit ((sampname ? sampName : "VOData"),
+ "VOClient Data Access");
+ samp_setSyncMode (samp_p);
+ sampStartup (samp_p);
+ }
+ */
+
+
+ /* The control logic below allows us to process more than one
+ ** "command-line". If we got our services and objects from the
+ ** true command-line the loop will break at the bottom and we only
+ ** execute once. The service and object lists were created when
+ ** processing the arguments above. OTOH, if we're using an argument
+ ** file, those lists are now NULL and we'll read each line of the
+ ** argfile and create them now. In either case, we clean up and
+ ** reset the lists at the bottom of the loop.
+ */
+
+ while (1) {
+
+ /* If we're processing from the stdin or an argument file,
+ ** get the next line of the file and fake the commandline to
+ ** set the resource and object lists. Note we clean up and
+ ** reset below to permit each iteration to process a different
+ ** number of resources or objects.
+ */
+ if (arg_fd) {
+ if (vot_getNextCmdline () != OK)
+ break;
+ }
+
+
+ /* Tally up the the number of services and objects to be queried.
+ */
+ if ((nservices = vot_countServiceList()) == 1)
+ svc_list = 0;
+ if ((nobjects = vot_countObjectList()) == 1)
+ obj_list = 0;
+
+#ifdef VO_INVENTORY
+ /* If we're calling the Inventory service, branch to do it here and
+ ** then continue with the loop.
+ */
+ if (inventory) {
+ if (debug)
+ fprintf (stderr, "inventory nserv = %d nobj = %d\n",
+ nservices, nobjects);
+
+ if (nobjects == 0 && sources == NULL) {
+ fprintf (stderr, "No object position(s) specified.\n");
+ exit (1);
+
+ } else {
+ vot_printSvcHdr ();
+ qs_time = time ((time_t) NULL);
+ (void) vot_doInventory ();
+ qe_time = time ((time_t) NULL);
+ }
+
+ vot_printProcTime ();
+ break;
+ }
+#endif
+
+ /* If we have services to call and aren't simply downloading URLs,
+ ** process the service queries first.
+ */
+ if (svcList && !url_proc) {
+
+ /* See whether any flags negate other options.
+ */
+ if (vot_validateOptions() == ERR)
+ break;
+
+ /* Print header information.
+ */
+ vot_printSvcHdr ();
+
+ /* Now run the serice queries. Each service is run on a separate
+ ** thread, we'll handle summary output and any postprocessing later.
+ */
+ vot_runSvcThreads ();
+ }
+
+ /* Process the access reference list to download any pending data.
+ */
+ if (acList && nacrefs)
+ vot_procAclist ();
+
+ /* Free up any memory we may have allocated. Counters and pointers
+ ** are reset in each routine.
+ */
+ vot_freeAclist (); /* access reference list */
+ vot_freeObjectList (); /* object list */
+ if (sv_apos < 0)
+ vot_freeServiceList (); /* VO resource list */
+ else
+ vot_resetServiceCounters ();
+
+
+ /* Print an approximate summary of the processing time required.
+ */
+ vot_printProcTime ();
+
+ /* If we're not processing from an argument file or the
+ ** stdin, we've processed the argv from the commandline, so
+ ** break here.
+ */
+ if (!arg_fd)
+ break;
+ }
+
+
+cleanup_:
+ if (arg_fd && arg_fd != stdin) /* close the argument file */
+ fclose (arg_fd);
+
+ if (wr_stdout && wrkdir[0] && access (wrkdir, R_OK|W_OK) == 0)
+ rmdir (wrkdir); /* clean up wrkdirs */
+
+ /*
+ if (samp)
+ samp_UnRegister (samp_p);
+ */
+
+ if (bpass) free ( (void *) bpass);
+ if (typestr) free ( (void *) typestr);
+
+ if (d2_band) free ( (void *) d2_band);
+ if (d2_time) free ( (void *) d2_time);
+ if (d2_format) free ( (void *) d2_format);
+ if (d2_version) free ( (void *) d2_version);
+
+ return ( status );
+}
+
+
+
+
+/* Set an argument that may optionally be specified as an entire word.
+*/
+
+#define ARG_DONE -1
+
+static char
+vot_setArgWord (char *arg, char *val)
+{
+#ifdef PARAM_DBG
+ fprintf (stderr, "setArg = '%s' val = '%s'\n", arg, val);
+#endif
+
+ if (arg[0] == '-') {
+ fprintf (stderr, "Invalid argument string '--'\n");
+ return (0);
+ /* '--' only FLAGS */
+ } else if (strncmp (arg, "debug", 5) == 0) {
+ debug++;
+ } else if (strncmp (arg, "vdebug", 6) == 0) {
+ debug=3;
+ } else if (strncmp (arg, "bandpass", 8) == 0) {
+ bpass = vot_requiredArg (val);
+
+ } else if (strncmp (arg, "cols", 4) == 0) {
+ cols = vot_requiredArg (val);
+
+ } else if (strncmp (arg, "delim", 5) == 0) {
+ delim = vot_requiredArg (val);
+ switch (delim[0]) {
+ case 's': delim = " "; break;
+ case 'c': delim = ","; break;
+ case 't': delim = "\t"; break;
+ case 'b': delim = "|"; break;
+ }
+
+ } else if (strncmp (arg, "extract", 7) == 0) {
+
+ if (!val) { /* just "--extract" */
+ extract |= EX_ALL;
+
+ } else {
+ switch (*val) {
+ case 'h': extract |= EX_HTML; break; /* html */
+ case 'k': extract |= EX_KML; break; /* KML */
+ case 'K': extract |= EX_KML;
+ extract |= EX_COLLECT; break; /* one-file KML */
+ case 'p': extract |= EX_POS; break; /* positions */
+ case 'u': extract |= EX_ACREF; break; /* urls */
+ case 'X': extract |= EX_XML;
+ format = (F_RAW | F_XML);
+ extract |= EX_COLLECT; break; /* one-file XML */
+ default: extract = EX_BOTH; break; /* all */
+ }
+ }
+
+ } else if (strncmp (arg, "ecols", 5) == 0) {
+ ecols = vot_requiredArg (val);
+
+ } else if (strncmp (arg, "get", 3) == 0) {
+ char *ip = vot_optionalArg (val);
+
+ extract |= EX_ACREF;
+ if (ip == NULL || !(isdigit(*ip)) ) {
+ /* No option implies we get all rows.
+ */
+ fileRange.nvalues = RANGE_ALL;
+ file_get = RANGE_ALL;
+ } else {
+ /* Next arg is a range string.
+ */
+ strcpy (fileRange.rstring, ip);
+ if (vot_decodeRanges (fileRange.rstring,
+ fileRange.ranges, MAX_RANGES, &fileRange.nvalues) < 0) {
+ fprintf (stderr, "Error decoding range string.\n");
+ }
+ file_get = fileRange.nvalues;
+
+ free ( (void *) ip);
+ }
+
+ } else if (strncmp (arg, "hskip", 5) == 0) {
+ char *ip = vot_optionalArg (val);
+ if (ip) {
+ table_hskip = vot_atoi ( ip );
+ free ( (void *) ip);
+ }
+
+ } else if (strncmp (arg, "kml", 3) == 0) {
+ char *ip = vot_requiredArg (val);
+
+ switch (arg[3]) {
+ case 'm': /* max placemarks --kmlmax=N */
+ kml_max = vot_atoi(val);
+ break;
+ case 'g': /* grouping --kmlgroup=type */
+ switch (*val) {
+ case 'b': /* group by both */
+ kml_byBoth = TRUE;
+ kml_byObj = FALSE, kml_bySvc = FALSE;
+ break;
+ case 'o': /* group by object */
+ kml_byObj = TRUE;
+ kml_byBoth = FALSE, kml_bySvc = FALSE;
+ break;
+ case 's': /* group by service */
+ kml_bySvc = TRUE;
+ kml_byObj = FALSE, kml_byBoth = FALSE;
+ break;
+ }
+ break;
+ case 's': /* sample placemarks --kmlsample=N */
+ kml_sample = vot_atoi(ip);
+ break;
+
+ case 'n': /* sample placemarks --kmlno<opt> */
+ switch (arg[5]) {
+ case 'l': /* disable labels */
+ kml_label = FALSE;
+ break;
+ case 'r': /* disable region box */
+ kml_region = FALSE;
+ break;
+ case 'v': /* disable verbose label*/
+ kml_verbose = FALSE;
+ break;
+ }
+ }
+
+ if (strncmp (val, "kmlgroup", 8) == 0)
+ extract |= EX_KML;
+ if (ip)
+ free ((void *) ip);
+
+ } else if (strncmp (arg, "max", 3) == 0) {
+ char *ip = vot_requiredArg (val);
+
+ switch (arg[3]) {
+ case 'd': /* --maxdownloads=<N> */
+ max_download = vot_atoi(ip);
+ max_download = min(MAX_DOWNLOADS,max_download);
+ break;
+ case 'p': /* --maxprocs=<N> */
+ max_procs = vot_atoi(ip);
+ max_procs = min(MAX_PROCS,max_procs);
+ break;
+ case 't': /* --maxthreads=<N> */
+ max_threads = vot_atoi(ip);
+ max_threads = min(MAX_THREADS,max_threads);
+ break;
+ }
+
+ } else if (strncmp (arg, "nlines", 6) == 0) {
+ char *ip = vot_requiredArg (val);
+ table_nlines = vot_atoi ( ip );
+ if (ip)
+ free ((void *) ip);
+
+ } else if (strncmp (arg, "object", 6) == 0) {
+ char *ip = vot_requiredArg (val);
+
+ use_name++;
+ if (!ip || ip[0] == '-') {
+ if (rd_stdin) {
+ fprintf (stderr, "ERROR: stdin can only be used once\n");
+ exit (1);
+
+ } else {
+ rd_stdin++;
+ fixed_obj++;
+ vot_readObjFile ("-");
+ }
+ } else if (inventory) {
+ vot_parseObjectList (ip, TRUE);
+ sources = ip;
+ if (debug)
+ fprintf (stderr, "setting 'obj' sources = '%s'\n", sources);
+ apos++;
+ } else
+ vot_parseObjectList (ip, TRUE);
+ if (svcList)
+ apos++;
+ if (ip)
+ free ((void *) ip);
+
+ } else if (strncmp (arg, "output", 6) == 0) {
+ char *ip = vot_requiredArg (arg);
+
+ output = (ip ? ip : "=");
+ if (output[0] == '-') {
+ wr_stdout++;
+ quiet++;
+ if ((extract & EX_XML) || (extract & EX_KML))
+ extract |= EX_COLLECT;
+
+ memset (wrkdir, 0, SZ_FNAME);
+ sprintf (wrkdir, "%s/vod%d", tmpdir, (int)getpid());
+ if (access (wrkdir, R_OK|W_OK) != 0)
+ mkdir (wrkdir, (mode_t)0666);
+ chdir (wrkdir);
+ }
+ if (ip)
+ free ((void *) ip);
+
+ } else if (strncmp (arg, "pos", 3) == 0) {
+ char posn[SZ_LINE];
+ char *ip = vot_requiredArg (val);
+
+ if (ip[0] == '-') {
+ if (strlen (ip) > 1) {
+ fprintf (stderr,"ERROR: the '--pos' flag requires ");
+ fprintf (stderr,"coords or '-' for stdin\n");
+ exit (1);
+ } else if (rd_stdin) {
+ fprintf (stderr, "ERROR: stdin can only be used once\n");
+ exit (1);
+ rd_stdin++, fixed_pos++;
+ } else {
+ vot_readObjFile ("-");
+ }
+ } else {
+ char v1[SZ_FNAME], v2[SZ_FNAME], *op;
+
+ op = strchr (val, (int)','); /* find delimiter */
+ memset (v1, 0, SZ_FNAME); /* clear arrays */
+ memset (v2, 0, SZ_FNAME);
+ if (op) {
+ *op = '\0';
+ strcpy (v1, ip); /* first arg */
+ strcpy (v2, op+1); /* second arg */
+ } else {
+ fprintf (stderr, "ERROR: Invalid '--pos' argument\n");
+ exit (1);
+ }
+
+ if (isSexagesimal(v1) || isDecimal(v1)) {
+ sprintf (posn, "%s %s", v1, v2);
+ fixed_pos++;
+ vot_parseObjectList (posn, TRUE);
+ } else if (inventory) {
+ vot_parseObjectList ((sources = ip), TRUE);
+ apos++;
+ } else
+ vot_parseObjectList (ip, TRUE);
+ }
+ if (fixed_svc)
+ apos++;
+ if (ip)
+ free ((void *) ip);
+
+ } else if (strncmp (arg, "sample", 6) == 0) {
+ table_sample = vot_atoi ( vot_requiredArg (arg) );
+
+ } else if (strncmp (arg, "sr", 2) == 0) {
+ char *ip = vot_requiredArg (val);
+ int len = strlen(ip);
+ char units = ip[len-1];
+
+ if (!isdigit(units))
+ ip[len-1] = '\0';
+ else
+ units = 'd';
+ switch (units) {
+ case 's': sr = vot_atof (ip) / 3600.; break;
+ case 'm': sr = vot_atof (ip) / 60.; break;
+ case 'd': sr = vot_atof (ip); break;
+ }
+ if (ip)
+ free ((void *) ip);
+
+
+ } else if (strncmp (arg, "svc", 3) == 0) {
+ char *ip = vot_requiredArg (val);
+
+ if (strncmp (ip, "http", 4) == 0)
+ force_svc++;
+ if (ip[0] == '-') {
+ if (strlen (ip) > 1) {
+ fprintf (stderr,"ERROR: the '-s' flag requires ");
+ fprintf (stderr,"a service name or '-' for stdin\n");
+ exit (1);
+ } else
+ vot_readSvcFile ("-", dalOnly);
+ } else {
+ vot_parseServiceList ((resources = ip), dalOnly);
+ if (debug)
+ fprintf (stderr, "setting resources = '%s'\n", resources);
+ if (inventory)
+ apos++;
+ }
+ fixed_svc++;
+ apos++;
+ if (fixed_pos)
+ apos++;
+ if (ip)
+ free ((void *) ip);
+
+ } else if (strncmp (arg, "type", 4) == 0) {
+ typestr = vot_requiredArg (val);
+
+ } else if (strncmp (arg, "verbose", 7) == 0) {
+ verbose = 2;
+ } else if (strncmp (arg, "vverbose", 8) == 0) {
+ verbose = 3;
+
+ } else if (strncmp (arg, "onefile", 7) == 0) {
+ extract |= EX_COLLECT; /* one-file output */
+
+ } else if (strncmp (arg, "wb", 2) == 0 ||
+ strncmp (arg, "webnoborder", 9) == 0) {
+ html_border = FALSE; /* disable table border */
+ } else if (strncmp (arg, "webborder", 7) == 0) {
+ html_border = TRUE; /* enable table border */
+
+ } else if (strncmp (arg, "wc", 2) == 0 ||
+ strncmp (arg, "webnocolor", 9) == 0) {
+ html_color = FALSE; /* disable border color */
+ } else if (strncmp (arg, "webcolor", 9) == 0) {
+ html_color = TRUE; /* enable border color */
+
+ } else if (strncmp (arg, "wh", 2) == 0 ||
+ strncmp (arg, "webnoheader", 9) == 0) {
+ html_header = FALSE; /* disable table header */
+ } else if (strncmp (arg, "webheader", 7) == 0) {
+ html_header = TRUE; /* enable table header */
+
+
+ } else if (strncmp (arg, "web", 3) == 0) {
+ char *ip = vot_requiredArg (val);
+ switch (ip[0]) {
+ case 'b': html_border = FALSE; break; /* disable table border */
+ case 'c': html_color = FALSE; break; /* disable verbose label */
+ case 'h': html_header = FALSE; break; /* disable region box */
+ }
+ if (ip)
+ free ((void *) ip);
+ /* DAL2 OPTION FLAGS */
+ } else if (strncmp (arg, "band", 4) == 0) {
+ d2_band = vot_requiredArg (val);
+ } else if (strncmp (arg, "time", 4) == 0) {
+ d2_time = vot_requiredArg (val);
+ } else if (strncmp (arg, "format", 6) == 0) {
+ d2_format = vot_requiredArg (val);
+ } else if (strncmp (arg, "version", 7) == 0) {
+ d2_version = vot_requiredArg (val);
+ }
+
+ return (ARG_DONE);
+}
+
+
+static char *
+vot_requiredArg (char *arg)
+{
+ if (! arg) {
+ fprintf (stderr, "ERROR: Missing '--%s' argument.\n", arg);
+ exit (1);
+ }
+
+ return ( strdup (arg) );
+}
+
+static char *
+vot_optionalArg (char *arg)
+{
+ return ( (arg ? strdup (arg) : NULL) );
+}
+
+
+
+/************************************************************************
+** PARSEARGTOKEN -- Parse the argument based on it's position on the
+** command line. Some actions will require the next argument in the
+** command, otherwise the 'next' pointer will usually be NULL. This
+** routine can be used to parse either the argv commands or those from
+** a file. The 'inc' variable will indicate how far to advance the
+** argument counter as a result of this procedure.
+*/
+static int
+vot_parseArgToken (char *arg, char *next, int pos, int *inc)
+{
+ char posn[64];
+
+ *inc = 0;
+
+ /* Parse the arguments according to an assumed calling
+ ** order, i.e.
+ **
+ ** vodata [ url_list | [ resource [obj | ra dec] [sr] ]
+ **
+ ** By default we assume size is in degrees, the ra/dec will
+ ** be assumed to be ICRS J200 and may be sexagesimal or decimal.
+ */
+//fprintf (stderr, "parseArg: '%s' '%s' %d apos=%d\n", arg, next, pos, apos);
+ switch (apos) {
+ case 0: /* <resource> | <url> */
+
+ if (arg[0] != '/' && (isSexagesimal (arg) || isDecimal (arg))) {
+ fprintf (stderr,
+ "\nERROR: First argument required to be resource or url.\n");
+ return (ERR);
+ }
+
+ if (strncmp (arg, "http", 4) == 0 && !force_svc && url_proc) {
+ /* If this is a simple URL, simply download the result. */
+ vot_addToAclist (arg, NULL);
+ if (!fixed_pos)
+ apos--;
+ url_proc++;
+
+#ifdef VO_INVENTORY
+ } else if (inventory) {
+ /* If we're doing an incentory call, the first arg is only
+ ** allowed to be either 'any', and 'ivorn', or (eventually) a
+ ** file of resources to be uploads.
+ */
+ if (strcasecmp ("any",arg) == 0 ||
+ strncmp (arg, "ivo://", 6) == 0 ||
+ access (arg, R_OK) == 0) {
+ if (strncmp (arg, "ivo://", 6) == 0) {
+ extern char *id;
+ id = arg;
+ }
+ if (access (arg, R_OK) == 0)
+ resources = arg;
+ vot_parseServiceList (arg, 0);
+
+ } else {
+ fprintf (stderr, "Invalid resource type for Inventory, '%s'\n",
+ arg);
+ exit (1);
+ }
+#endif
+
+ } else if (raw_vizier && strncmp ("ivo://CDS", arg, 9) == 0) {
+ char url[SZ_LINE];
+ char *res = &arg[17];
+ char *base =
+ "http://vizier.u-strasbg.fr/viz-bin/votable/-dtd/-A?-source=";
+
+ sprintf (url, "%s%s", base, res);
+
+ /*
+ */
+ vot_parseServiceList (url, 0);
+ if (!fixed_pos)
+ apos--;
+ url_proc++;
+
+ } else {
+ /* Restrict 'any' searches to DAL only to save time.
+ */
+ if (strncasecmp ("any", arg, 3) == 0)
+ dalOnly = 1;
+ vot_parseServiceList (arg, dalOnly);
+ if (fixed_pos)
+ apos++;
+ }
+
+ break;
+
+ case 1: /* <obj> | <pos>*/
+ /* Sanity checks. */
+ if (force_svc && typestr && strchr(typestr,(int)',')) {
+ fprintf (stderr,
+ "\nERROR: Only one type may be given to used-defined service.\n");
+ return (ERR);
+
+ } else if (force_svc && !typestr && !fixed_svc) {
+ fprintf (stderr,
+ "\nERROR: No type specified for used-defined service.\n");
+ return (ERR);
+
+ } else if (!url_proc && !svcList && !inventory) {
+ fprintf (stderr,
+ "\nERROR: No supported DAL service types found.\n");
+ return (ERR);
+ }
+
+ /* Parse the object or position. */
+ if (fixed_pos) {
+ *inc = 1;
+ } else if (isSexagesimal (arg) || isDecimal (arg)) {
+ memset (posn, 0, 64);
+ sprintf (posn, "%s %s", arg, next);
+ vot_parseObjectList (posn, TRUE);
+ *inc = 1;
+ } else {
+ use_name++;
+ if (inventory && access (arg, R_OK) == 0)
+ sources = arg;
+ vot_parseObjectList (arg, TRUE);
+ }
+ break;
+
+ case 2: /* <size> (degrees) */
+ sr = vot_atof (arg);
+ break;
+
+ default:
+ fprintf (stderr, "Warning: Unknown argument syntax\n");
+ vot_printUsage ();
+ return (ERR);
+ }
+
+ return (OK);
+}
+
+
+/************************************************************************
+** GETNEXTCMDLINE -- Process the next command line from the argument
+** file. We do this by reading a line of the file and tokenizing it
+** as if the values were given to us on the command-line. For the
+** moment we don't allow options to be set and permit only the positional
+** arguments (e.g. resource, object, coords).
+*/
+static int
+vot_getNextCmdline ()
+{
+ int i, inc;
+ char *tok, *sep = " ", *line, cmdline[SZ_LINE];
+ int a_argc = 0;
+ char a_argv[4][SZ_LINE];
+
+ extern char *vot_getline (FILE *fd);
+
+
+ memset (a_argv, 0, (4 * SZ_LINE));
+ memset (cmdline, 0, SZ_LINE);
+
+ if (( line = vot_getline (arg_fd)))
+ strcpy (cmdline, line);
+ else
+ return (ERR);
+
+
+ for (tok = strtok(cmdline, sep); tok; tok = strtok(NULL, sep)) {
+ strcpy (a_argv[a_argc++], tok);
+ }
+
+ if (voc_initVOClient ("runid=voc.vodata") == ERR)
+ exit (-1);
+
+ apos = sv_apos;
+ for (i=0; i < a_argc; i++) {
+ if (vot_parseArgToken (a_argv[i], a_argv[i+1], apos, &inc) != OK) {
+ exit (1);
+ } else
+ i += inc; /* add the argv[] increment */
+
+ apos++; /* update arg position */
+ }
+
+
+ /* Close the VOClient connection since each child will use its own.
+ */
+ voc_closeVOClient (0); /* close VOClient connection */
+
+ return (OK);
+}
+
+
+/************************************************************************
+** VALIDATEOPTIONS -- Verify that all the commandline options make sense
+** before we begin processing. Some options will require others and we
+** can only check after all the options have been set and parsed from
+** the command line.
+*/
+static int
+vot_validateOptions ()
+{
+ if (count)
+ fileRange.nvalues = RANGE_NONE;
+
+ if (nobjects < 1) {
+ if (apos && !meta && !all_data) {
+ /* User provided an object, but it was invalid.
+ */
+ fprintf (stderr, "Error: No valid position or object found.\n");
+ return (ERR);
+
+ } else {
+ /* No position/object supplied, use default.
+ */
+ if (!quiet && !meta)
+ fprintf (stderr, "# Using default position: 0.0 0.0\n");
+ vot_parseObjectList ("0.0 0.0", TRUE);
+ nobjects = vot_countObjectList();
+ }
+ }
+
+ if (output && output[0] == '-')
+ extract |= EX_COLLECT;
+
+ if (kml_sample)
+ kml_max *= kml_sample;
+
+ if (meta && nservices == 0) {
+ fprintf (stderr, "ERROR: No service specified.\n");
+ return (ERR);
+ } else if (meta && nservices == 1) {
+ output = "-";
+ wr_stdout++;
+ quiet++;
+ }
+
+ return (OK);
+}
+
+
+
+/************************************************************************
+** PRINTSVCHDR -- Print a header for service output.
+*/
+void
+vot_printSvcHdr ()
+{
+ if (!quiet) {
+ printf ("\n");
+ if (meta) {
+ if (nservices == 1)
+ fprintf (stderr, "# Service: %s\n", svcList->name);
+ fprintf (stderr, "# No. of Services: %d\n", nservices);
+ } else {
+ if (nservices == 1) {
+ fprintf (stderr, "# Service: %s\n", svcList->name);
+ fprintf (stderr, "# Title: %s\n", svcList->title);
+ }
+ fprintf (stderr, "# No. of Objects: %d\n", nobjects);
+ fprintf (stderr, "# No. of Services: %d\n", nservices);
+ }
+ fprintf (stderr, "# Search size: %f (degrees)\n#\n", sr);
+ if (count || inventory)
+ vot_printCountHdr ();
+ }
+
+ fflush (stdout);
+}
+
+
+/************************************************************************
+** RUNSVCTHREADS -- Begin a processing thread for each data service. We
+** split the object list over each service in parallel threads.
+*/
+static void
+vot_runSvcThreads ()
+{
+ int t, tc, rc, status, t_start, t_end, nthreads;
+/*
+ pthread_t thread[nservices];
+*/
+ static pthread_t thread[10000];
+ Service *svc = svcList;
+ Proc *new = (Proc *)NULL;
+ Proc *cur = (Proc *)NULL;
+ pthread_attr_t attr; /* thread attributes */
+
+
+ qs_time = time ((time_t) NULL);
+
+ if (verbose && !count && !meta && nservices > 1)
+ fprintf (stderr, "# Creating service processing threads...\n");
+
+ /* Pre-allocate the process lists so they're in the global memory
+ ** space.
+ */
+ for (svc=svcList; svc; svc=svc->next) {
+ for (t=0; t < nobjects; t++) {
+ new = (Proc *) calloc (1, sizeof (Proc));
+ new->svc = (Service *) svc; /* set back pointer */
+ if (t == 0) {
+ svc->proc = new;
+ cur = svc->proc;
+ } else {
+ cur->next = new;
+ cur = cur->next;
+ }
+ }
+ }
+
+ nthreads = min (nservices, max_threads);
+ t_start = 0;
+ t_end = nthreads;
+
+
+ /* Spawn the processing threads.
+ */
+ svc = svcList;
+ for (tc=0; tc < nservices; tc += nthreads) {
+ t_end = min((nservices-tc),nthreads);
+
+ /* Initialize the service processing thread attributes and run 'em.
+ */
+ pthread_attr_init (&attr);
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
+
+ for (t=0; t < t_end; t++, svc=svc->next) {
+ if ((rc = pthread_create (&thread[t], &attr, vot_procObjs,
+ (void *)svc))) {
+ fprintf (stderr,
+ "ERROR: pthread_create() fails, code: %d\n", rc);
+ exit (-1);
+ }
+ }
+
+ /* Free attribute and wait for the threads to complete.
+ */
+ for (t=0; t < t_end; t++) {
+ if ((rc = pthread_join (thread[t], (void **)&status)) ) {
+ /*
+ fprintf (stderr, "ERROR: pthread_join() fails, code: %d\n", rc);
+ exit (-1);
+ */
+ ;
+ }
+ }
+
+ pthread_attr_destroy (&attr);
+ }
+ qe_time = time ((time_t) NULL);
+
+ if ((debug && verbose > 1)) {
+ fprintf (stderr, "\n\n..........THREAD PROCS COMPLETED.....\n");
+ vot_printSvcList (svcList);
+ fprintf (stderr, "..........THREAD PROCS COMPLETED.....\n\n\n");
+ }
+
+
+ /* If we're only writing a KML file and not simply extracting them
+ ** as an extra, concatenate the results from each query to a single
+ ** file for easier browsing.
+ */
+ if (format & F_KML || (extract & EX_KML && extract & EX_COLLECT)) {
+ char fname[SZ_FNAME];
+ extern void vot_concatKML (char *fname);
+
+ memset (fname, 0, SZ_FNAME);
+ if (output && output[0] != '-')
+ sprintf (fname, "Query_%d.kml", (int)getpid());
+ else
+ strcpy (fname, "-");
+ if (nservices > 1 && nobjects > 1)
+ vot_concatKML (fname);
+
+ } else if (format & F_XML || (extract & EX_XML && extract & EX_COLLECT)) {
+ char fname[SZ_FNAME];
+ extern void vot_concatXML (char *fname);
+
+ memset (fname, 0, SZ_FNAME);
+ if (output && output[0] != '-')
+ sprintf (fname, "Query_%d.xml", (int)getpid());
+ else
+ strcpy (fname, "-");
+
+ if (nservices > 1 && nobjects > 1)
+ vot_concatXML (fname);
+
+ } else if (extract & EX_COLLECT) {
+ extern void vot_concat (void);
+
+ vot_concat (); /* concatenate results */
+ }
+
+
+ /* For verbose output, print a summary of the processing history.
+ */
+ if (!quiet && count && !meta) {
+ Proc *curproc = (Proc *) NULL;
+ Proc *proc = (Proc *) NULL;
+ char *pad, *lpad;
+
+ int tot_rec = 0; /* Total records found */
+ int tot_fail = 0; /* No. failed service calls */
+ int tot_nodata= 0; /* No. of no-data results */
+ int tot_query = 0; /* No. of queries */
+
+ tot_query = (nservices * nobjects);/* Total No. queries made */
+
+ for (svc=svcList; svc; svc=svc->next) {
+ tot_rec += (svc->count > 0 ? svc->count : 0);
+ tot_fail += svc->nfailed;
+ tot_nodata += svc->nnodata;
+ }
+
+ pad = (nobjects == 1) ? "\t\t\t" : "\t\t\t\t\t";
+ lpad = (nobjects == 1) ? "---------------" : "";
+ printf ("\n");
+ printf ("#%s-------------------------------------%s\n", pad, lpad);
+/*
+ printf ("#%s%4d (Records Found)\n", pad, tot_rec);
+ printf ("#%s%4d (Resources Queried)\n", pad, tot_query);
+ printf ("#%s%4d (Failed Requests)\n", pad, tot_fail);
+ printf ("#%s%4d (Completed Requests)\n", pad, (tot_query-tot_fail));
+ printf ("#%s\t (%d Results w/ Data)\n", pad,
+ (tot_query - tot_fail - tot_nodata));
+*/
+ fprintf (stderr, "#%s%4d (Records Found)\n", pad, tot_rec);
+ fprintf (stderr, "#%s%4d (Resources Queried)\n", pad, tot_query);
+ fprintf (stderr, "#%s%4d (Failed Requests)\n", pad, tot_fail);
+ fprintf (stderr, "#%s%4d (Completed Requests)\n", pad,
+ (tot_query - tot_fail));
+ fprintf (stderr, "#%s\t (%d Results w/ Data)\n", pad,
+ (tot_query - tot_fail - tot_nodata));
+ if (tot_nodata)
+ printf ("#%s\t (%d Results w/ No Data)\n", pad, tot_nodata);
+ printf ("#\n");
+
+ if (verbose < 3)
+ return;
+
+ svc = svcList;
+ for (t=0; t < nservices; t++, svc=svc->next) {
+ if (svc->nfailed || !FAILED_ONLY)
+ vot_printProcStat (svc->proc, svc->name, FAILED_ONLY);
+
+ /* Free the proctable structure.
+ */
+ for (curproc=svc->proc; curproc; curproc=proc) {
+ proc = curproc->next;
+ if (curproc)
+ free ((void *) curproc);
+ }
+ }
+ }
+}
+
+
+/************************************************************************
+** PRINTSVCLIST -- Debug routine to print the SvcList.
+*/
+void
+vot_printSvcList (Service *sl)
+{
+ Service *s;
+ Proc *p;
+
+ for (s=sl; s; s=s->next) {
+ fprintf (stderr, "%15s: nfail=%d nrefs=%d type=%d\ts=%ld\n",
+ s->name, s->nfailed, s->nrefs, s->type, (long)s);
+
+ for (p=s->proc; p; p=p->next) {
+ fprintf (stderr, "\t\tpid=%d status=%d obj=%s\t p=%ld\n",
+ p->pid, p->status, p->obj->name, (long)p);
+ }
+ }
+}
+
+
+/************************************************************************
+** PROCOBJS -- Create threads to process the object list. Our only
+** argument is the Service object to run.
+*/
+void *
+vot_procObjs (void *arg)
+{
+ int nobj, nprocs, nrunning, nremaining, nupdate;
+ int lock, nrep, status;
+ pid_t r_pid, pid;
+
+ Object *obj = objList;
+ Service *svc = (Service *)arg;
+ Proc *curproc = (Proc *) svc->proc;
+ svcParams pars;
+
+
+ /* Figure out how many threads to run at a time.
+ */
+ nprocs = ( (nobjects > max_threads) ? max_threads : nobjects );
+ nupdate = 10;
+
+ nrep = nrunning = 0;
+ nremaining = nobjects;
+
+ for (nobj=1; nremaining > 0; ) {
+
+ if (debug)
+ fprintf (stderr, "procObjs(%s): n=%d/%d nprocs=%d nrun=%d sr=%f\n",
+ svc->name, nobj, nobjects, nprocs, nrunning, sr);
+
+ /* Spawn a process thread for each object/position.
+ */
+ if (nrunning < nprocs && nobj <= nobjects) {
+
+ /* Set up the service parameter struct. Each thread gets its
+ ** own instance.
+ */
+ strcpy (pars.service_url, vizPatch(svc->service_url));
+ strcpy (pars.identifier, svc->identifier);
+ strcpy (pars.name, svc->name);
+ if (id_col && obj->id && obj->id[0])
+ strcpy (pars.oname, obj->id);
+ else
+ strcpy (pars.oname, obj->name);
+ strcpy (pars.title, svc->title);
+ pars.ra = obj->ra;
+ pars.dec = obj->dec;
+
+ /* Prior to Registry 1.0 we didn't have a real cone capability
+ ** for Vizier tables and needed to set flags to download the
+ ** entire table. This is no longer necessary, the user can set
+ ** a negative search radius to get the entire table if they choose.
+
+ pars.sr = sr;
+ */
+ if (all_data && svc->type == SVC_VIZIER)
+ pars.sr = -1.0;
+ else
+ pars.sr = sr;
+ pars.fmt = format;
+ pars.type = svc->type;
+ pars.index = nobj;
+ pars.obj_index = nobj - 1; /* zero-indexed */
+ pars.svc_index = svc->index;
+
+ if ((pid = (*(PFI)(*svc->func))((void *)&pars)) < 0) {
+ fprintf (stderr,"ERROR: process fork() fails\n");
+ pthread_exit ((void *) NULL);
+ }
+ nrunning++;
+ nobj++;
+
+ /* Allocate the process summary struct. Only save the status if
+ ** we'll be printing a summary later.
+ */
+ if ((extract & EX_COLLECT) || !quiet) {
+
+ /* Lock the thread to protect us from messing with the
+ ** service list data.
+ */
+ lock = pthread_mutex_lock (&svc_mutex);
+ curproc->pid = pid; /* load the process struct */
+ curproc->obj = obj;
+ curproc->status = 0;
+ memset (curproc->root, 0, SZ_FNAME);
+ if (use_name || all_named || id_col)
+ strcpy (curproc->root, vot_getOFName(&pars,NULL,(int)pid));
+ else
+ strcpy (curproc->root, vot_getOFIndex(&pars,NULL,(int)pid));
+
+
+ curproc = curproc->next; /* move on */
+ lock = pthread_mutex_unlock (&svc_mutex);
+ }
+
+ if (debug)
+ fprintf (stderr, "procObjs(%s): %d ra=%f dec=%f pid=%d\n",
+ svc->name, nobj, obj->ra, obj->dec, pid);
+
+ if (obj)
+ obj = obj->next;
+
+ } else {
+
+ /* Process table full, wait for any child processes to complete.
+ */
+ if (debug)
+ fprintf (stderr, "procObjs(%s:%d): waiting %d remaining....\n",
+ svc->name, getpid(), nremaining);
+
+ if ((r_pid = waitpid ((pid_t)-1, &status, (int) 0)) < 0 ) {
+ /* FIXME
+ if (verbose || debug)
+ fprintf (stderr, "ERROR: waitpid() fails, code[%d] %s\n",
+ (int)errno, strerror(errno));
+ pthread_exit ((void *) NULL);
+ */
+ }
+
+ status = WEXITSTATUS(status);
+ if (debug)
+ fprintf (stderr, "pid = %d stat = %d\n", r_pid, status);
+
+ lock = pthread_mutex_lock (&svc_mutex);
+ vot_setProcStat (svc, (int)r_pid, status);
+ lock = pthread_mutex_unlock (&svc_mutex);
+
+ nrunning--;
+ nremaining--;
+ }
+
+ if (!quiet && nobj < nobjects && (nobj % nupdate) == 0 &&
+ !count && !file_get && nrep == 0) {
+ fprintf (stderr,
+ "# Service %15s: Completed %3d of %4d objects (%d running)\n",
+ svc->name, nobj, nobjects, nrunning);
+ nrep = 1;
+ } else if (nrep == 1)
+ nrep = 0;
+ }
+
+ if (!quiet && !count && !file_get && !meta) {
+ fprintf (stderr, "# Service %25s: ", svc->name);
+ fprintf (stderr, "Finished processing (%d of %d succeeded).\n",
+ (nobjects - (svc->nfailed + svc->nnodata)),
+ nobjects);
+ }
+ if (debug)
+ fprintf (stderr, "procObjs done (%s).\n", svc->name);
+
+
+ pthread_exit (NULL);
+}
+
+
+static char *
+vizPatch (char *url)
+{
+ static char new[SZ_LINE], *ip, *op;
+
+ memset (new, 0, SZ_LINE);
+ for (ip=url, op=new; *ip; ) {
+ if (*ip == '&' && *(ip+1) == '/')
+ ip++;
+ *op++ = *ip++;
+ }
+
+ return (new);
+}
+
+
+/************************************************************************
+** SETPROCSTAT -- Set the process return status. 'procList' is the
+** process list running on this particular thread.
+*/
+static void
+vot_setProcStat (Service *svc, int pid, int status)
+{
+ Service *s = svcList;
+ Proc *pp;
+ int i, rc, sem_id, n = nservices;
+
+ if (svcList == (Service *) NULL)
+ return;
+
+ for (s=svcList; s; s=s->next, n--) {
+ for (pp=s->proc; pp; pp=pp->next) {
+ if (pp->pid == pid) {
+ /* Set the status for this svc/obj process.
+ */
+ pp->status = status;
+ if (status == E_REQFAIL)
+ s->nfailed++;
+ if (status == E_NODATA)
+ s->nnodata++;
+
+ /* If we created a URL extraction, add the URLS to the
+ ** access list.
+ */
+ if (extract == EX_ACREF || extract == EX_BOTH) {
+ char fname[SZ_FNAME], url[SZ_URL];
+ FILE *fd;
+ int nf = 1;
+
+ /* Get the filename of the URLs we'll get.
+ */
+ memset (fname, 0, SZ_FNAME);
+ sprintf (fname, "%s.urls", pp->root);
+
+ /* Construct a template for each file.
+ */
+ if (access (fname, R_OK) == 0) {
+ fd = fopen (fname, "r");
+ for (i=1; fgets (url, SZ_URL, fd); i++) {
+ url[strlen(url)-1] = '\0'; /* kill newline */
+
+ memset (fname, 0, SZ_FNAME);
+ if (file_get > 1)
+ sprintf (fname, "%s.%03d", pp->root, i);
+ else
+ sprintf (fname, "%s", pp->root);
+
+ if (file_get && is_in_range(fileRange.ranges,i)) {
+ vot_addToAclist (url, fname);
+ nf++;
+ }
+ }
+ fclose (fd);
+ }
+ }
+
+ /* Get the semaphore set by the child indicating the
+ ** result count.
+ */
+ sem_id = semget (pid, 0, 0);
+ pp->count = semctl (sem_id, 0, GETVAL, 0); /* get value */
+ s->count += pp->count;
+ rc = semctl (sem_id, 0, IPC_RMID, NULL); /* release it */
+ if (status != E_NODATA && s->count == 0)
+ s->nnodata++;
+
+ break;
+ }
+ }
+ }
+ if (s == (Service *) NULL && n) { /* no matching service found */
+ fprintf (stderr, "Warning: NO SERVICE FOUND....pid=%d status=%d\n",
+ pid, status);
+ return;
+ }
+}
+
+
+
+/************************************************************************
+** PRINTPROCSTAT -- Print a summary of the processing results. If
+** 'failed_only' is set this is an error summary only.
+*/
+static void
+vot_printProcStat (Proc *procList, char *svc_name, int failed_only)
+{
+ Proc *pp = procList;
+ FILE *fd = (failed_only ? stderr : stdout);
+
+ if (procList == (Proc *) NULL)
+ return;
+
+ fprintf (fd, "\nError Summary for '%s' :\n", svc_name);
+ while (pp) {
+ if (!failed_only || pp->status) {
+ fprintf (fd, " Pid %6d: Source: %-12.12s (%.6f,%.6f) %s\n",
+ pp->pid,
+ (pp->obj->name ? pp->obj->name : "(none)"),
+ pp->obj->ra, pp->obj->dec, vot_stat2code(pp->status));
+ }
+ pp = pp->next;
+ }
+}
+
+
+/************************************************************************
+** STAT2CODE -- Convert an error code to a text string for printing.
+*/
+static char *
+vot_stat2code (int status)
+{
+ switch (status) {
+ case E_NONE: return ("OK"); break;
+ case E_NODATA: return ("No Data Returned"); break;
+ case E_REQFAIL: return ("Request Failed"); break;
+ case E_FILOPEN: return ("File Open Error"); break;
+ case E_VOCINIT: return ("VOClient init fails"); break;
+ default: return ("Unknown Error"); break;
+ }
+
+ return (NULL);
+}
+
+
+/************************************************************************
+** CNVTYPE -- Convert an error code to a text string for printing.
+static char *
+vot_cnvType (char *intype)
+{
+ if (strcasecmp ("image", intype) == 0)
+ return ("siap");
+ else if (strcasecmp ("catalog", intype) == 0)
+ return ("cone");
+ else if (strcasecmp ("table", intype) == 0)
+ return ("tabularskyservice");
+ else
+ return (intype);
+}
+*/
+
+
+/************************************************************************
+** PRINTPROCTIME -- Print a summary of the processing times.
+*/
+static void
+vot_printProcTime ()
+{
+ if (!quiet) {
+ int r = ((int)re_time - (int)rs_time),
+ q = ((int)qe_time - (int)qs_time),
+ a = ((int)ae_time - (int)as_time);
+ int tot = (r + q + a);
+
+ extern char *toSexaTime (int n);
+
+
+ printf ("#\n");
+ printf ( "# Approx Time: %02d:%02d:%02d\t",
+ (tot / 3600), (tot / 60), (tot % 60));
+ printf ("(%02d:%02d Resolution, %02d:%02d Query, %02d:%02d Access)\n",
+ r / 60, r % 60,
+ q / 60, q % 60,
+ a / 60, a % 60);
+ }
+}
+
+
+/************************************************************************
+** USAGE -- Print a summary of the help options.
+*/
+static void
+Usage()
+{
+ vot_printUsage();
+
+ printf ("Where:\n");
+ printf ("\n");
+ printf (" <resource> ShortName/Identifier of data service \n");
+ printf (" <obj> Name of object to be resolved\n");
+ printf (" <ra> <dec> Decimal or Sexagesimal coords for query \n");
+ printf (" <url> URL to access or ServiceURL to query \n");
+ printf (" <sr> Search radius in degrees (def: 0.1) \n");
+ printf ("\n");
+ printf (" These values may optionally be in a file containing them.\n");
+ printf (" Resource and object names may be comma-delimited lists\n");
+ printf ("\n");
+ printf ("\n");
+ printf (" -h Print this help summary\n");
+ printf (" -v, --vverbose Verbose or very-verbose mode\n");
+ printf ("\n\tTask Behavior Flags:\n");
+ printf (" -a, --all Query all data for the resource\n");
+ printf (" -c, --count Print a count\n");
+ printf (" -g, --get <rng> Get the files associated with a query\n");
+ printf (" -m, --meta Print the column metadata for the resource\n");
+
+ printf ("\n\tQuery Options:\n");
+ printf (" -b <bandpass> Constrain by bandpass\n");
+ printf (" -i <file> Take arguments from file (or stdin)\n");
+ printf (" -o <obj> Specify object list\n");
+ printf (" -p <pos> Specify position list\n");
+ printf (" -r Set search radius\n");
+ printf (" -rs Set radius in arc-seconds\n");
+ printf (" -rm Set radius in arc-minutes\n");
+ printf (" -rd Set radius in degrees (default: 0.1)\n");
+ printf (" -s <svc> Specify the service name or url\n");
+ printf (" -t <type> Constrain by service type\n");
+
+ printf ("\n\tOutput Options:\n");
+ printf (" -A,--ascii ASCII table output (.txt extension)\n");
+ printf (" -C,--csv CSV table output (.csv extension)\n");
+ printf (" -H,--html HTML table output (.html extension)\n");
+#ifdef VO_INVENTORY
+ printf (" -I Output results from the Inventory Service\n");
+#endif
+ printf (" -K,--kml KML output (.kml extension)\n");
+ printf (" -R,--raw Raw (VOTable) output (.xml extension)\n");
+ printf (" -V,--votable VOTable output (.xml extension)\n");
+ printf (" -T,--tsv Tab-separated table output (.tsv extension)\n");
+ printf (" -O <root> Set the root part of output name\n");
+ printf ("\n");
+ printf (" -e,--extract Extract results to separate file\n");
+ printf (" --ep Extract only positions (to <file>.pos)\n");
+ printf (" --eu Extract only access urls (to <file>.urls)\n");
+ printf (" --eh Extract table to HTML (to <file>.html)\n");
+ printf (" --ek Extract table to individual KML (to <file>.kml)\n");
+ printf (" --eK Extract table to aggregate KML (to <file>.kml)\n");
+ printf (" -n,--nosave No-save results, print a count only\n");
+ printf (" -q,--quiet Suppress output to the screen\n");
+
+ printf ("\n\tFormat-specific Options:\n");
+ printf (" --km <N> Set max downloads (def: 100)\n");
+ printf (" --kgb Group KML output by both object and service\n");
+ printf (" --kgo Group KML output by object\n");
+ printf (" --kgs Group KML output by service\n");
+ printf (" --ks <N> Set result sample\n");
+ printf (" --kl Disable Placemark labels\n");
+ printf (" --kr Disable region box\n");
+ printf (" --kv Disable verbose labels\n");
+ printf ("\n");
+ printf (" --wb Disable HTML table borders\n");
+ printf (" --wc Disable HTML table verbose label\n");
+ printf (" --wh Disable HTML page header\n");
+
+ printf ("\n\tProcessing Options:\n");
+ printf (" --md <N> Set max downloads (def: 1)\n");
+ printf (" --mp <N> Set max number of processes per obj query\n");
+ printf (" --mt <N> Set max number of resource threads to run\n");
+ printf (" \n");
+
+ printf ("\n Notes:\n");
+ printf ("\t- Data Services may be listed by Registry ShortName of ");
+ printf ("Identifier\n");
+ printf ("\t- Sources may be object name, positions in decimal or sexages");
+ printf ("imal\n\t coords, or a file containing either.\n");
+
+ printf ("\n\n");
+ printf ("Resource Type Strings:\n");
+ printf (" catalog Cone search services\n");
+ printf (" image Simple Image Access services\n");
+ printf (" spectra Simple Spectral Access services\n");
+ printf (" table Vizier services\n");
+ printf (" <literal> ResourceType from registry record\n");
+ printf ("\n");
+ printf ("Allowed Bandpass Strings:\n");
+ printf (" Radio Millimeter Infrared (IR)\n");
+ printf (" Optical Ultraviolet (UV) X-Ray (xray)\n");
+ printf (" Gamma-Ray (GR)\n");
+ printf ("\n");
+
+ printf ("\n\n");
+ vot_printExamples();
+ printf ("\n\n");
+}
+
+
+static void
+vot_printExamples()
+{
+
+ printf ("Examples:\n---------\n\n");
+
+
+ printf ("\
+ 1) Query the GSC 2.3 catalog for stars a) within the 0.1 degree \n\
+ default search size around NGC 1234: b) around all positions \n\
+ contained in file 'pos.txt': c) for the list of objects given \n\
+ on the command line: d) query a list of services for a list \n\
+ of positions: e) print a count of results that would be returned\n\
+ from 3 services for each position in a file:\n\
+\n\
+ %% vodata gsc2.3 ngc1234 (a)\n\
+ %% vodata gsc2.3 pos.txt (b)\n\
+ %% vodata gsc2.3 m31,m51,m93 (c)\n\
+ %% vodata svcs.txt pos.txt (d)\n\
+ %% vodata hst,chandra,gsc2.3 pos.txt (e)\n\
+\n\
+ 2) Find all images by HST of NGC 4258, create a KML file for Google Sky:\n\
+\n\
+ %% vodata -K -t image -all hst ngc4258\n\
+\n\
+ 3) Query all (142) image services having data of the subdwarf\n\
+ galaxy IC 10, print a count of the results only:\n\
+\n\
+ %% vodata -c -t image any IC10\n\
+\n\
+ 4) Print a count of X-ray catalog data around Abell2712:\n\
+\n\
+ %% vodata -count -t catalog -b x-ray any abell2712\n\
+\n\
+ 5) Print the column metadata returned by the RC3 catalog service:\n\
+\n\
+ %% vodata -meta -t catalog rc3\n\
+\n\
+ 6) Use the Registry to query for resources using the search terms\n\
+ 'cooling flow'. Upon examining the output the user notices a\n\
+ Vizier paper titled 'Cooling Flows in 207 clusters of Galaxies'\n\
+ that looks interesting. Use the vodata task to download all\n\
+ tables associated with this paper, save tables in the default\n\
+ CSV format:\n\
+\n\
+ %% voregistry cooling flow\n\
+ %% vodata -O white97 -all J/MNRAS/292/419\n\n\n\
+ ");
+
+}
+
+
+static void
+vot_printUsage()
+{
+ printf ("\n");
+ printf ("Usage:\n");
+ printf ("\n");
+ printf (" vodata <flags> [[ <resource> [<obj> | <ra> <dec>] [<sr>] | [<url>]]\n");
+ printf ("\n");
+}
+
+
+
+/**
+ * Tests -- Task unit tests.
+ */
+static void
+Tests (char *input)
+{
+ Task *task = &self;
+
+ vo_taskTest (task, "--help", NULL);
+
+ vo_taskTestFile ("m31\nm51\nm99\n", "pos.txt");
+ vo_taskTestFile ("hst\nchandra\ngsc2.3\n", "svcs.txt");
+
+ vo_taskTest (task, "gsc2.3", "ngc1234", NULL);
+ vo_taskTest (task, "gsc2.3", "pos.txt", NULL);
+ vo_taskTest (task, "gsc2.3", "m31,m51,m93", NULL);
+ vo_taskTest (task, "svcs.txt", "pos.txt", NULL);
+ vo_taskTest (task, "hst,chandra,gsc2.3", "pos.txt", NULL);
+
+ vo_taskTest (task, "-c", "-t", "image", "any", "IC10", NULL);
+ vo_taskTest (task, "--count", "--type=image", "any", "IC10", NULL);
+ vo_taskTest (task, "-c", "-t", "catalog", "-b", "x-ray",
+ "any", "abell2712", NULL);
+ vo_taskTest (task, "--count", "--type=image", "--bandpass=x-ray",
+ "any", "abell2712", NULL);
+
+ vo_taskTest (task, "--meta", "rc3", NULL);
+
+ vo_taskTest (task, "-O", "white97", "-all", "J/MNRAS/292/419", NULL);
+
+ vo_taskTest (task, "-rv", "-t", "image", "xmm", NULL);
+ vo_taskTest (task, "-cq", "xmm-newton", "3c273", NULL);
+ vo_taskTest (task, "--count", "--quiet", "xmm-newton", "3c273", NULL);
+ vo_taskTest (task, "--get", "xmm-newton", "3c273", NULL);
+
+ vo_taskTest (task, "-e", "-O", "2mass", "-t", "image", "2mass",
+ "12:34:56.7", "-23:12:45.2", NULL);
+ vo_taskTest (task, "-e", "--output=2mass", "--type=image", "2mass",
+ "12:34:56.7", "-23:12:45.2", NULL);
+
+ vo_taskTest (task, "-e", "ivo://nasa.heasarc/abell",
+ "0.0", "0.0", "180.0", NULL);
+
+ vo_taskTest (task, "-a", "galex", "m51", NULL);
+ vo_taskTest (task, "--all", "galex", "m51", NULL);
+
+
+ if (access ("pos.txt", F_OK) == 0) unlink ("pos.txt");
+ if (access ("svcs.txt", F_OK) == 0) unlink ("svcs.txt");
+
+ vo_taskTestReport (self);
+}
+